mirror of
https://github.com/reactos/reactos.git
synced 2025-07-10 21:44:13 +00:00
[USB]
- We proudly merge the first charge of the usb-bringup branch. We do want to stress hardware support is still under heavy development and testing in real hardware is experimental - Merge the Human Interface Device Stack(HID) which is used for mice / keyboards and other devices which use the USB interface, consisting of hidusb, hidparse, hidclass, mouhid, kbdhid - Merge the composite driver, supports USB composite devices, laid out in usbccgp - Merge the generic hub driver, which supports the USB root hub and in future USB hubs. Driver is usbhub - Merge the Open Host Controller Interface driver (ohci) - Merge the Enhanced Host Controller Interface driver (ehci) - Merge the many fixes in other areas of ReactOS needed for USB to work (ntoskrnl, pci, inf, umpnpmgr, usetup) - Special thanks goes the Haiku team, whose excellent code has provided a great base for the development of the new ReactOS USB / HID stack - The development of the USB stack has shown the great potential when ReactOS developers team up together to achieve a common goal. The involved developers are here, listed alphabetically: Alex Ionescu Amine Khaldi Cameron Gutman Johannes Anderwald Michel Martin Thomas Faber Thomas Lotz(Haiku) Let's start the ReactOS revolution svn path=/trunk/; revision=55555
This commit is contained in:
commit
022f4b2ce5
192 changed files with 74821 additions and 2501 deletions
|
@ -2811,7 +2811,7 @@ InstallDevice(PCWSTR DeviceInstance, BOOL ShowWizard)
|
|||
&DeviceKey) == ERROR_SUCCESS)
|
||||
{
|
||||
if (RegQueryValueExW(DeviceKey,
|
||||
L"ClassGUID",
|
||||
L"Class",
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
|
|
|
@ -63,6 +63,7 @@ InstallDriver(
|
|||
if (!SetupFindFirstLineW(hInf, L"BootBusExtenders.Load", Driver, &Context)
|
||||
&& !SetupFindFirstLineW(hInf, L"BusExtenders.Load", Driver, &Context)
|
||||
&& !SetupFindFirstLineW(hInf, L"SCSI.Load", Driver, &Context)
|
||||
&& !SetupFindFirstLineW(hInf, L"InputDevicesSupport.Load", Driver, &Context)
|
||||
&& !SetupFindFirstLineW(hInf, L"Keyboard.Load", Driver, &Context))
|
||||
return FALSE;
|
||||
if (!INF_GetDataField(&Context, 1, &ImagePath))
|
||||
|
|
|
@ -728,19 +728,19 @@ LanguagePage(PINPUT_RECORD Ir)
|
|||
static PAGE_NUMBER
|
||||
SetupStartPage(PINPUT_RECORD Ir)
|
||||
{
|
||||
SYSTEM_DEVICE_INFORMATION Sdi;
|
||||
//SYSTEM_DEVICE_INFORMATION Sdi;
|
||||
NTSTATUS Status;
|
||||
WCHAR FileNameBuffer[MAX_PATH];
|
||||
INFCONTEXT Context;
|
||||
PWCHAR Value;
|
||||
UINT ErrorLine;
|
||||
ULONG ReturnSize;
|
||||
//ULONG ReturnSize;
|
||||
PGENERIC_LIST_ENTRY ListEntry;
|
||||
INT IntValue;
|
||||
|
||||
CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
|
||||
|
||||
|
||||
#if 0
|
||||
/* Check whether a harddisk is available */
|
||||
Status = NtQuerySystemInformation(SystemDeviceInformation,
|
||||
&Sdi,
|
||||
|
@ -759,6 +759,7 @@ SetupStartPage(PINPUT_RECORD Ir)
|
|||
MUIDisplayError(ERROR_NO_HDD, Ir, POPUP_WAIT_ENTER);
|
||||
return QUIT_PAGE;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Get the source path and source root path */
|
||||
Status = GetSourcePaths(&SourcePath,
|
||||
|
@ -1465,8 +1466,6 @@ SelectPartitionPage(PINPUT_RECORD Ir)
|
|||
}
|
||||
}
|
||||
|
||||
CheckActiveBootPartition(PartitionList);
|
||||
|
||||
DrawPartitionList(PartitionList);
|
||||
|
||||
/* Warn about partitions created by Linux Fdisk */
|
||||
|
@ -2381,8 +2380,6 @@ FormatPartitionPage(PINPUT_RECORD Ir)
|
|||
else if (!FileSystemList->Selected->FormatFunc)
|
||||
return QUIT_PAGE;
|
||||
|
||||
CheckActiveBootPartition(PartitionList);
|
||||
|
||||
#ifndef NDEBUG
|
||||
CONSOLE_PrintTextXY(6, 12,
|
||||
"Disk: %I64u Cylinder: %I64u Track: %I64u",
|
||||
|
@ -2442,19 +2439,6 @@ FormatPartitionPage(PINPUT_RECORD Ir)
|
|||
PathBuffer);
|
||||
DPRINT("DestinationRootPath: %wZ\n", &DestinationRootPath);
|
||||
|
||||
|
||||
/* Set SystemRootPath */
|
||||
RtlFreeUnicodeString(&SystemRootPath);
|
||||
swprintf(PathBuffer,
|
||||
L"\\Device\\Harddisk%lu\\Partition%lu",
|
||||
PartitionList->ActiveBootDisk->DiskNumber,
|
||||
PartitionList->ActiveBootPartition->
|
||||
PartInfo[PartitionList->ActiveBootPartitionNumber].PartitionNumber);
|
||||
RtlCreateUnicodeString(&SystemRootPath,
|
||||
PathBuffer);
|
||||
DPRINT("SystemRootPath: %wZ\n", &SystemRootPath);
|
||||
|
||||
|
||||
if (FileSystemList->Selected->FormatFunc)
|
||||
{
|
||||
Status = FormatPartition(&DestinationRootPath,
|
||||
|
@ -2505,15 +2489,6 @@ CheckFileSystemPage(PINPUT_RECORD Ir)
|
|||
RtlCreateUnicodeString(&DestinationRootPath, PathBuffer);
|
||||
DPRINT("DestinationRootPath: %wZ\n", &DestinationRootPath);
|
||||
|
||||
/* Set SystemRootPath */
|
||||
RtlFreeUnicodeString(&SystemRootPath);
|
||||
swprintf(PathBuffer,
|
||||
L"\\Device\\Harddisk%lu\\Partition%lu",
|
||||
PartitionList->ActiveBootDisk->DiskNumber,
|
||||
PartitionList->ActiveBootPartition->PartInfo[PartNum].PartitionNumber);
|
||||
RtlCreateUnicodeString(&SystemRootPath, PathBuffer);
|
||||
DPRINT("SystemRootPath: %wZ\n", &SystemRootPath);
|
||||
|
||||
CONSOLE_SetTextXY(6, 8, MUIGetString(STRING_CHECKINGPART));
|
||||
|
||||
CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
|
||||
|
@ -3371,9 +3346,31 @@ BootLoaderPage(PINPUT_RECORD Ir)
|
|||
UCHAR PartitionType;
|
||||
BOOLEAN InstallOnFloppy;
|
||||
USHORT Line = 12;
|
||||
WCHAR PathBuffer[MAX_PATH];
|
||||
|
||||
CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
|
||||
|
||||
/* Find or set the active partition */
|
||||
CheckActiveBootPartition(PartitionList);
|
||||
|
||||
/* Update the partition table because we may have changed the active partition */
|
||||
if (WritePartitionsToDisk(PartitionList) == FALSE)
|
||||
{
|
||||
DPRINT("WritePartitionsToDisk() failed\n");
|
||||
MUIDisplayError(ERROR_WRITE_PTABLE, Ir, POPUP_WAIT_ENTER);
|
||||
return QUIT_PAGE;
|
||||
}
|
||||
|
||||
RtlFreeUnicodeString(&SystemRootPath);
|
||||
swprintf(PathBuffer,
|
||||
L"\\Device\\Harddisk%lu\\Partition%lu",
|
||||
PartitionList->ActiveBootDisk->DiskNumber,
|
||||
PartitionList->ActiveBootPartition->
|
||||
PartInfo[PartitionList->ActiveBootPartitionNumber].PartitionNumber);
|
||||
RtlCreateUnicodeString(&SystemRootPath,
|
||||
PathBuffer);
|
||||
DPRINT("SystemRootPath: %wZ\n", &SystemRootPath);
|
||||
|
||||
PartitionType = PartitionList->ActiveBootPartition->
|
||||
PartInfo[PartitionList->ActiveBootPartitionNumber].PartitionType;
|
||||
|
||||
|
|
|
@ -838,8 +838,12 @@ AddDiskToList (HANDLE FileHandle,
|
|||
|
||||
if (!DiskEntry->BiosFound)
|
||||
{
|
||||
#if 0
|
||||
RtlFreeHeap(ProcessHeap, 0, DiskEntry);
|
||||
return;
|
||||
#else
|
||||
DPRINT1("WARNING: Setup could not find a matching BIOS disk entry. Disk %d is not be bootable by the BIOS!\n", DiskNumber);
|
||||
#endif
|
||||
}
|
||||
|
||||
InitializeListHead (&DiskEntry->PartListHead);
|
||||
|
@ -871,7 +875,7 @@ AddDiskToList (HANDLE FileHandle,
|
|||
|
||||
GetDriverName (DiskEntry);
|
||||
|
||||
InsertAscendingList(&List->DiskListHead, DiskEntry, DISKENTRY, ListEntry, BiosDiskNumber);
|
||||
InsertAscendingList(&List->DiskListHead, DiskEntry, DISKENTRY, ListEntry, DiskNumber);
|
||||
|
||||
/*
|
||||
* Allocate a buffer for 26 logical drives (2 entries each == 52)
|
||||
|
@ -2373,9 +2377,8 @@ CheckActiveBootPartition (PPARTLIST List)
|
|||
}
|
||||
#endif
|
||||
|
||||
DiskEntry = CONTAINING_RECORD (List->DiskListHead.Flink,
|
||||
DISKENTRY,
|
||||
ListEntry);
|
||||
/* Choose the currently selected disk */
|
||||
DiskEntry = List->CurrentDisk;
|
||||
|
||||
/* Check for empty partition list */
|
||||
if (IsListEmpty (&DiskEntry->PartListHead))
|
||||
|
@ -2436,7 +2439,7 @@ CheckActiveBootPartition (PPARTLIST List)
|
|||
List->ActiveBootPartitionNumber = i;
|
||||
|
||||
DPRINT("Found bootable partition disk %d, drive letter %c\n",
|
||||
DiskEntry->BiosDiskNumber, PartEntry->DriveLetter[i]);
|
||||
DiskEntry->DiskNumber, PartEntry->DriveLetter[i]);
|
||||
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -1398,20 +1398,6 @@ HKLM,"SYSTEM\CurrentControlSet\Hardware Profiles\Current\System\CurrentControlSe
|
|||
HKLM,"SYSTEM\CurrentControlSet\Hardware Profiles\Current\System\CurrentControlSet\Services\Vga\Device0","DefaultSettings.XResolution",0x00010001,640
|
||||
HKLM,"SYSTEM\CurrentControlSet\Hardware Profiles\Current\System\CurrentControlSet\Services\Vga\Device0","DefaultSettings.YResolution",0x00010001,480
|
||||
|
||||
; USB uhci/ehci driver
|
||||
;HKLM,"SYSTEM\CurrentControlSet\Services\usbdrv","ErrorControl",0x00010001,0x00000000
|
||||
;HKLM,"SYSTEM\CurrentControlSet\Services\usbdrv","Group",0x00000000,"Base"
|
||||
;HKLM,"SYSTEM\CurrentControlSet\Services\usbdrv","ImagePath",0x00020000,"system32\drivers\usbdrv.sys"
|
||||
;HKLM,"SYSTEM\CurrentControlSet\Services\usbdrv","Start",0x00010001,0x00000001
|
||||
;HKLM,"SYSTEM\CurrentControlSet\Services\usbdrv","Type",0x00010001,0x00000001
|
||||
|
||||
; USB storage driver
|
||||
;HKLM,"SYSTEM\CurrentControlSet\Services\usbstor","ErrorControl",0x00010001,0x00000000
|
||||
;HKLM,"SYSTEM\CurrentControlSet\Services\usbstor","Group",0x00000000,"Extended Base"
|
||||
;HKLM,"SYSTEM\CurrentControlSet\Services\usbstor","ImagePath",0x00020000,"system32\drivers\usbstor.sys"
|
||||
;HKLM,"SYSTEM\CurrentControlSet\Services\usbstor","Start",0x00010001,0x00000003
|
||||
;HKLM,"SYSTEM\CurrentControlSet\Services\usbstor","Type",0x00010001,0x00000001
|
||||
|
||||
; Windows Installer Service
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\MSIserver","DisplayName",0x00000000,"ReactOS Installer"
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\MSIserver","Description",0x00000000,"Controls installation, maintenance, and removal of software packaged as an msi (Windows Installer)"
|
||||
|
|
|
@ -8,6 +8,58 @@ HKLM,"SYSTEM\CurrentControlSet\Control","WaitToKillServiceTimeout",2,"20000"
|
|||
HKLM,"SYSTEM\CurrentControlSet\Control\Biosinfo","InfName",2,"biosinfo.inf"
|
||||
HKLM,"SYSTEM\CurrentControlSet\Control\PnP",,0x00000012
|
||||
|
||||
; Critical Device Database
|
||||
|
||||
HKLM,"SYSTEM\CurrentControlSet\Control\CriticalDeviceDatabase\acpipic_up","ClassGUID",0x00000000,"{4D36E966-E325-11CE-BFC1-08002BE10318}"
|
||||
HKLM,"SYSTEM\CurrentControlSet\Control\CriticalDeviceDatabase\e_isa_up","ClassGUID",0x00000000,"{4D36E966-E325-11CE-BFC1-08002BE10318}"
|
||||
|
||||
HKLM,"SYSTEM\CurrentControlSet\Control\CriticalDeviceDatabase\*PNP0A03","Service",0x00000000,"pci"
|
||||
HKLM,"SYSTEM\CurrentControlSet\Control\CriticalDeviceDatabase\*PNP0A03","ClassGUID",0x00000000,"{4D36E97D-E325-11CE-BFC1-08002BE10318}"
|
||||
|
||||
HKLM,"SYSTEM\CurrentControlSet\Control\CriticalDeviceDatabase\*PNP0C08","Service",0x00000000,"acpi"
|
||||
HKLM,"SYSTEM\CurrentControlSet\Control\CriticalDeviceDatabase\*PNP0C08","ClassGUID",0x00000000,"{4D36E97D-E325-11CE-BFC1-08002BE10318}"
|
||||
|
||||
;HKLM,"SYSTEM\CurrentControlSet\Control\CriticalDeviceDatabase\PCI#CC_0C0300","Service",0x00000000,"usbuhci"
|
||||
;HKLM,"SYSTEM\CurrentControlSet\Control\CriticalDeviceDatabase\PCI#CC_0C0300","ClassGUID",0x00000000,"{36FC9E60-C465-11CF-8056-444553540000}"
|
||||
|
||||
HKLM,"SYSTEM\CurrentControlSet\Control\CriticalDeviceDatabase\PCI#CC_0C0310","Service",0x00000000,"usbohci"
|
||||
HKLM,"SYSTEM\CurrentControlSet\Control\CriticalDeviceDatabase\PCI#CC_0C0310","ClassGUID",0x00000000,"{36FC9E60-C465-11CF-8056-444553540000}"
|
||||
|
||||
HKLM,"SYSTEM\CurrentControlSet\Control\CriticalDeviceDatabase\PCI#CC_0C0320","Service",0x00000000,"usbehci"
|
||||
HKLM,"SYSTEM\CurrentControlSet\Control\CriticalDeviceDatabase\PCI#CC_0C0320","ClassGUID",0x00000000,"{36FC9E60-C465-11CF-8056-444553540000}"
|
||||
|
||||
HKLM,"SYSTEM\CurrentControlSet\Control\CriticalDeviceDatabase\USB#Class_08&SubClass_06&Prot_50","Service",0x00000000,"usbstor"
|
||||
HKLM,"SYSTEM\CurrentControlSet\Control\CriticalDeviceDatabase\USB#Class_08&SubClass_06&Prot_50","ClassGUID",0x00000000,"{36FC9E60-C465-11CF-8056-444553540000}"
|
||||
|
||||
HKLM,"SYSTEM\CurrentControlSet\Control\CriticalDeviceDatabase\USB#COMPOSITE","Service",0x00000000,"usbccgp"
|
||||
HKLM,"SYSTEM\CurrentControlSet\Control\CriticalDeviceDatabase\USB#COMPOSITE","ClassGUID",0x00000000,"{36FC9E60-C465-11CF-8056-444553540000}"
|
||||
|
||||
HKLM,"SYSTEM\CurrentControlSet\Control\CriticalDeviceDatabase\USB#CLASS_09","Service",0x00000000,"usbhub"
|
||||
HKLM,"SYSTEM\CurrentControlSet\Control\CriticalDeviceDatabase\USB#CLASS_09","ClassGUID",0x00000000,"{36FC9E60-C465-11CF-8056-444553540000}"
|
||||
|
||||
HKLM,"SYSTEM\CurrentControlSet\Control\CriticalDeviceDatabase\USB#ROOT_HUB","Service",0x00000000,"usbhub"
|
||||
HKLM,"SYSTEM\CurrentControlSet\Control\CriticalDeviceDatabase\USB#ROOT_HUB","ClassGUID",0x00000000,"{36FC9E60-C465-11CF-8056-444553540000}"
|
||||
|
||||
HKLM,"SYSTEM\CurrentControlSet\Control\CriticalDeviceDatabase\USB#ROOT_HUB20","Service",0x00000000,"usbhub"
|
||||
HKLM,"SYSTEM\CurrentControlSet\Control\CriticalDeviceDatabase\USB#ROOT_HUB20","ClassGUID",0x00000000,"{36FC9E60-C465-11CF-8056-444553540000}"
|
||||
|
||||
HKLM,"SYSTEM\CurrentControlSet\Control\CriticalDeviceDatabase\GenDisk","Service",0x00000000,"disk"
|
||||
HKLM,"SYSTEM\CurrentControlSet\Control\CriticalDeviceDatabase\GenDisk","ClassGUID",0x00000000,"{4D36E967-E325-11CE-BFC1-08002BE10318}"
|
||||
|
||||
HKLM,"SYSTEM\CurrentControlSet\Control\CriticalDeviceDatabase\USB#Class_03","Service",0x00000000,"hidusb"
|
||||
HKLM,"SYSTEM\CurrentControlSet\Control\CriticalDeviceDatabase\USB#Class_03","ClassGUID",0x00000000,"{745a17a0-74d3-11d0-b6fe-00a0c90f57da}"
|
||||
|
||||
HKLM,"SYSTEM\CurrentControlSet\Control\CriticalDeviceDatabase\GENERIC_HID_DEVICE","Service",0x00000000,"hidusb"
|
||||
HKLM,"SYSTEM\CurrentControlSet\Control\CriticalDeviceDatabase\GENERIC_HID_DEVICE","ClassGUID",0x00000000,"{745a17a0-74d3-11d0-b6fe-00a0c90f57da}"
|
||||
|
||||
HKLM,"SYSTEM\CurrentControlSet\Control\CriticalDeviceDatabase\HID_DEVICE_SYSTEM_KEYBOARD","Service",0x00000000,"kbdhid"
|
||||
HKLM,"SYSTEM\CurrentControlSet\Control\CriticalDeviceDatabase\HID_DEVICE_SYSTEM_KEYBOARD","ClassGUID",0x00000000,"{4D36E96B-E325-11CE-BFC1-08002BE10318}"
|
||||
|
||||
HKLM,"SYSTEM\CurrentControlSet\Control\CriticalDeviceDatabase\HID_DEVICE_SYSTEM_MOUSE","Service",0x00000000,"mouhid"
|
||||
HKLM,"SYSTEM\CurrentControlSet\Control\CriticalDeviceDatabase\HID_DEVICE_SYSTEM_MOUSE","ClassGUID",0x00000000,"{4D36E96F-E325-11CE-BFC1-08002BE10318}"
|
||||
|
||||
|
||||
|
||||
HKLM,"SYSTEM\CurrentControlSet\Control\SafeBoot","AlternateShell",2,"cmd.exe"
|
||||
|
||||
; Safe Boot drivers
|
||||
|
@ -1413,10 +1465,82 @@ HKLM,"SYSTEM\CurrentControlSet\Services\Packet","ImagePath",0x00020000,"system32
|
|||
HKLM,"SYSTEM\CurrentControlSet\Services\Packet","Start",0x00010001,0x00000004
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\Packet","Type",0x00010001,0x00000001
|
||||
|
||||
; USB HID driver
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\hidusb","ErrorControl",0x00010001,0x00000001
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\hidusb","Group",0x00000000,"Extended Base"
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\hidusb","ImagePath",0x00020000,"system32\drivers\hidusb.sys"
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\hidusb","Start",0x00010001,0x00000003
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\hidusb","Type",0x00010001,0x00000001
|
||||
|
||||
; HID keyboard driver
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\kbdhid","ErrorControl",0x00010001,0x00000001
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\kbdhid","Group",0x00000000,"Keyboard Port"
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\kbdhid","ImagePath",0x00020000,"system32\drivers\kbdhid.sys"
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\kbdhid","Start",0x00010001,0x00000003
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\kbdhid","Type",0x00010001,0x00000001
|
||||
|
||||
; HID mouse driver
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\mouhid","ErrorControl",0x00010001,0x00000001
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\mouhid","Group",0x00000000,"Pointer Port"
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\mouhid","ImagePath",0x00020000,"system32\drivers\mouhid.sys"
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\mouhid","Start",0x00010001,0x00000003
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\mouhid","Type",0x00010001,0x00000001
|
||||
|
||||
; USB hub driver
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\usbhub","ErrorControl",0x00010001,0x00000001
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\usbhub","Group",0x00000000,"Boot Bus Extender"
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\usbhub","ImagePath",0x00020000,"system32\drivers\usbhub.sys"
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\usbhub","Start",0x00010001,0x00000000
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\usbhub","Type",0x00010001,0x00000001
|
||||
|
||||
; EHCI controller driver
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\usbehci","ErrorControl",0x00010001,0x00000001
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\usbehci","Group",0x00000000,"Boot Bus Extender"
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\usbehci","ImagePath",0x00020000,"system32\drivers\usbehci.sys"
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\usbehci","Start",0x00010001,0x00000000
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\usbehci","Type",0x00010001,0x00000001
|
||||
|
||||
; OHCI controller driver
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\usbohci","ErrorControl",0x00010001,0x00000001
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\usbohci","Group",0x00000000,"Boot Bus Extender"
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\usbohci","ImagePath",0x00020000,"system32\drivers\usbohci.sys"
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\usbohci","Start",0x00010001,0x00000000
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\usbohci","Type",0x00010001,0x00000001
|
||||
|
||||
; UHCI controller driver
|
||||
;HKLM,"SYSTEM\CurrentControlSet\Services\usbuhci","ErrorControl",0x00010001,0x00000001
|
||||
;HKLM,"SYSTEM\CurrentControlSet\Services\usbuhci","Group",0x00000000,"Boot Bus Extender"
|
||||
;HKLM,"SYSTEM\CurrentControlSet\Services\usbuhci","ImagePath",0x00020000,"system32\drivers\usbuhci.sys"
|
||||
;HKLM,"SYSTEM\CurrentControlSet\Services\usbuhci","Start",0x00010001,0x00000000
|
||||
;HKLM,"SYSTEM\CurrentControlSet\Services\usbuhci","Type",0x00010001,0x00000001
|
||||
|
||||
; USB storage driver
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\usbstor","ErrorControl",0x00010001,0x00000001
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\usbstor","Group",0x00000000,"Primary Disk"
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\usbstor","ImagePath",0x00020000,"system32\drivers\usbstor.sys"
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\usbstor","Start",0x00010001,0x00000000
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\usbstor","Type",0x00010001,0x00000001
|
||||
|
||||
; USB composite generic parent
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\usbccgp","ErrorControl",0x00010001,0x00000001
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\usbccgp","Group",0x00000000,"Boot Bus Extender"
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\usbccgp","ImagePath",0x00020000,"system32\drivers\usbccgp.sys"
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\usbccgp","Start",0x00010001,0x00000000
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\usbccgp","Type",0x00010001,0x00000001
|
||||
|
||||
; ACPI driver
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\acpi","ErrorControl",0x00010001,0x00000001
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\acpi","Group",0x00000000,"Boot Bus Extender"
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\acpi","ImagePath",0x00020000,"system32\drivers\acpi.sys"
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\acpi","Start",0x00010001,0x00000000
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\acpi","Type",0x00010001,0x00000001
|
||||
|
||||
; PCI Bus driver
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\Pci","ErrorControl",0x00010001,0x00000001
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\Pci","Group",0x00000000,"Boot Bus "
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\Pci","Tag",0x00010001,0x00000002
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\Pci","Group",0x00000000,"Boot Bus Extender"
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\Pci","ImagePath",0x00020000,"system32\drivers\pci.sys"
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\Pci","Start",0x00010001,0x00000000
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\Pci","Type",0x00010001,0x00000001
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\Pci\Parameters","1045C621",0x00030003,04,00,00,00,00,00,00,00
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\Pci\Parameters","10950640",0x00030003,04,00,00,00,00,00,00,00
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\Pci\Parameters","80861230",0x00030003,04,00,00,00,00,00,00,00
|
||||
|
@ -1730,20 +1854,6 @@ HKLM,"SYSTEM\CurrentControlSet\Hardware Profiles\Current\System\CurrentControlSe
|
|||
HKLM,"SYSTEM\CurrentControlSet\Hardware Profiles\Current\System\CurrentControlSet\Services\Vga\Device0","DefaultSettings.XResolution",0x00010001,640
|
||||
HKLM,"SYSTEM\CurrentControlSet\Hardware Profiles\Current\System\CurrentControlSet\Services\Vga\Device0","DefaultSettings.YResolution",0x00010001,480
|
||||
|
||||
; USB uhci/ehci driver
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\usbdrv","ErrorControl",0x00010001,0x00000000
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\usbdrv","Group",0x00000000,"Base"
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\usbdrv","ImagePath",0x00020000,"system32\drivers\usbdrv.sys"
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\usbdrv","Start",0x00010001,0x00000004
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\usbdrv","Type",0x00010001,0x00000001
|
||||
|
||||
; USB storage driver
|
||||
;HKLM,"SYSTEM\CurrentControlSet\Services\usbstor","ErrorControl",0x00010001,0x00000000
|
||||
;HKLM,"SYSTEM\CurrentControlSet\Services\usbstor","Group",0x00000000,"Extended Base"
|
||||
;HKLM,"SYSTEM\CurrentControlSet\Services\usbstor","ImagePath",0x00020000,"system32\drivers\usbstor.sys"
|
||||
;HKLM,"SYSTEM\CurrentControlSet\Services\usbstor","Start",0x00010001,0x00000003
|
||||
;HKLM,"SYSTEM\CurrentControlSet\Services\usbstor","Type",0x00010001,0x00000001
|
||||
|
||||
; Windows Installer Service
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\MSIserver","DisplayName",0x00000000,"ReactOS Installer"
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\MSIserver","Description",0x00000000,"Controls installation, maintenance, and removal of software packaged as an msi (Windows Installer)"
|
||||
|
|
|
@ -542,11 +542,7 @@ drivers\serial\serial\serial.sys 2
|
|||
drivers\storage\ide\pciide\pciide.sys 2
|
||||
drivers\storage\ide\pciidex\pciidex.sys 2
|
||||
|
||||
;drivers\usb\miniport\usbohci\usbohci.sys 2
|
||||
;drivers\usb\miniport\usbuhci\usbuhci.sys 2
|
||||
;drivers\usb\usbhub\usbhub.sys 2
|
||||
;drivers\usb\usbport\usbport.sys 2
|
||||
;drivers\usb\nt4compat\usbdriver\usbdriver.sys 2
|
||||
drivers\hid\mouhid\mouhid.sys 2
|
||||
|
||||
drivers\video\displays\vga\vgaddi.dll 1
|
||||
drivers\video\displays\framebuf\framebuf.dll 1
|
||||
|
@ -671,6 +667,7 @@ media\inf\font.inf 6
|
|||
media\inf\fdc.inf 6
|
||||
media\inf\hal.inf 6
|
||||
media\inf\hdc.inf 6
|
||||
media\inf\input.inf 6
|
||||
media\inf\intl.inf 6
|
||||
media\inf\layout.inf 6
|
||||
media\inf\machine.inf 6
|
||||
|
|
|
@ -32,7 +32,17 @@ kdcom.dll=,,,,,,,,,,,,2
|
|||
disk.sys=,,,,,,x,,,,,,4
|
||||
floppy.sys=,,,,,,x,,,,,,4
|
||||
i8042prt.sys=,,,,,,x,,,,,,4
|
||||
usbdrv.sys=,,,,,,,,,,,,4
|
||||
hidclass.sys=,,,,,,,,,,,,4
|
||||
hidparse.sys=,,,,,,,,,,,,4
|
||||
hidusb.sys=,,,,,,,,,,,,4
|
||||
usbccgp.sys=,,,,,,x,,,,,,4
|
||||
usbd.sys=,,,,,,x,,,,,,4
|
||||
usbhub.sys=,,,,,,x,,,,,,4
|
||||
;usbuhci.sys=,,,,,,x,,,,,,4
|
||||
usbohci.sys=,,,,,,x,,,,,,4
|
||||
usbehci.sys=,,,,,,x,,,,,,4
|
||||
usbstor.sys=,,,,,,x,,,,,,4
|
||||
kbdhid.sys=,,,,,,,,,,,,4
|
||||
kbdclass.sys=,,,,,,x,,,,,,4
|
||||
l_intl.nls=,,,,,,,,,,,,2
|
||||
ntfs.sys=,,,,,,,,,,,,4
|
||||
|
@ -62,18 +72,41 @@ PCI\CC_0104 = uniata
|
|||
PCI\CC_0105 = uniata
|
||||
PCI\CC_0106 = uniata
|
||||
*PNP0600 = uniata
|
||||
USB\CLASS_09 = usbhub
|
||||
USB\ROOT_HUB = usbhub
|
||||
USB\ROOT_HUB20 = usbhub
|
||||
;PCI\CC_0C0300 = usbuhci
|
||||
PCI\CC_0C0310 = usbohci
|
||||
PCI\CC_0C0320 = usbehci
|
||||
USB\Class_08&SubClass_06&Prot_50 = usbstor
|
||||
HID_DEVICE_SYSTEM_KEYBOARD = kbdhid
|
||||
USB\COMPOSITE = usbccgp
|
||||
GenDisk = disk
|
||||
USB\Class_03 = hidusb
|
||||
GENERIC_HID_DEVICE = hidusb
|
||||
|
||||
[BootBusExtenders.Load]
|
||||
acpi = acpi.sys
|
||||
pci = pci.sys
|
||||
isapnp = isapnp.sys
|
||||
|
||||
[InputDevicesSupport.Load]
|
||||
usbehci = usbehci.sys
|
||||
usbohci = usbohci.sys
|
||||
;usbuhci = usbuhci.sys
|
||||
usbhub = usbhub.sys
|
||||
usbccgp = usbccgp.sys
|
||||
hidusb = hidusb.sys
|
||||
usbstor = usbstor.sys
|
||||
kbdhid = kbdhid.sys
|
||||
|
||||
[BusExtenders.Load]
|
||||
pciide = pciide.sys
|
||||
|
||||
[SCSI.Load]
|
||||
uniata = uniata.sys
|
||||
buslogic = buslogic.sys
|
||||
disk = disk.sys
|
||||
|
||||
[Cabinets]
|
||||
Cabinet=reactos.cab
|
||||
|
|
|
@ -70,7 +70,7 @@ HidD_FlushQueue(IN HANDLE HidDeviceObject)
|
|||
return DeviceIoControl(HidDeviceObject, IOCTL_HID_FLUSH_QUEUE,
|
||||
NULL, 0,
|
||||
NULL, 0,
|
||||
&RetLen, NULL);
|
||||
&RetLen, NULL) != 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -150,7 +150,7 @@ HidD_GetFeature(IN HANDLE HidDeviceObject,
|
|||
return DeviceIoControl(HidDeviceObject, IOCTL_HID_GET_FEATURE,
|
||||
NULL, 0,
|
||||
ReportBuffer, ReportBufferLength,
|
||||
&RetLen, NULL);
|
||||
&RetLen, NULL) != 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -182,7 +182,7 @@ HidD_GetInputReport(IN HANDLE HidDeviceObject,
|
|||
return DeviceIoControl(HidDeviceObject, IOCTL_HID_GET_INPUT_REPORT,
|
||||
NULL, 0,
|
||||
ReportBuffer, ReportBufferLength,
|
||||
&RetLen, NULL);
|
||||
&RetLen, NULL) != 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -201,7 +201,7 @@ HidD_GetManufacturerString(IN HANDLE HidDeviceObject,
|
|||
return DeviceIoControl(HidDeviceObject, IOCTL_HID_GET_MANUFACTURER_STRING,
|
||||
NULL, 0,
|
||||
Buffer, BufferLength,
|
||||
&RetLen, NULL);
|
||||
&RetLen, NULL) != 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -219,7 +219,7 @@ HidD_GetNumInputBuffers(IN HANDLE HidDeviceObject,
|
|||
return DeviceIoControl(HidDeviceObject, IOCTL_GET_NUM_DEVICE_INPUT_BUFFERS,
|
||||
NULL, 0,
|
||||
NumberBuffers, sizeof(ULONG),
|
||||
&RetLen, NULL);
|
||||
&RetLen, NULL) != 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -238,7 +238,7 @@ HidD_GetPhysicalDescriptor(IN HANDLE HidDeviceObject,
|
|||
return DeviceIoControl(HidDeviceObject, IOCTL_GET_PHYSICAL_DESCRIPTOR,
|
||||
NULL, 0,
|
||||
Buffer, BufferLength,
|
||||
&RetLen, NULL);
|
||||
&RetLen, NULL) != 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -254,7 +254,7 @@ HidD_GetPreparsedData(IN HANDLE HidDeviceObject,
|
|||
{
|
||||
HID_COLLECTION_INFORMATION hci;
|
||||
DWORD RetLen;
|
||||
BOOL Ret;
|
||||
BOOLEAN Ret;
|
||||
|
||||
if(PreparsedData == NULL)
|
||||
{
|
||||
|
@ -279,7 +279,7 @@ HidD_GetPreparsedData(IN HANDLE HidDeviceObject,
|
|||
Ret = DeviceIoControl(HidDeviceObject, IOCTL_HID_GET_COLLECTION_DESCRIPTOR,
|
||||
NULL, 0,
|
||||
*PreparsedData, hci.DescriptorSize,
|
||||
&RetLen, NULL);
|
||||
&RetLen, NULL) != 0;
|
||||
|
||||
if(!Ret)
|
||||
{
|
||||
|
@ -312,7 +312,7 @@ HidD_GetProductString(IN HANDLE HidDeviceObject,
|
|||
return DeviceIoControl(HidDeviceObject, IOCTL_HID_GET_PRODUCT_STRING,
|
||||
NULL, 0,
|
||||
Buffer, BufferLength,
|
||||
&RetLen, NULL);
|
||||
&RetLen, NULL) != 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -331,7 +331,7 @@ HidD_GetSerialNumberString(IN HANDLE HidDeviceObject,
|
|||
return DeviceIoControl(HidDeviceObject, IOCTL_HID_GET_SERIALNUMBER_STRING,
|
||||
NULL, 0,
|
||||
Buffer, BufferLength,
|
||||
&RetLen, NULL);
|
||||
&RetLen, NULL) != 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -394,7 +394,7 @@ HidD_SetFeature(IN HANDLE HidDeviceObject,
|
|||
return DeviceIoControl(HidDeviceObject, IOCTL_HID_SET_FEATURE,
|
||||
ReportBuffer, ReportBufferLength,
|
||||
NULL, 0,
|
||||
&RetLen, NULL);
|
||||
&RetLen, NULL) != 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -412,7 +412,7 @@ HidD_SetNumInputBuffers(IN HANDLE HidDeviceObject,
|
|||
return DeviceIoControl(HidDeviceObject, IOCTL_SET_NUM_DEVICE_INPUT_BUFFERS,
|
||||
&NumberBuffers, sizeof(ULONG),
|
||||
NULL, 0,
|
||||
&RetLen, NULL);
|
||||
&RetLen, NULL) != 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -431,7 +431,112 @@ HidD_SetOutputReport(IN HANDLE HidDeviceObject,
|
|||
return DeviceIoControl(HidDeviceObject, IOCTL_HID_SET_OUTPUT_REPORT,
|
||||
ReportBuffer, ReportBufferLength,
|
||||
NULL, 0,
|
||||
&RetLen, NULL);
|
||||
&RetLen, NULL) != 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* HidD_GetIndexedString EXPORTED
|
||||
*
|
||||
* @implemented
|
||||
*/
|
||||
HIDAPI
|
||||
BOOLEAN WINAPI
|
||||
HidD_GetIndexedString(IN HANDLE HidDeviceObject,
|
||||
IN ULONG StringIndex,
|
||||
OUT PVOID Buffer,
|
||||
IN ULONG BufferLength)
|
||||
{
|
||||
DWORD RetLen;
|
||||
return DeviceIoControl(HidDeviceObject, IOCTL_HID_GET_INDEXED_STRING,
|
||||
&StringIndex, sizeof(ULONG),
|
||||
Buffer, BufferLength,
|
||||
&RetLen, NULL) != 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* HidD_GetMsGenreDescriptor EXPORTED
|
||||
*
|
||||
* @implemented
|
||||
*/
|
||||
HIDAPI
|
||||
BOOLEAN WINAPI
|
||||
HidD_GetMsGenreDescriptor(IN HANDLE HidDeviceObject,
|
||||
OUT PVOID Buffer,
|
||||
IN ULONG BufferLength)
|
||||
{
|
||||
DWORD RetLen;
|
||||
return DeviceIoControl(HidDeviceObject, IOCTL_HID_GET_MS_GENRE_DESCRIPTOR,
|
||||
0, 0,
|
||||
Buffer, BufferLength,
|
||||
&RetLen, NULL) != 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* HidD_GetConfiguration EXPORTED
|
||||
*
|
||||
* @implemented
|
||||
*/
|
||||
HIDAPI
|
||||
BOOLEAN WINAPI
|
||||
HidD_GetConfiguration(IN HANDLE HidDeviceObject,
|
||||
OUT PHIDD_CONFIGURATION Configuration,
|
||||
IN ULONG ConfigurationLength)
|
||||
{
|
||||
|
||||
// magic cookie
|
||||
Configuration->cookie = (PVOID)HidD_GetConfiguration;
|
||||
|
||||
return DeviceIoControl(HidDeviceObject, IOCTL_HID_GET_DRIVER_CONFIG,
|
||||
0, 0,
|
||||
&Configuration->size, ConfigurationLength - sizeof(ULONG),
|
||||
(PULONG)&Configuration->cookie, NULL) != 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* HidD_SetConfiguration EXPORTED
|
||||
*
|
||||
* @implemented
|
||||
*/
|
||||
HIDAPI
|
||||
BOOLEAN WINAPI
|
||||
HidD_SetConfiguration(IN HANDLE HidDeviceObject,
|
||||
IN PHIDD_CONFIGURATION Configuration,
|
||||
IN ULONG ConfigurationLength)
|
||||
{
|
||||
BOOLEAN Ret = FALSE;
|
||||
|
||||
if (Configuration->cookie == (PVOID)HidD_GetConfiguration)
|
||||
{
|
||||
Ret = DeviceIoControl(HidDeviceObject, IOCTL_HID_SET_DRIVER_CONFIG,
|
||||
0, 0,
|
||||
(PVOID)&Configuration->size, ConfigurationLength - sizeof(ULONG),
|
||||
(PULONG)&Configuration->cookie, NULL) != 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
}
|
||||
|
||||
return Ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* HidP_GetUsagesEx EXPORTED
|
||||
*
|
||||
* @implemented
|
||||
*/
|
||||
HIDAPI
|
||||
NTSTATUS WINAPI
|
||||
HidP_GetUsagesEx(IN HIDP_REPORT_TYPE ReportType,
|
||||
IN USHORT LinkCollection,
|
||||
OUT PUSAGE_AND_PAGE ButtonList,
|
||||
IN OUT ULONG *UsageLength,
|
||||
IN PHIDP_PREPARSED_DATA PreparsedData,
|
||||
IN PCHAR Report,
|
||||
IN ULONG ReportLength)
|
||||
{
|
||||
return HidP_GetUsages(ReportType, ButtonList->UsagePage, LinkCollection, &ButtonList->Usage, UsageLength, PreparsedData, Report, ReportLength);
|
||||
}
|
||||
|
||||
|
||||
/* EOF */
|
||||
|
|
|
@ -11,63 +11,6 @@
|
|||
*/
|
||||
#include <precomp.h>
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
*/
|
||||
HIDAPI
|
||||
BOOLEAN WINAPI
|
||||
HidD_GetConfiguration(IN HANDLE HidDeviceObject,
|
||||
OUT PHIDD_CONFIGURATION Configuration,
|
||||
IN ULONG ConfigurationLength)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
*/
|
||||
HIDAPI
|
||||
BOOLEAN WINAPI
|
||||
HidD_GetIndexedString(IN HANDLE HidDeviceObject,
|
||||
IN ULONG StringIndex,
|
||||
OUT PVOID Buffer,
|
||||
IN ULONG BufferLength)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
*/
|
||||
HIDAPI
|
||||
BOOLEAN WINAPI
|
||||
HidD_GetMsGenreDescriptor(IN HANDLE HidDeviceObject,
|
||||
OUT PVOID Buffer,
|
||||
IN ULONG BufferLength)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
*/
|
||||
HIDAPI
|
||||
BOOLEAN WINAPI
|
||||
HidD_SetConfiguration(IN HANDLE HidDeviceObject,
|
||||
IN PHIDD_CONFIGURATION Configuration,
|
||||
IN ULONG ConfigurationLength)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
*/
|
||||
|
@ -241,24 +184,6 @@ HidP_GetUsages(IN HIDP_REPORT_TYPE ReportType,
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
*/
|
||||
HIDAPI
|
||||
NTSTATUS WINAPI
|
||||
HidP_GetUsagesEx(IN HIDP_REPORT_TYPE ReportType,
|
||||
IN USHORT LinkCollection,
|
||||
OUT PUSAGE_AND_PAGE ButtonList,
|
||||
IN OUT ULONG *UsageLength,
|
||||
IN PHIDP_PREPARSED_DATA PreparsedData,
|
||||
IN PCHAR Report,
|
||||
IN ULONG ReportLength)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return HIDP_STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
*/
|
||||
|
|
|
@ -4,6 +4,8 @@ add_subdirectory(battery)
|
|||
add_subdirectory(bus)
|
||||
add_subdirectory(directx)
|
||||
add_subdirectory(filesystems)
|
||||
add_subdirectory(filters)
|
||||
add_subdirectory(hid)
|
||||
add_subdirectory(input)
|
||||
add_subdirectory(ksfilter)
|
||||
add_subdirectory(network)
|
||||
|
|
|
@ -1136,6 +1136,12 @@ Bus_PDO_QueryResourceRequirements(
|
|||
return Irp->IoStatus.Status;
|
||||
}
|
||||
|
||||
/* Handle the PCI root manually */
|
||||
if (wcsstr(DeviceData->HardwareIDs, L"PNP0A03") != 0)
|
||||
{
|
||||
return Irp->IoStatus.Status;
|
||||
}
|
||||
|
||||
/* Get current resources */
|
||||
while (TRUE)
|
||||
{
|
||||
|
@ -1315,7 +1321,7 @@ Bus_PDO_QueryResourceRequirements(
|
|||
RequirementDescriptor->ShareDisposition = CmResourceShareDriverExclusive;
|
||||
RequirementDescriptor->u.Port.Alignment = io_data->Alignment;
|
||||
RequirementDescriptor->u.Port.MinimumAddress.QuadPart = io_data->Minimum;
|
||||
RequirementDescriptor->u.Port.MaximumAddress.QuadPart = io_data->Maximum;
|
||||
RequirementDescriptor->u.Port.MaximumAddress.QuadPart = io_data->Maximum + io_data->AddressLength - 1;
|
||||
|
||||
RequirementDescriptor++;
|
||||
break;
|
||||
|
@ -1330,7 +1336,7 @@ Bus_PDO_QueryResourceRequirements(
|
|||
RequirementDescriptor->ShareDisposition = CmResourceShareShared;
|
||||
RequirementDescriptor->Flags = 0;
|
||||
RequirementDescriptor->u.BusNumber.MinBusNumber = addr16_data->Minimum;
|
||||
RequirementDescriptor->u.BusNumber.MaxBusNumber = addr16_data->Maximum;
|
||||
RequirementDescriptor->u.BusNumber.MaxBusNumber = addr16_data->Maximum + addr16_data->AddressLength - 1;
|
||||
RequirementDescriptor->u.BusNumber.Length = addr16_data->AddressLength;
|
||||
}
|
||||
else if (addr16_data->ResourceType == ACPI_IO_RANGE)
|
||||
|
@ -1341,7 +1347,7 @@ Bus_PDO_QueryResourceRequirements(
|
|||
if (addr16_data->Decode == ACPI_POS_DECODE)
|
||||
RequirementDescriptor->Flags |= CM_RESOURCE_PORT_POSITIVE_DECODE;
|
||||
RequirementDescriptor->u.Port.MinimumAddress.QuadPart = addr16_data->Minimum;
|
||||
RequirementDescriptor->u.Port.MaximumAddress.QuadPart = addr16_data->Maximum;
|
||||
RequirementDescriptor->u.Port.MaximumAddress.QuadPart = addr16_data->Maximum + addr16_data->AddressLength - 1;
|
||||
RequirementDescriptor->u.Port.Length = addr16_data->AddressLength;
|
||||
}
|
||||
else
|
||||
|
@ -1360,7 +1366,7 @@ Bus_PDO_QueryResourceRequirements(
|
|||
case ACPI_PREFETCHABLE_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE; break;
|
||||
}
|
||||
RequirementDescriptor->u.Memory.MinimumAddress.QuadPart = addr16_data->Minimum;
|
||||
RequirementDescriptor->u.Memory.MaximumAddress.QuadPart = addr16_data->Maximum;
|
||||
RequirementDescriptor->u.Memory.MaximumAddress.QuadPart = addr16_data->Maximum + addr16_data->AddressLength - 1;
|
||||
RequirementDescriptor->u.Memory.Length = addr16_data->AddressLength;
|
||||
}
|
||||
RequirementDescriptor++;
|
||||
|
@ -1376,7 +1382,7 @@ Bus_PDO_QueryResourceRequirements(
|
|||
RequirementDescriptor->ShareDisposition = CmResourceShareShared;
|
||||
RequirementDescriptor->Flags = 0;
|
||||
RequirementDescriptor->u.BusNumber.MinBusNumber = addr32_data->Minimum;
|
||||
RequirementDescriptor->u.BusNumber.MaxBusNumber = addr32_data->Maximum;
|
||||
RequirementDescriptor->u.BusNumber.MaxBusNumber = addr32_data->Maximum + addr32_data->AddressLength - 1;
|
||||
RequirementDescriptor->u.BusNumber.Length = addr32_data->AddressLength;
|
||||
}
|
||||
else if (addr32_data->ResourceType == ACPI_IO_RANGE)
|
||||
|
@ -1387,7 +1393,7 @@ Bus_PDO_QueryResourceRequirements(
|
|||
if (addr32_data->Decode == ACPI_POS_DECODE)
|
||||
RequirementDescriptor->Flags |= CM_RESOURCE_PORT_POSITIVE_DECODE;
|
||||
RequirementDescriptor->u.Port.MinimumAddress.QuadPart = addr32_data->Minimum;
|
||||
RequirementDescriptor->u.Port.MaximumAddress.QuadPart = addr32_data->Maximum;
|
||||
RequirementDescriptor->u.Port.MaximumAddress.QuadPart = addr32_data->Maximum + addr32_data->AddressLength - 1;
|
||||
RequirementDescriptor->u.Port.Length = addr32_data->AddressLength;
|
||||
}
|
||||
else
|
||||
|
@ -1406,7 +1412,7 @@ Bus_PDO_QueryResourceRequirements(
|
|||
case ACPI_PREFETCHABLE_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE; break;
|
||||
}
|
||||
RequirementDescriptor->u.Memory.MinimumAddress.QuadPart = addr32_data->Minimum;
|
||||
RequirementDescriptor->u.Memory.MaximumAddress.QuadPart = addr32_data->Maximum;
|
||||
RequirementDescriptor->u.Memory.MaximumAddress.QuadPart = addr32_data->Maximum + addr32_data->AddressLength - 1;
|
||||
RequirementDescriptor->u.Memory.Length = addr32_data->AddressLength;
|
||||
}
|
||||
RequirementDescriptor++;
|
||||
|
@ -1423,7 +1429,7 @@ Bus_PDO_QueryResourceRequirements(
|
|||
RequirementDescriptor->ShareDisposition = CmResourceShareShared;
|
||||
RequirementDescriptor->Flags = 0;
|
||||
RequirementDescriptor->u.BusNumber.MinBusNumber = (ULONG)addr64_data->Minimum;
|
||||
RequirementDescriptor->u.BusNumber.MaxBusNumber = (ULONG)addr64_data->Maximum;
|
||||
RequirementDescriptor->u.BusNumber.MaxBusNumber = (ULONG)addr64_data->Maximum + addr64_data->AddressLength - 1;
|
||||
RequirementDescriptor->u.BusNumber.Length = addr64_data->AddressLength;
|
||||
}
|
||||
else if (addr64_data->ResourceType == ACPI_IO_RANGE)
|
||||
|
@ -1434,7 +1440,7 @@ Bus_PDO_QueryResourceRequirements(
|
|||
if (addr64_data->Decode == ACPI_POS_DECODE)
|
||||
RequirementDescriptor->Flags |= CM_RESOURCE_PORT_POSITIVE_DECODE;
|
||||
RequirementDescriptor->u.Port.MinimumAddress.QuadPart = addr64_data->Minimum;
|
||||
RequirementDescriptor->u.Port.MaximumAddress.QuadPart = addr64_data->Maximum;
|
||||
RequirementDescriptor->u.Port.MaximumAddress.QuadPart = addr64_data->Maximum + addr64_data->AddressLength - 1;
|
||||
RequirementDescriptor->u.Port.Length = addr64_data->AddressLength;
|
||||
}
|
||||
else
|
||||
|
@ -1453,7 +1459,7 @@ Bus_PDO_QueryResourceRequirements(
|
|||
case ACPI_PREFETCHABLE_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE; break;
|
||||
}
|
||||
RequirementDescriptor->u.Memory.MinimumAddress.QuadPart = addr64_data->Minimum;
|
||||
RequirementDescriptor->u.Memory.MaximumAddress.QuadPart = addr64_data->Maximum;
|
||||
RequirementDescriptor->u.Memory.MaximumAddress.QuadPart = addr64_data->Maximum + addr64_data->AddressLength - 1;
|
||||
RequirementDescriptor->u.Memory.Length = addr64_data->AddressLength;
|
||||
}
|
||||
RequirementDescriptor++;
|
||||
|
@ -1470,7 +1476,7 @@ Bus_PDO_QueryResourceRequirements(
|
|||
RequirementDescriptor->ShareDisposition = CmResourceShareShared;
|
||||
RequirementDescriptor->Flags = 0;
|
||||
RequirementDescriptor->u.BusNumber.MinBusNumber = (ULONG)addr64_data->Minimum;
|
||||
RequirementDescriptor->u.BusNumber.MaxBusNumber = (ULONG)addr64_data->Maximum;
|
||||
RequirementDescriptor->u.BusNumber.MaxBusNumber = (ULONG)addr64_data->Maximum + addr64_data->AddressLength - 1;
|
||||
RequirementDescriptor->u.BusNumber.Length = addr64_data->AddressLength;
|
||||
}
|
||||
else if (addr64_data->ResourceType == ACPI_IO_RANGE)
|
||||
|
@ -1481,7 +1487,7 @@ Bus_PDO_QueryResourceRequirements(
|
|||
if (addr64_data->Decode == ACPI_POS_DECODE)
|
||||
RequirementDescriptor->Flags |= CM_RESOURCE_PORT_POSITIVE_DECODE;
|
||||
RequirementDescriptor->u.Port.MinimumAddress.QuadPart = addr64_data->Minimum;
|
||||
RequirementDescriptor->u.Port.MaximumAddress.QuadPart = addr64_data->Maximum;
|
||||
RequirementDescriptor->u.Port.MaximumAddress.QuadPart = addr64_data->Maximum + addr64_data->AddressLength - 1;
|
||||
RequirementDescriptor->u.Port.Length = addr64_data->AddressLength;
|
||||
}
|
||||
else
|
||||
|
@ -1500,7 +1506,7 @@ Bus_PDO_QueryResourceRequirements(
|
|||
case ACPI_PREFETCHABLE_MEMORY: RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE; break;
|
||||
}
|
||||
RequirementDescriptor->u.Memory.MinimumAddress.QuadPart = addr64_data->Minimum;
|
||||
RequirementDescriptor->u.Memory.MaximumAddress.QuadPart = addr64_data->Maximum;
|
||||
RequirementDescriptor->u.Memory.MaximumAddress.QuadPart = addr64_data->Maximum + addr64_data->AddressLength - 1;
|
||||
RequirementDescriptor->u.Memory.Length = addr64_data->AddressLength;
|
||||
}
|
||||
RequirementDescriptor++;
|
||||
|
@ -1518,7 +1524,7 @@ Bus_PDO_QueryResourceRequirements(
|
|||
else
|
||||
RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
|
||||
RequirementDescriptor->u.Memory.MinimumAddress.QuadPart = mem24_data->Minimum;
|
||||
RequirementDescriptor->u.Memory.MaximumAddress.QuadPart = mem24_data->Maximum;
|
||||
RequirementDescriptor->u.Memory.MaximumAddress.QuadPart = mem24_data->Maximum + mem24_data->AddressLength - 1;
|
||||
RequirementDescriptor->u.Memory.Length = mem24_data->AddressLength;
|
||||
|
||||
RequirementDescriptor++;
|
||||
|
@ -1536,7 +1542,7 @@ Bus_PDO_QueryResourceRequirements(
|
|||
else
|
||||
RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
|
||||
RequirementDescriptor->u.Memory.MinimumAddress.QuadPart = mem32_data->Minimum;
|
||||
RequirementDescriptor->u.Memory.MaximumAddress.QuadPart = mem32_data->Maximum;
|
||||
RequirementDescriptor->u.Memory.MaximumAddress.QuadPart = mem32_data->Maximum + mem32_data->AddressLength - 1;
|
||||
RequirementDescriptor->u.Memory.Length = mem32_data->AddressLength;
|
||||
|
||||
RequirementDescriptor++;
|
||||
|
@ -1554,7 +1560,7 @@ Bus_PDO_QueryResourceRequirements(
|
|||
else
|
||||
RequirementDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
|
||||
RequirementDescriptor->u.Memory.MinimumAddress.QuadPart = fixedmem32_data->Address;
|
||||
RequirementDescriptor->u.Memory.MaximumAddress.QuadPart = fixedmem32_data->Address;
|
||||
RequirementDescriptor->u.Memory.MaximumAddress.QuadPart = fixedmem32_data->Address + fixedmem32_data->AddressLength - 1;
|
||||
RequirementDescriptor->u.Memory.Length = fixedmem32_data->AddressLength;
|
||||
|
||||
RequirementDescriptor++;
|
||||
|
|
|
@ -96,7 +96,6 @@ FdoEnumerateDevices(
|
|||
{
|
||||
PFDO_DEVICE_EXTENSION DeviceExtension;
|
||||
PCI_COMMON_CONFIG PciConfig;
|
||||
PLIST_ENTRY CurrentEntry;
|
||||
PPCI_DEVICE Device;
|
||||
PCI_SLOT_NUMBER SlotNumber;
|
||||
ULONG DeviceNumber;
|
||||
|
@ -108,15 +107,6 @@ FdoEnumerateDevices(
|
|||
|
||||
DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
|
||||
/* Mark all devices to be removed. If we don't discover them again during
|
||||
enumeration, assume that they have been surprise removed */
|
||||
CurrentEntry = DeviceExtension->DeviceListHead.Flink;
|
||||
while (CurrentEntry != &DeviceExtension->DeviceListHead) {
|
||||
Device = CONTAINING_RECORD(CurrentEntry, PCI_DEVICE, ListEntry);
|
||||
Device->RemovePending = TRUE;
|
||||
CurrentEntry = CurrentEntry->Flink;
|
||||
}
|
||||
|
||||
DeviceExtension->DeviceListCount = 0;
|
||||
|
||||
/* Enumerate devices on the PCI bus */
|
||||
|
@ -190,9 +180,6 @@ FdoEnumerateDevices(
|
|||
&DeviceExtension->DeviceListLock);
|
||||
}
|
||||
|
||||
/* Don't remove this device */
|
||||
Device->RemovePending = FALSE;
|
||||
|
||||
DeviceExtension->DeviceListCount++;
|
||||
|
||||
/* Skip to next device if the current one is not a multifunction device */
|
||||
|
@ -354,7 +341,6 @@ FdoQueryBusRelations(
|
|||
}
|
||||
}
|
||||
|
||||
if (!Device->RemovePending) {
|
||||
/* Reference the physical device object. The PnP manager
|
||||
will dereference it again when it is no longer needed */
|
||||
ObReferenceObject(Device->Pdo);
|
||||
|
@ -362,7 +348,6 @@ FdoQueryBusRelations(
|
|||
Relations->Objects[i] = Device->Pdo;
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
CurrentEntry = CurrentEntry->Flink;
|
||||
}
|
||||
|
|
|
@ -17,8 +17,12 @@ typedef struct _PCI_DEVICE
|
|||
PCI_SLOT_NUMBER SlotNumber;
|
||||
// PCI configuration data
|
||||
PCI_COMMON_CONFIG PciConfig;
|
||||
// Flag used during enumeration to locate removed devices
|
||||
BOOLEAN RemovePending;
|
||||
// Enable memory space
|
||||
BOOLEAN EnableMemorySpace;
|
||||
// Enable I/O space
|
||||
BOOLEAN EnableIoSpace;
|
||||
// Enable bus master
|
||||
BOOLEAN EnableBusMaster;
|
||||
} PCI_DEVICE, *PPCI_DEVICE;
|
||||
|
||||
|
||||
|
|
|
@ -766,6 +766,9 @@ PdoQueryResources(
|
|||
Descriptor->u.Port.Start.QuadPart =
|
||||
(ULONGLONG)Base;
|
||||
Descriptor->u.Port.Length = Length;
|
||||
|
||||
/* Enable IO space access */
|
||||
DeviceExtension->PciDevice->EnableIoSpace = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -775,6 +778,9 @@ PdoQueryResources(
|
|||
Descriptor->u.Memory.Start.QuadPart =
|
||||
(ULONGLONG)Base;
|
||||
Descriptor->u.Memory.Length = Length;
|
||||
|
||||
/* Enable memory space access */
|
||||
DeviceExtension->PciDevice->EnableMemorySpace = TRUE;
|
||||
}
|
||||
|
||||
Descriptor++;
|
||||
|
@ -792,6 +798,9 @@ PdoQueryResources(
|
|||
Descriptor->u.Interrupt.Vector = PciConfig.u.type0.InterruptLine;
|
||||
Descriptor->u.Interrupt.Affinity = 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
/* Allow bus master mode */
|
||||
DeviceExtension->PciDevice->EnableBusMaster = TRUE;
|
||||
}
|
||||
else if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_BRIDGE_TYPE)
|
||||
{
|
||||
|
@ -821,6 +830,9 @@ PdoQueryResources(
|
|||
Descriptor->u.Port.Start.QuadPart =
|
||||
(ULONGLONG)Base;
|
||||
Descriptor->u.Port.Length = Length;
|
||||
|
||||
/* Enable IO space access */
|
||||
DeviceExtension->PciDevice->EnableIoSpace = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -830,6 +842,9 @@ PdoQueryResources(
|
|||
Descriptor->u.Memory.Start.QuadPart =
|
||||
(ULONGLONG)Base;
|
||||
Descriptor->u.Memory.Length = Length;
|
||||
|
||||
/* Enable memory space access */
|
||||
DeviceExtension->PciDevice->EnableMemorySpace = TRUE;
|
||||
}
|
||||
|
||||
Descriptor++;
|
||||
|
@ -1212,6 +1227,7 @@ PdoStartDevice(
|
|||
ULONG i, ii;
|
||||
PPDO_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
|
||||
UCHAR Irq;
|
||||
USHORT Command;
|
||||
|
||||
if (!RawResList)
|
||||
return STATUS_SUCCESS;
|
||||
|
@ -1228,7 +1244,7 @@ PdoStartDevice(
|
|||
|
||||
if (RawPartialDesc->Type == CmResourceTypeInterrupt)
|
||||
{
|
||||
DPRINT1("Assigning IRQ %x to PCI device (%x, %x)\n",
|
||||
DPRINT1("Assigning IRQ %d to PCI device 0x%x on bus 0x%x\n",
|
||||
RawPartialDesc->u.Interrupt.Vector,
|
||||
DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
|
||||
DeviceExtension->PciDevice->BusNumber);
|
||||
|
@ -1244,6 +1260,48 @@ PdoStartDevice(
|
|||
}
|
||||
}
|
||||
|
||||
Command = 0;
|
||||
|
||||
DPRINT1("Enabling command flags for PCI device 0x%x on bus 0x%x: ",
|
||||
DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
|
||||
DeviceExtension->PciDevice->BusNumber);
|
||||
if (DeviceExtension->PciDevice->EnableBusMaster)
|
||||
{
|
||||
Command |= PCI_ENABLE_BUS_MASTER;
|
||||
DbgPrint("[Bus master] ");
|
||||
}
|
||||
|
||||
if (DeviceExtension->PciDevice->EnableMemorySpace)
|
||||
{
|
||||
Command |= PCI_ENABLE_MEMORY_SPACE;
|
||||
DbgPrint("[Memory space enable] ");
|
||||
}
|
||||
|
||||
if (DeviceExtension->PciDevice->EnableIoSpace)
|
||||
{
|
||||
Command |= PCI_ENABLE_IO_SPACE;
|
||||
DbgPrint("[I/O space enable] ");
|
||||
}
|
||||
|
||||
if (Command != 0)
|
||||
{
|
||||
DbgPrint("\n");
|
||||
|
||||
/* OR with the previous value */
|
||||
Command |= DeviceExtension->PciDevice->PciConfig.Command;
|
||||
|
||||
HalSetBusDataByOffset(PCIConfiguration,
|
||||
DeviceExtension->PciDevice->BusNumber,
|
||||
DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
|
||||
&Command,
|
||||
FIELD_OFFSET(PCI_COMMON_CONFIG, Command),
|
||||
sizeof(USHORT));
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgPrint("None\n");
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -1443,11 +1501,34 @@ PdoPnpControl(
|
|||
case IRP_MN_STOP_DEVICE:
|
||||
case IRP_MN_QUERY_REMOVE_DEVICE:
|
||||
case IRP_MN_CANCEL_REMOVE_DEVICE:
|
||||
case IRP_MN_REMOVE_DEVICE:
|
||||
case IRP_MN_SURPRISE_REMOVAL:
|
||||
Status = STATUS_SUCCESS;
|
||||
break;
|
||||
|
||||
case IRP_MN_REMOVE_DEVICE:
|
||||
{
|
||||
PPDO_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
|
||||
PFDO_DEVICE_EXTENSION FdoDeviceExtension = DeviceExtension->Fdo->DeviceExtension;
|
||||
KIRQL OldIrql;
|
||||
|
||||
/* Remove it from the device list */
|
||||
KeAcquireSpinLock(&FdoDeviceExtension->DeviceListLock, &OldIrql);
|
||||
RemoveEntryList(&DeviceExtension->PciDevice->ListEntry);
|
||||
FdoDeviceExtension->DeviceListCount--;
|
||||
KeReleaseSpinLock(&FdoDeviceExtension->DeviceListLock, OldIrql);
|
||||
|
||||
/* Free the device */
|
||||
ExFreePool(DeviceExtension->PciDevice);
|
||||
|
||||
/* Complete the IRP */
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
|
||||
/* Delete the DO */
|
||||
IoDeleteDevice(DeviceObject);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
case IRP_MN_QUERY_INTERFACE:
|
||||
DPRINT("IRP_MN_QUERY_INTERFACE received\n");
|
||||
Status = PdoQueryInterface(DeviceObject, Irp, IrpSp);
|
||||
|
|
|
@ -1196,9 +1196,16 @@ PciGetEnhancedCapabilities(IN PPCI_PDO_EXTENSION PdoExtension,
|
|||
CapPtr = PciData->u.type0.CapabilitiesPtr;
|
||||
}
|
||||
|
||||
/* Make sure the pointer is spec-aligned and located, and save it */
|
||||
/* Skip garbage capabilities pointer */
|
||||
if (((CapPtr & 0x3) != 0) || (CapPtr < PCI_COMMON_HDR_LENGTH))
|
||||
{
|
||||
/* Report no extended capabilities */
|
||||
PdoExtension->CapabilitiesPtr = 0;
|
||||
PdoExtension->HackFlags |= PCI_HACK_NO_PM_CAPS;
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINT1("Device has capabilities at: %lx\n", CapPtr);
|
||||
ASSERT(((CapPtr & 0x3) == 0) && (CapPtr >= PCI_COMMON_HDR_LENGTH));
|
||||
PdoExtension->CapabilitiesPtr = CapPtr;
|
||||
|
||||
/* Check for PCI-to-PCI Bridges and AGP bridges */
|
||||
|
@ -1264,6 +1271,7 @@ PciGetEnhancedCapabilities(IN PPCI_PDO_EXTENSION PdoExtension,
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* At the very end of all this, does this device not have power management? */
|
||||
if (PdoExtension->HackFlags & PCI_HACK_NO_PM_CAPS)
|
||||
|
|
|
@ -127,7 +127,6 @@ PciFdoIrpQueryRemoveDevice(IN PIRP Irp,
|
|||
IN PPCI_FDO_EXTENSION DeviceExtension)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
while (TRUE);
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
|
|
|
@ -91,7 +91,6 @@ PciPdoSetPowerState(IN PIRP Irp,
|
|||
IN PPCI_PDO_EXTENSION DeviceExtension)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
while (TRUE);
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
|
@ -210,7 +209,6 @@ PciPdoIrpQueryRemoveDevice(IN PIRP Irp,
|
|||
IN PPCI_PDO_EXTENSION DeviceExtension)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
while (TRUE);
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
|
@ -429,7 +427,6 @@ PciPdoIrpQueryDeviceState(IN PIRP Irp,
|
|||
IN PPCI_PDO_EXTENSION DeviceExtension)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
while (TRUE);
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,12 @@
|
|||
<directory name="filesystems">
|
||||
<xi:include href="filesystems/directory.rbuild" />
|
||||
</directory>
|
||||
<directory name="hid">
|
||||
<xi:include href="hid/directory.rbuild" />
|
||||
</directory>
|
||||
<directory name="filters>
|
||||
<xi:include href="filters/directory.rbuild" />
|
||||
</directory>
|
||||
<directory name="input">
|
||||
<xi:include href="input/directory.rbuild" />
|
||||
</directory>
|
||||
|
|
2
reactos/drivers/filters/CMakeLists.txt
Normal file
2
reactos/drivers/filters/CMakeLists.txt
Normal file
|
@ -0,0 +1,2 @@
|
|||
|
||||
add_subdirectory(mountmgr)
|
7
reactos/drivers/filters/directory.rbuild
Normal file
7
reactos/drivers/filters/directory.rbuild
Normal file
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0"?>
|
||||
<!DOCTYPE group SYSTEM "../../tools/rbuild/project.dtd">
|
||||
<group xmlns:xi="http://www.w3.org/2001/XInclude">
|
||||
<directory name="mountmgr">
|
||||
<xi:include href="mountmgr/mountmgr.rbuild" />
|
||||
</directory>
|
||||
</group>
|
18
reactos/drivers/filters/mountmgr/CMakeLists.txt
Normal file
18
reactos/drivers/filters/mountmgr/CMakeLists.txt
Normal file
|
@ -0,0 +1,18 @@
|
|||
|
||||
list(APPEND SOURCE
|
||||
database.c
|
||||
device.c
|
||||
mountmgr.c
|
||||
notify.c
|
||||
point.c
|
||||
symlink.c
|
||||
uniqueid.c
|
||||
mountmgr.rc)
|
||||
|
||||
add_library(mountmgr SHARED ${SOURCE})
|
||||
target_link_libraries(mountmgr wdmguid ioevent)
|
||||
allow_warnings(mountmgr)
|
||||
set_module_type(mountmgr kernelmodedriver)
|
||||
add_importlibs(mountmgr ntoskrnl hal)
|
||||
add_pch(mountmgr mntmgr.h)
|
||||
add_cd_file(TARGET mountmgr DESTINATION reactos/system32/drivers NO_CAB FOR all)
|
1561
reactos/drivers/filters/mountmgr/database.c
Normal file
1561
reactos/drivers/filters/mountmgr/database.c
Normal file
File diff suppressed because it is too large
Load diff
1601
reactos/drivers/filters/mountmgr/device.c
Normal file
1601
reactos/drivers/filters/mountmgr/device.c
Normal file
File diff suppressed because it is too large
Load diff
453
reactos/drivers/filters/mountmgr/mntmgr.h
Normal file
453
reactos/drivers/filters/mountmgr/mntmgr.h
Normal file
|
@ -0,0 +1,453 @@
|
|||
#ifndef _MNTMGR_H_
|
||||
#define _MNTMGR_H_
|
||||
|
||||
#include <ntifs.h>
|
||||
#include <ntddk.h>
|
||||
#include <mountdev.h>
|
||||
#include <ntddvol.h>
|
||||
#include <wdmguid.h>
|
||||
#include <ioevent.h>
|
||||
#include <psfuncs.h>
|
||||
#include <ntdddisk.h>
|
||||
#include <ntddvol.h>
|
||||
|
||||
/* Enter FIXME */
|
||||
#ifdef IsEqualGUID
|
||||
#undef IsEqualGUID
|
||||
#endif
|
||||
|
||||
#define IsEqualGUID(rguid1, rguid2) (!RtlCompareMemory(rguid1, rguid2, sizeof(GUID)))
|
||||
|
||||
#define FILE_READ_PROPERTIES 0x00000008
|
||||
#define FILE_WRITE_PROPERTIES 0x00000010
|
||||
|
||||
#define GPT_BASIC_DATA_ATTRIBUTE_NO_DRIVE_LETTER 0x80000000
|
||||
/* Leave FIXME */
|
||||
|
||||
typedef struct _DEVICE_EXTENSION
|
||||
{
|
||||
PDEVICE_OBJECT DeviceObject; // 0x0
|
||||
PDRIVER_OBJECT DriverObject; // 0x4
|
||||
LIST_ENTRY DeviceListHead; // 0x8
|
||||
LIST_ENTRY OfflineDeviceListHead; // 0x10
|
||||
PVOID NotificationEntry; // 0x18
|
||||
KSEMAPHORE DeviceLock; // 0x1C
|
||||
KSEMAPHORE RemoteDatabaseLock; // 0x30
|
||||
ULONG AutomaticDriveLetter; // 0x44
|
||||
LIST_ENTRY IrpListHead; // 0x48
|
||||
ULONG EpicNumber; // 0x50
|
||||
LIST_ENTRY SavedLinksListHead; // 0x54
|
||||
BOOLEAN ProcessedSuggestions; // 0x5C
|
||||
BOOLEAN NoAutoMount; // 0x5D
|
||||
LIST_ENTRY WorkerQueueListHead; // 0x60
|
||||
KSEMAPHORE WorkerSemaphore; // 0x68
|
||||
LONG WorkerReferences; // 0x7C
|
||||
KSPIN_LOCK WorkerLock; // 0x80
|
||||
LIST_ENTRY UniqueIdWorkerItemListHead; // 0x84
|
||||
PMOUNTDEV_UNIQUE_ID DriveLetterData; // 0x8C
|
||||
UNICODE_STRING RegistryPath; // 0x90
|
||||
LONG WorkerThreadStatus; // 0x98
|
||||
LIST_ENTRY OnlineNotificationListHead; // 0x9C
|
||||
ULONG OnlineNotificationWorkerActive; // 0xA4
|
||||
ULONG OnlineNotificationCount; // 0xA8
|
||||
KEVENT OnlineNotificationEvent; // 0xAC
|
||||
} DEVICE_EXTENSION, *PDEVICE_EXTENSION; // 0xBC
|
||||
|
||||
typedef struct _DEVICE_INFORMATION
|
||||
{
|
||||
LIST_ENTRY DeviceListEntry; // 0x00
|
||||
LIST_ENTRY SymbolicLinksListHead; // 0x08
|
||||
LIST_ENTRY ReplicatedUniqueIdsListHead; // 0x10
|
||||
LIST_ENTRY AssociatedDevicesHead; // 0x18
|
||||
UNICODE_STRING SymbolicName; // 0x20
|
||||
PMOUNTDEV_UNIQUE_ID UniqueId; // 0x28
|
||||
UNICODE_STRING DeviceName; // 0x2C
|
||||
BOOLEAN KeepLinks; // 0x34
|
||||
UCHAR SuggestedDriveLetter; // 0x35
|
||||
BOOLEAN Volume; // 0x36
|
||||
BOOLEAN Removable; // 0x37
|
||||
BOOLEAN LetterAssigned; // 0x38
|
||||
BOOLEAN NeedsReconcile; // 0x39
|
||||
BOOLEAN NoDatabase; // 0x3A
|
||||
BOOLEAN SkipNotifications; // 0x3B
|
||||
ULONG Migrated; // 0x3C
|
||||
LONG MountState; // 0x40
|
||||
PVOID TargetDeviceNotificationEntry; // 0x44
|
||||
PDEVICE_EXTENSION DeviceExtension; // 0x48
|
||||
} DEVICE_INFORMATION, *PDEVICE_INFORMATION; // 0x4C
|
||||
|
||||
typedef struct _SYMLINK_INFORMATION
|
||||
{
|
||||
LIST_ENTRY SymbolicLinksListEntry; // 0x00
|
||||
UNICODE_STRING Name; // 0x08
|
||||
BOOLEAN Online; // 0x10
|
||||
} SYMLINK_INFORMATION, *PSYMLINK_INFORMATION; // 0x14
|
||||
|
||||
typedef struct _SAVED_LINK_INFORMATION
|
||||
{
|
||||
LIST_ENTRY SavedLinksListEntry; // 0x0
|
||||
LIST_ENTRY SymbolicLinksListHead; // 0x8
|
||||
PMOUNTDEV_UNIQUE_ID UniqueId; // 0x10
|
||||
} SAVED_LINK_INFORMATION, *PSAVED_LINK_INFORMATION; // 0x14
|
||||
|
||||
typedef struct _UNIQUE_ID_REPLICATE
|
||||
{
|
||||
LIST_ENTRY ReplicatedUniqueIdsListEntry; // 0x0
|
||||
PMOUNTDEV_UNIQUE_ID UniqueId; // 0x8
|
||||
} UNIQUE_ID_REPLICATE, *PUNIQUE_ID_REPLICATE; // 0xC
|
||||
|
||||
typedef struct _DATABASE_ENTRY
|
||||
{
|
||||
ULONG EntrySize; // 0x00
|
||||
ULONG DatabaseOffset; // 0x04
|
||||
USHORT SymbolicNameOffset; // 0x08
|
||||
USHORT SymbolicNameLength; // 0x0A
|
||||
USHORT UniqueIdOffset; // 0x0C
|
||||
USHORT UniqueIdLength; // 0x0E
|
||||
} DATABASE_ENTRY, *PDATABASE_ENTRY; // 0x10
|
||||
|
||||
typedef struct _ASSOCIATED_DEVICE_ENTRY
|
||||
{
|
||||
LIST_ENTRY AssociatedDevicesEntry; // 0x00
|
||||
PDEVICE_INFORMATION DeviceInformation; // 0x08
|
||||
UNICODE_STRING String; // 0x0C
|
||||
} ASSOCIATED_DEVICE_ENTRY, *PASSOCIATED_DEVICE_ENTRY; // 0x14
|
||||
|
||||
typedef struct _ONLINE_NOTIFICATION_WORK_ITEM
|
||||
{
|
||||
WORK_QUEUE_ITEM; // 0x00
|
||||
PDEVICE_EXTENSION DeviceExtension; // 0x10
|
||||
UNICODE_STRING SymbolicName; // 0x14
|
||||
} ONLINE_NOTIFICATION_WORK_ITEM, *PONLINE_NOTIFICATION_WORK_ITEM; // 0x1C
|
||||
|
||||
typedef struct _RECONCILE_WORK_ITEM
|
||||
{
|
||||
LIST_ENTRY WorkerQueueListEntry; // 0x00
|
||||
PIO_WORKITEM WorkItem; // 0x08
|
||||
PWORKER_THREAD_ROUTINE WorkerRoutine; // 0x0C
|
||||
PVOID Context; // 0x10
|
||||
PDEVICE_EXTENSION DeviceExtension; // 0x14
|
||||
PDEVICE_INFORMATION DeviceInformation; // 0x18
|
||||
} RECONCILE_WORK_ITEM, *PRECONCILE_WORK_ITEM; // 0x1C
|
||||
|
||||
typedef struct _MIGRATE_WORK_ITEM
|
||||
{
|
||||
PIO_WORKITEM WorkItem; // 0x0
|
||||
PDEVICE_INFORMATION DeviceInformation; // 0x4
|
||||
PKEVENT Event; // 0x8
|
||||
NTSTATUS Status; // 0x0C
|
||||
HANDLE Database; // 0x10
|
||||
} MIGRATE_WORK_ITEM, *PMIGRATE_WORK_ITEM; // 0x14
|
||||
|
||||
typedef struct _UNIQUE_ID_WORK_ITEM
|
||||
{
|
||||
LIST_ENTRY UniqueIdWorkerItemListEntry; // 0x0
|
||||
PIO_WORKITEM WorkItem; // 0x8
|
||||
PDEVICE_EXTENSION DeviceExtension; // 0xC
|
||||
PIRP Irp; // 0x10
|
||||
PVOID IrpBuffer; // 0x14
|
||||
PKEVENT Event; // 0x1C
|
||||
UNICODE_STRING DeviceName; // 0x20
|
||||
ULONG IrpBufferLength; // 0x28
|
||||
ULONG StackSize; // 0x2C
|
||||
} UNIQUE_ID_WORK_ITEM, *PUNIQUE_ID_WORK_ITEM; // 0x30
|
||||
|
||||
PDEVICE_OBJECT gdeviceObject;
|
||||
|
||||
/* Memory allocation helpers */
|
||||
#define AllocatePool(Size) ExAllocatePoolWithTag(PagedPool, Size, 'AtnM')
|
||||
#define FreePool(P) ExFreePoolWithTag(P, 'AtnM')
|
||||
|
||||
/* Misc macros */
|
||||
#define MAX(a, b) ((a > b) ? a : b)
|
||||
|
||||
#define LETTER_POSITION 0xC
|
||||
#define COLON_POSITION 0xD
|
||||
#define DRIVE_LETTER_LENGTH 0x1C
|
||||
|
||||
/* mountmgr.c */
|
||||
|
||||
extern UNICODE_STRING DosDevicesMount;
|
||||
extern UNICODE_STRING ReparseIndex;
|
||||
extern UNICODE_STRING DeviceFloppy;
|
||||
extern UNICODE_STRING DeviceMount;
|
||||
extern UNICODE_STRING DeviceCdRom;
|
||||
extern UNICODE_STRING SafeVolumes;
|
||||
extern UNICODE_STRING DosDevices;
|
||||
extern UNICODE_STRING DosGlobal;
|
||||
extern UNICODE_STRING Global;
|
||||
extern UNICODE_STRING Volume;
|
||||
extern KEVENT UnloadEvent;
|
||||
extern LONG Unloading;
|
||||
|
||||
DRIVER_INITIALIZE DriverEntry;
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
MountMgrCancel(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
MountMgrMountedDeviceArrival(
|
||||
IN PDEVICE_EXTENSION Extension,
|
||||
IN PUNICODE_STRING SymbolicName,
|
||||
IN BOOLEAN FromVolume
|
||||
);
|
||||
|
||||
VOID
|
||||
MountMgrMountedDeviceRemoval(
|
||||
IN PDEVICE_EXTENSION Extension,
|
||||
IN PUNICODE_STRING DeviceName
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
FindDeviceInfo(
|
||||
IN PDEVICE_EXTENSION DeviceExtension,
|
||||
IN PUNICODE_STRING SymbolicName,
|
||||
IN BOOLEAN DeviceNameGiven,
|
||||
OUT PDEVICE_INFORMATION * DeviceInformation
|
||||
);
|
||||
|
||||
VOID
|
||||
MountMgrFreeDeadDeviceInfo(
|
||||
IN PDEVICE_INFORMATION DeviceInformation
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
QueryDeviceInformation(
|
||||
IN PUNICODE_STRING SymbolicName,
|
||||
OUT PUNICODE_STRING DeviceName OPTIONAL,
|
||||
OUT PMOUNTDEV_UNIQUE_ID * UniqueId OPTIONAL,
|
||||
OUT PBOOLEAN Removable OPTIONAL,
|
||||
OUT PBOOLEAN GptDriveLetter OPTIONAL,
|
||||
OUT PBOOLEAN HasGuid OPTIONAL,
|
||||
IN OUT LPGUID StableGuid OPTIONAL,
|
||||
OUT PBOOLEAN Valid OPTIONAL
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
HasDriveLetter(
|
||||
IN PDEVICE_INFORMATION DeviceInformation
|
||||
);
|
||||
|
||||
/* database.c */
|
||||
|
||||
extern PWSTR DatabasePath;
|
||||
extern PWSTR OfflinePath;
|
||||
|
||||
VOID
|
||||
ReconcileThisDatabaseWithMaster(
|
||||
IN PDEVICE_EXTENSION DeviceExtension,
|
||||
IN PDEVICE_INFORMATION DeviceInformation
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
WaitForRemoteDatabaseSemaphore(
|
||||
IN PDEVICE_EXTENSION DeviceExtension
|
||||
);
|
||||
|
||||
VOID
|
||||
ReleaseRemoteDatabaseSemaphore(
|
||||
IN PDEVICE_EXTENSION DeviceExtension
|
||||
);
|
||||
|
||||
VOID
|
||||
ChangeRemoteDatabaseUniqueId(
|
||||
IN PDEVICE_INFORMATION DeviceInformation,
|
||||
IN PMOUNTDEV_UNIQUE_ID OldUniqueId,
|
||||
IN PMOUNTDEV_UNIQUE_ID NewUniqueId
|
||||
);
|
||||
|
||||
VOID
|
||||
ReconcileAllDatabasesWithMaster(
|
||||
IN PDEVICE_EXTENSION DeviceExtension
|
||||
);
|
||||
|
||||
VOID
|
||||
DeleteFromLocalDatabase(
|
||||
IN PUNICODE_STRING SymbolicLink,
|
||||
IN PMOUNTDEV_UNIQUE_ID UniqueId
|
||||
);
|
||||
|
||||
VOID
|
||||
DeleteRegistryDriveLetter(
|
||||
IN PMOUNTDEV_UNIQUE_ID UniqueId
|
||||
);
|
||||
|
||||
VOID
|
||||
DeleteNoDriveLetterEntry(
|
||||
IN PMOUNTDEV_UNIQUE_ID UniqueId
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
QueryVolumeName(
|
||||
IN HANDLE RootDirectory,
|
||||
IN PFILE_REPARSE_POINT_INFORMATION ReparsePointInformation,
|
||||
IN PUNICODE_STRING FileName OPTIONAL,
|
||||
OUT PUNICODE_STRING SymbolicName,
|
||||
OUT PUNICODE_STRING VolumeName
|
||||
);
|
||||
|
||||
/* device.c */
|
||||
|
||||
DRIVER_DISPATCH MountMgrDeviceControl;
|
||||
|
||||
/* notify.c */
|
||||
VOID
|
||||
IssueUniqueIdChangeNotifyWorker(
|
||||
IN PUNIQUE_ID_WORK_ITEM WorkItem,
|
||||
IN PMOUNTDEV_UNIQUE_ID UniqueId
|
||||
);
|
||||
|
||||
VOID
|
||||
WaitForOnlinesToComplete(
|
||||
IN PDEVICE_EXTENSION DeviceExtension
|
||||
);
|
||||
|
||||
VOID
|
||||
RegisterForTargetDeviceNotification(
|
||||
IN PDEVICE_EXTENSION DeviceExtension,
|
||||
IN PDEVICE_INFORMATION DeviceInformation
|
||||
);
|
||||
|
||||
VOID
|
||||
SendOnlineNotification(
|
||||
IN PUNICODE_STRING SymbolicName
|
||||
);
|
||||
|
||||
VOID
|
||||
IssueUniqueIdChangeNotify(
|
||||
IN PDEVICE_EXTENSION DeviceExtension,
|
||||
IN PUNICODE_STRING DeviceName,
|
||||
IN PMOUNTDEV_UNIQUE_ID UniqueId
|
||||
);
|
||||
|
||||
VOID
|
||||
PostOnlineNotification(
|
||||
IN PDEVICE_EXTENSION DeviceExtension,
|
||||
IN PUNICODE_STRING SymbolicName
|
||||
);
|
||||
|
||||
VOID
|
||||
MountMgrNotify(
|
||||
IN PDEVICE_EXTENSION DeviceExtension
|
||||
);
|
||||
|
||||
VOID
|
||||
MountMgrNotifyNameChange(
|
||||
IN PDEVICE_EXTENSION DeviceExtension,
|
||||
IN PUNICODE_STRING DeviceName,
|
||||
IN BOOLEAN ValidateVolume
|
||||
);
|
||||
|
||||
/* uniqueid.c */
|
||||
VOID
|
||||
MountMgrUniqueIdChangeRoutine(
|
||||
IN PDEVICE_EXTENSION DeviceExtension,
|
||||
IN PMOUNTDEV_UNIQUE_ID OldUniqueId,
|
||||
IN PMOUNTDEV_UNIQUE_ID NewUniqueId
|
||||
);
|
||||
|
||||
VOID
|
||||
CreateNoDriveLetterEntry(
|
||||
IN PMOUNTDEV_UNIQUE_ID UniqueId
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
HasNoDriveLetterEntry(
|
||||
IN PMOUNTDEV_UNIQUE_ID UniqueId
|
||||
);
|
||||
|
||||
/* point.c */
|
||||
NTSTATUS
|
||||
MountMgrCreatePointWorker(
|
||||
IN PDEVICE_EXTENSION DeviceExtension,
|
||||
IN PUNICODE_STRING SymbolicLinkName,
|
||||
IN PUNICODE_STRING DeviceName
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
QueryPointsFromSymbolicLinkName(
|
||||
IN PDEVICE_EXTENSION DeviceExtension,
|
||||
IN PUNICODE_STRING SymbolicName,
|
||||
IN PIRP Irp
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
QueryPointsFromMemory(
|
||||
IN PDEVICE_EXTENSION DeviceExtension,
|
||||
IN PIRP Irp,
|
||||
IN PMOUNTDEV_UNIQUE_ID UniqueId OPTIONAL,
|
||||
IN PUNICODE_STRING SymbolicName OPTIONAL
|
||||
);
|
||||
|
||||
/* symlink.c */
|
||||
NTSTATUS
|
||||
GlobalCreateSymbolicLink(
|
||||
IN PUNICODE_STRING DosName,
|
||||
IN PUNICODE_STRING DeviceName
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
GlobalDeleteSymbolicLink(
|
||||
IN PUNICODE_STRING DosName
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
QuerySuggestedLinkName(
|
||||
IN PUNICODE_STRING SymbolicName,
|
||||
OUT PUNICODE_STRING SuggestedLinkName,
|
||||
OUT PBOOLEAN UseOnlyIfThereAreNoOtherLinks
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
QuerySymbolicLinkNamesFromStorage(
|
||||
IN PDEVICE_EXTENSION DeviceExtension,
|
||||
IN PDEVICE_INFORMATION DeviceInformation,
|
||||
IN PUNICODE_STRING SuggestedLinkName,
|
||||
IN BOOLEAN UseOnlyIfThereAreNoOtherLinks,
|
||||
OUT PUNICODE_STRING * SymLinks,
|
||||
OUT PULONG SymLinkCount,
|
||||
IN BOOLEAN HasGuid,
|
||||
IN LPGUID Guid
|
||||
);
|
||||
|
||||
PSAVED_LINK_INFORMATION
|
||||
RemoveSavedLinks(
|
||||
IN PDEVICE_EXTENSION DeviceExtension,
|
||||
IN PMOUNTDEV_UNIQUE_ID UniqueId
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
RedirectSavedLink(
|
||||
IN PSAVED_LINK_INFORMATION SavedLinkInformation,
|
||||
IN PUNICODE_STRING DosName,
|
||||
IN PUNICODE_STRING NewLink
|
||||
);
|
||||
|
||||
VOID
|
||||
SendLinkCreated(
|
||||
IN PUNICODE_STRING SymbolicName
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
CreateNewVolumeName(
|
||||
OUT PUNICODE_STRING VolumeName,
|
||||
IN PGUID VolumeGuid OPTIONAL
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
IsDriveLetter(
|
||||
PUNICODE_STRING SymbolicName
|
||||
);
|
||||
|
||||
VOID
|
||||
DeleteSymbolicLinkNameFromMemory(
|
||||
IN PDEVICE_EXTENSION DeviceExtension,
|
||||
IN PUNICODE_STRING SymbolicLink,
|
||||
IN BOOLEAN MarkOffline
|
||||
);
|
||||
|
||||
#endif /* _MNTMGR_H_ */
|
1896
reactos/drivers/filters/mountmgr/mountmgr.c
Normal file
1896
reactos/drivers/filters/mountmgr/mountmgr.c
Normal file
File diff suppressed because it is too large
Load diff
20
reactos/drivers/filters/mountmgr/mountmgr.rbuild
Normal file
20
reactos/drivers/filters/mountmgr/mountmgr.rbuild
Normal file
|
@ -0,0 +1,20 @@
|
|||
<?xml version="1.0"?>
|
||||
<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
|
||||
<module name="mountmgr" type="kernelmodedriver" installbase="system32/drivers" installname="mountmgr.sys" allowwarnings="true">
|
||||
<bootstrap installbase="$(CDOUTPUT)/system32/drivers" />
|
||||
<define name="NTDDI_VERSION">0x05020400</define>
|
||||
<include base="mountmgr">.</include>
|
||||
<library>ntoskrnl</library>
|
||||
<library>hal</library>
|
||||
<library>ioevent</library>
|
||||
<library>wdmguid</library>
|
||||
<file>database.c</file>
|
||||
<file>device.c</file>
|
||||
<file>mountmgr.c</file>
|
||||
<file>notify.c</file>
|
||||
<file>point.c</file>
|
||||
<file>symlink.c</file>
|
||||
<file>uniqueid.c</file>
|
||||
<file>mountmgr.rc</file>
|
||||
<pch>mntmgr.h</pch>
|
||||
</module>
|
6
reactos/drivers/filters/mountmgr/mountmgr.rc
Normal file
6
reactos/drivers/filters/mountmgr/mountmgr.rc
Normal file
|
@ -0,0 +1,6 @@
|
|||
|
||||
#define REACTOS_VERSION_DLL
|
||||
#define REACTOS_STR_FILE_DESCRIPTION "Mount Point Manager\0"
|
||||
#define REACTOS_STR_INTERNAL_NAME "mountmgr.sys\0"
|
||||
#define REACTOS_STR_ORIGINAL_FILENAME "mountmgr.sys\0"
|
||||
#include <reactos/version.rc>
|
757
reactos/drivers/filters/mountmgr/notify.c
Normal file
757
reactos/drivers/filters/mountmgr/notify.c
Normal file
|
@ -0,0 +1,757 @@
|
|||
/*
|
||||
* ReactOS kernel
|
||||
* Copyright (C) 2011 ReactOS Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: drivers/filesystem/mountmgr/notify.c
|
||||
* PURPOSE: Mount Manager - Notifications handlers
|
||||
* PROGRAMMER: Pierre Schweitzer (pierre.schweitzer@reactos.org)
|
||||
* Alex Ionescu (alex.ionescu@reactos.org)
|
||||
*/
|
||||
|
||||
/* INCLUDES *****************************************************************/
|
||||
|
||||
#include "mntmgr.h"
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
VOID
|
||||
SendOnlineNotification(IN PUNICODE_STRING SymbolicName)
|
||||
{
|
||||
PIRP Irp;
|
||||
KEVENT Event;
|
||||
NTSTATUS Status;
|
||||
PFILE_OBJECT FileObject;
|
||||
PIO_STACK_LOCATION Stack;
|
||||
PDEVICE_OBJECT DeviceObject;
|
||||
IO_STATUS_BLOCK IoStatusBlock;
|
||||
|
||||
/* Get device object */
|
||||
Status = IoGetDeviceObjectPointer(SymbolicName,
|
||||
FILE_READ_ATTRIBUTES,
|
||||
&FileObject,
|
||||
&DeviceObject);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* And attached device object */
|
||||
DeviceObject = IoGetAttachedDeviceReference(FileObject->DeviceObject);
|
||||
|
||||
/* And send VOLUME_ONLINE */
|
||||
KeInitializeEvent(&Event, NotificationEvent, FALSE);
|
||||
Irp = IoBuildDeviceIoControlRequest(IOCTL_VOLUME_ONLINE,
|
||||
DeviceObject,
|
||||
NULL, 0,
|
||||
NULL, 0,
|
||||
FALSE,
|
||||
&Event,
|
||||
&IoStatusBlock);
|
||||
if (!Irp)
|
||||
{
|
||||
goto Cleanup;
|
||||
}
|
||||
|
||||
Stack = IoGetNextIrpStackLocation(Irp);
|
||||
Stack->FileObject = FileObject;
|
||||
|
||||
Status = IofCallDriver(DeviceObject, Irp);
|
||||
if (Status == STATUS_PENDING)
|
||||
{
|
||||
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
|
||||
}
|
||||
|
||||
Cleanup:
|
||||
ObfDereferenceObject(DeviceObject);
|
||||
ObfDereferenceObject(FileObject);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
VOID
|
||||
NTAPI
|
||||
SendOnlineNotificationWorker(IN PVOID Parameter)
|
||||
{
|
||||
KIRQL OldIrql;
|
||||
PLIST_ENTRY Head;
|
||||
PDEVICE_EXTENSION DeviceExtension;
|
||||
PONLINE_NOTIFICATION_WORK_ITEM WorkItem;
|
||||
PONLINE_NOTIFICATION_WORK_ITEM NewWorkItem;
|
||||
|
||||
WorkItem = (PONLINE_NOTIFICATION_WORK_ITEM)Parameter;
|
||||
DeviceExtension = WorkItem->DeviceExtension;
|
||||
|
||||
/* First, send the notification */
|
||||
SendOnlineNotification(&(WorkItem->SymbolicName));
|
||||
|
||||
OldIrql = KfAcquireSpinLock(&(DeviceExtension->WorkerLock));
|
||||
/* If there are no notifications running any longer, reset event */
|
||||
if (--DeviceExtension->OnlineNotificationCount == 0)
|
||||
{
|
||||
KeSetEvent(&(DeviceExtension->OnlineNotificationEvent), 0, FALSE);
|
||||
}
|
||||
|
||||
/* If there are still notifications in queue */
|
||||
if (!IsListEmpty(&(DeviceExtension->OnlineNotificationListHead)))
|
||||
{
|
||||
/* Queue a new one for execution */
|
||||
Head = RemoveHeadList(&(DeviceExtension->OnlineNotificationListHead));
|
||||
NewWorkItem = CONTAINING_RECORD(Head, ONLINE_NOTIFICATION_WORK_ITEM, List);
|
||||
KfReleaseSpinLock(&(DeviceExtension->WorkerLock), OldIrql);
|
||||
NewWorkItem->List.Blink = NULL;
|
||||
NewWorkItem->List.Flink = NULL;
|
||||
ExQueueWorkItem((PWORK_QUEUE_ITEM)NewWorkItem, DelayedWorkQueue);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Mark it's over */
|
||||
DeviceExtension->OnlineNotificationWorkerActive = 0;
|
||||
KfReleaseSpinLock(&(DeviceExtension->WorkerLock), OldIrql);
|
||||
}
|
||||
|
||||
FreePool(WorkItem->SymbolicName.Buffer);
|
||||
FreePool(WorkItem);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
VOID
|
||||
PostOnlineNotification(IN PDEVICE_EXTENSION DeviceExtension,
|
||||
IN PUNICODE_STRING SymbolicName)
|
||||
{
|
||||
KIRQL OldIrql;
|
||||
PONLINE_NOTIFICATION_WORK_ITEM WorkItem;
|
||||
|
||||
/* Allocate a notification work item */
|
||||
WorkItem = AllocatePool(sizeof(ONLINE_NOTIFICATION_WORK_ITEM));
|
||||
if (!WorkItem)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
WorkItem->List.Flink = NULL;
|
||||
WorkItem->DeviceExtension = DeviceExtension;
|
||||
WorkItem->WorkerRoutine = SendOnlineNotificationWorker;
|
||||
WorkItem->Parameter = WorkItem;
|
||||
WorkItem->SymbolicName.Length = SymbolicName->Length;
|
||||
WorkItem->SymbolicName.MaximumLength = SymbolicName->Length + sizeof(WCHAR);
|
||||
WorkItem->SymbolicName.Buffer = AllocatePool(WorkItem->SymbolicName.MaximumLength);
|
||||
if (!WorkItem->SymbolicName.Buffer)
|
||||
{
|
||||
FreePool(WorkItem);
|
||||
return;
|
||||
}
|
||||
|
||||
RtlCopyMemory(WorkItem->SymbolicName.Buffer, SymbolicName->Buffer, SymbolicName->Length);
|
||||
WorkItem->SymbolicName.Buffer[SymbolicName->Length / sizeof(WCHAR)] = UNICODE_NULL;
|
||||
|
||||
OldIrql = KfAcquireSpinLock(&(DeviceExtension->WorkerLock));
|
||||
DeviceExtension->OnlineNotificationCount++;
|
||||
|
||||
/* If no worker are active */
|
||||
if (DeviceExtension->OnlineNotificationWorkerActive == 0)
|
||||
{
|
||||
/* Queue that one for execution */
|
||||
DeviceExtension->OnlineNotificationWorkerActive == 1;
|
||||
ExQueueWorkItem((PWORK_QUEUE_ITEM)WorkItem, DelayedWorkQueue);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Otherwise, just put it in the queue list */
|
||||
InsertTailList(&(DeviceExtension->OnlineNotificationListHead), &(WorkItem->List));
|
||||
}
|
||||
|
||||
KfReleaseSpinLock(&(DeviceExtension->WorkerLock), OldIrql);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
VOID
|
||||
WaitForOnlinesToComplete(IN PDEVICE_EXTENSION DeviceExtension)
|
||||
{
|
||||
KIRQL OldIrql;
|
||||
|
||||
KeInitializeEvent(&(DeviceExtension->OnlineNotificationEvent), NotificationEvent, FALSE);
|
||||
|
||||
OldIrql = KfAcquireSpinLock(&(DeviceExtension->WorkerLock));
|
||||
|
||||
/* Just wait all the worker are done */
|
||||
if (DeviceExtension->OnlineNotificationCount != 1)
|
||||
{
|
||||
DeviceExtension->OnlineNotificationCount--;
|
||||
KfReleaseSpinLock(&(DeviceExtension->WorkerLock), OldIrql);
|
||||
|
||||
KeWaitForSingleObject(&(DeviceExtension->OnlineNotificationEvent),
|
||||
Executive,
|
||||
KernelMode,
|
||||
FALSE,
|
||||
NULL);
|
||||
|
||||
OldIrql = KfAcquireSpinLock(&(DeviceExtension->WorkerLock));
|
||||
DeviceExtension->OnlineNotificationCount++;
|
||||
}
|
||||
|
||||
KfReleaseSpinLock(&(DeviceExtension->WorkerLock), OldIrql);
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
MountMgrTargetDeviceNotification(IN PVOID NotificationStructure,
|
||||
IN PVOID Context)
|
||||
{
|
||||
PDEVICE_EXTENSION DeviceExtension;
|
||||
PDEVICE_INFORMATION DeviceInformation;
|
||||
PDEVICE_INTERFACE_CHANGE_NOTIFICATION Notification;
|
||||
|
||||
DeviceInformation = Context;
|
||||
DeviceExtension = DeviceInformation->DeviceExtension;
|
||||
Notification = NotificationStructure;
|
||||
|
||||
/* If it's to signal that removal is complete, then, execute the function */
|
||||
if (IsEqualGUID(&(Notification->Event), &GUID_TARGET_DEVICE_REMOVE_COMPLETE))
|
||||
{
|
||||
MountMgrMountedDeviceRemoval(DeviceExtension, Notification->SymbolicLinkName);
|
||||
}
|
||||
/* It it's to signal that a volume has been mounted
|
||||
* Verify if a database sync is required and execute it
|
||||
*/
|
||||
else if (IsEqualGUID(&(Notification->Event), &GUID_IO_VOLUME_MOUNT))
|
||||
{
|
||||
if (InterlockedCompareExchange(&(DeviceInformation->MountState),
|
||||
FALSE,
|
||||
TRUE) == TRUE)
|
||||
{
|
||||
InterlockedDecrement(&(DeviceInformation->MountState));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (DeviceInformation->NeedsReconcile)
|
||||
{
|
||||
DeviceInformation->NeedsReconcile = FALSE;
|
||||
ReconcileThisDatabaseWithMaster(DeviceExtension, DeviceInformation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
VOID
|
||||
RegisterForTargetDeviceNotification(IN PDEVICE_EXTENSION DeviceExtension,
|
||||
IN PDEVICE_INFORMATION DeviceInformation)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PFILE_OBJECT FileObject;
|
||||
PDEVICE_OBJECT DeviceObject;
|
||||
|
||||
/* Get device object */
|
||||
Status = IoGetDeviceObjectPointer(&(DeviceInformation->DeviceName),
|
||||
FILE_READ_ATTRIBUTES,
|
||||
&FileObject,
|
||||
&DeviceObject);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* And simply register for notifications */
|
||||
Status = IoRegisterPlugPlayNotification(EventCategoryTargetDeviceChange,
|
||||
0, FileObject,
|
||||
DeviceExtension->DriverObject,
|
||||
MountMgrTargetDeviceNotification,
|
||||
DeviceInformation,
|
||||
&(DeviceInformation->TargetDeviceNotificationEntry));
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DeviceInformation->TargetDeviceNotificationEntry = NULL;
|
||||
}
|
||||
|
||||
ObfDereferenceObject(FileObject);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
VOID
|
||||
MountMgrNotify(IN PDEVICE_EXTENSION DeviceExtension)
|
||||
{
|
||||
PIRP Irp;
|
||||
KIRQL OldIrql;
|
||||
LIST_ENTRY CopyList;
|
||||
PLIST_ENTRY NextEntry;
|
||||
|
||||
/* Increase the epic number */
|
||||
DeviceExtension->EpicNumber++;
|
||||
|
||||
InitializeListHead(&CopyList);
|
||||
|
||||
/* Copy all the pending IRPs for notification */
|
||||
IoAcquireCancelSpinLock(&OldIrql);
|
||||
while (!IsListEmpty(&(DeviceExtension->IrpListHead)))
|
||||
{
|
||||
NextEntry = RemoveHeadList(&(DeviceExtension->IrpListHead));
|
||||
Irp = CONTAINING_RECORD(NextEntry, IRP, Tail.Overlay.ListEntry);
|
||||
InsertTailList(&CopyList, &(Irp->Tail.Overlay.ListEntry));
|
||||
}
|
||||
IoReleaseCancelSpinLock(OldIrql);
|
||||
|
||||
/* Then, notifiy them one by one */
|
||||
while (!IsListEmpty(&CopyList))
|
||||
{
|
||||
NextEntry = RemoveHeadList(&CopyList);
|
||||
Irp = CONTAINING_RECORD(NextEntry, IRP, Tail.Overlay.ListEntry);
|
||||
|
||||
*((PULONG)Irp->AssociatedIrp.SystemBuffer) = DeviceExtension->EpicNumber;
|
||||
Irp->IoStatus.Information = sizeof(DeviceExtension->EpicNumber);
|
||||
|
||||
IofCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
VOID
|
||||
MountMgrNotifyNameChange(IN PDEVICE_EXTENSION DeviceExtension,
|
||||
IN PUNICODE_STRING DeviceName,
|
||||
IN BOOLEAN ValidateVolume)
|
||||
{
|
||||
PIRP Irp;
|
||||
KEVENT Event;
|
||||
NTSTATUS Status;
|
||||
PLIST_ENTRY NextEntry;
|
||||
PFILE_OBJECT FileObject;
|
||||
PIO_STACK_LOCATION Stack;
|
||||
PDEVICE_OBJECT DeviceObject;
|
||||
IO_STATUS_BLOCK IoStatusBlock;
|
||||
PDEVICE_RELATIONS DeviceRelations;
|
||||
PDEVICE_INFORMATION DeviceInformation;
|
||||
TARGET_DEVICE_CUSTOM_NOTIFICATION DeviceNotification;
|
||||
|
||||
/* If we have to validate volume */
|
||||
if (ValidateVolume)
|
||||
{
|
||||
/* Then, ensure we can find the device */
|
||||
NextEntry = DeviceExtension->DeviceListHead.Flink;
|
||||
while (NextEntry != &(DeviceExtension->DeviceListHead))
|
||||
{
|
||||
DeviceInformation = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry);
|
||||
if (RtlCompareUnicodeString(DeviceName, &(DeviceInformation->DeviceName), TRUE) == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (NextEntry == &(DeviceExtension->DeviceListHead) ||
|
||||
!DeviceInformation->Volume)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Then, get device object */
|
||||
Status = IoGetDeviceObjectPointer(DeviceName,
|
||||
FILE_READ_ATTRIBUTES,
|
||||
&FileObject,
|
||||
&DeviceObject);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
DeviceObject = IoGetAttachedDeviceReference(FileObject->DeviceObject);
|
||||
|
||||
KeInitializeEvent(&Event, NotificationEvent, FALSE);
|
||||
|
||||
/* Set up empty IRP (yes, yes!) */
|
||||
Irp = IoBuildDeviceIoControlRequest(0,
|
||||
DeviceObject,
|
||||
NULL,
|
||||
0,
|
||||
NULL,
|
||||
0,
|
||||
FALSE,
|
||||
&Event,
|
||||
&IoStatusBlock);
|
||||
if (!Irp)
|
||||
{
|
||||
ObfDereferenceObject(DeviceObject);
|
||||
ObfDereferenceObject(FileObject);
|
||||
}
|
||||
|
||||
Stack = IoGetNextIrpStackLocation(Irp);
|
||||
|
||||
Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
|
||||
Irp->IoStatus.Information = 0;
|
||||
|
||||
/* Properly set it, we want to query device relations */
|
||||
Stack->MajorFunction = IRP_MJ_PNP;
|
||||
Stack->MinorFunction = IRP_MN_QUERY_DEVICE_RELATIONS;
|
||||
Stack->Parameters.QueryDeviceRelations.Type = TargetDeviceRelation;
|
||||
Stack->FileObject = FileObject;
|
||||
|
||||
/* And call driver */
|
||||
Status = IofCallDriver(DeviceObject, Irp);
|
||||
if (Status == STATUS_PENDING)
|
||||
{
|
||||
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
|
||||
Status = IoStatusBlock.Status;
|
||||
}
|
||||
|
||||
ObfDereferenceObject(DeviceObject);
|
||||
ObfDereferenceObject(FileObject);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Validate device return */
|
||||
DeviceRelations = (PDEVICE_RELATIONS)IoStatusBlock.Information;
|
||||
if (DeviceRelations->Count < 1)
|
||||
{
|
||||
ExFreePool(DeviceRelations);
|
||||
return;
|
||||
}
|
||||
|
||||
DeviceObject = DeviceRelations->Objects[0];
|
||||
ExFreePool(DeviceRelations);
|
||||
|
||||
/* Set up real notification */
|
||||
DeviceNotification.Version = 1;
|
||||
DeviceNotification.Size = sizeof(TARGET_DEVICE_CUSTOM_NOTIFICATION);
|
||||
DeviceNotification.Event = GUID_IO_VOLUME_NAME_CHANGE;
|
||||
DeviceNotification.FileObject = NULL;
|
||||
DeviceNotification.NameBufferOffset = -1;
|
||||
|
||||
/* And report */
|
||||
IoReportTargetDeviceChangeAsynchronous(DeviceObject,
|
||||
&DeviceNotification,
|
||||
NULL, NULL);
|
||||
|
||||
ObfDereferenceObject(DeviceObject);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
VOID
|
||||
RemoveWorkItem(IN PUNIQUE_ID_WORK_ITEM WorkItem)
|
||||
{
|
||||
PDEVICE_EXTENSION DeviceExtension;
|
||||
|
||||
KeWaitForSingleObject(&(DeviceExtension->DeviceLock), Executive, KernelMode, FALSE, NULL);
|
||||
|
||||
/* If even if being worked, it's too late */
|
||||
if (WorkItem->Event)
|
||||
{
|
||||
KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
|
||||
KeSetEvent(WorkItem->Event, 0, FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Otherwise, remove it from the list, and delete it */
|
||||
RemoveEntryList(&(WorkItem->UniqueIdWorkerItemListEntry));
|
||||
KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
|
||||
IoFreeIrp(WorkItem->Irp);
|
||||
FreePool(WorkItem->DeviceName.Buffer);
|
||||
FreePool(WorkItem->IrpBuffer);
|
||||
FreePool(WorkItem);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
VOID
|
||||
NTAPI
|
||||
UniqueIdChangeNotifyWorker(IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PVOID Context)
|
||||
{
|
||||
PUNIQUE_ID_WORK_ITEM WorkItem = Context;
|
||||
PMOUNTDEV_UNIQUE_ID OldUniqueId, NewUniqueId;
|
||||
PMOUNTDEV_UNIQUE_ID_CHANGE_NOTIFY_OUTPUT UniqueIdChange;
|
||||
|
||||
/* Validate worker */
|
||||
if (!NT_SUCCESS(WorkItem->Irp->IoStatus.Status))
|
||||
{
|
||||
RemoveWorkItem(WorkItem);
|
||||
return;
|
||||
}
|
||||
|
||||
UniqueIdChange = WorkItem->Irp->AssociatedIrp.SystemBuffer;
|
||||
/* Get the old unique ID */
|
||||
OldUniqueId = AllocatePool(UniqueIdChange->OldUniqueIdLength + sizeof(MOUNTDEV_UNIQUE_ID));
|
||||
if (!OldUniqueId)
|
||||
{
|
||||
RemoveWorkItem(WorkItem);
|
||||
return;
|
||||
}
|
||||
|
||||
OldUniqueId->UniqueIdLength = UniqueIdChange->OldUniqueIdLength;
|
||||
RtlCopyMemory(OldUniqueId->UniqueId,
|
||||
(PVOID)((ULONG_PTR)UniqueIdChange + UniqueIdChange->OldUniqueIdOffset),
|
||||
UniqueIdChange->OldUniqueIdLength);
|
||||
|
||||
/* Get the new unique ID */
|
||||
NewUniqueId = AllocatePool(UniqueIdChange->NewUniqueIdLength + sizeof(MOUNTDEV_UNIQUE_ID));
|
||||
if (!NewUniqueId)
|
||||
{
|
||||
FreePool(OldUniqueId);
|
||||
RemoveWorkItem(WorkItem);
|
||||
return;
|
||||
}
|
||||
|
||||
NewUniqueId->UniqueIdLength = UniqueIdChange->NewUniqueIdLength;
|
||||
RtlCopyMemory(NewUniqueId->UniqueId,
|
||||
(PVOID)((ULONG_PTR)UniqueIdChange + UniqueIdChange->NewUniqueIdOffset),
|
||||
UniqueIdChange->NewUniqueIdLength);
|
||||
|
||||
/* Call the real worker */
|
||||
MountMgrUniqueIdChangeRoutine(WorkItem->DeviceExtension, OldUniqueId, NewUniqueId);
|
||||
IssueUniqueIdChangeNotifyWorker(WorkItem, NewUniqueId);
|
||||
|
||||
FreePool(NewUniqueId);
|
||||
FreePool(OldUniqueId);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
UniqueIdChangeNotifyCompletion(IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp,
|
||||
IN PVOID Context)
|
||||
{
|
||||
PUNIQUE_ID_WORK_ITEM WorkItem = Context;
|
||||
|
||||
/* Simply queue the work item */
|
||||
IoQueueWorkItem(WorkItem->WorkItem,
|
||||
UniqueIdChangeNotifyWorker,
|
||||
DelayedWorkQueue,
|
||||
WorkItem);
|
||||
|
||||
return STATUS_MORE_PROCESSING_REQUIRED;
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
VOID
|
||||
IssueUniqueIdChangeNotifyWorker(IN PUNIQUE_ID_WORK_ITEM WorkItem,
|
||||
IN PMOUNTDEV_UNIQUE_ID UniqueId)
|
||||
{
|
||||
PIRP Irp;
|
||||
NTSTATUS Status;
|
||||
PFILE_OBJECT FileObject;
|
||||
PIO_STACK_LOCATION Stack;
|
||||
PDEVICE_OBJECT DeviceObject;
|
||||
|
||||
/* Get the device object */
|
||||
Status = IoGetDeviceObjectPointer(&(WorkItem->DeviceName),
|
||||
FILE_READ_ATTRIBUTES,
|
||||
&FileObject,
|
||||
&DeviceObject);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
RemoveWorkItem(WorkItem);
|
||||
return;
|
||||
}
|
||||
|
||||
/* And then, the attached device */
|
||||
DeviceObject = IoGetAttachedDeviceReference(FileObject->DeviceObject);
|
||||
|
||||
/* Initialize the IRP */
|
||||
Irp = WorkItem->Irp;
|
||||
IoInitializeIrp(Irp, IoSizeOfIrp(WorkItem->StackSize), WorkItem->StackSize);
|
||||
|
||||
if (InterlockedExchange((PLONG)&(WorkItem->Event), 0) != 0)
|
||||
{
|
||||
ObfDereferenceObject(FileObject);
|
||||
ObfDereferenceObject(DeviceObject);
|
||||
RemoveWorkItem(WorkItem);
|
||||
return;
|
||||
}
|
||||
|
||||
Irp->AssociatedIrp.SystemBuffer = WorkItem->IrpBuffer;
|
||||
Irp->Tail.Overlay.Thread = PsGetCurrentThread();
|
||||
RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, UniqueId, UniqueId->UniqueIdLength + sizeof(USHORT));
|
||||
|
||||
Stack = IoGetNextIrpStackLocation(Irp);
|
||||
|
||||
Stack->Parameters.DeviceIoControl.InputBufferLength = UniqueId->UniqueIdLength + sizeof(USHORT);
|
||||
Stack->Parameters.DeviceIoControl.OutputBufferLength = WorkItem->IrpBufferLength;
|
||||
Stack->Parameters.DeviceIoControl.Type3InputBuffer = 0;
|
||||
Stack->Parameters.DeviceIoControl.IoControlCode = IOCTL_MOUNTDEV_UNIQUE_ID_CHANGE_NOTIFY;
|
||||
Stack->MajorFunction = IRP_MJ_DEVICE_CONTROL;
|
||||
|
||||
Status = IoSetCompletionRoutineEx(WorkItem->DeviceExtension->DeviceObject,
|
||||
Irp,
|
||||
UniqueIdChangeNotifyCompletion,
|
||||
WorkItem,
|
||||
TRUE, TRUE, TRUE);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ObfDereferenceObject(FileObject);
|
||||
ObfDereferenceObject(DeviceObject);
|
||||
RemoveWorkItem(WorkItem);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Call the driver */
|
||||
IofCallDriver(DeviceObject, Irp);
|
||||
ObfDereferenceObject(FileObject);
|
||||
ObfDereferenceObject(DeviceObject);
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
VOID
|
||||
IssueUniqueIdChangeNotify(IN PDEVICE_EXTENSION DeviceExtension,
|
||||
IN PUNICODE_STRING DeviceName,
|
||||
IN PMOUNTDEV_UNIQUE_ID UniqueId)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PVOID IrpBuffer = NULL;
|
||||
PFILE_OBJECT FileObject;
|
||||
PDEVICE_OBJECT DeviceObject;
|
||||
PUNIQUE_ID_WORK_ITEM WorkItem = NULL;
|
||||
|
||||
/* Get the associated device object */
|
||||
Status = IoGetDeviceObjectPointer(DeviceName,
|
||||
FILE_READ_ATTRIBUTES,
|
||||
&FileObject,
|
||||
&DeviceObject);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* And then, get attached device */
|
||||
DeviceObject = IoGetAttachedDeviceReference(FileObject->DeviceObject);
|
||||
|
||||
ObfDereferenceObject(FileObject);
|
||||
|
||||
/* Allocate a work item */
|
||||
WorkItem = AllocatePool(sizeof(UNIQUE_ID_WORK_ITEM));
|
||||
if (!WorkItem)
|
||||
{
|
||||
ObfDereferenceObject(DeviceObject);
|
||||
return;
|
||||
}
|
||||
|
||||
WorkItem->Event = NULL;
|
||||
WorkItem->WorkItem = IoAllocateWorkItem(DeviceExtension->DeviceObject);
|
||||
if (!WorkItem->WorkItem)
|
||||
{
|
||||
ObfDereferenceObject(DeviceObject);
|
||||
goto Cleanup;
|
||||
}
|
||||
|
||||
WorkItem->DeviceExtension = DeviceExtension;
|
||||
WorkItem->StackSize = DeviceObject->StackSize;
|
||||
/* Already provide the IRP */
|
||||
WorkItem->Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
|
||||
|
||||
ObfDereferenceObject(DeviceObject);
|
||||
|
||||
if (!WorkItem->Irp)
|
||||
{
|
||||
goto Cleanup;
|
||||
}
|
||||
|
||||
/* Ensure it has enough space */
|
||||
IrpBuffer = AllocatePool(sizeof(MOUNTDEV_UNIQUE_ID_CHANGE_NOTIFY_OUTPUT) + 1024);
|
||||
if (!IrpBuffer)
|
||||
{
|
||||
goto Cleanup;
|
||||
}
|
||||
|
||||
WorkItem->DeviceName.Length = DeviceName->Length;
|
||||
WorkItem->DeviceName.MaximumLength = DeviceName->Length + sizeof(WCHAR);
|
||||
WorkItem->DeviceName.Buffer = AllocatePool(WorkItem->DeviceName.MaximumLength);
|
||||
if (!WorkItem->DeviceName.Buffer)
|
||||
{
|
||||
goto Cleanup;
|
||||
}
|
||||
|
||||
RtlCopyMemory(WorkItem->DeviceName.Buffer, DeviceName->Buffer, DeviceName->Length);
|
||||
WorkItem->DeviceName.Buffer[DeviceName->Length / sizeof(WCHAR)] = UNICODE_NULL;
|
||||
|
||||
WorkItem->IrpBuffer = IrpBuffer;
|
||||
WorkItem->IrpBufferLength = sizeof(MOUNTDEV_UNIQUE_ID_CHANGE_NOTIFY_OUTPUT) + 1024;
|
||||
|
||||
/* Add the worker in the list */
|
||||
KeWaitForSingleObject(&(DeviceExtension->DeviceLock), Executive, KernelMode, FALSE, NULL);
|
||||
InsertHeadList(&(DeviceExtension->UniqueIdWorkerItemListHead), &(WorkItem->UniqueIdWorkerItemListEntry));
|
||||
KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
|
||||
|
||||
/* And call the worker */
|
||||
IssueUniqueIdChangeNotifyWorker(WorkItem, UniqueId);
|
||||
|
||||
return;
|
||||
|
||||
Cleanup:
|
||||
if (IrpBuffer)
|
||||
{
|
||||
FreePool(IrpBuffer);
|
||||
}
|
||||
|
||||
if (WorkItem->Irp)
|
||||
{
|
||||
IoFreeIrp(WorkItem->Irp);
|
||||
}
|
||||
|
||||
if (WorkItem->WorkItem)
|
||||
{
|
||||
IoFreeWorkItem(WorkItem->WorkItem);
|
||||
}
|
||||
|
||||
if (WorkItem)
|
||||
{
|
||||
FreePool(WorkItem);
|
||||
}
|
||||
}
|
572
reactos/drivers/filters/mountmgr/point.c
Normal file
572
reactos/drivers/filters/mountmgr/point.c
Normal file
|
@ -0,0 +1,572 @@
|
|||
/*
|
||||
* ReactOS kernel
|
||||
* Copyright (C) 2011-2012 ReactOS Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: drivers/filesystem/mountmgr/point.c
|
||||
* PURPOSE: Mount Manager - Mount points
|
||||
* PROGRAMMER: Pierre Schweitzer (pierre.schweitzer@reactos.org)
|
||||
*/
|
||||
|
||||
/* INCLUDES *****************************************************************/
|
||||
|
||||
#include "mntmgr.h"
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
NTSTATUS
|
||||
MountMgrCreatePointWorker(IN PDEVICE_EXTENSION DeviceExtension,
|
||||
IN PUNICODE_STRING SymbolicLinkName,
|
||||
IN PUNICODE_STRING DeviceName)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PLIST_ENTRY DeviceEntry;
|
||||
PMOUNTDEV_UNIQUE_ID UniqueId;
|
||||
PSYMLINK_INFORMATION SymlinkInformation;
|
||||
UNICODE_STRING SymLink, TargetDeviceName;
|
||||
PDEVICE_INFORMATION DeviceInformation, DeviceInfo;
|
||||
|
||||
/* Get device name */
|
||||
Status = QueryDeviceInformation(SymbolicLinkName,
|
||||
&TargetDeviceName,
|
||||
NULL, NULL, NULL,
|
||||
NULL, NULL, NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* First of all, try to find device */
|
||||
for (DeviceEntry = DeviceExtension->DeviceListHead.Flink;
|
||||
DeviceEntry != &(DeviceExtension->DeviceListHead);
|
||||
DeviceEntry = DeviceEntry->Flink)
|
||||
{
|
||||
DeviceInformation = CONTAINING_RECORD(DeviceEntry, DEVICE_INFORMATION, DeviceListEntry);
|
||||
|
||||
if (RtlCompareUnicodeString(&TargetDeviceName, &(DeviceInformation->DeviceName), TRUE) == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy symbolic link name and null terminate it */
|
||||
SymLink.Buffer = AllocatePool(SymbolicLinkName->Length + sizeof(UNICODE_NULL));
|
||||
if (!SymLink.Buffer)
|
||||
{
|
||||
FreePool(TargetDeviceName.Buffer);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
RtlCopyMemory(SymLink.Buffer, SymbolicLinkName->Buffer, SymbolicLinkName->Length);
|
||||
SymLink.Buffer[SymbolicLinkName->Length / sizeof(WCHAR)] = UNICODE_NULL;
|
||||
SymLink.Length = SymbolicLinkName->Length;
|
||||
SymLink.MaximumLength = SymbolicLinkName->Length + sizeof(UNICODE_NULL);
|
||||
|
||||
/* If we didn't find device */
|
||||
if (DeviceEntry == &(DeviceExtension->DeviceListHead))
|
||||
{
|
||||
/* Then, try with unique ID */
|
||||
Status = QueryDeviceInformation(SymbolicLinkName,
|
||||
NULL, &UniqueId,
|
||||
NULL, NULL, NULL,
|
||||
NULL, NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
FreePool(TargetDeviceName.Buffer);
|
||||
FreePool(SymLink.Buffer);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Create a link to the device */
|
||||
Status = GlobalCreateSymbolicLink(&SymLink, &TargetDeviceName);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
FreePool(UniqueId);
|
||||
FreePool(TargetDeviceName.Buffer);
|
||||
FreePool(SymLink.Buffer);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* If caller provided driver letter, delete it */
|
||||
if (IsDriveLetter(&SymLink))
|
||||
{
|
||||
DeleteRegistryDriveLetter(UniqueId);
|
||||
}
|
||||
|
||||
/* Device will be identified with its unique ID */
|
||||
Status = RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE,
|
||||
DatabasePath,
|
||||
SymLink.Buffer,
|
||||
REG_BINARY,
|
||||
UniqueId->UniqueId,
|
||||
UniqueId->UniqueIdLength);
|
||||
|
||||
FreePool(UniqueId);
|
||||
FreePool(TargetDeviceName.Buffer);
|
||||
FreePool(SymLink.Buffer);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* If call provided a driver letter whereas device already has one
|
||||
* fail, this is not doable
|
||||
*/
|
||||
if (IsDriveLetter(&SymLink) && HasDriveLetter(DeviceInformation))
|
||||
{
|
||||
FreePool(TargetDeviceName.Buffer);
|
||||
FreePool(SymLink.Buffer);
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* Now, create a link */
|
||||
Status = GlobalCreateSymbolicLink(&SymLink, &TargetDeviceName);
|
||||
FreePool(TargetDeviceName.Buffer);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
FreePool(SymLink.Buffer);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Associate Unique ID <-> symbolic name */
|
||||
UniqueId = DeviceInformation->UniqueId;
|
||||
Status = RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE,
|
||||
DatabasePath,
|
||||
SymLink.Buffer,
|
||||
REG_BINARY,
|
||||
UniqueId->UniqueId,
|
||||
UniqueId->UniqueIdLength);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
GlobalDeleteSymbolicLink(&SymLink);
|
||||
FreePool(SymLink.Buffer);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Now, prepare to save the link with the device */
|
||||
SymlinkInformation = AllocatePool(sizeof(SYMLINK_INFORMATION));
|
||||
if (!SymlinkInformation)
|
||||
{
|
||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
GlobalDeleteSymbolicLink(&SymLink);
|
||||
FreePool(SymLink.Buffer);
|
||||
return Status;
|
||||
}
|
||||
|
||||
SymlinkInformation->Name.Length = SymLink.Length;
|
||||
SymlinkInformation->Name.MaximumLength = SymLink.Length + sizeof(UNICODE_NULL);
|
||||
SymlinkInformation->Name.Buffer = AllocatePool(SymlinkInformation->Name.MaximumLength);
|
||||
if (!SymlinkInformation->Name.Buffer)
|
||||
{
|
||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
FreePool(SymlinkInformation);
|
||||
GlobalDeleteSymbolicLink(&SymLink);
|
||||
FreePool(SymLink.Buffer);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Save the link and mark it online */
|
||||
RtlCopyMemory(SymlinkInformation->Name.Buffer, SymLink.Buffer, SymlinkInformation->Name.Length);
|
||||
SymlinkInformation->Name.Buffer[SymlinkInformation->Name.Length / sizeof(WCHAR)] = UNICODE_NULL;
|
||||
SymlinkInformation->Online = TRUE;
|
||||
InsertTailList(&DeviceInformation->SymbolicLinksListHead, &SymlinkInformation->SymbolicLinksListEntry);
|
||||
SendLinkCreated(&(SymlinkInformation->Name));
|
||||
|
||||
/* If we have a drive letter */
|
||||
if (IsDriveLetter(&SymLink))
|
||||
{
|
||||
/* Then, delete the no drive letter entry */
|
||||
DeleteNoDriveLetterEntry(UniqueId);
|
||||
|
||||
/* And post online notification if asked */
|
||||
if (!DeviceInformation->SkipNotifications)
|
||||
{
|
||||
PostOnlineNotification(DeviceExtension, &DeviceInformation->SymbolicName);
|
||||
}
|
||||
}
|
||||
|
||||
/* If that's a volume with automatic drive letter, it's now time to resync databases */
|
||||
if (MOUNTMGR_IS_VOLUME_NAME(&SymLink) && DeviceExtension->AutomaticDriveLetter)
|
||||
{
|
||||
for (DeviceEntry = DeviceExtension->DeviceListHead.Flink;
|
||||
DeviceEntry != &(DeviceExtension->DeviceListHead);
|
||||
DeviceEntry = DeviceEntry->Flink)
|
||||
{
|
||||
DeviceInfo = CONTAINING_RECORD(DeviceEntry, DEVICE_INFORMATION, DeviceListEntry);
|
||||
|
||||
/* If there's one, ofc! */
|
||||
if (!DeviceInfo->NoDatabase)
|
||||
{
|
||||
ReconcileThisDatabaseWithMaster(DeviceExtension, DeviceInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Notify & quit */
|
||||
FreePool(SymLink.Buffer);
|
||||
MountMgrNotify(DeviceExtension);
|
||||
|
||||
if (!DeviceInformation->Volume)
|
||||
{
|
||||
MountMgrNotifyNameChange(DeviceExtension, DeviceName, FALSE);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
NTSTATUS
|
||||
QueryPointsFromMemory(IN PDEVICE_EXTENSION DeviceExtension,
|
||||
IN PIRP Irp,
|
||||
IN PMOUNTDEV_UNIQUE_ID UniqueId OPTIONAL,
|
||||
IN PUNICODE_STRING SymbolicName OPTIONAL)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PIO_STACK_LOCATION Stack;
|
||||
UNICODE_STRING DeviceName;
|
||||
ULONG TotalSize, TotalSymLinks;
|
||||
PMOUNTMGR_MOUNT_POINTS MountPoints;
|
||||
PDEVICE_INFORMATION DeviceInformation;
|
||||
PLIST_ENTRY DeviceEntry, SymlinksEntry;
|
||||
PSYMLINK_INFORMATION SymlinkInformation;
|
||||
|
||||
/* If we got a symbolic link, query device */
|
||||
if (SymbolicName)
|
||||
{
|
||||
Status = QueryDeviceInformation(SymbolicName,
|
||||
&DeviceName,
|
||||
NULL, NULL,
|
||||
NULL, NULL,
|
||||
NULL, NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
/* Browse all the links to count number of links & size used */
|
||||
TotalSize = 0;
|
||||
TotalSymLinks = 0;
|
||||
for (DeviceEntry = DeviceExtension->DeviceListHead.Flink;
|
||||
DeviceEntry != &(DeviceExtension->DeviceListHead);
|
||||
DeviceEntry = DeviceEntry->Flink)
|
||||
{
|
||||
DeviceInformation = CONTAINING_RECORD(DeviceEntry, DEVICE_INFORMATION, DeviceListEntry);
|
||||
|
||||
/* If we were given an unique ID, it has to match */
|
||||
if (UniqueId)
|
||||
{
|
||||
if (UniqueId->UniqueIdLength != DeviceInformation->UniqueId->UniqueIdLength)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (RtlCompareMemory(UniqueId->UniqueId,
|
||||
DeviceInformation->UniqueId->UniqueId,
|
||||
UniqueId->UniqueIdLength) != UniqueId->UniqueIdLength)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
/* Or, if we had a symlink, it has to match */
|
||||
else if (SymbolicName)
|
||||
{
|
||||
if (!RtlEqualUnicodeString(&DeviceName, &(DeviceInformation->DeviceName), TRUE))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Once here, it matched, save device name & unique ID size */
|
||||
TotalSize += DeviceInformation->DeviceName.Length + DeviceInformation->UniqueId->UniqueIdLength;
|
||||
|
||||
/* And count number of symlinks (and their size) */
|
||||
for (SymlinksEntry = DeviceInformation->SymbolicLinksListHead.Flink;
|
||||
SymlinksEntry != &(DeviceInformation->SymbolicLinksListHead);
|
||||
SymlinksEntry = SymlinksEntry->Flink)
|
||||
{
|
||||
SymlinkInformation = CONTAINING_RECORD(SymlinksEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
|
||||
|
||||
TotalSize += SymlinkInformation->Name.Length;
|
||||
TotalSymLinks++;
|
||||
}
|
||||
|
||||
/* We had a specific item to find
|
||||
* if we reach that point, we found it, no need to continue
|
||||
*/
|
||||
if (UniqueId || SymbolicName)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we were looking for specific item, ensure we found it */
|
||||
if (UniqueId || SymbolicName)
|
||||
{
|
||||
if (DeviceEntry == &(DeviceExtension->DeviceListHead))
|
||||
{
|
||||
if (DeviceName.Buffer)
|
||||
{
|
||||
FreePool(DeviceName.Buffer);
|
||||
}
|
||||
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now, ensure output buffer can hold everything */
|
||||
Stack = IoGetNextIrpStackLocation(Irp);
|
||||
MountPoints = (PMOUNTMGR_MOUNT_POINTS)Irp->AssociatedIrp.SystemBuffer;
|
||||
|
||||
/* Ensure we set output to let user reallocate! */
|
||||
MountPoints->Size = sizeof(MOUNTMGR_MOUNT_POINTS) + TotalSize;
|
||||
MountPoints->NumberOfMountPoints = TotalSymLinks;
|
||||
|
||||
if (MountPoints->Size > Stack->Parameters.DeviceIoControl.OutputBufferLength)
|
||||
{
|
||||
return STATUS_BUFFER_OVERFLOW;
|
||||
}
|
||||
|
||||
/* Now, start putting mount points */
|
||||
TotalSymLinks = 0;
|
||||
TotalSize = 0;
|
||||
for (DeviceEntry = DeviceExtension->DeviceListHead.Flink;
|
||||
DeviceEntry != &(DeviceExtension->DeviceListHead);
|
||||
DeviceEntry = DeviceEntry->Flink)
|
||||
{
|
||||
DeviceInformation = CONTAINING_RECORD(DeviceEntry, DEVICE_INFORMATION, DeviceListEntry);
|
||||
|
||||
/* Find back correct mount point */
|
||||
if (UniqueId)
|
||||
{
|
||||
if (!UniqueId->UniqueIdLength != DeviceInformation->UniqueId->UniqueIdLength)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (RtlCompareMemory(UniqueId->UniqueId,
|
||||
DeviceInformation->UniqueId->UniqueId,
|
||||
UniqueId->UniqueIdLength) != UniqueId->UniqueIdLength)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (SymbolicName)
|
||||
{
|
||||
if (!RtlEqualUnicodeString(&DeviceName, &(DeviceInformation->DeviceName), TRUE))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now we've got it, but all the data */
|
||||
for (SymlinksEntry = DeviceInformation->SymbolicLinksListHead.Flink;
|
||||
SymlinksEntry != &(DeviceInformation->SymbolicLinksListHead);
|
||||
SymlinksEntry = SymlinksEntry->Flink)
|
||||
{
|
||||
SymlinkInformation = CONTAINING_RECORD(SymlinksEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
|
||||
|
||||
|
||||
MountPoints->MountPoints[TotalSymLinks].SymbolicLinkNameOffset = sizeof(MOUNTMGR_MOUNT_POINTS) +
|
||||
TotalSize;
|
||||
MountPoints->MountPoints[TotalSymLinks].SymbolicLinkNameLength = SymlinkInformation->Name.Length;
|
||||
MountPoints->MountPoints[TotalSymLinks].UniqueIdOffset = sizeof(MOUNTMGR_MOUNT_POINTS) +
|
||||
SymlinkInformation->Name.Length +
|
||||
TotalSize;
|
||||
MountPoints->MountPoints[TotalSymLinks].UniqueIdLength = DeviceInformation->UniqueId->UniqueIdLength;
|
||||
MountPoints->MountPoints[TotalSymLinks].DeviceNameOffset = sizeof(MOUNTMGR_MOUNT_POINTS) +
|
||||
SymlinkInformation->Name.Length +
|
||||
DeviceInformation->UniqueId->UniqueIdLength +
|
||||
TotalSize;
|
||||
MountPoints->MountPoints[TotalSymLinks].DeviceNameLength = DeviceInformation->DeviceName.Length;
|
||||
|
||||
RtlCopyMemory((PWSTR)((ULONG_PTR)MountPoints + MountPoints->MountPoints[TotalSymLinks].SymbolicLinkNameOffset),
|
||||
SymlinkInformation->Name.Buffer, SymlinkInformation->Name.Length);
|
||||
RtlCopyMemory((PWSTR)((ULONG_PTR)MountPoints + MountPoints->MountPoints[TotalSymLinks].UniqueIdOffset),
|
||||
DeviceInformation->UniqueId->UniqueId, DeviceInformation->UniqueId->UniqueIdLength);
|
||||
RtlCopyMemory((PWSTR)((ULONG_PTR)MountPoints + MountPoints->MountPoints[TotalSymLinks].DeviceNameOffset),
|
||||
DeviceInformation->DeviceName.Buffer, DeviceInformation->DeviceName.Length);
|
||||
|
||||
/* Update counters */
|
||||
TotalSymLinks++;
|
||||
TotalSize += SymlinkInformation->Name.Length + DeviceInformation->UniqueId->UniqueIdLength +
|
||||
DeviceInformation->DeviceName.Length;
|
||||
}
|
||||
|
||||
if (UniqueId || SymbolicName)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
NTSTATUS
|
||||
QueryPointsFromSymbolicLinkName(IN PDEVICE_EXTENSION DeviceExtension,
|
||||
IN PUNICODE_STRING SymbolicName,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
ULONG TotalLength;
|
||||
PIO_STACK_LOCATION Stack;
|
||||
UNICODE_STRING DeviceName;
|
||||
PMOUNTMGR_MOUNT_POINTS MountPoints;
|
||||
PDEVICE_INFORMATION DeviceInformation;
|
||||
PLIST_ENTRY DeviceEntry, SymlinksEntry;
|
||||
PSYMLINK_INFORMATION SymlinkInformation;
|
||||
|
||||
/* Find device */
|
||||
Status = QueryDeviceInformation(SymbolicName, &DeviceName,
|
||||
NULL, NULL, NULL,
|
||||
NULL, NULL, NULL);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* Look for the device information */
|
||||
for (DeviceEntry = DeviceExtension->DeviceListHead.Flink;
|
||||
DeviceEntry != &(DeviceExtension->DeviceListHead);
|
||||
DeviceEntry = DeviceEntry->Flink)
|
||||
{
|
||||
DeviceInformation = CONTAINING_RECORD(DeviceEntry, DEVICE_INFORMATION, DeviceListEntry);
|
||||
|
||||
if (RtlEqualUnicodeString(&DeviceName, &(DeviceInformation->DeviceName), TRUE) == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
FreePool(DeviceName.Buffer);
|
||||
|
||||
if (DeviceEntry == &(DeviceExtension->DeviceListHead))
|
||||
{
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* Check for the link */
|
||||
for (SymlinksEntry = DeviceInformation->SymbolicLinksListHead.Flink;
|
||||
SymlinksEntry != &(DeviceInformation->SymbolicLinksListHead);
|
||||
SymlinksEntry = DeviceEntry->Flink)
|
||||
{
|
||||
SymlinkInformation = CONTAINING_RECORD(SymlinksEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
|
||||
|
||||
if (RtlEqualUnicodeString(SymbolicName, &SymlinkInformation->Name, TRUE) == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (SymlinksEntry == &(DeviceInformation->SymbolicLinksListHead))
|
||||
{
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Browse all the devices to try to find the one
|
||||
* that has the given link...
|
||||
*/
|
||||
for (DeviceEntry = DeviceExtension->DeviceListHead.Flink;
|
||||
DeviceEntry != &(DeviceExtension->DeviceListHead);
|
||||
DeviceEntry = DeviceEntry->Flink)
|
||||
{
|
||||
DeviceInformation = CONTAINING_RECORD(DeviceEntry, DEVICE_INFORMATION, DeviceListEntry);
|
||||
|
||||
for (SymlinksEntry = DeviceInformation->SymbolicLinksListHead.Flink;
|
||||
SymlinksEntry != &(DeviceInformation->SymbolicLinksListHead);
|
||||
SymlinksEntry = SymlinksEntry->Flink)
|
||||
{
|
||||
SymlinkInformation = CONTAINING_RECORD(SymlinksEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);
|
||||
|
||||
if (RtlEqualUnicodeString(SymbolicName, &SymlinkInformation->Name, TRUE) == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (SymlinksEntry != &(DeviceInformation->SymbolicLinksListHead))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Even that way we didn't find, give up! */
|
||||
if (DeviceEntry == &(DeviceExtension->DeviceListHead))
|
||||
{
|
||||
return STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get output buffer */
|
||||
Stack = IoGetNextIrpStackLocation(Irp);
|
||||
MountPoints = (PMOUNTMGR_MOUNT_POINTS)Irp->AssociatedIrp.SystemBuffer;
|
||||
|
||||
/* Compute output length */
|
||||
TotalLength = DeviceInformation->UniqueId->UniqueIdLength +
|
||||
SymlinkInformation->Name.Length + DeviceInformation->DeviceName.Length;
|
||||
|
||||
/* Give length to allow reallocation */
|
||||
MountPoints->Size = sizeof(MOUNTMGR_MOUNT_POINTS) + TotalLength;
|
||||
MountPoints->NumberOfMountPoints = 1;
|
||||
|
||||
if (MountPoints->Size > Stack->Parameters.DeviceIoControl.OutputBufferLength)
|
||||
{
|
||||
return STATUS_BUFFER_OVERFLOW;
|
||||
}
|
||||
|
||||
/* Write out data */
|
||||
MountPoints->MountPoints[0].SymbolicLinkNameOffset = sizeof(MOUNTMGR_MOUNT_POINTS);
|
||||
MountPoints->MountPoints[0].SymbolicLinkNameLength = SymlinkInformation->Name.Length;
|
||||
/* If link is online write it's unique ID, otherwise, forget about it */
|
||||
if (SymlinkInformation->Online)
|
||||
{
|
||||
MountPoints->MountPoints[0].UniqueIdOffset = sizeof(MOUNTMGR_MOUNT_POINTS) +
|
||||
SymlinkInformation->Name.Length;
|
||||
MountPoints->MountPoints[0].UniqueIdLength = DeviceInformation->UniqueId->UniqueIdLength;
|
||||
}
|
||||
else
|
||||
{
|
||||
MountPoints->MountPoints[0].UniqueIdOffset = 0;
|
||||
MountPoints->MountPoints[0].UniqueIdLength = 0;
|
||||
}
|
||||
|
||||
MountPoints->MountPoints[0].DeviceNameOffset = sizeof(MOUNTMGR_MOUNT_POINTS) +
|
||||
SymlinkInformation->Name.Length +
|
||||
DeviceInformation->UniqueId->UniqueIdLength;
|
||||
MountPoints->MountPoints[0].DeviceNameLength = DeviceInformation->DeviceName.Length;
|
||||
|
||||
RtlCopyMemory((PWSTR)((ULONG_PTR)MountPoints + MountPoints->MountPoints[0].SymbolicLinkNameOffset),
|
||||
SymlinkInformation->Name.Buffer, SymlinkInformation->Name.Length);
|
||||
|
||||
if (SymlinkInformation->Online)
|
||||
{
|
||||
RtlCopyMemory((PWSTR)((ULONG_PTR)MountPoints + MountPoints->MountPoints[0].UniqueIdOffset),
|
||||
DeviceInformation->UniqueId->UniqueId, DeviceInformation->UniqueId->UniqueIdLength);
|
||||
}
|
||||
|
||||
RtlCopyMemory((PWSTR)((ULONG_PTR)MountPoints + MountPoints->MountPoints[0].DeviceNameOffset),
|
||||
DeviceInformation->DeviceName.Buffer, DeviceInformation->DeviceName.Length);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
1004
reactos/drivers/filters/mountmgr/symlink.c
Normal file
1004
reactos/drivers/filters/mountmgr/symlink.c
Normal file
File diff suppressed because it is too large
Load diff
436
reactos/drivers/filters/mountmgr/uniqueid.c
Normal file
436
reactos/drivers/filters/mountmgr/uniqueid.c
Normal file
|
@ -0,0 +1,436 @@
|
|||
/*
|
||||
* ReactOS kernel
|
||||
* Copyright (C) 2011 ReactOS Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: drivers/filesystem/mountmgr/uniqueid.c
|
||||
* PURPOSE: Mount Manager - Unique ID
|
||||
* PROGRAMMER: Pierre Schweitzer (pierre.schweitzer@reactos.org)
|
||||
*/
|
||||
|
||||
/* INCLUDES *****************************************************************/
|
||||
|
||||
#include "mntmgr.h"
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ChangeUniqueIdRoutine(IN PWSTR ValueName,
|
||||
IN ULONG ValueType,
|
||||
IN PVOID ValueData,
|
||||
IN ULONG ValueLength,
|
||||
IN PVOID Context,
|
||||
IN PVOID EntryContext)
|
||||
{
|
||||
PMOUNTDEV_UNIQUE_ID OldUniqueId = Context;
|
||||
PMOUNTDEV_UNIQUE_ID NewUniqueId = EntryContext;
|
||||
|
||||
/* Validate parameters not to corrupt registry */
|
||||
if ((ValueType != REG_BINARY) ||
|
||||
(OldUniqueId->UniqueIdLength != ValueLength))
|
||||
{
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (RtlCompareMemory(OldUniqueId->UniqueId, ValueData, ValueLength) == ValueLength)
|
||||
{
|
||||
/* Write new data */
|
||||
RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE,
|
||||
DatabasePath,
|
||||
ValueName,
|
||||
REG_BINARY,
|
||||
NewUniqueId,
|
||||
NewUniqueId->UniqueIdLength);
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
VOID
|
||||
MountMgrUniqueIdChangeRoutine(IN PDEVICE_EXTENSION DeviceExtension,
|
||||
IN PMOUNTDEV_UNIQUE_ID OldUniqueId,
|
||||
IN PMOUNTDEV_UNIQUE_ID NewUniqueId)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
BOOLEAN ResyncNeeded;
|
||||
PUNIQUE_ID_REPLICATE DuplicateId;
|
||||
PDEVICE_INFORMATION DeviceInformation;
|
||||
RTL_QUERY_REGISTRY_TABLE QueryTable[2];
|
||||
PMOUNTDEV_UNIQUE_ID UniqueId, NewDuplicateId;
|
||||
PLIST_ENTRY ListHead, NextEntry, ReplicatedHead, NextReplicated;
|
||||
|
||||
/* Synchronise with remote databases */
|
||||
Status = WaitForRemoteDatabaseSemaphore(DeviceExtension);
|
||||
KeWaitForSingleObject(&(DeviceExtension->DeviceLock), Executive, KernelMode, FALSE, NULL);
|
||||
|
||||
RtlZeroMemory(QueryTable, sizeof(QueryTable));
|
||||
QueryTable[0].QueryRoutine = ChangeUniqueIdRoutine;
|
||||
QueryTable[0].EntryContext = NewUniqueId;
|
||||
|
||||
/* Write new data */
|
||||
RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
|
||||
DatabasePath,
|
||||
QueryTable,
|
||||
OldUniqueId,
|
||||
NULL);
|
||||
|
||||
/* Browse all the devices to find the one that
|
||||
* owns the old unique ID
|
||||
*/
|
||||
ListHead = &(DeviceExtension->DeviceListHead);
|
||||
NextEntry = ListHead->Flink;
|
||||
while (ListHead != NextEntry)
|
||||
{
|
||||
DeviceInformation = CONTAINING_RECORD(NextEntry,
|
||||
DEVICE_INFORMATION,
|
||||
DeviceListEntry);
|
||||
|
||||
if (DeviceInformation->UniqueId->UniqueIdLength == OldUniqueId->UniqueIdLength &&
|
||||
RtlCompareMemory(OldUniqueId->UniqueId,
|
||||
DeviceInformation->UniqueId->UniqueId,
|
||||
OldUniqueId->UniqueIdLength) == OldUniqueId->UniqueIdLength)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
NextEntry = NextEntry->Flink;
|
||||
}
|
||||
|
||||
/* If we didn't find any release everything and quit */
|
||||
if (ListHead == NextEntry)
|
||||
{
|
||||
KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT,
|
||||
1, FALSE);
|
||||
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
ReleaseRemoteDatabaseSemaphore(DeviceExtension);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* If lock failed, then, just update this database */
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ReconcileThisDatabaseWithMaster(DeviceExtension, DeviceInformation);
|
||||
KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT,
|
||||
1, FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Allocate new unique ID */
|
||||
UniqueId = AllocatePool(NewUniqueId->UniqueIdLength + sizeof(MOUNTDEV_UNIQUE_ID));
|
||||
if (!UniqueId)
|
||||
{
|
||||
KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT,
|
||||
1, FALSE);
|
||||
ReleaseRemoteDatabaseSemaphore(DeviceExtension);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Release old one */
|
||||
FreePool(DeviceInformation->UniqueId);
|
||||
/* And set new one */
|
||||
DeviceInformation->UniqueId = UniqueId;
|
||||
UniqueId->UniqueIdLength = NewUniqueId->UniqueIdLength;
|
||||
RtlCopyMemory(UniqueId->UniqueId, NewUniqueId->UniqueId, NewUniqueId->UniqueIdLength);
|
||||
|
||||
/* Now, check if it's required to update replicated unique IDs as well */
|
||||
ListHead = &(DeviceExtension->DeviceListHead);
|
||||
NextEntry = ListHead->Flink;
|
||||
while (ListHead != NextEntry)
|
||||
{
|
||||
DeviceInformation = CONTAINING_RECORD(NextEntry,
|
||||
DEVICE_INFORMATION,
|
||||
DeviceListEntry);
|
||||
ResyncNeeded = FALSE;
|
||||
|
||||
ReplicatedHead = &(DeviceInformation->ReplicatedUniqueIdsListHead);
|
||||
NextReplicated = ReplicatedHead->Flink;
|
||||
while (ReplicatedHead != NextReplicated)
|
||||
{
|
||||
DuplicateId = CONTAINING_RECORD(NextReplicated,
|
||||
UNIQUE_ID_REPLICATE,
|
||||
ReplicatedUniqueIdsListEntry);
|
||||
|
||||
if (DuplicateId->UniqueId->UniqueIdLength == OldUniqueId->UniqueIdLength)
|
||||
{
|
||||
if (RtlCompareMemory(DuplicateId->UniqueId->UniqueId,
|
||||
OldUniqueId->UniqueId,
|
||||
OldUniqueId->UniqueIdLength) == OldUniqueId->UniqueIdLength)
|
||||
{
|
||||
/* It was our old unique ID */
|
||||
NewDuplicateId = AllocatePool(NewUniqueId->UniqueIdLength + sizeof(MOUNTDEV_UNIQUE_ID));
|
||||
if (NewDuplicateId)
|
||||
{
|
||||
/* Update it */
|
||||
ResyncNeeded = TRUE;
|
||||
FreePool(DuplicateId->UniqueId);
|
||||
|
||||
DuplicateId->UniqueId = NewDuplicateId;
|
||||
DuplicateId->UniqueId->UniqueIdLength = NewUniqueId->UniqueIdLength;
|
||||
RtlCopyMemory(NewDuplicateId->UniqueId, NewUniqueId->UniqueId, NewUniqueId->UniqueIdLength);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NextReplicated = NextReplicated->Flink;
|
||||
}
|
||||
|
||||
/* If resync is required on this device, do it */
|
||||
if (ResyncNeeded)
|
||||
{
|
||||
ChangeRemoteDatabaseUniqueId(DeviceInformation, OldUniqueId, NewUniqueId);
|
||||
}
|
||||
|
||||
NextEntry = NextEntry->Flink;
|
||||
}
|
||||
|
||||
KeReleaseSemaphore(&(DeviceExtension->DeviceLock), IO_NO_INCREMENT, 1, FALSE);
|
||||
ReleaseRemoteDatabaseSemaphore(DeviceExtension);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
BOOLEAN
|
||||
IsUniqueIdPresent(IN PDEVICE_EXTENSION DeviceExtension,
|
||||
IN PDATABASE_ENTRY DatabaseEntry)
|
||||
{
|
||||
PLIST_ENTRY NextEntry;
|
||||
PDEVICE_INFORMATION DeviceInformation;
|
||||
|
||||
/* If no device, no unique ID (O'rly?!)
|
||||
* ./)/).
|
||||
* (°-°)
|
||||
* (___) ORLY?
|
||||
* " "
|
||||
*/
|
||||
if (IsListEmpty(&(DeviceExtension->DeviceListHead)))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Now we know that we have devices, find the one */
|
||||
for (NextEntry = DeviceExtension->DeviceListHead.Flink;
|
||||
NextEntry != &(DeviceExtension->DeviceListHead);
|
||||
NextEntry = NextEntry->Flink)
|
||||
{
|
||||
DeviceInformation = CONTAINING_RECORD(NextEntry,
|
||||
DEVICE_INFORMATION,
|
||||
DeviceListEntry);
|
||||
|
||||
if (DeviceInformation->UniqueId->UniqueIdLength != DatabaseEntry->UniqueIdLength)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/* It's matching! */
|
||||
if (RtlCompareMemory((PVOID)((ULONG_PTR)DatabaseEntry + DatabaseEntry->UniqueIdOffset),
|
||||
DeviceInformation->UniqueId->UniqueId,
|
||||
DatabaseEntry->UniqueIdLength) == DatabaseEntry->UniqueIdLength)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* No luck... */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
VOID
|
||||
CreateNoDriveLetterEntry(IN PMOUNTDEV_UNIQUE_ID UniqueId)
|
||||
{
|
||||
UUID Guid;
|
||||
PWCHAR String;
|
||||
UNICODE_STRING GuidString;
|
||||
|
||||
/* Entry with no drive letter are made that way:
|
||||
* Instead of having a path with the letter,
|
||||
* you have GUID with the unique ID.
|
||||
*/
|
||||
if (!NT_SUCCESS(ExUuidCreate(&Guid)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Convert to string */
|
||||
if (!NT_SUCCESS(RtlStringFromGUID(&Guid, &GuidString)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* No letter entries must start with #, so allocate a proper string */
|
||||
String = AllocatePool(GuidString.Length + 2 * sizeof(WCHAR));
|
||||
if (!String)
|
||||
{
|
||||
ExFreePoolWithTag(GuidString.Buffer, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Write the complete string */
|
||||
String[0] = L'#';
|
||||
RtlCopyMemory(String + 1, GuidString.Buffer, GuidString.Length);
|
||||
String[GuidString.Length / sizeof(WCHAR)] = UNICODE_NULL;
|
||||
|
||||
/* Don't need that one anymore */
|
||||
ExFreePoolWithTag(GuidString.Buffer, 0);
|
||||
|
||||
/* Write the entry */
|
||||
RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE,
|
||||
DatabasePath,
|
||||
String,
|
||||
REG_BINARY,
|
||||
UniqueId->UniqueId,
|
||||
UniqueId->UniqueIdLength);
|
||||
|
||||
FreePool(String);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CheckForNoDriveLetterEntry(IN PWSTR ValueName,
|
||||
IN ULONG ValueType,
|
||||
IN PVOID ValueData,
|
||||
IN ULONG ValueLength,
|
||||
IN PVOID Context,
|
||||
IN PVOID EntryContext)
|
||||
{
|
||||
PBOOLEAN EntryPresent = EntryContext;
|
||||
PMOUNTDEV_UNIQUE_ID UniqueId = Context;
|
||||
|
||||
/* Check if matches no drive letter entry */
|
||||
if (ValueName[0] != L'#' || ValueType != REG_BINARY ||
|
||||
UniqueId->UniqueIdLength != ValueLength)
|
||||
{
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* Compare unique ID */
|
||||
if (RtlCompareMemory(UniqueId->UniqueId, ValueData, ValueLength) == ValueLength)
|
||||
{
|
||||
*EntryPresent = TRUE;
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
BOOLEAN
|
||||
HasNoDriveLetterEntry(IN PMOUNTDEV_UNIQUE_ID UniqueId)
|
||||
{
|
||||
BOOLEAN EntryPresent = FALSE;
|
||||
RTL_QUERY_REGISTRY_TABLE QueryTable[2];
|
||||
|
||||
RtlZeroMemory(QueryTable, sizeof(QueryTable));
|
||||
QueryTable[0].QueryRoutine = CheckForNoDriveLetterEntry;
|
||||
QueryTable[0].EntryContext = &EntryPresent;
|
||||
|
||||
RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
|
||||
DatabasePath,
|
||||
QueryTable,
|
||||
UniqueId,
|
||||
NULL);
|
||||
|
||||
return EntryPresent;
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
VOID
|
||||
UpdateReplicatedUniqueIds(IN PDEVICE_INFORMATION DeviceInformation, IN PDATABASE_ENTRY DatabaseEntry)
|
||||
{
|
||||
PLIST_ENTRY NextEntry;
|
||||
PUNIQUE_ID_REPLICATE ReplicatedUniqueId, NewEntry;
|
||||
|
||||
/* Browse all the device replicated unique IDs */
|
||||
for (NextEntry = DeviceInformation->ReplicatedUniqueIdsListHead.Flink;
|
||||
NextEntry != &(DeviceInformation->ReplicatedUniqueIdsListHead);
|
||||
NextEntry = NextEntry->Flink)
|
||||
{
|
||||
ReplicatedUniqueId = CONTAINING_RECORD(NextEntry,
|
||||
UNIQUE_ID_REPLICATE,
|
||||
ReplicatedUniqueIdsListEntry);
|
||||
|
||||
if (ReplicatedUniqueId->UniqueId->UniqueIdLength != DatabaseEntry->UniqueIdLength)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/* If we find the UniqueId to update, break */
|
||||
if (RtlCompareMemory(ReplicatedUniqueId->UniqueId->UniqueId,
|
||||
(PVOID)((ULONG_PTR)DatabaseEntry + DatabaseEntry->UniqueIdOffset),
|
||||
ReplicatedUniqueId->UniqueId->UniqueIdLength) == ReplicatedUniqueId->UniqueId->UniqueIdLength)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* We found the unique ID, no need to continue */
|
||||
if (NextEntry != &(DeviceInformation->ReplicatedUniqueIdsListHead))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Allocate a new entry for unique ID */
|
||||
NewEntry = AllocatePool(sizeof(UNIQUE_ID_REPLICATE));
|
||||
if (!NewEntry)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Allocate the unique ID */
|
||||
NewEntry->UniqueId = AllocatePool(DatabaseEntry->UniqueIdLength + sizeof(MOUNTDEV_UNIQUE_ID));
|
||||
if (!NewEntry->UniqueId)
|
||||
{
|
||||
FreePool(NewEntry);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Copy */
|
||||
NewEntry->UniqueId->UniqueIdLength = DatabaseEntry->UniqueIdLength;
|
||||
RtlCopyMemory(NewEntry->UniqueId->UniqueId,
|
||||
(PVOID)((ULONG_PTR)DatabaseEntry + DatabaseEntry->UniqueIdOffset),
|
||||
DatabaseEntry->UniqueIdLength);
|
||||
/* And insert into replicated unique IDs list */
|
||||
InsertTailList(&DeviceInformation->ReplicatedUniqueIdsListHead, &NewEntry->ReplicatedUniqueIdsListEntry);
|
||||
|
||||
return;
|
||||
}
|
5
reactos/drivers/hid/CMakeLists.txt
Normal file
5
reactos/drivers/hid/CMakeLists.txt
Normal file
|
@ -0,0 +1,5 @@
|
|||
add_subdirectory(hidclass)
|
||||
add_subdirectory(hidparse)
|
||||
add_subdirectory(hidusb)
|
||||
add_subdirectory(kbdhid)
|
||||
add_subdirectory(mouhid)
|
19
reactos/drivers/hid/directory.rbuild
Normal file
19
reactos/drivers/hid/directory.rbuild
Normal file
|
@ -0,0 +1,19 @@
|
|||
<?xml version="1.0"?>
|
||||
<!DOCTYPE group SYSTEM "../../tools/rbuild/project.dtd">
|
||||
<group xmlns:xi="http://www.w3.org/2001/XInclude">
|
||||
<directory name="hidclass">
|
||||
<xi:include href="hidclass/hidclass.rbuild" />
|
||||
</directory>
|
||||
<directory name="hidparse">
|
||||
<xi:include href="hidparse/hidparse.rbuild" />
|
||||
</directory>
|
||||
<directory name="hidusb">
|
||||
<xi:include href="hidusb/hidusb.rbuild" />
|
||||
</directory>
|
||||
<directory name="kbdhid">
|
||||
<xi:include href="kbdhid/kbdhid.rbuild" />
|
||||
</directory>
|
||||
<directory name="mouhid">
|
||||
<xi:include href="mouhid/mouhid.rbuild" />
|
||||
</directory>
|
||||
</group>
|
21
reactos/drivers/hid/hidclass/CMakeLists.txt
Normal file
21
reactos/drivers/hid/hidclass/CMakeLists.txt
Normal file
|
@ -0,0 +1,21 @@
|
|||
|
||||
spec2def(hidclass.sys hidclass.spec)
|
||||
|
||||
list(APPEND SOURCE
|
||||
fdo.c
|
||||
hidclass.c
|
||||
hidclass.rc
|
||||
pdo.c
|
||||
${CMAKE_CURRENT_BINARY_DIR}/hidclass.def)
|
||||
|
||||
add_library(hidclass SHARED ${SOURCE})
|
||||
|
||||
set_entrypoint(hidclass 0)
|
||||
set_subsystem(hidclass native)
|
||||
set_target_properties(hidclass PROPERTIES SUFFIX ".sys")
|
||||
|
||||
|
||||
add_importlibs(hidclass ntoskrnl hidparse hal)
|
||||
add_importlib_target(hidclass.spec)
|
||||
|
||||
add_cd_file(TARGET hidclass DESTINATION reactos/system32/drivers NO_CAB FOR all)
|
598
reactos/drivers/hid/hidclass/fdo.c
Normal file
598
reactos/drivers/hid/hidclass/fdo.c
Normal file
|
@ -0,0 +1,598 @@
|
|||
/*
|
||||
* PROJECT: ReactOS Universal Serial Bus Human Interface Device Driver
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* FILE: drivers/hid/hidclass/fdo.c
|
||||
* PURPOSE: HID Class Driver
|
||||
* PROGRAMMERS:
|
||||
* Michael Martin (michael.martin@reactos.org)
|
||||
* Johannes Anderwald (johannes.anderwald@reactos.org)
|
||||
*/
|
||||
#include "precomp.h"
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
HidClassFDO_QueryCapabilitiesCompletionRoutine(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp,
|
||||
IN PVOID Context)
|
||||
{
|
||||
//
|
||||
// set event
|
||||
//
|
||||
KeSetEvent((PRKEVENT)Context, 0, FALSE);
|
||||
|
||||
//
|
||||
// completion is done in the HidClassFDO_QueryCapabilities routine
|
||||
//
|
||||
return STATUS_MORE_PROCESSING_REQUIRED;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
HidClassFDO_QueryCapabilities(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN OUT PDEVICE_CAPABILITIES Capabilities)
|
||||
{
|
||||
PIRP Irp;
|
||||
KEVENT Event;
|
||||
NTSTATUS Status;
|
||||
PIO_STACK_LOCATION IoStack;
|
||||
PHIDCLASS_FDO_EXTENSION FDODeviceExtension;
|
||||
|
||||
//
|
||||
// get device extension
|
||||
//
|
||||
FDODeviceExtension = (PHIDCLASS_FDO_EXTENSION)DeviceObject->DeviceExtension;
|
||||
ASSERT(FDODeviceExtension->Common.IsFDO);
|
||||
|
||||
//
|
||||
// init event
|
||||
//
|
||||
KeInitializeEvent(&Event, NotificationEvent, FALSE);
|
||||
|
||||
//
|
||||
// now allocte the irp
|
||||
//
|
||||
Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
|
||||
if (!Irp)
|
||||
{
|
||||
//
|
||||
// no memory
|
||||
//
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
//
|
||||
// get next stack location
|
||||
//
|
||||
IoStack = IoGetNextIrpStackLocation(Irp);
|
||||
|
||||
//
|
||||
// init stack location
|
||||
//
|
||||
IoStack->MajorFunction = IRP_MJ_PNP;
|
||||
IoStack->MinorFunction = IRP_MN_QUERY_CAPABILITIES;
|
||||
IoStack->Parameters.DeviceCapabilities.Capabilities = Capabilities;
|
||||
|
||||
//
|
||||
// set completion routine
|
||||
//
|
||||
IoSetCompletionRoutine(Irp, HidClassFDO_QueryCapabilitiesCompletionRoutine, (PVOID)&Event, TRUE, TRUE, TRUE);
|
||||
|
||||
//
|
||||
// init capabilities
|
||||
//
|
||||
RtlZeroMemory(Capabilities, sizeof(DEVICE_CAPABILITIES));
|
||||
Capabilities->Size = sizeof(DEVICE_CAPABILITIES);
|
||||
Capabilities->Version = 1; // FIXME hardcoded constant
|
||||
Capabilities->Address = MAXULONG;
|
||||
Capabilities->UINumber = MAXULONG;
|
||||
|
||||
//
|
||||
// pnp irps have default completion code
|
||||
//
|
||||
Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
|
||||
|
||||
//
|
||||
// call lower device
|
||||
//
|
||||
Status = IoCallDriver(FDODeviceExtension->Common.HidDeviceExtension.NextDeviceObject, Irp);
|
||||
if (Status == STATUS_PENDING)
|
||||
{
|
||||
//
|
||||
// wait for completion
|
||||
//
|
||||
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
|
||||
}
|
||||
|
||||
//
|
||||
// get status
|
||||
//
|
||||
Status = Irp->IoStatus.Status;
|
||||
|
||||
//
|
||||
// complete request
|
||||
//
|
||||
IoFreeIrp(Irp);
|
||||
|
||||
//
|
||||
// done
|
||||
//
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
HidClassFDO_DispatchRequestSynchronousCompletion(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp,
|
||||
IN PVOID Context)
|
||||
{
|
||||
//
|
||||
// signal event
|
||||
//
|
||||
KeSetEvent((PRKEVENT)Context, 0, FALSE);
|
||||
|
||||
//
|
||||
// done
|
||||
//
|
||||
return STATUS_MORE_PROCESSING_REQUIRED;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
HidClassFDO_DispatchRequestSynchronous(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
KEVENT Event;
|
||||
PHIDCLASS_COMMON_DEVICE_EXTENSION CommonDeviceExtension;
|
||||
NTSTATUS Status;
|
||||
PIO_STACK_LOCATION IoStack;
|
||||
|
||||
//
|
||||
// init event
|
||||
//
|
||||
KeInitializeEvent(&Event, NotificationEvent, FALSE);
|
||||
|
||||
//
|
||||
// get device extension
|
||||
//
|
||||
CommonDeviceExtension = (PHIDCLASS_COMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
|
||||
//
|
||||
// set completion routine
|
||||
//
|
||||
IoSetCompletionRoutine(Irp, HidClassFDO_DispatchRequestSynchronousCompletion, &Event, TRUE, TRUE, TRUE);
|
||||
|
||||
ASSERT(Irp->CurrentLocation > 0);
|
||||
//
|
||||
// create stack location
|
||||
//
|
||||
IoSetNextIrpStackLocation(Irp);
|
||||
|
||||
//
|
||||
// get next stack location
|
||||
//
|
||||
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||
|
||||
//
|
||||
// store device object
|
||||
//
|
||||
IoStack->DeviceObject = DeviceObject;
|
||||
|
||||
//
|
||||
// call driver
|
||||
//
|
||||
DPRINT("IoStack MajorFunction %x MinorFunction %x\n", IoStack->MajorFunction, IoStack->MinorFunction);
|
||||
Status = CommonDeviceExtension->DriverExtension->MajorFunction[IoStack->MajorFunction](DeviceObject, Irp);
|
||||
|
||||
//
|
||||
// wait for the request to finish
|
||||
//
|
||||
if (Status == STATUS_PENDING)
|
||||
{
|
||||
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
|
||||
|
||||
//
|
||||
// update status
|
||||
//
|
||||
Status = Irp->IoStatus.Status;
|
||||
}
|
||||
|
||||
//
|
||||
// done
|
||||
//
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
HidClassFDO_GetDescriptors(
|
||||
IN PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
PHIDCLASS_FDO_EXTENSION FDODeviceExtension;
|
||||
PIRP Irp;
|
||||
PIO_STACK_LOCATION IoStack;
|
||||
NTSTATUS Status;
|
||||
|
||||
//
|
||||
// get device extension
|
||||
//
|
||||
FDODeviceExtension = (PHIDCLASS_FDO_EXTENSION)DeviceObject->DeviceExtension;
|
||||
ASSERT(FDODeviceExtension->Common.IsFDO);
|
||||
|
||||
//
|
||||
// lets allocate irp
|
||||
//
|
||||
Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
|
||||
if (!Irp)
|
||||
{
|
||||
//
|
||||
// no memory
|
||||
//
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
//
|
||||
// get stack location
|
||||
//
|
||||
IoStack = IoGetNextIrpStackLocation(Irp);
|
||||
|
||||
//
|
||||
// init stack location
|
||||
//
|
||||
IoStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
|
||||
IoStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_HID_GET_DEVICE_DESCRIPTOR;
|
||||
IoStack->Parameters.DeviceIoControl.OutputBufferLength = sizeof(HID_DESCRIPTOR);
|
||||
IoStack->Parameters.DeviceIoControl.InputBufferLength = 0;
|
||||
IoStack->Parameters.DeviceIoControl.Type3InputBuffer = NULL;
|
||||
Irp->UserBuffer = &FDODeviceExtension->HidDescriptor;
|
||||
|
||||
//
|
||||
// send request
|
||||
//
|
||||
Status = HidClassFDO_DispatchRequestSynchronous(DeviceObject, Irp);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
//
|
||||
// failed to get device descriptor
|
||||
//
|
||||
DPRINT1("[HIDCLASS] IOCTL_HID_GET_DEVICE_DESCRIPTOR failed with %x\n", Status);
|
||||
IoFreeIrp(Irp);
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// lets get device attributes
|
||||
//
|
||||
IoStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_HID_GET_DEVICE_ATTRIBUTES;
|
||||
IoStack->Parameters.DeviceIoControl.OutputBufferLength = sizeof(HID_DEVICE_ATTRIBUTES);
|
||||
Irp->UserBuffer = &FDODeviceExtension->Common.Attributes;
|
||||
|
||||
//
|
||||
// send request
|
||||
//
|
||||
Status = HidClassFDO_DispatchRequestSynchronous(DeviceObject, Irp);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
//
|
||||
// failed to get device descriptor
|
||||
//
|
||||
DPRINT1("[HIDCLASS] IOCTL_HID_GET_DEVICE_ATTRIBUTES failed with %x\n", Status);
|
||||
IoFreeIrp(Irp);
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// sanity checks
|
||||
//
|
||||
ASSERT(FDODeviceExtension->HidDescriptor.bLength == sizeof(HID_DESCRIPTOR));
|
||||
ASSERT(FDODeviceExtension->HidDescriptor.bNumDescriptors > 0);
|
||||
ASSERT(FDODeviceExtension->HidDescriptor.DescriptorList[0].wReportLength > 0);
|
||||
ASSERT(FDODeviceExtension->HidDescriptor.DescriptorList[0].bReportType == HID_REPORT_DESCRIPTOR_TYPE);
|
||||
|
||||
|
||||
//
|
||||
// now allocate space for the report descriptor
|
||||
//
|
||||
FDODeviceExtension->ReportDescriptor = (PUCHAR)ExAllocatePool(NonPagedPool, FDODeviceExtension->HidDescriptor.DescriptorList[0].wReportLength);
|
||||
if (!FDODeviceExtension->ReportDescriptor)
|
||||
{
|
||||
//
|
||||
// not enough memory
|
||||
//
|
||||
IoFreeIrp(Irp);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
//
|
||||
// init stack location
|
||||
//
|
||||
IoStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_HID_GET_REPORT_DESCRIPTOR;
|
||||
IoStack->Parameters.DeviceIoControl.OutputBufferLength = FDODeviceExtension->HidDescriptor.DescriptorList[0].wReportLength;
|
||||
Irp->UserBuffer = FDODeviceExtension->ReportDescriptor;
|
||||
|
||||
//
|
||||
// send request
|
||||
//
|
||||
Status = HidClassFDO_DispatchRequestSynchronous(DeviceObject, Irp);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
//
|
||||
// failed to get device descriptor
|
||||
//
|
||||
DPRINT1("[HIDCLASS] IOCTL_HID_GET_REPORT_DESCRIPTOR failed with %x\n", Status);
|
||||
IoFreeIrp(Irp);
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// completed successfully
|
||||
//
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
HidClassFDO_StartDevice(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PHIDCLASS_FDO_EXTENSION FDODeviceExtension;
|
||||
|
||||
//
|
||||
// get device extension
|
||||
//
|
||||
FDODeviceExtension = (PHIDCLASS_FDO_EXTENSION)DeviceObject->DeviceExtension;
|
||||
ASSERT(FDODeviceExtension->Common.IsFDO);
|
||||
|
||||
//
|
||||
// query capabilities
|
||||
//
|
||||
Status = HidClassFDO_QueryCapabilities(DeviceObject, &FDODeviceExtension->Capabilities);
|
||||
ASSERT(Status == STATUS_SUCCESS);
|
||||
|
||||
//
|
||||
// lets start the lower device too
|
||||
//
|
||||
IoSkipCurrentIrpStackLocation(Irp);
|
||||
Status = HidClassFDO_DispatchRequestSynchronous(DeviceObject, Irp);
|
||||
ASSERT(Status == STATUS_SUCCESS);
|
||||
|
||||
//
|
||||
// lets get the descriptors
|
||||
//
|
||||
Status = HidClassFDO_GetDescriptors(DeviceObject);
|
||||
ASSERT(Status == STATUS_SUCCESS);
|
||||
|
||||
//
|
||||
// now get the the collection description
|
||||
//
|
||||
Status = HidP_GetCollectionDescription(FDODeviceExtension->ReportDescriptor, FDODeviceExtension->HidDescriptor.DescriptorList[0].wReportLength, NonPagedPool, &FDODeviceExtension->Common.DeviceDescription);
|
||||
ASSERT(Status == STATUS_SUCCESS);
|
||||
|
||||
//
|
||||
// complete request
|
||||
//
|
||||
Irp->IoStatus.Status = Status;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
HidClassFDO_RemoveDevice(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
PHIDCLASS_FDO_EXTENSION FDODeviceExtension = DeviceObject->DeviceExtension;
|
||||
NTSTATUS Status;
|
||||
|
||||
/* Pass the IRP down */
|
||||
IoSkipCurrentIrpStackLocation(Irp);
|
||||
Status = IoCallDriver(FDODeviceExtension->Common.HidDeviceExtension.NextDeviceObject, Irp);
|
||||
|
||||
/* Now teardown our portion of the device stack */
|
||||
IoDetachDevice(FDODeviceExtension->Common.HidDeviceExtension.NextDeviceObject);
|
||||
IoDeleteDevice(DeviceObject);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
HidClassFDO_CopyDeviceRelations(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
OUT PDEVICE_RELATIONS *OutRelations)
|
||||
{
|
||||
PDEVICE_RELATIONS DeviceRelations;
|
||||
PHIDCLASS_FDO_EXTENSION FDODeviceExtension;
|
||||
ULONG Index;
|
||||
|
||||
//
|
||||
// get device extension
|
||||
//
|
||||
FDODeviceExtension = (PHIDCLASS_FDO_EXTENSION)DeviceObject->DeviceExtension;
|
||||
ASSERT(FDODeviceExtension->Common.IsFDO);
|
||||
|
||||
//
|
||||
// allocate result
|
||||
//
|
||||
DeviceRelations = (PDEVICE_RELATIONS)ExAllocatePool(NonPagedPool, sizeof(DEVICE_RELATIONS) + (FDODeviceExtension->DeviceRelations->Count-1) * sizeof(PDEVICE_OBJECT));
|
||||
if (!DeviceRelations)
|
||||
{
|
||||
//
|
||||
// no memory
|
||||
//
|
||||
*OutRelations = NULL;
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
//
|
||||
// copy device objects
|
||||
//
|
||||
for(Index = 0; Index < FDODeviceExtension->DeviceRelations->Count; Index++)
|
||||
{
|
||||
//
|
||||
// reference pdo
|
||||
//
|
||||
ObReferenceObject(FDODeviceExtension->DeviceRelations->Objects[Index]);
|
||||
|
||||
//
|
||||
// store object
|
||||
//
|
||||
DeviceRelations->Objects[Index] = FDODeviceExtension->DeviceRelations->Objects[Index];
|
||||
}
|
||||
|
||||
//
|
||||
// set object count
|
||||
//
|
||||
DeviceRelations->Count = FDODeviceExtension->DeviceRelations->Count;
|
||||
|
||||
//
|
||||
// store result
|
||||
//
|
||||
*OutRelations = DeviceRelations;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
HidClassFDO_DeviceRelations(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
PHIDCLASS_FDO_EXTENSION FDODeviceExtension;
|
||||
PIO_STACK_LOCATION IoStack;
|
||||
NTSTATUS Status;
|
||||
PDEVICE_RELATIONS DeviceRelations;
|
||||
|
||||
//
|
||||
// get device extension
|
||||
//
|
||||
FDODeviceExtension = (PHIDCLASS_FDO_EXTENSION)DeviceObject->DeviceExtension;
|
||||
ASSERT(FDODeviceExtension->Common.IsFDO);
|
||||
|
||||
//
|
||||
// get current irp stack location
|
||||
//
|
||||
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||
|
||||
//
|
||||
// check relations type
|
||||
//
|
||||
if (IoStack->Parameters.QueryDeviceRelations.Type != BusRelations)
|
||||
{
|
||||
//
|
||||
// only bus relations are handled
|
||||
//
|
||||
IoSkipCurrentIrpStackLocation(Irp);
|
||||
return IoCallDriver(FDODeviceExtension->Common.HidDeviceExtension.NextDeviceObject, Irp);
|
||||
}
|
||||
|
||||
if (FDODeviceExtension->DeviceRelations == NULL)
|
||||
{
|
||||
//
|
||||
// time to create the pdos
|
||||
//
|
||||
Status = HidClassPDO_CreatePDO(DeviceObject, &FDODeviceExtension->DeviceRelations);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
//
|
||||
// failed
|
||||
//
|
||||
DPRINT1("[HIDCLASS] HidClassPDO_CreatePDO failed with %x\n", Status);
|
||||
Irp->IoStatus.Status = Status;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
//
|
||||
// sanity check
|
||||
//
|
||||
ASSERT(FDODeviceExtension->DeviceRelations->Count > 0);
|
||||
}
|
||||
|
||||
//
|
||||
// now copy device relations
|
||||
//
|
||||
Status = HidClassFDO_CopyDeviceRelations(DeviceObject, &DeviceRelations);
|
||||
//
|
||||
// store result
|
||||
//
|
||||
Irp->IoStatus.Status = Status;
|
||||
Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
|
||||
|
||||
//
|
||||
// complete request
|
||||
//
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
HidClassFDO_PnP(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
PIO_STACK_LOCATION IoStack;
|
||||
PHIDCLASS_FDO_EXTENSION FDODeviceExtension;
|
||||
|
||||
//
|
||||
// get device extension
|
||||
//
|
||||
FDODeviceExtension = (PHIDCLASS_FDO_EXTENSION)DeviceObject->DeviceExtension;
|
||||
ASSERT(FDODeviceExtension->Common.IsFDO);
|
||||
|
||||
//
|
||||
// get current irp stack location
|
||||
//
|
||||
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||
switch(IoStack->MinorFunction)
|
||||
{
|
||||
case IRP_MN_START_DEVICE:
|
||||
{
|
||||
return HidClassFDO_StartDevice(DeviceObject, Irp);
|
||||
}
|
||||
case IRP_MN_REMOVE_DEVICE:
|
||||
{
|
||||
return HidClassFDO_RemoveDevice(DeviceObject, Irp);
|
||||
}
|
||||
case IRP_MN_QUERY_REMOVE_DEVICE:
|
||||
case IRP_MN_QUERY_STOP_DEVICE:
|
||||
{
|
||||
//
|
||||
// set status to succes
|
||||
//
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
|
||||
//
|
||||
// forward to lower device
|
||||
//
|
||||
IoSkipCurrentIrpStackLocation(Irp);
|
||||
return IoCallDriver(FDODeviceExtension->Common.HidDeviceExtension.NextDeviceObject, Irp);
|
||||
}
|
||||
case IRP_MN_CANCEL_REMOVE_DEVICE:
|
||||
case IRP_MN_CANCEL_STOP_DEVICE:
|
||||
{
|
||||
//
|
||||
// set status to succes
|
||||
//
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
|
||||
//
|
||||
// forward to lower device
|
||||
//
|
||||
IoSkipCurrentIrpStackLocation(Irp);
|
||||
return IoCallDriver(FDODeviceExtension->Common.HidDeviceExtension.NextDeviceObject, Irp);
|
||||
}
|
||||
case IRP_MN_QUERY_DEVICE_RELATIONS:
|
||||
{
|
||||
return HidClassFDO_DeviceRelations(DeviceObject, Irp);
|
||||
}
|
||||
default:
|
||||
{
|
||||
//
|
||||
// dispatch to lower device
|
||||
//
|
||||
IoSkipCurrentIrpStackLocation(Irp);
|
||||
return IoCallDriver(FDODeviceExtension->Common.HidDeviceExtension.NextDeviceObject, Irp);
|
||||
}
|
||||
}
|
||||
}
|
1032
reactos/drivers/hid/hidclass/hidclass.c
Normal file
1032
reactos/drivers/hid/hidclass/hidclass.c
Normal file
File diff suppressed because it is too large
Load diff
13
reactos/drivers/hid/hidclass/hidclass.rbuild
Normal file
13
reactos/drivers/hid/hidclass/hidclass.rbuild
Normal file
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0"?>
|
||||
<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
|
||||
<module name="hidclass" type="kernelmodedriver" entrypoint="0" installbase="system32/drivers" installname="hidclass.sys">
|
||||
<importlibrary definition="hidclass.spec" />
|
||||
<bootstrap installbase="$(CDOUTPUT)/system32/drivers" />
|
||||
<library>ntoskrnl</library>
|
||||
<library>hidparse</library>
|
||||
<library>hal</library>
|
||||
<file>fdo.c</file>
|
||||
<file>hidclass.c</file>
|
||||
<file>hidclass.rc</file>
|
||||
<file>pdo.c</file>
|
||||
</module>
|
5
reactos/drivers/hid/hidclass/hidclass.rc
Normal file
5
reactos/drivers/hid/hidclass/hidclass.rc
Normal file
|
@ -0,0 +1,5 @@
|
|||
#define REACTOS_VERSION_DLL
|
||||
#define REACTOS_STR_FILE_DESCRIPTION "USB HID Bus Driver\0"
|
||||
#define REACTOS_STR_INTERNAL_NAME "hidclass\0"
|
||||
#define REACTOS_STR_ORIGINAL_FILENAME "hidclass.sys\0"
|
||||
#include <reactos/version.rc>
|
4
reactos/drivers/hid/hidclass/hidclass.spec
Normal file
4
reactos/drivers/hid/hidclass/hidclass.spec
Normal file
|
@ -0,0 +1,4 @@
|
|||
@ stdcall -private DllInitialize(long)
|
||||
@ stdcall -private DllUnload()
|
||||
@ stdcall HidRegisterMinidriver(ptr)
|
||||
|
759
reactos/drivers/hid/hidclass/pdo.c
Normal file
759
reactos/drivers/hid/hidclass/pdo.c
Normal file
|
@ -0,0 +1,759 @@
|
|||
/*
|
||||
* PROJECT: ReactOS Universal Serial Bus Human Interface Device Driver
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* FILE: drivers/hid/hidclass/fdo.c
|
||||
* PURPOSE: HID Class Driver
|
||||
* PROGRAMMERS:
|
||||
* Michael Martin (michael.martin@reactos.org)
|
||||
* Johannes Anderwald (johannes.anderwald@reactos.org)
|
||||
*/
|
||||
#include "precomp.h"
|
||||
|
||||
PHIDP_COLLECTION_DESC
|
||||
HidClassPDO_GetCollectionDescription(
|
||||
PHIDP_DEVICE_DESC DeviceDescription,
|
||||
ULONG CollectionNumber)
|
||||
{
|
||||
ULONG Index;
|
||||
|
||||
for(Index = 0; Index < DeviceDescription->CollectionDescLength; Index++)
|
||||
{
|
||||
if (DeviceDescription->CollectionDesc[Index].CollectionNumber == CollectionNumber)
|
||||
{
|
||||
//
|
||||
// found collection
|
||||
//
|
||||
return &DeviceDescription->CollectionDesc[Index];
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// failed to find collection
|
||||
//
|
||||
DPRINT1("[HIDCLASS] GetCollectionDescription CollectionNumber %x not found\n", CollectionNumber);
|
||||
ASSERT(FALSE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PHIDP_REPORT_IDS
|
||||
HidClassPDO_GetReportDescription(
|
||||
PHIDP_DEVICE_DESC DeviceDescription,
|
||||
ULONG CollectionNumber)
|
||||
{
|
||||
ULONG Index;
|
||||
|
||||
for(Index = 0; Index < DeviceDescription->ReportIDsLength; Index++)
|
||||
{
|
||||
if (DeviceDescription->ReportIDs[Index].CollectionNumber == CollectionNumber)
|
||||
{
|
||||
//
|
||||
// found collection
|
||||
//
|
||||
return &DeviceDescription->ReportIDs[Index];
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// failed to find collection
|
||||
//
|
||||
DPRINT1("[HIDCLASS] GetReportDescription CollectionNumber %x not found\n", CollectionNumber);
|
||||
ASSERT(FALSE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
HidClassPDO_HandleQueryDeviceId(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
LPWSTR Buffer;
|
||||
LPWSTR NewBuffer, Ptr;
|
||||
ULONG Length;
|
||||
|
||||
//
|
||||
// copy current stack location
|
||||
//
|
||||
IoCopyCurrentIrpStackLocationToNext(Irp);
|
||||
|
||||
//
|
||||
// call mini-driver
|
||||
//
|
||||
Status = HidClassFDO_DispatchRequestSynchronous(DeviceObject, Irp);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
//
|
||||
// failed
|
||||
//
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// get buffer
|
||||
//
|
||||
Buffer = (LPWSTR)Irp->IoStatus.Information;
|
||||
Length = wcslen(Buffer);
|
||||
|
||||
//
|
||||
// allocate new buffer
|
||||
//
|
||||
NewBuffer = (LPWSTR)ExAllocatePool(NonPagedPool, (Length + 1) * sizeof(WCHAR));
|
||||
if (!NewBuffer)
|
||||
{
|
||||
//
|
||||
// failed to allocate buffer
|
||||
//
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
//
|
||||
// replace bus
|
||||
//
|
||||
wcscpy(NewBuffer, L"HID\\");
|
||||
|
||||
//
|
||||
// get offset to first '\\'
|
||||
//
|
||||
Ptr = wcschr(Buffer, L'\\');
|
||||
if (Ptr)
|
||||
{
|
||||
//
|
||||
// append result
|
||||
//
|
||||
wcscat(NewBuffer, Ptr + 1);
|
||||
}
|
||||
|
||||
//
|
||||
// free old buffer
|
||||
//
|
||||
ExFreePool(Buffer);
|
||||
|
||||
//
|
||||
// store result
|
||||
//
|
||||
DPRINT("NewBuffer %S\n", NewBuffer);
|
||||
Irp->IoStatus.Information = (ULONG_PTR)NewBuffer;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
HidClassPDO_HandleQueryHardwareId(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PHIDCLASS_PDO_DEVICE_EXTENSION PDODeviceExtension;
|
||||
WCHAR Buffer[200];
|
||||
ULONG Offset = 0;
|
||||
LPWSTR Ptr;
|
||||
PHIDP_COLLECTION_DESC CollectionDescription;
|
||||
|
||||
//
|
||||
// get device extension
|
||||
//
|
||||
PDODeviceExtension = (PHIDCLASS_PDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
ASSERT(PDODeviceExtension->Common.IsFDO == FALSE);
|
||||
|
||||
//
|
||||
// copy current stack location
|
||||
//
|
||||
IoCopyCurrentIrpStackLocationToNext(Irp);
|
||||
|
||||
//
|
||||
// call mini-driver
|
||||
//
|
||||
Status = HidClassFDO_DispatchRequestSynchronous(DeviceObject, Irp);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
//
|
||||
// failed
|
||||
//
|
||||
return Status;
|
||||
}
|
||||
|
||||
if (PDODeviceExtension->Common.DeviceDescription.CollectionDescLength > 1)
|
||||
{
|
||||
//
|
||||
// multi-tlc device
|
||||
//
|
||||
Offset = swprintf(&Buffer[Offset], L"HID\\Vid_%04x&Pid_%04x&Rev_%04x&Col%02x", PDODeviceExtension->Common.Attributes.VendorID, PDODeviceExtension->Common.Attributes.ProductID, PDODeviceExtension->Common.Attributes.VersionNumber, PDODeviceExtension->CollectionNumber) + 1;
|
||||
Offset += swprintf(&Buffer[Offset], L"HID\\Vid_%04x&Pid_%04x&Col%02x", PDODeviceExtension->Common.Attributes.VendorID, PDODeviceExtension->Common.Attributes.ProductID, PDODeviceExtension->CollectionNumber) + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// single tlc device
|
||||
//
|
||||
Offset = swprintf(&Buffer[Offset], L"HID\\Vid_%04x&Pid_%04x&Rev_%04x", PDODeviceExtension->Common.Attributes.VendorID, PDODeviceExtension->Common.Attributes.ProductID, PDODeviceExtension->Common.Attributes.VersionNumber) + 1;
|
||||
Offset += swprintf(&Buffer[Offset], L"HID\\Vid_%04x&Pid_%04x", PDODeviceExtension->Common.Attributes.VendorID, PDODeviceExtension->Common.Attributes.ProductID) + 1;
|
||||
}
|
||||
|
||||
//
|
||||
// get collection description
|
||||
//
|
||||
CollectionDescription = HidClassPDO_GetCollectionDescription(&PDODeviceExtension->Common.DeviceDescription, PDODeviceExtension->CollectionNumber);
|
||||
ASSERT(CollectionDescription);
|
||||
|
||||
if (CollectionDescription->UsagePage == HID_USAGE_PAGE_GENERIC)
|
||||
{
|
||||
switch(CollectionDescription->Usage)
|
||||
{
|
||||
case HID_USAGE_GENERIC_POINTER:
|
||||
case HID_USAGE_GENERIC_MOUSE:
|
||||
//
|
||||
// Pointer / Mouse
|
||||
//
|
||||
Offset += swprintf(&Buffer[Offset], L"HID_DEVICE_SYSTEM_MOUSE") + 1;
|
||||
break;
|
||||
case HID_USAGE_GENERIC_GAMEPAD:
|
||||
case HID_USAGE_GENERIC_JOYSTICK:
|
||||
//
|
||||
// Joystick / Gamepad
|
||||
//
|
||||
Offset += swprintf(&Buffer[Offset], L"HID_DEVICE_SYSTEM_GAME") + 1;
|
||||
break;
|
||||
case HID_USAGE_GENERIC_KEYBOARD:
|
||||
case HID_USAGE_GENERIC_KEYPAD:
|
||||
//
|
||||
// Keyboard / Keypad
|
||||
//
|
||||
Offset += swprintf(&Buffer[Offset], L"HID_DEVICE_SYSTEM_KEYBOARD") + 1;
|
||||
break;
|
||||
case HID_USAGE_GENERIC_SYSTEM_CTL:
|
||||
//
|
||||
// System Control
|
||||
//
|
||||
Offset += swprintf(&Buffer[Offset], L"HID_DEVICE_SYSTEM_CONTROL") + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (CollectionDescription->UsagePage == HID_USAGE_PAGE_CONSUMER && CollectionDescription->Usage == HID_USAGE_CONSUMERCTRL)
|
||||
{
|
||||
//
|
||||
// Consumer Audio Control
|
||||
//
|
||||
Offset += swprintf(&Buffer[Offset], L"HID_DEVICE_SYSTEM_CONSUMER") + 1;
|
||||
}
|
||||
|
||||
//
|
||||
// add HID_DEVICE_UP:0001_U:0002'
|
||||
//
|
||||
Offset += swprintf(&Buffer[Offset], L"HID_DEVICE_UP:%04x_U:%04x", CollectionDescription->UsagePage, CollectionDescription->Usage) + 1;
|
||||
|
||||
//
|
||||
// add HID
|
||||
//
|
||||
Offset +=swprintf(&Buffer[Offset], L"HID_DEVICE") + 1;
|
||||
|
||||
//
|
||||
// free old buffer
|
||||
//
|
||||
ExFreePool((PVOID)Irp->IoStatus.Information);
|
||||
|
||||
//
|
||||
// allocate buffer
|
||||
//
|
||||
Ptr = (LPWSTR)ExAllocatePool(NonPagedPool, (Offset +1)* sizeof(WCHAR));
|
||||
if (!Ptr)
|
||||
{
|
||||
//
|
||||
// no memory
|
||||
//
|
||||
Irp->IoStatus.Information = 0;
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
//
|
||||
// copy buffer
|
||||
//
|
||||
RtlCopyMemory(Ptr, Buffer, Offset * sizeof(WCHAR));
|
||||
Ptr[Offset] = UNICODE_NULL;
|
||||
|
||||
//
|
||||
// store result
|
||||
//
|
||||
Irp->IoStatus.Information = (ULONG_PTR)Ptr;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
HidClassPDO_HandleQueryInstanceId(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
LPWSTR Buffer;
|
||||
PHIDCLASS_PDO_DEVICE_EXTENSION PDODeviceExtension;
|
||||
|
||||
//
|
||||
// get device extension
|
||||
//
|
||||
PDODeviceExtension = (PHIDCLASS_PDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
ASSERT(PDODeviceExtension->Common.IsFDO == FALSE);
|
||||
|
||||
|
||||
//
|
||||
// allocate buffer
|
||||
//
|
||||
Buffer = ExAllocatePool(NonPagedPool, 5 * sizeof(WCHAR));
|
||||
if (!Buffer)
|
||||
{
|
||||
//
|
||||
// failed
|
||||
//
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
//
|
||||
// write device id
|
||||
//
|
||||
swprintf(Buffer, L"%04x", PDODeviceExtension->CollectionNumber);
|
||||
Irp->IoStatus.Information = (ULONG_PTR)Buffer;
|
||||
|
||||
//
|
||||
// done
|
||||
//
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
HidClassPDO_HandleQueryCompatibleId(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
LPWSTR Buffer;
|
||||
|
||||
Buffer = (LPWSTR)ExAllocatePool(NonPagedPool, 2 * sizeof(WCHAR));
|
||||
if (!Buffer)
|
||||
{
|
||||
//
|
||||
// no memory
|
||||
//
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
//
|
||||
// zero buffer
|
||||
//
|
||||
Buffer[0] = 0;
|
||||
Buffer[1] = 0;
|
||||
|
||||
//
|
||||
// store result
|
||||
//
|
||||
Irp->IoStatus.Information = (ULONG_PTR)Buffer;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
HidClassPDO_PnP(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
PHIDCLASS_PDO_DEVICE_EXTENSION PDODeviceExtension;
|
||||
PIO_STACK_LOCATION IoStack;
|
||||
NTSTATUS Status;
|
||||
PPNP_BUS_INFORMATION BusInformation;
|
||||
PDEVICE_RELATIONS DeviceRelation;
|
||||
ULONG Index, bFound;
|
||||
|
||||
//
|
||||
// get device extension
|
||||
//
|
||||
PDODeviceExtension = (PHIDCLASS_PDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
ASSERT(PDODeviceExtension->Common.IsFDO == FALSE);
|
||||
|
||||
//
|
||||
// get current irp stack location
|
||||
//
|
||||
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||
|
||||
//
|
||||
// handle request
|
||||
//
|
||||
switch(IoStack->MinorFunction)
|
||||
{
|
||||
case IRP_MN_QUERY_ID:
|
||||
{
|
||||
if (IoStack->Parameters.QueryId.IdType == BusQueryDeviceID)
|
||||
{
|
||||
//
|
||||
// handle query device id
|
||||
//
|
||||
Status = HidClassPDO_HandleQueryDeviceId(DeviceObject, Irp);
|
||||
break;
|
||||
}
|
||||
else if (IoStack->Parameters.QueryId.IdType == BusQueryHardwareIDs)
|
||||
{
|
||||
//
|
||||
// handle instance id
|
||||
//
|
||||
Status = HidClassPDO_HandleQueryHardwareId(DeviceObject, Irp);
|
||||
break;
|
||||
}
|
||||
else if (IoStack->Parameters.QueryId.IdType == BusQueryInstanceID)
|
||||
{
|
||||
//
|
||||
// handle instance id
|
||||
//
|
||||
Status = HidClassPDO_HandleQueryInstanceId(DeviceObject, Irp);
|
||||
break;
|
||||
}
|
||||
else if (IoStack->Parameters.QueryId.IdType == BusQueryCompatibleIDs)
|
||||
{
|
||||
//
|
||||
// handle instance id
|
||||
//
|
||||
Status = HidClassPDO_HandleQueryCompatibleId(DeviceObject, Irp);
|
||||
break;
|
||||
}
|
||||
|
||||
DPRINT1("[HIDCLASS]: IRP_MN_QUERY_ID IdType %x unimplemented\n", IoStack->Parameters.QueryId.IdType);
|
||||
Status = STATUS_NOT_SUPPORTED;
|
||||
Irp->IoStatus.Information = 0;
|
||||
break;
|
||||
}
|
||||
case IRP_MN_QUERY_CAPABILITIES:
|
||||
{
|
||||
if (IoStack->Parameters.DeviceCapabilities.Capabilities == NULL)
|
||||
{
|
||||
//
|
||||
// invalid request
|
||||
//
|
||||
Status = STATUS_DEVICE_CONFIGURATION_ERROR;
|
||||
}
|
||||
|
||||
//
|
||||
// copy capabilities
|
||||
//
|
||||
RtlCopyMemory(IoStack->Parameters.DeviceCapabilities.Capabilities, &PDODeviceExtension->Capabilities, sizeof(DEVICE_CAPABILITIES));
|
||||
Status = STATUS_SUCCESS;
|
||||
break;
|
||||
}
|
||||
case IRP_MN_QUERY_BUS_INFORMATION:
|
||||
{
|
||||
//
|
||||
//
|
||||
//
|
||||
BusInformation = (PPNP_BUS_INFORMATION)ExAllocatePool(NonPagedPool, sizeof(PNP_BUS_INFORMATION));
|
||||
|
||||
//
|
||||
// fill in result
|
||||
//
|
||||
RtlCopyMemory(&BusInformation->BusTypeGuid, &GUID_BUS_TYPE_HID, sizeof(GUID));
|
||||
BusInformation->LegacyBusType = PNPBus;
|
||||
BusInformation->BusNumber = 0; //FIXME
|
||||
|
||||
//
|
||||
// store result
|
||||
//
|
||||
Irp->IoStatus.Information = (ULONG_PTR)BusInformation;
|
||||
Status = STATUS_SUCCESS;
|
||||
break;
|
||||
}
|
||||
case IRP_MN_QUERY_PNP_DEVICE_STATE:
|
||||
{
|
||||
//
|
||||
// FIXME set flags when driver fails / disabled
|
||||
//
|
||||
Status = STATUS_SUCCESS;
|
||||
break;
|
||||
}
|
||||
case IRP_MN_QUERY_DEVICE_RELATIONS:
|
||||
{
|
||||
//
|
||||
// only target relations are supported
|
||||
//
|
||||
if (IoStack->Parameters.QueryDeviceRelations.Type != TargetDeviceRelation)
|
||||
{
|
||||
//
|
||||
// not supported
|
||||
//
|
||||
Status = Irp->IoStatus.Status;
|
||||
break;
|
||||
}
|
||||
|
||||
//
|
||||
// allocate device relations
|
||||
//
|
||||
DeviceRelation = (PDEVICE_RELATIONS)ExAllocatePool(NonPagedPool, sizeof(DEVICE_RELATIONS));
|
||||
if (!DeviceRelation)
|
||||
{
|
||||
//
|
||||
// no memory
|
||||
//
|
||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
break;
|
||||
}
|
||||
|
||||
//
|
||||
// init device relation
|
||||
//
|
||||
DeviceRelation->Count = 1;
|
||||
DeviceRelation->Objects[0] = DeviceObject;
|
||||
ObReferenceObject(DeviceRelation->Objects[0]);
|
||||
|
||||
//
|
||||
// store result
|
||||
//
|
||||
Irp->IoStatus.Information = (ULONG_PTR)DeviceRelation;
|
||||
Status = STATUS_SUCCESS;
|
||||
break;
|
||||
}
|
||||
case IRP_MN_START_DEVICE:
|
||||
{
|
||||
//
|
||||
// FIXME: support polled devices
|
||||
//
|
||||
ASSERT(PDODeviceExtension->Common.DriverExtension->DevicesArePolled == FALSE);
|
||||
|
||||
//
|
||||
// now register the device interface
|
||||
//
|
||||
Status = IoRegisterDeviceInterface(PDODeviceExtension->Common.HidDeviceExtension.PhysicalDeviceObject, &GUID_DEVINTERFACE_HID, NULL, &PDODeviceExtension->DeviceInterface);
|
||||
DPRINT("[HIDCLASS] IoRegisterDeviceInterfaceState Status %x\n", Status);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
//
|
||||
// enable device interface
|
||||
//
|
||||
Status = IoSetDeviceInterfaceState(&PDODeviceExtension->DeviceInterface, TRUE);
|
||||
DPRINT("[HIDCLASS] IoSetDeviceInterFaceState %x\n", Status);
|
||||
}
|
||||
|
||||
//
|
||||
// done
|
||||
//
|
||||
Status = STATUS_SUCCESS;
|
||||
break;
|
||||
}
|
||||
case IRP_MN_REMOVE_DEVICE:
|
||||
{
|
||||
/* Disable the device interface */
|
||||
if (PDODeviceExtension->DeviceInterface.Length != 0)
|
||||
IoSetDeviceInterfaceState(&PDODeviceExtension->DeviceInterface, FALSE);
|
||||
|
||||
//
|
||||
// remove us from the fdo's pdo list
|
||||
//
|
||||
bFound = FALSE;
|
||||
for(Index = 0; Index < PDODeviceExtension->FDODeviceExtension->DeviceRelations->Count; Index++)
|
||||
{
|
||||
if (PDODeviceExtension->FDODeviceExtension->DeviceRelations->Objects[Index] == DeviceObject)
|
||||
{
|
||||
//
|
||||
// remove us
|
||||
//
|
||||
bFound = TRUE;
|
||||
PDODeviceExtension->FDODeviceExtension->DeviceRelations->Objects[Index] = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Complete the IRP */
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
|
||||
if (bFound)
|
||||
{
|
||||
/* Delete our device object*/
|
||||
IoDeleteDevice(DeviceObject);
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
case IRP_MN_QUERY_INTERFACE:
|
||||
{
|
||||
DPRINT1("[HIDCLASS] PDO IRP_MN_QUERY_INTERFACE not implemented\n");
|
||||
ASSERT(FALSE);
|
||||
|
||||
//
|
||||
// do nothing
|
||||
//
|
||||
Status = Irp->IoStatus.Status;
|
||||
break;
|
||||
}
|
||||
case IRP_MN_QUERY_REMOVE_DEVICE:
|
||||
case IRP_MN_CANCEL_STOP_DEVICE:
|
||||
case IRP_MN_QUERY_STOP_DEVICE:
|
||||
case IRP_MN_CANCEL_REMOVE_DEVICE:
|
||||
{
|
||||
//
|
||||
// no/op
|
||||
//
|
||||
Status = STATUS_SUCCESS;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
//
|
||||
// do nothing
|
||||
//
|
||||
Status = Irp->IoStatus.Status;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// complete request
|
||||
//
|
||||
if (Status != STATUS_PENDING)
|
||||
{
|
||||
//
|
||||
// store result
|
||||
//
|
||||
Irp->IoStatus.Status = Status;
|
||||
|
||||
//
|
||||
// complete request
|
||||
//
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
}
|
||||
|
||||
//
|
||||
// done processing
|
||||
//
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
HidClassPDO_CreatePDO(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
OUT PDEVICE_RELATIONS *OutDeviceRelations)
|
||||
{
|
||||
PHIDCLASS_FDO_EXTENSION FDODeviceExtension;
|
||||
NTSTATUS Status;
|
||||
PDEVICE_OBJECT PDODeviceObject;
|
||||
PHIDCLASS_PDO_DEVICE_EXTENSION PDODeviceExtension;
|
||||
ULONG Index;
|
||||
PDEVICE_RELATIONS DeviceRelations;
|
||||
ULONG Length;
|
||||
|
||||
//
|
||||
// get device extension
|
||||
//
|
||||
FDODeviceExtension = (PHIDCLASS_FDO_EXTENSION)DeviceObject->DeviceExtension;
|
||||
ASSERT(FDODeviceExtension->Common.IsFDO);
|
||||
|
||||
//
|
||||
// first allocate device relations
|
||||
//
|
||||
Length = sizeof(DEVICE_RELATIONS) + sizeof(PDEVICE_OBJECT) * FDODeviceExtension->Common.DeviceDescription.CollectionDescLength;
|
||||
DeviceRelations = (PDEVICE_RELATIONS)ExAllocatePool(NonPagedPool, Length);
|
||||
if (!DeviceRelations)
|
||||
{
|
||||
//
|
||||
// no memory
|
||||
//
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
//
|
||||
// zero device relations
|
||||
//
|
||||
RtlZeroMemory(DeviceRelations, Length);
|
||||
|
||||
//
|
||||
// lets create a PDO for top level collection
|
||||
//
|
||||
Index = 0;
|
||||
do
|
||||
{
|
||||
//
|
||||
// lets create the device object
|
||||
//
|
||||
Status = IoCreateDevice(FDODeviceExtension->Common.DriverExtension->DriverObject, sizeof(HIDCLASS_PDO_DEVICE_EXTENSION), NULL, FILE_DEVICE_UNKNOWN, FILE_AUTOGENERATED_DEVICE_NAME, FALSE, &PDODeviceObject);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
//
|
||||
// failed to create device
|
||||
//
|
||||
DPRINT1("[HIDCLASS] Failed to create PDO %x\n", Status);
|
||||
break;
|
||||
}
|
||||
|
||||
//
|
||||
// patch stack size
|
||||
//
|
||||
PDODeviceObject->StackSize = DeviceObject->StackSize + 1;
|
||||
|
||||
//
|
||||
// get device extension
|
||||
//
|
||||
PDODeviceExtension = (PHIDCLASS_PDO_DEVICE_EXTENSION)PDODeviceObject->DeviceExtension;
|
||||
|
||||
//
|
||||
// init device extension
|
||||
//
|
||||
PDODeviceExtension->Common.HidDeviceExtension.MiniDeviceExtension = FDODeviceExtension->Common.HidDeviceExtension.MiniDeviceExtension;
|
||||
PDODeviceExtension->Common.HidDeviceExtension.NextDeviceObject = FDODeviceExtension->Common.HidDeviceExtension.NextDeviceObject;
|
||||
PDODeviceExtension->Common.HidDeviceExtension.PhysicalDeviceObject = FDODeviceExtension->Common.HidDeviceExtension.PhysicalDeviceObject;
|
||||
PDODeviceExtension->Common.IsFDO = FALSE;
|
||||
PDODeviceExtension->FDODeviceExtension = FDODeviceExtension;
|
||||
PDODeviceExtension->FDODeviceObject = DeviceObject;
|
||||
PDODeviceExtension->Common.DriverExtension = FDODeviceExtension->Common.DriverExtension;
|
||||
PDODeviceExtension->CollectionNumber = FDODeviceExtension->Common.DeviceDescription.CollectionDesc[Index].CollectionNumber;
|
||||
|
||||
//
|
||||
// copy device data
|
||||
//
|
||||
RtlCopyMemory(&PDODeviceExtension->Common.Attributes, &FDODeviceExtension->Common.Attributes, sizeof(HID_DEVICE_ATTRIBUTES));
|
||||
RtlCopyMemory(&PDODeviceExtension->Common.DeviceDescription, &FDODeviceExtension->Common.DeviceDescription, sizeof(HIDP_DEVICE_DESC));
|
||||
RtlCopyMemory(&PDODeviceExtension->Capabilities, &FDODeviceExtension->Capabilities, sizeof(DEVICE_CAPABILITIES));
|
||||
|
||||
//
|
||||
// set device flags
|
||||
//
|
||||
PDODeviceObject->Flags |= DO_MAP_IO_BUFFER;
|
||||
|
||||
//
|
||||
// device is initialized
|
||||
//
|
||||
PDODeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
|
||||
|
||||
//
|
||||
// store device object in device relations
|
||||
//
|
||||
DeviceRelations->Objects[Index] = PDODeviceObject;
|
||||
DeviceRelations->Count++;
|
||||
|
||||
//
|
||||
// move to next
|
||||
//
|
||||
Index++;
|
||||
|
||||
}while(Index < FDODeviceExtension->Common.DeviceDescription.CollectionDescLength);
|
||||
|
||||
|
||||
//
|
||||
// check if creating succeeded
|
||||
//
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
//
|
||||
// failed
|
||||
//
|
||||
for(Index = 0; Index < DeviceRelations->Count; Index++)
|
||||
{
|
||||
//
|
||||
// delete device
|
||||
//
|
||||
IoDeleteDevice(DeviceRelations->Objects[Index]);
|
||||
}
|
||||
|
||||
//
|
||||
// free device relations
|
||||
//
|
||||
ExFreePool(DeviceRelations);
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// store device relations
|
||||
//
|
||||
*OutDeviceRelations = DeviceRelations;
|
||||
|
||||
//
|
||||
// done
|
||||
//
|
||||
return STATUS_SUCCESS;
|
||||
}
|
202
reactos/drivers/hid/hidclass/precomp.h
Normal file
202
reactos/drivers/hid/hidclass/precomp.h
Normal file
|
@ -0,0 +1,202 @@
|
|||
#pragma once
|
||||
|
||||
#define _HIDPI_NO_FUNCTION_MACROS_
|
||||
#define NDEBUG
|
||||
#include <ntddk.h>
|
||||
#include <initguid.h>
|
||||
#include <hidport.h>
|
||||
#include <hidpddi.h>
|
||||
#include <stdio.h>
|
||||
#include <wdmguid.h>
|
||||
#include <debug.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
PDRIVER_OBJECT DriverObject;
|
||||
ULONG DeviceExtensionSize;
|
||||
BOOLEAN DevicesArePolled;
|
||||
PDRIVER_DISPATCH MajorFunction[IRP_MJ_MAXIMUM_FUNCTION + 1];
|
||||
PDRIVER_ADD_DEVICE AddDevice;
|
||||
PDRIVER_UNLOAD DriverUnload;
|
||||
KSPIN_LOCK Lock;
|
||||
|
||||
}HIDCLASS_DRIVER_EXTENSION, *PHIDCLASS_DRIVER_EXTENSION;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
//
|
||||
// hid device extension
|
||||
//
|
||||
HID_DEVICE_EXTENSION HidDeviceExtension;
|
||||
|
||||
//
|
||||
// if it is a pdo
|
||||
//
|
||||
BOOLEAN IsFDO;
|
||||
|
||||
//
|
||||
// driver extension
|
||||
//
|
||||
PHIDCLASS_DRIVER_EXTENSION DriverExtension;
|
||||
|
||||
//
|
||||
// device description
|
||||
//
|
||||
HIDP_DEVICE_DESC DeviceDescription;
|
||||
|
||||
//
|
||||
// hid attributes
|
||||
//
|
||||
HID_DEVICE_ATTRIBUTES Attributes;
|
||||
|
||||
}HIDCLASS_COMMON_DEVICE_EXTENSION, *PHIDCLASS_COMMON_DEVICE_EXTENSION;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
//
|
||||
// parts shared by fdo and pdo
|
||||
//
|
||||
HIDCLASS_COMMON_DEVICE_EXTENSION Common;
|
||||
|
||||
//
|
||||
// device capabilities
|
||||
//
|
||||
DEVICE_CAPABILITIES Capabilities;
|
||||
|
||||
//
|
||||
// hid descriptor
|
||||
//
|
||||
HID_DESCRIPTOR HidDescriptor;
|
||||
|
||||
//
|
||||
// report descriptor
|
||||
//
|
||||
PUCHAR ReportDescriptor;
|
||||
|
||||
//
|
||||
// device relations
|
||||
//
|
||||
PDEVICE_RELATIONS DeviceRelations;
|
||||
|
||||
}HIDCLASS_FDO_EXTENSION, *PHIDCLASS_FDO_EXTENSION;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
//
|
||||
// parts shared by fdo and pdo
|
||||
//
|
||||
HIDCLASS_COMMON_DEVICE_EXTENSION Common;
|
||||
|
||||
//
|
||||
// device capabilities
|
||||
//
|
||||
DEVICE_CAPABILITIES Capabilities;
|
||||
|
||||
//
|
||||
// collection index
|
||||
//
|
||||
ULONG CollectionNumber;
|
||||
|
||||
//
|
||||
// device interface
|
||||
//
|
||||
UNICODE_STRING DeviceInterface;
|
||||
|
||||
//
|
||||
// FDO device object
|
||||
//
|
||||
PDEVICE_OBJECT FDODeviceObject;
|
||||
|
||||
//
|
||||
// fdo device extension
|
||||
//
|
||||
PHIDCLASS_FDO_EXTENSION FDODeviceExtension;
|
||||
|
||||
}HIDCLASS_PDO_DEVICE_EXTENSION, *PHIDCLASS_PDO_DEVICE_EXTENSION;
|
||||
|
||||
typedef struct __HIDCLASS_FILEOP_CONTEXT__
|
||||
{
|
||||
//
|
||||
// device extension
|
||||
//
|
||||
PHIDCLASS_PDO_DEVICE_EXTENSION DeviceExtension;
|
||||
|
||||
//
|
||||
// spin lock
|
||||
//
|
||||
KSPIN_LOCK Lock;
|
||||
|
||||
//
|
||||
// read irp pending list
|
||||
//
|
||||
LIST_ENTRY ReadPendingIrpListHead;
|
||||
|
||||
//
|
||||
// completed irp list
|
||||
//
|
||||
LIST_ENTRY IrpCompletedListHead;
|
||||
|
||||
}HIDCLASS_FILEOP_CONTEXT, *PHIDCLASS_FILEOP_CONTEXT;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
//
|
||||
// original request
|
||||
//
|
||||
PIRP OriginalIrp;
|
||||
|
||||
//
|
||||
// file op
|
||||
//
|
||||
PHIDCLASS_FILEOP_CONTEXT FileOp;
|
||||
|
||||
//
|
||||
// buffer for reading report
|
||||
//
|
||||
PVOID InputReportBuffer;
|
||||
|
||||
//
|
||||
// buffer length
|
||||
//
|
||||
ULONG InputReportBufferLength;
|
||||
|
||||
//
|
||||
// work item
|
||||
//
|
||||
PIO_WORKITEM CompletionWorkItem;
|
||||
|
||||
}HIDCLASS_IRP_CONTEXT, *PHIDCLASS_IRP_CONTEXT;
|
||||
|
||||
/* fdo.c */
|
||||
NTSTATUS
|
||||
HidClassFDO_PnP(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp);
|
||||
|
||||
NTSTATUS
|
||||
HidClassFDO_DispatchRequestSynchronous(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp);
|
||||
|
||||
/* pdo.c */
|
||||
NTSTATUS
|
||||
HidClassPDO_CreatePDO(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
OUT PDEVICE_RELATIONS *OutDeviceRelations);
|
||||
|
||||
NTSTATUS
|
||||
HidClassPDO_PnP(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp);
|
||||
|
||||
PHIDP_COLLECTION_DESC
|
||||
HidClassPDO_GetCollectionDescription(
|
||||
PHIDP_DEVICE_DESC DeviceDescription,
|
||||
ULONG CollectionNumber);
|
||||
|
||||
PHIDP_REPORT_IDS
|
||||
HidClassPDO_GetReportDescription(
|
||||
PHIDP_DEVICE_DESC DeviceDescription,
|
||||
ULONG CollectionNumber);
|
||||
|
||||
/* eof */
|
18
reactos/drivers/hid/hidparse/CMakeLists.txt
Normal file
18
reactos/drivers/hid/hidparse/CMakeLists.txt
Normal file
|
@ -0,0 +1,18 @@
|
|||
|
||||
spec2def(hidparse.sys hidparse.spec)
|
||||
add_definitions(-DDEBUG_MODE)
|
||||
|
||||
include_directories(
|
||||
${REACTOS_SOURCE_DIR}/ntoskrnl/include
|
||||
${REACTOS_SOURCE_DIR}/lib/drivers/hidparser)
|
||||
|
||||
|
||||
add_library(hidparse SHARED hidparse.c hidparse.rc ${CMAKE_CURRENT_BINARY_DIR}/hidparse.def)
|
||||
|
||||
set_module_type(hidparse kernelmodedriver)
|
||||
add_importlibs(hidparse ntoskrnl)
|
||||
add_importlib_target(hidparse.spec)
|
||||
|
||||
target_link_libraries(hidparse hidparser)
|
||||
|
||||
add_cd_file(TARGET hidparse DESTINATION reactos/system32/drivers NO_CAB FOR all)
|
645
reactos/drivers/hid/hidparse/hidparse.c
Normal file
645
reactos/drivers/hid/hidparse/hidparse.c
Normal file
|
@ -0,0 +1,645 @@
|
|||
/*
|
||||
* PROJECT: ReactOS Universal Serial Bus Bulk Enhanced Host Controller Interface
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* FILE: drivers/usb/hidparse/hidparse.c
|
||||
* PURPOSE: HID Parser
|
||||
* PROGRAMMERS:
|
||||
* Michael Martin (michael.martin@reactos.org)
|
||||
* Johannes Anderwald (johannes.anderwald@reactos.org)
|
||||
*/
|
||||
|
||||
#include "hidparse.h"
|
||||
|
||||
PVOID
|
||||
NTAPI
|
||||
AllocFunction(
|
||||
IN ULONG ItemSize)
|
||||
{
|
||||
PVOID Item = ExAllocatePool(NonPagedPool, ItemSize);
|
||||
if (Item)
|
||||
{
|
||||
//
|
||||
// zero item
|
||||
//
|
||||
RtlZeroMemory(Item, ItemSize);
|
||||
}
|
||||
|
||||
//
|
||||
// done
|
||||
//
|
||||
return Item;
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
FreeFunction(
|
||||
IN PVOID Item)
|
||||
{
|
||||
//
|
||||
// free item
|
||||
//
|
||||
ExFreePool(Item);
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
ZeroFunction(
|
||||
IN PVOID Item,
|
||||
IN ULONG ItemSize)
|
||||
{
|
||||
//
|
||||
// zero item
|
||||
//
|
||||
RtlZeroMemory(Item, ItemSize);
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
CopyFunction(
|
||||
IN PVOID Target,
|
||||
IN PVOID Source,
|
||||
IN ULONG Length)
|
||||
{
|
||||
//
|
||||
// copy item
|
||||
//
|
||||
RtlCopyMemory(Target, Source, Length);
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
DebugFunction(
|
||||
IN LPCSTR FormatStr, ...)
|
||||
{
|
||||
|
||||
va_list args;
|
||||
unsigned int i;
|
||||
char printbuffer[1024];
|
||||
|
||||
va_start(args, FormatStr);
|
||||
i = vsprintf(printbuffer, FormatStr, args);
|
||||
va_end(args);
|
||||
|
||||
DbgPrint(printbuffer);
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
HidP_FreeCollectionDescription (
|
||||
IN PHIDP_DEVICE_DESC DeviceDescription)
|
||||
{
|
||||
HID_PARSER Parser;
|
||||
|
||||
//
|
||||
// init parser
|
||||
//
|
||||
HidParser_InitParser(AllocFunction, FreeFunction, ZeroFunction, CopyFunction, DebugFunction, &Parser);
|
||||
|
||||
//
|
||||
// free collection
|
||||
//
|
||||
HidParser_FreeCollectionDescription(&Parser, DeviceDescription);
|
||||
}
|
||||
|
||||
|
||||
HIDAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
HidP_GetCaps(
|
||||
IN PHIDP_PREPARSED_DATA PreparsedData,
|
||||
OUT PHIDP_CAPS Capabilities)
|
||||
{
|
||||
HID_PARSER Parser;
|
||||
|
||||
//
|
||||
// init parser
|
||||
//
|
||||
HidParser_InitParser(AllocFunction, FreeFunction, ZeroFunction, CopyFunction, DebugFunction, &Parser);
|
||||
|
||||
//
|
||||
// get caps
|
||||
//
|
||||
return HidParser_GetCaps(&Parser, PreparsedData, Capabilities);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
HidP_GetCollectionDescription(
|
||||
IN PHIDP_REPORT_DESCRIPTOR ReportDesc,
|
||||
IN ULONG DescLength,
|
||||
IN POOL_TYPE PoolType,
|
||||
OUT PHIDP_DEVICE_DESC DeviceDescription)
|
||||
{
|
||||
HID_PARSER Parser;
|
||||
|
||||
//
|
||||
// init parser
|
||||
//
|
||||
HidParser_InitParser(AllocFunction, FreeFunction, ZeroFunction, CopyFunction, DebugFunction, &Parser);
|
||||
|
||||
//
|
||||
// get description;
|
||||
//
|
||||
return HidParser_GetCollectionDescription(&Parser, ReportDesc, DescLength, PoolType, DeviceDescription);
|
||||
}
|
||||
|
||||
HIDAPI
|
||||
ULONG
|
||||
NTAPI
|
||||
HidP_MaxUsageListLength(
|
||||
IN HIDP_REPORT_TYPE ReportType,
|
||||
IN USAGE UsagePage OPTIONAL,
|
||||
IN PHIDP_PREPARSED_DATA PreparsedData)
|
||||
{
|
||||
HID_PARSER Parser;
|
||||
|
||||
//
|
||||
// sanity check
|
||||
//
|
||||
ASSERT(ReportType == HidP_Input || ReportType == HidP_Output || ReportType == HidP_Feature);
|
||||
|
||||
//
|
||||
// init parser
|
||||
//
|
||||
HidParser_InitParser(AllocFunction, FreeFunction, ZeroFunction, CopyFunction, DebugFunction, &Parser);
|
||||
|
||||
|
||||
//
|
||||
// get usage length
|
||||
//
|
||||
return HidParser_MaxUsageListLength(&Parser, PreparsedData, ReportType, UsagePage);
|
||||
}
|
||||
|
||||
HIDAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
HidP_GetSpecificValueCaps(
|
||||
IN HIDP_REPORT_TYPE ReportType,
|
||||
IN USAGE UsagePage,
|
||||
IN USHORT LinkCollection,
|
||||
IN USAGE Usage,
|
||||
OUT PHIDP_VALUE_CAPS ValueCaps,
|
||||
IN OUT PULONG ValueCapsLength,
|
||||
IN PHIDP_PREPARSED_DATA PreparsedData)
|
||||
{
|
||||
HID_PARSER Parser;
|
||||
|
||||
//
|
||||
// sanity check
|
||||
//
|
||||
ASSERT(ReportType == HidP_Input || ReportType == HidP_Output || ReportType == HidP_Feature);
|
||||
|
||||
//
|
||||
// init parser
|
||||
//
|
||||
HidParser_InitParser(AllocFunction, FreeFunction, ZeroFunction, CopyFunction, DebugFunction, &Parser);
|
||||
|
||||
//
|
||||
// get value caps
|
||||
//
|
||||
return HidParser_GetSpecificValueCaps(&Parser, PreparsedData, ReportType, UsagePage, LinkCollection, Usage, ValueCaps, ValueCapsLength);
|
||||
}
|
||||
|
||||
HIDAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
HidP_GetUsages(
|
||||
IN HIDP_REPORT_TYPE ReportType,
|
||||
IN USAGE UsagePage,
|
||||
IN USHORT LinkCollection OPTIONAL,
|
||||
OUT USAGE *UsageList,
|
||||
IN OUT ULONG *UsageLength,
|
||||
IN PHIDP_PREPARSED_DATA PreparsedData,
|
||||
IN PCHAR Report,
|
||||
IN ULONG ReportLength)
|
||||
{
|
||||
HID_PARSER Parser;
|
||||
|
||||
//
|
||||
// sanity check
|
||||
//
|
||||
ASSERT(ReportType == HidP_Input || ReportType == HidP_Output || ReportType == HidP_Feature);
|
||||
|
||||
//
|
||||
// init parser
|
||||
//
|
||||
HidParser_InitParser(AllocFunction, FreeFunction, ZeroFunction, CopyFunction, DebugFunction, &Parser);
|
||||
|
||||
//
|
||||
// get usages
|
||||
//
|
||||
return HidParser_GetUsages(&Parser, PreparsedData, ReportType, UsagePage, LinkCollection, UsageList, UsageLength, Report, ReportLength);
|
||||
}
|
||||
|
||||
|
||||
#undef HidP_GetButtonCaps
|
||||
|
||||
HIDAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
HidP_UsageListDifference(
|
||||
IN PUSAGE PreviousUsageList,
|
||||
IN PUSAGE CurrentUsageList,
|
||||
OUT PUSAGE BreakUsageList,
|
||||
OUT PUSAGE MakeUsageList,
|
||||
IN ULONG UsageListLength)
|
||||
{
|
||||
return HidParser_UsageListDifference(PreviousUsageList, CurrentUsageList, BreakUsageList, MakeUsageList, UsageListLength);
|
||||
}
|
||||
|
||||
HIDAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
HidP_GetUsagesEx(
|
||||
IN HIDP_REPORT_TYPE ReportType,
|
||||
IN USHORT LinkCollection,
|
||||
OUT PUSAGE_AND_PAGE ButtonList,
|
||||
IN OUT ULONG *UsageLength,
|
||||
IN PHIDP_PREPARSED_DATA PreparsedData,
|
||||
IN PCHAR Report,
|
||||
IN ULONG ReportLength)
|
||||
{
|
||||
return HidP_GetUsages(ReportType, HID_USAGE_PAGE_UNDEFINED, LinkCollection, (PUSAGE)ButtonList, UsageLength, PreparsedData, Report, ReportLength);
|
||||
}
|
||||
|
||||
HIDAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
HidP_UsageAndPageListDifference(
|
||||
IN PUSAGE_AND_PAGE PreviousUsageList,
|
||||
IN PUSAGE_AND_PAGE CurrentUsageList,
|
||||
OUT PUSAGE_AND_PAGE BreakUsageList,
|
||||
OUT PUSAGE_AND_PAGE MakeUsageList,
|
||||
IN ULONG UsageListLength)
|
||||
{
|
||||
return HidParser_UsageAndPageListDifference(PreviousUsageList, CurrentUsageList, BreakUsageList, MakeUsageList, UsageListLength);
|
||||
}
|
||||
|
||||
HIDAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
HidP_GetScaledUsageValue(
|
||||
IN HIDP_REPORT_TYPE ReportType,
|
||||
IN USAGE UsagePage,
|
||||
IN USHORT LinkCollection OPTIONAL,
|
||||
IN USAGE Usage,
|
||||
OUT PLONG UsageValue,
|
||||
IN PHIDP_PREPARSED_DATA PreparsedData,
|
||||
IN PCHAR Report,
|
||||
IN ULONG ReportLength)
|
||||
{
|
||||
HID_PARSER Parser;
|
||||
|
||||
//
|
||||
// sanity check
|
||||
//
|
||||
ASSERT(ReportType == HidP_Input || ReportType == HidP_Output || ReportType == HidP_Feature);
|
||||
|
||||
//
|
||||
// init parser
|
||||
//
|
||||
HidParser_InitParser(AllocFunction, FreeFunction, ZeroFunction, CopyFunction, DebugFunction, &Parser);
|
||||
|
||||
//
|
||||
// get scaled usage value
|
||||
//
|
||||
return HidParser_GetScaledUsageValue(&Parser, PreparsedData, ReportType, UsagePage, LinkCollection, Usage, UsageValue, Report, ReportLength);
|
||||
}
|
||||
|
||||
HIDAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
HidP_TranslateUsageAndPagesToI8042ScanCodes(
|
||||
IN PUSAGE_AND_PAGE ChangedUsageList,
|
||||
IN ULONG UsageListLength,
|
||||
IN HIDP_KEYBOARD_DIRECTION KeyAction,
|
||||
IN OUT PHIDP_KEYBOARD_MODIFIER_STATE ModifierState,
|
||||
IN PHIDP_INSERT_SCANCODES InsertCodesProcedure,
|
||||
IN PVOID InsertCodesContext)
|
||||
{
|
||||
HID_PARSER Parser;
|
||||
|
||||
//
|
||||
// init parser
|
||||
//
|
||||
HidParser_InitParser(AllocFunction, FreeFunction, ZeroFunction, CopyFunction, DebugFunction, &Parser);
|
||||
|
||||
//
|
||||
// translate usage pages
|
||||
//
|
||||
return HidParser_TranslateUsageAndPagesToI8042ScanCodes(&Parser, ChangedUsageList, UsageListLength, KeyAction, ModifierState, InsertCodesProcedure, InsertCodesContext);
|
||||
}
|
||||
|
||||
|
||||
|
||||
HIDAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
HidP_GetButtonCaps(
|
||||
HIDP_REPORT_TYPE ReportType,
|
||||
PHIDP_BUTTON_CAPS ButtonCaps,
|
||||
PUSHORT ButtonCapsLength,
|
||||
PHIDP_PREPARSED_DATA PreparsedData)
|
||||
{
|
||||
return HidP_GetSpecificButtonCaps(ReportType, HID_USAGE_PAGE_UNDEFINED, 0, 0, ButtonCaps, (PULONG)ButtonCapsLength, PreparsedData);
|
||||
}
|
||||
|
||||
HIDAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
HidP_GetSpecificButtonCaps(
|
||||
IN HIDP_REPORT_TYPE ReportType,
|
||||
IN USAGE UsagePage,
|
||||
IN USHORT LinkCollection,
|
||||
IN USAGE Usage,
|
||||
OUT PHIDP_BUTTON_CAPS ButtonCaps,
|
||||
IN OUT PULONG ButtonCapsLength,
|
||||
IN PHIDP_PREPARSED_DATA PreparsedData)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
ASSERT(FALSE);
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
HIDAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
HidP_GetData(
|
||||
IN HIDP_REPORT_TYPE ReportType,
|
||||
OUT PHIDP_DATA DataList,
|
||||
IN OUT PULONG DataLength,
|
||||
IN PHIDP_PREPARSED_DATA PreparsedData,
|
||||
IN PCHAR Report,
|
||||
IN ULONG ReportLength)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
ASSERT(FALSE);
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
HIDAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
HidP_GetExtendedAttributes(
|
||||
IN HIDP_REPORT_TYPE ReportType,
|
||||
IN USAGE UsagePage,
|
||||
IN PHIDP_PREPARSED_DATA PreparsedData,
|
||||
OUT PHIDP_EXTENDED_ATTRIBUTES Attributes,
|
||||
IN OUT PULONG LengthAttributes)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
ASSERT(FALSE);
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
HIDAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
HidP_GetLinkCollectionNodes(
|
||||
OUT PHIDP_LINK_COLLECTION_NODE LinkCollectionNodes,
|
||||
IN OUT PULONG LinkCollectionNodesLength,
|
||||
IN PHIDP_PREPARSED_DATA PreparsedData)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
ASSERT(FALSE);
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
HIDAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
HidP_GetUsageValue(
|
||||
IN HIDP_REPORT_TYPE ReportType,
|
||||
IN USAGE UsagePage,
|
||||
IN USHORT LinkCollection,
|
||||
IN USAGE Usage,
|
||||
OUT PULONG UsageValue,
|
||||
IN PHIDP_PREPARSED_DATA PreparsedData,
|
||||
IN PCHAR Report,
|
||||
IN ULONG ReportLength)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
ASSERT(FALSE);
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
HidP_SysPowerEvent (
|
||||
IN PCHAR HidPacket,
|
||||
IN USHORT HidPacketLength,
|
||||
IN PHIDP_PREPARSED_DATA Ppd,
|
||||
OUT PULONG OutputBuffer)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
ASSERT(FALSE);
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
HidP_SysPowerCaps (
|
||||
IN PHIDP_PREPARSED_DATA Ppd,
|
||||
OUT PULONG OutputBuffer)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
ASSERT(FALSE);
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
HIDAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
HidP_GetUsageValueArray(
|
||||
IN HIDP_REPORT_TYPE ReportType,
|
||||
IN USAGE UsagePage,
|
||||
IN USHORT LinkCollection OPTIONAL,
|
||||
IN USAGE Usage,
|
||||
OUT PCHAR UsageValue,
|
||||
IN USHORT UsageValueByteLength,
|
||||
IN PHIDP_PREPARSED_DATA PreparsedData,
|
||||
IN PCHAR Report,
|
||||
IN ULONG ReportLength)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
ASSERT(FALSE);
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
HIDAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
HidP_UnsetUsages(
|
||||
IN HIDP_REPORT_TYPE ReportType,
|
||||
IN USAGE UsagePage,
|
||||
IN USHORT LinkCollection,
|
||||
IN PUSAGE UsageList,
|
||||
IN OUT PULONG UsageLength,
|
||||
IN PHIDP_PREPARSED_DATA PreparsedData,
|
||||
IN OUT PCHAR Report,
|
||||
IN ULONG ReportLength)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
ASSERT(FALSE);
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
HIDAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
HidP_TranslateUsagesToI8042ScanCodes(
|
||||
IN PUSAGE ChangedUsageList,
|
||||
IN ULONG UsageListLength,
|
||||
IN HIDP_KEYBOARD_DIRECTION KeyAction,
|
||||
IN OUT PHIDP_KEYBOARD_MODIFIER_STATE ModifierState,
|
||||
IN PHIDP_INSERT_SCANCODES InsertCodesProcedure,
|
||||
IN PVOID InsertCodesContext)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
ASSERT(FALSE);
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
HIDAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
HidP_SetUsages(
|
||||
IN HIDP_REPORT_TYPE ReportType,
|
||||
IN USAGE UsagePage,
|
||||
IN USHORT LinkCollection,
|
||||
IN PUSAGE UsageList,
|
||||
IN OUT PULONG UsageLength,
|
||||
IN PHIDP_PREPARSED_DATA PreparsedData,
|
||||
IN OUT PCHAR Report,
|
||||
IN ULONG ReportLength)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
ASSERT(FALSE);
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
HIDAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
HidP_SetUsageValueArray(
|
||||
IN HIDP_REPORT_TYPE ReportType,
|
||||
IN USAGE UsagePage,
|
||||
IN USHORT LinkCollection OPTIONAL,
|
||||
IN USAGE Usage,
|
||||
IN PCHAR UsageValue,
|
||||
IN USHORT UsageValueByteLength,
|
||||
IN PHIDP_PREPARSED_DATA PreparsedData,
|
||||
OUT PCHAR Report,
|
||||
IN ULONG ReportLength)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
ASSERT(FALSE);
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
HIDAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
HidP_SetUsageValue(
|
||||
IN HIDP_REPORT_TYPE ReportType,
|
||||
IN USAGE UsagePage,
|
||||
IN USHORT LinkCollection,
|
||||
IN USAGE Usage,
|
||||
IN ULONG UsageValue,
|
||||
IN PHIDP_PREPARSED_DATA PreparsedData,
|
||||
IN OUT PCHAR Report,
|
||||
IN ULONG ReportLength)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
ASSERT(FALSE);
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
HIDAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
HidP_SetScaledUsageValue(
|
||||
IN HIDP_REPORT_TYPE ReportType,
|
||||
IN USAGE UsagePage,
|
||||
IN USHORT LinkCollection OPTIONAL,
|
||||
IN USAGE Usage,
|
||||
IN LONG UsageValue,
|
||||
IN PHIDP_PREPARSED_DATA PreparsedData,
|
||||
IN OUT PCHAR Report,
|
||||
IN ULONG ReportLength)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
ASSERT(FALSE);
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
HIDAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
HidP_SetData(
|
||||
IN HIDP_REPORT_TYPE ReportType,
|
||||
IN PHIDP_DATA DataList,
|
||||
IN OUT PULONG DataLength,
|
||||
IN PHIDP_PREPARSED_DATA PreparsedData,
|
||||
IN OUT PCHAR Report,
|
||||
IN ULONG ReportLength)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
ASSERT(FALSE);
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
HIDAPI
|
||||
ULONG
|
||||
NTAPI
|
||||
HidP_MaxDataListLength(
|
||||
IN HIDP_REPORT_TYPE ReportType,
|
||||
IN PHIDP_PREPARSED_DATA PreparsedData)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
ASSERT(FALSE);
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
HIDAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
HidP_InitializeReportForID(
|
||||
IN HIDP_REPORT_TYPE ReportType,
|
||||
IN UCHAR ReportID,
|
||||
IN PHIDP_PREPARSED_DATA PreparsedData,
|
||||
IN OUT PCHAR Report,
|
||||
IN ULONG ReportLength)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
ASSERT(FALSE);
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
#undef HidP_GetValueCaps
|
||||
|
||||
HIDAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
HidP_GetValueCaps(
|
||||
HIDP_REPORT_TYPE ReportType,
|
||||
PHIDP_VALUE_CAPS ValueCaps,
|
||||
PULONG ValueCapsLength,
|
||||
PHIDP_PREPARSED_DATA PreparsedData)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
ASSERT(FALSE);
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
DriverEntry(
|
||||
IN PDRIVER_OBJECT DriverObject,
|
||||
IN PUNICODE_STRING RegPath)
|
||||
{
|
||||
|
||||
DPRINT("********* HID PARSE *********\n");
|
||||
return STATUS_SUCCESS;
|
||||
}
|
11
reactos/drivers/hid/hidparse/hidparse.h
Normal file
11
reactos/drivers/hid/hidparse/hidparse.h
Normal file
|
@ -0,0 +1,11 @@
|
|||
#pragma once
|
||||
|
||||
#define _HIDPI_
|
||||
#define _HIDPI_NO_FUNCTION_MACROS_
|
||||
#include <ntddk.h>
|
||||
#include <hidpddi.h>
|
||||
#include <hidpi.h>
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
#include "hidparser.h"
|
||||
#include <stdio.h>
|
13
reactos/drivers/hid/hidparse/hidparse.rbuild
Normal file
13
reactos/drivers/hid/hidparse/hidparse.rbuild
Normal file
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0"?>
|
||||
<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
|
||||
<module name="hidparse" type="kernelmodedriver" installbase="system32/drivers" installname="hidparse.sys">
|
||||
<importlibrary definition="hidparse.spec" />
|
||||
<bootstrap installbase="$(CDOUTPUT)/system32/drivers" />
|
||||
<define name="DEBUG_MODE" />
|
||||
<include base="ntoskrnl">include</include>
|
||||
<include base="ReactOS">lib/drivers/hidparser</include>
|
||||
<library>ntoskrnl</library>
|
||||
<library>hidparser</library>
|
||||
<file>hidparse.c</file>
|
||||
<file>hidparse.rc</file>
|
||||
</module>
|
5
reactos/drivers/hid/hidparse/hidparse.rc
Normal file
5
reactos/drivers/hid/hidparse/hidparse.rc
Normal file
|
@ -0,0 +1,5 @@
|
|||
#define REACTOS_VERSION_DLL
|
||||
#define REACTOS_STR_FILE_DESCRIPTION "USB HID Parser\0"
|
||||
#define REACTOS_STR_INTERNAL_NAME "hidparse\0"
|
||||
#define REACTOS_STR_ORIGINAL_FILENAME "hidparse.sys\0"
|
||||
#include <reactos/version.rc>
|
53
reactos/drivers/hid/hidparse/hidparse.spec
Normal file
53
reactos/drivers/hid/hidparse/hidparse.spec
Normal file
|
@ -0,0 +1,53 @@
|
|||
@ stdcall HidP_FreeCollectionDescription(ptr)
|
||||
@ stdcall HidP_GetButtonCaps(long ptr ptr ptr)
|
||||
@ stdcall HidP_GetCaps(ptr ptr)
|
||||
@ stdcall HidP_GetCollectionDescription(ptr long long ptr)
|
||||
@ stdcall HidP_GetData(long ptr ptr ptr ptr long)
|
||||
@ stdcall HidP_GetExtendedAttributes(long long ptr ptr long)
|
||||
@ stdcall HidP_GetLinkCollectionNodes(ptr ptr ptr)
|
||||
@ stdcall HidP_GetScaledUsageValue(long long long long ptr ptr ptr long)
|
||||
@ stdcall HidP_GetSpecificButtonCaps(long long long long ptr ptr ptr)
|
||||
@ stdcall HidP_GetSpecificValueCaps(long long long long ptr ptr ptr)
|
||||
@ stdcall HidP_GetUsageValue(long long long long ptr ptr ptr long)
|
||||
@ stdcall HidP_GetUsageValueArray(long long long long ptr long ptr ptr long)
|
||||
@ stdcall HidP_GetUsages(long long long ptr ptr ptr ptr long)
|
||||
@ stdcall HidP_GetUsagesEx(long long ptr ptr ptr ptr long)
|
||||
@ stdcall HidP_GetValueCaps(long ptr ptr ptr)
|
||||
@ stdcall HidP_InitializeReportForID(long long ptr ptr long)
|
||||
@ stdcall HidP_MaxDataListLength(long ptr)
|
||||
@ stdcall HidP_MaxUsageListLength(long long ptr)
|
||||
@ stdcall HidP_SetData(long ptr ptr ptr ptr long)
|
||||
@ stdcall HidP_SetScaledUsageValue(long long long long long ptr ptr long)
|
||||
@ stdcall HidP_SetUsageValue(long long long long long ptr ptr long)
|
||||
@ stdcall HidP_SetUsageValueArray(long long long long ptr long long ptr long)
|
||||
@ stdcall HidP_SetUsages(long long long ptr ptr ptr ptr long)
|
||||
@ stdcall HidP_SysPowerCaps(ptr ptr)
|
||||
@ stdcall HidP_SysPowerEvent(ptr long ptr ptr)
|
||||
@ stdcall HidP_TranslateUsageAndPagesToI8042ScanCodes(ptr long long ptr ptr ptr)
|
||||
@ stdcall HidP_TranslateUsagesToI8042ScanCodes(ptr long long ptr ptr ptr)
|
||||
@ stdcall HidP_UnsetUsages(long long long ptr ptr ptr ptr long)
|
||||
@ stdcall HidP_UsageAndPageListDifference(ptr ptr ptr ptr long)
|
||||
@ stdcall HidP_UsageListDifference(ptr ptr ptr ptr long)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
11
reactos/drivers/hid/hidusb/CMakeLists.txt
Normal file
11
reactos/drivers/hid/hidusb/CMakeLists.txt
Normal file
|
@ -0,0 +1,11 @@
|
|||
|
||||
list(APPEND SOURCE
|
||||
hidusb.c
|
||||
hidusb.rc)
|
||||
|
||||
add_library(hidusb SHARED ${SOURCE})
|
||||
|
||||
set_module_type(hidusb kernelmodedriver)
|
||||
add_importlibs(hidusb hidclass ntoskrnl usbd hal)
|
||||
|
||||
add_cd_file(TARGET hidusb DESTINATION reactos/system32/drivers NO_CAB FOR all)
|
1814
reactos/drivers/hid/hidusb/hidusb.c
Normal file
1814
reactos/drivers/hid/hidusb/hidusb.c
Normal file
File diff suppressed because it is too large
Load diff
88
reactos/drivers/hid/hidusb/hidusb.h
Normal file
88
reactos/drivers/hid/hidusb/hidusb.h
Normal file
|
@ -0,0 +1,88 @@
|
|||
#pragma once
|
||||
|
||||
#define _HIDPI_
|
||||
#define _HIDPI_NO_FUNCTION_MACROS_
|
||||
#define NDEBUG
|
||||
#include <ntddk.h>
|
||||
#include <hidport.h>
|
||||
#include <debug.h>
|
||||
#include <hubbusif.h>
|
||||
#include <usbbusif.h>
|
||||
#include <usbioctl.h>
|
||||
#include <usb.h>
|
||||
#include <usbdlib.h>
|
||||
|
||||
#include <hidport.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
//
|
||||
// event for completion
|
||||
//
|
||||
KEVENT Event;
|
||||
|
||||
//
|
||||
// device descriptor
|
||||
//
|
||||
PUSB_DEVICE_DESCRIPTOR DeviceDescriptor;
|
||||
|
||||
//
|
||||
// configuration descriptor
|
||||
//
|
||||
PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor;
|
||||
|
||||
//
|
||||
// interface information
|
||||
//
|
||||
PUSBD_INTERFACE_INFORMATION InterfaceInfo;
|
||||
|
||||
//
|
||||
// configuration handle
|
||||
//
|
||||
USBD_CONFIGURATION_HANDLE ConfigurationHandle;
|
||||
|
||||
//
|
||||
// hid descriptor
|
||||
//
|
||||
PHID_DESCRIPTOR HidDescriptor;
|
||||
}HID_USB_DEVICE_EXTENSION, *PHID_USB_DEVICE_EXTENSION;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
//
|
||||
// request irp
|
||||
//
|
||||
PIRP Irp;
|
||||
|
||||
//
|
||||
// work item
|
||||
//
|
||||
PIO_WORKITEM WorkItem;
|
||||
|
||||
//
|
||||
// device object
|
||||
//
|
||||
PDEVICE_OBJECT DeviceObject;
|
||||
|
||||
}HID_USB_RESET_CONTEXT, *PHID_USB_RESET_CONTEXT;
|
||||
|
||||
|
||||
NTSTATUS
|
||||
Hid_GetDescriptor(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN USHORT UrbFunction,
|
||||
IN USHORT UrbLength,
|
||||
IN OUT PVOID *UrbBuffer,
|
||||
IN OUT PULONG UrbBufferLength,
|
||||
IN UCHAR DescriptorType,
|
||||
IN UCHAR Index,
|
||||
IN USHORT LanguageIndex);
|
||||
|
||||
NTSTATUS
|
||||
Hid_DispatchUrb(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PURB Urb);
|
||||
|
||||
#define USB_SET_IDLE_REQUEST 0xA
|
||||
#define USB_GET_PROTOCOL_REQUEST 0x3
|
||||
|
11
reactos/drivers/hid/hidusb/hidusb.rbuild
Normal file
11
reactos/drivers/hid/hidusb/hidusb.rbuild
Normal file
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0"?>
|
||||
<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
|
||||
<module name="hidusb" type="kernelmodedriver" installbase="system32/drivers" installname="hidusb.sys">
|
||||
<bootstrap installbase="$(CDOUTPUT)/system32/drivers" />
|
||||
<library>ntoskrnl</library>
|
||||
<library>hidclass</library>
|
||||
<library>usbd</library>
|
||||
<library>hal</library>
|
||||
<file>hidusb.c</file>
|
||||
<file>hidusb.rc</file>
|
||||
</module>
|
5
reactos/drivers/hid/hidusb/hidusb.rc
Normal file
5
reactos/drivers/hid/hidusb/hidusb.rc
Normal file
|
@ -0,0 +1,5 @@
|
|||
#define REACTOS_VERSION_DLL
|
||||
#define REACTOS_STR_FILE_DESCRIPTION "USB HID Interface Driver\0"
|
||||
#define REACTOS_STR_INTERNAL_NAME "hidusb\0"
|
||||
#define REACTOS_STR_ORIGINAL_FILENAME "hidusb.sys\0"
|
||||
#include <reactos/version.rc>
|
11
reactos/drivers/hid/kbdhid/CMakeLists.txt
Normal file
11
reactos/drivers/hid/kbdhid/CMakeLists.txt
Normal file
|
@ -0,0 +1,11 @@
|
|||
|
||||
add_definitions(-DDEBUG_MODE)
|
||||
|
||||
include_directories(${REACTOS_SOURCE_DIR}/ntoskrnl/include)
|
||||
|
||||
add_library(kbdhid SHARED kbdhid.c kbdhid.rc)
|
||||
|
||||
set_module_type(kbdhid kernelmodedriver)
|
||||
add_importlibs(kbdhid ntoskrnl hal hidparse)
|
||||
|
||||
add_cd_file(TARGET kbdhid DESTINATION reactos/system32/drivers NO_CAB FOR all)
|
923
reactos/drivers/hid/kbdhid/kbdhid.c
Normal file
923
reactos/drivers/hid/kbdhid/kbdhid.c
Normal file
|
@ -0,0 +1,923 @@
|
|||
/*
|
||||
* PROJECT: ReactOS HID Stack
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* FILE: drivers/hid/kbdhid/kbdhid.c
|
||||
* PURPOSE: Keyboard HID Driver
|
||||
* PROGRAMMERS:
|
||||
* Michael Martin (michael.martin@reactos.org)
|
||||
* Johannes Anderwald (johannes.anderwald@reactos.org)
|
||||
*/
|
||||
|
||||
#include "kbdhid.h"
|
||||
|
||||
VOID
|
||||
KbdHid_DispatchInputData(
|
||||
IN PKBDHID_DEVICE_EXTENSION DeviceExtension,
|
||||
IN PKEYBOARD_INPUT_DATA InputData)
|
||||
{
|
||||
KIRQL OldIrql;
|
||||
ULONG InputDataConsumed;
|
||||
|
||||
if (!DeviceExtension->ClassService)
|
||||
return;
|
||||
|
||||
/* sanity check */
|
||||
ASSERT(DeviceExtension->ClassService);
|
||||
ASSERT(DeviceExtension->ClassDeviceObject);
|
||||
|
||||
/* raise irql */
|
||||
KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
|
||||
|
||||
/* dispatch input data */
|
||||
(*(PSERVICE_CALLBACK_ROUTINE)DeviceExtension->ClassService)(DeviceExtension->ClassDeviceObject, InputData, InputData + 1, &InputDataConsumed);
|
||||
|
||||
/* lower irql to previous level */
|
||||
KeLowerIrql(OldIrql);
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
KbdHid_InsertScanCodes(
|
||||
IN PVOID Context,
|
||||
IN PCHAR NewScanCodes,
|
||||
IN ULONG Length)
|
||||
{
|
||||
KEYBOARD_INPUT_DATA InputData;
|
||||
ULONG Index;
|
||||
PKBDHID_DEVICE_EXTENSION DeviceExtension;
|
||||
|
||||
/* get device extension */
|
||||
DeviceExtension = (PKBDHID_DEVICE_EXTENSION)Context;
|
||||
|
||||
for(Index = 0; Index < Length; Index++)
|
||||
{
|
||||
DPRINT("[KBDHID] ScanCode Index %lu ScanCode %x\n", Index, NewScanCodes[Index] & 0xFF);
|
||||
|
||||
/* init input data */
|
||||
RtlZeroMemory(&InputData, sizeof(KEYBOARD_INPUT_DATA));
|
||||
|
||||
/* use keyboard unit id */
|
||||
InputData.UnitId = DeviceExtension->KeyboardTypematic.UnitId;
|
||||
|
||||
if (((UCHAR)(NewScanCodes[Index] & 0xFF))> 0x7F)
|
||||
{
|
||||
/* scan codes greater than 0x7F are a key break */
|
||||
InputData.Flags |= KEY_BREAK;
|
||||
}
|
||||
|
||||
/* store key code */
|
||||
InputData.MakeCode = NewScanCodes[Index];
|
||||
|
||||
/* dispatch scan codes */
|
||||
KbdHid_DispatchInputData((PKBDHID_DEVICE_EXTENSION)Context, &InputData);
|
||||
}
|
||||
|
||||
/* done */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KbdHid_ReadCompletion(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp,
|
||||
IN PVOID Context)
|
||||
{
|
||||
PKBDHID_DEVICE_EXTENSION DeviceExtension;
|
||||
NTSTATUS Status;
|
||||
ULONG ButtonLength;
|
||||
|
||||
/* get device extension */
|
||||
DeviceExtension = (PKBDHID_DEVICE_EXTENSION)Context;
|
||||
|
||||
if (Irp->IoStatus.Status == STATUS_PRIVILEGE_NOT_HELD ||
|
||||
Irp->IoStatus.Status == STATUS_DEVICE_NOT_CONNECTED ||
|
||||
Irp->IoStatus.Status == STATUS_CANCELLED ||
|
||||
DeviceExtension->StopReadReport)
|
||||
{
|
||||
/* failed to read or should be stopped*/
|
||||
DPRINT1("[KBDHID] ReadCompletion terminating read Status %x\n", Irp->IoStatus.Status);
|
||||
|
||||
/* report no longer active */
|
||||
DeviceExtension->ReadReportActive = FALSE;
|
||||
|
||||
/* request stopping of the report cycle */
|
||||
DeviceExtension->StopReadReport = FALSE;
|
||||
|
||||
/* signal completion event */
|
||||
KeSetEvent(&DeviceExtension->ReadCompletionEvent, 0, 0);
|
||||
return STATUS_MORE_PROCESSING_REQUIRED;
|
||||
}
|
||||
|
||||
//
|
||||
// print out raw report
|
||||
//
|
||||
ASSERT(DeviceExtension->ReportLength >= 9);
|
||||
DPRINT("[KBDHID] ReadCompletion %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", DeviceExtension->Report[0], DeviceExtension->Report[1], DeviceExtension->Report[2],
|
||||
DeviceExtension->Report[3], DeviceExtension->Report[4], DeviceExtension->Report[5],
|
||||
DeviceExtension->Report[6], DeviceExtension->Report[7], DeviceExtension->Report[8]);
|
||||
|
||||
|
||||
/* get current usages */
|
||||
ButtonLength = DeviceExtension->UsageListLength;
|
||||
Status = HidP_GetUsagesEx(HidP_Input, HIDP_LINK_COLLECTION_UNSPECIFIED, DeviceExtension->CurrentUsageList, &ButtonLength, DeviceExtension->PreparsedData, DeviceExtension->Report, DeviceExtension->ReportLength);
|
||||
ASSERT(Status == HIDP_STATUS_SUCCESS);
|
||||
|
||||
/* FIXME check if needs mapping */
|
||||
|
||||
/* get usage difference */
|
||||
Status = HidP_UsageAndPageListDifference(DeviceExtension->PreviousUsageList, DeviceExtension->CurrentUsageList, DeviceExtension->BreakUsageList, DeviceExtension->MakeUsageList, DeviceExtension->UsageListLength);
|
||||
ASSERT(Status == HIDP_STATUS_SUCCESS);
|
||||
|
||||
/* replace previous usage list with current list */
|
||||
RtlMoveMemory(DeviceExtension->PreviousUsageList, DeviceExtension->CurrentUsageList, sizeof(USAGE_AND_PAGE) * DeviceExtension->UsageListLength);
|
||||
|
||||
/* translate break usage list */
|
||||
HidP_TranslateUsageAndPagesToI8042ScanCodes(DeviceExtension->BreakUsageList, DeviceExtension->UsageListLength, HidP_Keyboard_Break, &DeviceExtension->ModifierState, KbdHid_InsertScanCodes, DeviceExtension);
|
||||
ASSERT(Status == HIDP_STATUS_SUCCESS);
|
||||
|
||||
/* translate new usage list */
|
||||
HidP_TranslateUsageAndPagesToI8042ScanCodes(DeviceExtension->MakeUsageList, DeviceExtension->UsageListLength, HidP_Keyboard_Make, &DeviceExtension->ModifierState, KbdHid_InsertScanCodes, DeviceExtension);
|
||||
ASSERT(Status == HIDP_STATUS_SUCCESS);
|
||||
|
||||
/* re-init read */
|
||||
KbdHid_InitiateRead(DeviceExtension);
|
||||
|
||||
/* stop completion */
|
||||
return STATUS_MORE_PROCESSING_REQUIRED;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
KbdHid_InitiateRead(
|
||||
IN PKBDHID_DEVICE_EXTENSION DeviceExtension)
|
||||
{
|
||||
PIO_STACK_LOCATION IoStack;
|
||||
NTSTATUS Status;
|
||||
|
||||
/* re-use irp */
|
||||
IoReuseIrp(DeviceExtension->Irp, STATUS_SUCCESS);
|
||||
|
||||
/* init irp */
|
||||
DeviceExtension->Irp->MdlAddress = DeviceExtension->ReportMDL;
|
||||
|
||||
/* get next stack location */
|
||||
IoStack = IoGetNextIrpStackLocation(DeviceExtension->Irp);
|
||||
|
||||
/* init stack location */
|
||||
IoStack->Parameters.Read.Length = DeviceExtension->ReportLength;
|
||||
IoStack->Parameters.Read.Key = 0;
|
||||
IoStack->Parameters.Read.ByteOffset.QuadPart = 0LL;
|
||||
IoStack->MajorFunction = IRP_MJ_READ;
|
||||
IoStack->FileObject = DeviceExtension->FileObject;
|
||||
|
||||
/* set completion routine */
|
||||
IoSetCompletionRoutine(DeviceExtension->Irp, KbdHid_ReadCompletion, DeviceExtension, TRUE, TRUE, TRUE);
|
||||
|
||||
/* read is active */
|
||||
DeviceExtension->ReadReportActive = TRUE;
|
||||
|
||||
/* start the read */
|
||||
Status = IoCallDriver(DeviceExtension->NextDeviceObject, DeviceExtension->Irp);
|
||||
|
||||
/* done */
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KbdHid_CreateCompletion(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp,
|
||||
IN PVOID Context)
|
||||
{
|
||||
KeSetEvent((PKEVENT)Context, 0, FALSE);
|
||||
return STATUS_MORE_PROCESSING_REQUIRED;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KbdHid_Create(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
PIO_STACK_LOCATION IoStack;
|
||||
NTSTATUS Status;
|
||||
KEVENT Event;
|
||||
PKBDHID_DEVICE_EXTENSION DeviceExtension;
|
||||
|
||||
DPRINT("[KBDHID]: IRP_MJ_CREATE\n");
|
||||
|
||||
/* get device extension */
|
||||
DeviceExtension = (PKBDHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
|
||||
/* get stack location */
|
||||
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||
|
||||
/* copy stack location to next */
|
||||
IoCopyCurrentIrpStackLocationToNext(Irp);
|
||||
|
||||
/* init event */
|
||||
KeInitializeEvent(&Event, NotificationEvent, FALSE);
|
||||
|
||||
/* prepare irp */
|
||||
IoSetCompletionRoutine(Irp, KbdHid_CreateCompletion, &Event, TRUE, TRUE, TRUE);
|
||||
|
||||
/* call lower driver */
|
||||
Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
|
||||
if (Status == STATUS_PENDING)
|
||||
{
|
||||
/* request pending */
|
||||
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
|
||||
}
|
||||
|
||||
/* check for success */
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* failed */
|
||||
Irp->IoStatus.Status = Status;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* is the driver already in use */
|
||||
if (DeviceExtension->FileObject == NULL)
|
||||
{
|
||||
/* did the caller specify correct attributes */
|
||||
ASSERT(IoStack->Parameters.Create.SecurityContext);
|
||||
if (IoStack->Parameters.Create.SecurityContext->DesiredAccess)
|
||||
{
|
||||
/* store file object */
|
||||
DeviceExtension->FileObject = IoStack->FileObject;
|
||||
|
||||
/* reset event */
|
||||
KeResetEvent(&DeviceExtension->ReadCompletionEvent);
|
||||
|
||||
/* initiating read */
|
||||
Status = KbdHid_InitiateRead(DeviceExtension);
|
||||
DPRINT("[KBDHID] KbdHid_InitiateRead: status %x\n", Status);
|
||||
if (Status == STATUS_PENDING)
|
||||
{
|
||||
/* report irp is pending */
|
||||
Status = STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* complete request */
|
||||
Irp->IoStatus.Status = Status;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KbdHid_Close(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
PKBDHID_DEVICE_EXTENSION DeviceExtension;
|
||||
|
||||
/* get device extension */
|
||||
DeviceExtension = (PKBDHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
|
||||
DPRINT("[KBDHID] IRP_MJ_CLOSE ReadReportActive %x\n", DeviceExtension->ReadReportActive);
|
||||
|
||||
if (DeviceExtension->ReadReportActive)
|
||||
{
|
||||
/* request stopping of the report cycle */
|
||||
DeviceExtension->StopReadReport = TRUE;
|
||||
|
||||
/* wait until the reports have been read */
|
||||
KeWaitForSingleObject(&DeviceExtension->ReadCompletionEvent, Executive, KernelMode, FALSE, NULL);
|
||||
|
||||
/* cancel irp */
|
||||
IoCancelIrp(DeviceExtension->Irp);
|
||||
}
|
||||
|
||||
DPRINT("[KBDHID] IRP_MJ_CLOSE ReadReportActive %x\n", DeviceExtension->ReadReportActive);
|
||||
|
||||
/* remove file object */
|
||||
DeviceExtension->FileObject = NULL;
|
||||
|
||||
/* skip location */
|
||||
IoSkipCurrentIrpStackLocation(Irp);
|
||||
|
||||
/* pass irp to down the stack */
|
||||
return IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KbdHid_InternalDeviceControl(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
PIO_STACK_LOCATION IoStack;
|
||||
PKBDHID_DEVICE_EXTENSION DeviceExtension;
|
||||
PCONNECT_DATA Data;
|
||||
PKEYBOARD_ATTRIBUTES Attributes;
|
||||
|
||||
/* get current stack location */
|
||||
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||
|
||||
DPRINT("[KBDHID] InternalDeviceControl %x\n", IoStack->Parameters.DeviceIoControl.IoControlCode);
|
||||
|
||||
/* get device extension */
|
||||
DeviceExtension = (PKBDHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
|
||||
if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KEYBOARD_QUERY_ATTRIBUTES)
|
||||
{
|
||||
/* verify output buffer length */
|
||||
if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(MOUSE_ATTRIBUTES))
|
||||
{
|
||||
/* invalid request */
|
||||
DPRINT1("[MOUHID] IOCTL_MOUSE_QUERY_ATTRIBUTES Buffer too small\n");
|
||||
Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
/* get output buffer */
|
||||
Attributes = (PKEYBOARD_ATTRIBUTES)Irp->AssociatedIrp.SystemBuffer;
|
||||
|
||||
/* copy attributes */
|
||||
RtlCopyMemory(Attributes, &DeviceExtension->Attributes, sizeof(KEYBOARD_ATTRIBUTES));
|
||||
|
||||
/* complete request */
|
||||
Irp->IoStatus.Information = sizeof(MOUSE_ATTRIBUTES);
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_KEYBOARD_CONNECT)
|
||||
{
|
||||
/* verify input buffer length */
|
||||
if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(CONNECT_DATA))
|
||||
{
|
||||
/* invalid request */
|
||||
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* is it already connected */
|
||||
if (DeviceExtension->ClassService)
|
||||
{
|
||||
/* already connected */
|
||||
Irp->IoStatus.Status = STATUS_SHARING_VIOLATION;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_SHARING_VIOLATION;
|
||||
}
|
||||
|
||||
/* get connect data */
|
||||
Data = (PCONNECT_DATA)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
|
||||
|
||||
/* store connect details */
|
||||
DeviceExtension->ClassDeviceObject = Data->ClassDeviceObject;
|
||||
DeviceExtension->ClassService = Data->ClassService;
|
||||
|
||||
/* completed successfully */
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_KEYBOARD_DISCONNECT)
|
||||
{
|
||||
/* not implemented */
|
||||
Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_KEYBOARD_ENABLE)
|
||||
{
|
||||
/* not supported */
|
||||
Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_KEYBOARD_DISABLE)
|
||||
{
|
||||
/* not supported */
|
||||
Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KEYBOARD_QUERY_INDICATORS)
|
||||
{
|
||||
if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(KEYBOARD_INDICATOR_PARAMETERS))
|
||||
{
|
||||
/* invalid parameter */
|
||||
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* copy indicators */
|
||||
RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, &DeviceExtension->KeyboardIndicator, sizeof(KEYBOARD_INDICATOR_PARAMETERS));
|
||||
|
||||
/* complete request */
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
Irp->IoStatus.Information = sizeof(KEYBOARD_INDICATOR_PARAMETERS);
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KEYBOARD_QUERY_TYPEMATIC)
|
||||
{
|
||||
if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(KEYBOARD_TYPEMATIC_PARAMETERS))
|
||||
{
|
||||
/* invalid parameter */
|
||||
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* copy indicators */
|
||||
RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, &DeviceExtension->KeyboardTypematic, sizeof(KEYBOARD_TYPEMATIC_PARAMETERS));
|
||||
|
||||
/* done */
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
Irp->IoStatus.Information = sizeof(KEYBOARD_TYPEMATIC_PARAMETERS);
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KEYBOARD_SET_INDICATORS)
|
||||
{
|
||||
if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(KEYBOARD_INDICATOR_PARAMETERS))
|
||||
{
|
||||
/* invalid parameter */
|
||||
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* copy indicators */
|
||||
RtlCopyMemory(&DeviceExtension->KeyboardIndicator, Irp->AssociatedIrp.SystemBuffer, sizeof(KEYBOARD_INDICATOR_PARAMETERS));
|
||||
|
||||
/* done */
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
Irp->IoStatus.Information = 0;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KEYBOARD_SET_TYPEMATIC)
|
||||
{
|
||||
if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(KEYBOARD_TYPEMATIC_PARAMETERS))
|
||||
{
|
||||
/* invalid parameter */
|
||||
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* copy indicators */
|
||||
RtlCopyMemory(&DeviceExtension->KeyboardTypematic, Irp->AssociatedIrp.SystemBuffer, sizeof(KEYBOARD_TYPEMATIC_PARAMETERS));
|
||||
|
||||
/* done */
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
Irp->IoStatus.Information = 0;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KEYBOARD_QUERY_INDICATOR_TRANSLATION)
|
||||
{
|
||||
/* not implemented */
|
||||
DPRINT1("IOCTL_KEYBOARD_QUERY_INDICATOR_TRANSLATION not implemented\n");
|
||||
Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
/* unknown control code */
|
||||
DPRINT1("[KBDHID] Unknown DeviceControl %x\n", IoStack->Parameters.DeviceIoControl.IoControlCode);
|
||||
/* unknown request not supported */
|
||||
Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KbdHid_DeviceControl(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
PKBDHID_DEVICE_EXTENSION DeviceExtension;
|
||||
|
||||
/* get device extension */
|
||||
DeviceExtension = (PKBDHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
|
||||
/* skip stack location */
|
||||
IoSkipCurrentIrpStackLocation(Irp);
|
||||
|
||||
/* pass and forget */
|
||||
return IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KbdHid_Power(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
KbdHid_SubmitRequest(
|
||||
PDEVICE_OBJECT DeviceObject,
|
||||
ULONG IoControlCode,
|
||||
ULONG InputBufferSize,
|
||||
PVOID InputBuffer,
|
||||
ULONG OutputBufferSize,
|
||||
PVOID OutputBuffer)
|
||||
{
|
||||
KEVENT Event;
|
||||
PKBDHID_DEVICE_EXTENSION DeviceExtension;
|
||||
PIRP Irp;
|
||||
NTSTATUS Status;
|
||||
IO_STATUS_BLOCK IoStatus;
|
||||
|
||||
/* get device extension */
|
||||
DeviceExtension = (PKBDHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
|
||||
/* init event */
|
||||
KeInitializeEvent(&Event, NotificationEvent, FALSE);
|
||||
|
||||
/* build request */
|
||||
Irp = IoBuildDeviceIoControlRequest(IoControlCode, DeviceExtension->NextDeviceObject, InputBuffer, InputBufferSize, OutputBuffer, OutputBufferSize, FALSE, &Event, &IoStatus);
|
||||
if (!Irp)
|
||||
{
|
||||
/* no memory */
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
/* send request */
|
||||
Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
|
||||
if (Status == STATUS_PENDING)
|
||||
{
|
||||
/* wait for request to complete */
|
||||
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
|
||||
Status = IoStatus.Status;
|
||||
}
|
||||
|
||||
/* done */
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KbdHid_StartDevice(
|
||||
IN PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
ULONG Buttons;
|
||||
HID_COLLECTION_INFORMATION Information;
|
||||
PHIDP_PREPARSED_DATA PreparsedData;
|
||||
HIDP_CAPS Capabilities;
|
||||
PKBDHID_DEVICE_EXTENSION DeviceExtension;
|
||||
PUSAGE_AND_PAGE Buffer;
|
||||
|
||||
/* get device extension */
|
||||
DeviceExtension = (PKBDHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
|
||||
/* query collection information */
|
||||
Status = KbdHid_SubmitRequest(DeviceObject, IOCTL_HID_GET_COLLECTION_INFORMATION, 0, NULL, sizeof(HID_COLLECTION_INFORMATION), &Information);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* failed to query collection information */
|
||||
DPRINT1("[KBDHID] failed to obtain collection information with %x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* lets allocate space for preparsed data */
|
||||
PreparsedData = (PHIDP_PREPARSED_DATA)ExAllocatePool(NonPagedPool, Information.DescriptorSize);
|
||||
if (!PreparsedData)
|
||||
{
|
||||
/* no memory */
|
||||
DPRINT1("[KBDHID] no memory size %u\n", Information.DescriptorSize);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
/* now obtain the preparsed data */
|
||||
Status = KbdHid_SubmitRequest(DeviceObject, IOCTL_HID_GET_COLLECTION_DESCRIPTOR, 0, NULL, Information.DescriptorSize, PreparsedData);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* failed to get preparsed data */
|
||||
DPRINT1("[KBDHID] failed to obtain collection information with %x\n", Status);
|
||||
ExFreePool(PreparsedData);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* lets get the caps */
|
||||
Status = HidP_GetCaps(PreparsedData, &Capabilities);
|
||||
if (Status != HIDP_STATUS_SUCCESS)
|
||||
{
|
||||
/* failed to get capabilities */
|
||||
DPRINT1("[KBDHID] failed to obtain caps with %x\n", Status);
|
||||
ExFreePool(PreparsedData);
|
||||
return Status;
|
||||
}
|
||||
|
||||
DPRINT("[KBDHID] Usage %x UsagePage %x InputReportLength %lu\n", Capabilities.Usage, Capabilities.UsagePage, Capabilities.InputReportByteLength);
|
||||
|
||||
/* init input report*/
|
||||
DeviceExtension->ReportLength = Capabilities.InputReportByteLength;
|
||||
ASSERT(DeviceExtension->ReportLength);
|
||||
DeviceExtension->Report = (PCHAR)ExAllocatePool(NonPagedPool, DeviceExtension->ReportLength);
|
||||
ASSERT(DeviceExtension->Report);
|
||||
RtlZeroMemory(DeviceExtension->Report, DeviceExtension->ReportLength);
|
||||
|
||||
/* build mdl */
|
||||
DeviceExtension->ReportMDL = IoAllocateMdl(DeviceExtension->Report, DeviceExtension->ReportLength, FALSE, FALSE, NULL);
|
||||
ASSERT(DeviceExtension->ReportMDL);
|
||||
|
||||
/* init mdl */
|
||||
MmBuildMdlForNonPagedPool(DeviceExtension->ReportMDL);
|
||||
|
||||
/* get max number of buttons */
|
||||
Buttons = HidP_MaxUsageListLength(HidP_Input, HID_USAGE_PAGE_KEYBOARD, PreparsedData);
|
||||
DPRINT("[KBDHID] Buttons %lu\n", Buttons);
|
||||
ASSERT(Buttons > 0);
|
||||
|
||||
/* now allocate an array for those buttons */
|
||||
Buffer = (PUSAGE_AND_PAGE)ExAllocatePool(NonPagedPool, sizeof(USAGE_AND_PAGE) * 4 * Buttons);
|
||||
if (!Buffer)
|
||||
{
|
||||
/* no memory */
|
||||
ExFreePool(PreparsedData);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
/* init usage lists */
|
||||
RtlZeroMemory(Buffer, sizeof(USAGE_AND_PAGE) * 4 * Buttons);
|
||||
DeviceExtension->CurrentUsageList = Buffer;
|
||||
Buffer += Buttons;
|
||||
DeviceExtension->PreviousUsageList = Buffer;
|
||||
Buffer += Buttons;
|
||||
DeviceExtension->MakeUsageList = Buffer;
|
||||
Buffer += Buttons;
|
||||
DeviceExtension->BreakUsageList = Buffer;
|
||||
|
||||
//
|
||||
// FIMXE: implement device hacks
|
||||
//
|
||||
// UsageMappings
|
||||
// KeyboardTypeOverride
|
||||
// KeyboardSubTypeOverride
|
||||
// KeyboardNumberTotalKeysOverride
|
||||
// KeyboardNumberFunctionKeysOverride
|
||||
// KeyboardNumberIndicatorsOverride
|
||||
|
||||
/* store number of buttons */
|
||||
DeviceExtension->UsageListLength = (USHORT)Buttons;
|
||||
|
||||
/* store preparsed data */
|
||||
DeviceExtension->PreparsedData = PreparsedData;
|
||||
|
||||
/* completed successfully */
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KbdHid_StartDeviceCompletion(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp,
|
||||
IN PVOID Context)
|
||||
{
|
||||
KeSetEvent((PKEVENT)Context, 0, FALSE);
|
||||
return STATUS_MORE_PROCESSING_REQUIRED;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KbdHid_Flush(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
PIO_STACK_LOCATION IoStack;
|
||||
PKBDHID_DEVICE_EXTENSION DeviceExtension;
|
||||
|
||||
/* get device extension */
|
||||
DeviceExtension = (PKBDHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
|
||||
/* skip current stack location */
|
||||
IoSkipCurrentIrpStackLocation(Irp);
|
||||
|
||||
/* get next stack location */
|
||||
IoStack = IoGetNextIrpStackLocation(Irp);
|
||||
|
||||
/* change request to hid flush queue request */
|
||||
IoStack->MajorFunction = IRP_MJ_DEVICE_CONTROL;
|
||||
IoStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_HID_FLUSH_QUEUE;
|
||||
|
||||
/* call device */
|
||||
return IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KbdHid_Pnp(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
PIO_STACK_LOCATION IoStack;
|
||||
KEVENT Event;
|
||||
NTSTATUS Status;
|
||||
PKBDHID_DEVICE_EXTENSION DeviceExtension;
|
||||
|
||||
/* get device extension */
|
||||
DeviceExtension = (PKBDHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
|
||||
/* get current irp stack */
|
||||
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||
DPRINT("[KBDHID] IRP_MJ_PNP Request: %x\n", IoStack->MinorFunction);
|
||||
|
||||
if (IoStack->MinorFunction == IRP_MN_STOP_DEVICE ||
|
||||
IoStack->MinorFunction == IRP_MN_CANCEL_REMOVE_DEVICE ||
|
||||
IoStack->MinorFunction == IRP_MN_QUERY_STOP_DEVICE ||
|
||||
IoStack->MinorFunction == IRP_MN_CANCEL_STOP_DEVICE ||
|
||||
IoStack->MinorFunction == IRP_MN_QUERY_REMOVE_DEVICE)
|
||||
{
|
||||
/* indicate success */
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
|
||||
/* skip irp stack location */
|
||||
IoSkipCurrentIrpStackLocation(Irp);
|
||||
|
||||
/* dispatch to lower device */
|
||||
return IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
|
||||
}
|
||||
else if (IoStack->MinorFunction == IRP_MN_REMOVE_DEVICE)
|
||||
{
|
||||
/* FIXME synchronization */
|
||||
|
||||
/* cancel irp */
|
||||
IoCancelIrp(DeviceExtension->Irp);
|
||||
|
||||
/* indicate success */
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
|
||||
/* skip irp stack location */
|
||||
IoSkipCurrentIrpStackLocation(Irp);
|
||||
|
||||
/* dispatch to lower device */
|
||||
Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
|
||||
|
||||
IoFreeIrp(DeviceExtension->Irp);
|
||||
IoDetachDevice(DeviceExtension->NextDeviceObject);
|
||||
IoDeleteDevice(DeviceObject);
|
||||
return Status;
|
||||
}
|
||||
else if (IoStack->MinorFunction == IRP_MN_START_DEVICE)
|
||||
{
|
||||
/* init event */
|
||||
KeInitializeEvent(&Event, NotificationEvent, FALSE);
|
||||
|
||||
/* copy stack location */
|
||||
IoCopyCurrentIrpStackLocationToNext (Irp);
|
||||
|
||||
/* set completion routine */
|
||||
IoSetCompletionRoutine(Irp, KbdHid_StartDeviceCompletion, &Event, TRUE, TRUE, TRUE);
|
||||
Irp->IoStatus.Status = 0;
|
||||
|
||||
/* pass request */
|
||||
Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
|
||||
if (Status == STATUS_PENDING)
|
||||
{
|
||||
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
|
||||
Status = Irp->IoStatus.Status;
|
||||
}
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* failed */
|
||||
Irp->IoStatus.Status = Status;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* lets start the device */
|
||||
Status = KbdHid_StartDevice(DeviceObject);
|
||||
DPRINT("KbdHid_StartDevice %x\n", Status);
|
||||
|
||||
/* complete request */
|
||||
Irp->IoStatus.Status = Status;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
|
||||
/* done */
|
||||
return Status;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* skip irp stack location */
|
||||
IoSkipCurrentIrpStackLocation(Irp);
|
||||
|
||||
/* dispatch to lower device */
|
||||
return IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
|
||||
}
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KbdHid_AddDevice(
|
||||
IN PDRIVER_OBJECT DriverObject,
|
||||
IN PDEVICE_OBJECT PhysicalDeviceObject)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PDEVICE_OBJECT DeviceObject, NextDeviceObject;
|
||||
PKBDHID_DEVICE_EXTENSION DeviceExtension;
|
||||
POWER_STATE State;
|
||||
|
||||
/* create device object */
|
||||
Status = IoCreateDevice(DriverObject, sizeof(KBDHID_DEVICE_EXTENSION), NULL, FILE_DEVICE_KEYBOARD, 0, FALSE, &DeviceObject);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* failed to create device object */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* now attach it */
|
||||
NextDeviceObject = IoAttachDeviceToDeviceStack(DeviceObject, PhysicalDeviceObject);
|
||||
if (!NextDeviceObject)
|
||||
{
|
||||
/* failed to attach */
|
||||
IoDeleteDevice(DeviceObject);
|
||||
return STATUS_DEVICE_NOT_CONNECTED;
|
||||
}
|
||||
|
||||
/* get device extension */
|
||||
DeviceExtension = (PKBDHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
|
||||
/* zero extension */
|
||||
RtlZeroMemory(DeviceExtension, sizeof(KBDHID_DEVICE_EXTENSION));
|
||||
|
||||
/* init device extension */
|
||||
DeviceExtension->NextDeviceObject = NextDeviceObject;
|
||||
KeInitializeEvent(&DeviceExtension->ReadCompletionEvent, NotificationEvent, FALSE);
|
||||
|
||||
/* init keyboard attributes */
|
||||
DeviceExtension->Attributes.KeyboardIdentifier.Type = KEYBOARD_TYPE_UNKNOWN;
|
||||
DeviceExtension->Attributes.KeyboardIdentifier.Subtype = MICROSOFT_KBD_101_TYPE;
|
||||
DeviceExtension->Attributes.NumberOfFunctionKeys = MICROSOFT_KBD_FUNC;
|
||||
DeviceExtension->Attributes.NumberOfIndicators = 3; // caps, num lock, scroll lock
|
||||
DeviceExtension->Attributes.NumberOfKeysTotal = 101;
|
||||
DeviceExtension->Attributes.InputDataQueueLength = 1;
|
||||
DeviceExtension->Attributes.KeyRepeatMinimum.Rate = KEYBOARD_TYPEMATIC_RATE_MINIMUM;
|
||||
DeviceExtension->Attributes.KeyRepeatMinimum.Delay = KEYBOARD_TYPEMATIC_DELAY_MINIMUM;
|
||||
DeviceExtension->Attributes.KeyRepeatMaximum.Rate = KEYBOARD_TYPEMATIC_RATE_DEFAULT;
|
||||
DeviceExtension->Attributes.KeyRepeatMaximum.Delay = KEYBOARD_TYPEMATIC_DELAY_MAXIMUM;
|
||||
|
||||
/* allocate irp */
|
||||
DeviceExtension->Irp = IoAllocateIrp(NextDeviceObject->StackSize, FALSE);
|
||||
|
||||
/* FIXME handle allocation error */
|
||||
ASSERT(DeviceExtension->Irp);
|
||||
|
||||
/* set power state to D0 */
|
||||
State.DeviceState = PowerDeviceD0;
|
||||
PoSetPowerState(DeviceObject, DevicePowerState, State);
|
||||
|
||||
/* init device object */
|
||||
DeviceObject->Flags |= DO_BUFFERED_IO | DO_POWER_PAGABLE;
|
||||
DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
|
||||
|
||||
/* completed successfully */
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
KbdHid_Unload(
|
||||
IN PDRIVER_OBJECT DriverObject)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
DriverEntry(
|
||||
IN PDRIVER_OBJECT DriverObject,
|
||||
IN PUNICODE_STRING RegPath)
|
||||
{
|
||||
/* initialize driver object */
|
||||
DriverObject->DriverUnload = KbdHid_Unload;
|
||||
DriverObject->DriverExtension->AddDevice = KbdHid_AddDevice;
|
||||
DriverObject->MajorFunction[IRP_MJ_CREATE] = KbdHid_Create;
|
||||
DriverObject->MajorFunction[IRP_MJ_CLOSE] = KbdHid_Close;
|
||||
DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = KbdHid_Flush;
|
||||
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = KbdHid_DeviceControl;
|
||||
DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = KbdHid_InternalDeviceControl;
|
||||
DriverObject->MajorFunction[IRP_MJ_POWER] = KbdHid_Power;
|
||||
DriverObject->MajorFunction[IRP_MJ_PNP] = KbdHid_Pnp;
|
||||
DriverObject->DriverUnload = KbdHid_Unload;
|
||||
DriverObject->DriverExtension->AddDevice = KbdHid_AddDevice;
|
||||
|
||||
/* done */
|
||||
return STATUS_SUCCESS;
|
||||
}
|
146
reactos/drivers/hid/kbdhid/kbdhid.h
Normal file
146
reactos/drivers/hid/kbdhid/kbdhid.h
Normal file
|
@ -0,0 +1,146 @@
|
|||
#pragma once
|
||||
|
||||
#define _HIDPI_NO_FUNCTION_MACROS_
|
||||
#include <ntddk.h>
|
||||
#include <hidclass.h>
|
||||
#include <hidpddi.h>
|
||||
#include <hidpi.h>
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
#include <kbdmou.h>
|
||||
//#include <kbd.h>
|
||||
#include <ntddkbd.h>
|
||||
#include <debug.h>
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
//
|
||||
// lower device object
|
||||
//
|
||||
PDEVICE_OBJECT NextDeviceObject;
|
||||
|
||||
//
|
||||
// irp which is used for reading input reports
|
||||
//
|
||||
PIRP Irp;
|
||||
|
||||
//
|
||||
// event
|
||||
//
|
||||
KEVENT ReadCompletionEvent;
|
||||
|
||||
//
|
||||
// device object for class callback
|
||||
//
|
||||
PDEVICE_OBJECT ClassDeviceObject;
|
||||
|
||||
//
|
||||
// class callback
|
||||
//
|
||||
PVOID ClassService;
|
||||
|
||||
//
|
||||
// usage list length
|
||||
//
|
||||
USHORT UsageListLength;
|
||||
|
||||
//
|
||||
// current usage list length
|
||||
//
|
||||
PUSAGE_AND_PAGE CurrentUsageList;
|
||||
|
||||
//
|
||||
// previous usage list
|
||||
//
|
||||
PUSAGE_AND_PAGE PreviousUsageList;
|
||||
|
||||
//
|
||||
// removed usage item list
|
||||
//
|
||||
PUSAGE_AND_PAGE BreakUsageList;
|
||||
|
||||
//
|
||||
// new item usage list
|
||||
//
|
||||
PUSAGE_AND_PAGE MakeUsageList;
|
||||
|
||||
//
|
||||
// preparsed data
|
||||
//
|
||||
PHIDP_PREPARSED_DATA PreparsedData;
|
||||
|
||||
//
|
||||
// mdl for reading input report
|
||||
//
|
||||
PMDL ReportMDL;
|
||||
|
||||
//
|
||||
// input report buffer
|
||||
//
|
||||
PCHAR Report;
|
||||
|
||||
//
|
||||
// input report length
|
||||
//
|
||||
ULONG ReportLength;
|
||||
|
||||
//
|
||||
// file object the device is reading reports from
|
||||
//
|
||||
PFILE_OBJECT FileObject;
|
||||
|
||||
//
|
||||
// report read is active
|
||||
//
|
||||
UCHAR ReadReportActive;
|
||||
|
||||
//
|
||||
// stop reading flag
|
||||
//
|
||||
UCHAR StopReadReport;
|
||||
|
||||
//
|
||||
// keyboard attributes
|
||||
//
|
||||
KEYBOARD_ATTRIBUTES Attributes;
|
||||
|
||||
//
|
||||
// keyboard modifier state
|
||||
//
|
||||
HIDP_KEYBOARD_MODIFIER_STATE ModifierState;
|
||||
|
||||
//
|
||||
// keyboard indicator state
|
||||
//
|
||||
KEYBOARD_INDICATOR_PARAMETERS KeyboardIndicator;
|
||||
|
||||
//
|
||||
// keyboard type matic
|
||||
//
|
||||
KEYBOARD_TYPEMATIC_PARAMETERS KeyboardTypematic;
|
||||
|
||||
|
||||
|
||||
}KBDHID_DEVICE_EXTENSION, *PKBDHID_DEVICE_EXTENSION;
|
||||
|
||||
/* defaults from kbfiltr.h */
|
||||
#define KEYBOARD_TYPEMATIC_RATE_MINIMUM 2
|
||||
#define KEYBOARD_TYPEMATIC_RATE_MAXIMUM 30
|
||||
#define KEYBOARD_TYPEMATIC_RATE_DEFAULT 30
|
||||
#define KEYBOARD_TYPEMATIC_DELAY_MINIMUM 250
|
||||
#define KEYBOARD_TYPEMATIC_DELAY_MAXIMUM 1000
|
||||
#define KEYBOARD_TYPEMATIC_DELAY_DEFAULT 250
|
||||
|
||||
/* FIXME: write kbd.h */
|
||||
#define MICROSOFT_KBD_FUNC 12
|
||||
#define KEYBOARD_TYPE_UNKNOWN (0x51)
|
||||
#define MICROSOFT_KBD_101_TYPE 0
|
||||
|
||||
|
||||
|
||||
|
||||
NTSTATUS
|
||||
KbdHid_InitiateRead(
|
||||
IN PKBDHID_DEVICE_EXTENSION DeviceExtension);
|
||||
|
12
reactos/drivers/hid/kbdhid/kbdhid.rbuild
Normal file
12
reactos/drivers/hid/kbdhid/kbdhid.rbuild
Normal file
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0"?>
|
||||
<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
|
||||
<module name="kbdhid" type="kernelmodedriver" installbase="system32/drivers" installname="kbdhid.sys">
|
||||
<bootstrap installbase="$(CDOUTPUT)/system32/drivers" />
|
||||
<define name="DEBUG_MODE" />
|
||||
<include base="ntoskrnl">include</include>
|
||||
<library>ntoskrnl</library>
|
||||
<library>hal</library>
|
||||
<library>hidparse</library>
|
||||
<file>kbdhid.c</file>
|
||||
<file>kbdhid.rc</file>
|
||||
</module>
|
5
reactos/drivers/hid/kbdhid/kbdhid.rc
Normal file
5
reactos/drivers/hid/kbdhid/kbdhid.rc
Normal file
|
@ -0,0 +1,5 @@
|
|||
#define REACTOS_VERSION_DLL
|
||||
#define REACTOS_STR_FILE_DESCRIPTION "Keyboard HID Class Driver\0"
|
||||
#define REACTOS_STR_INTERNAL_NAME "kbdhid\0"
|
||||
#define REACTOS_STR_ORIGINAL_FILENAME "kbdhid.sys\0"
|
||||
#include <reactos/version.rc>
|
11
reactos/drivers/hid/mouhid/CMakeLists.txt
Normal file
11
reactos/drivers/hid/mouhid/CMakeLists.txt
Normal file
|
@ -0,0 +1,11 @@
|
|||
|
||||
add_definitions(-DDEBUG_MODE)
|
||||
|
||||
include_directories(${REACTOS_SOURCE_DIR}/ntoskrnl/include)
|
||||
|
||||
add_library(mouhid SHARED mouhid.c mouhid.rc)
|
||||
|
||||
set_module_type(mouhid kernelmodedriver)
|
||||
add_importlibs(mouhid ntoskrnl hal hidparse)
|
||||
|
||||
add_cd_file(TARGET mouhid DESTINATION reactos/system32/drivers FOR all)
|
979
reactos/drivers/hid/mouhid/mouhid.c
Normal file
979
reactos/drivers/hid/mouhid/mouhid.c
Normal file
|
@ -0,0 +1,979 @@
|
|||
/*
|
||||
* PROJECT: ReactOS HID Stack
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* FILE: drivers/hid/mouhid/mouhid.c
|
||||
* PURPOSE: Mouse HID Driver
|
||||
* PROGRAMMERS:
|
||||
* Michael Martin (michael.martin@reactos.org)
|
||||
* Johannes Anderwald (johannes.anderwald@reactos.org)
|
||||
*/
|
||||
|
||||
#include "mouhid.h"
|
||||
|
||||
static USHORT MouHid_ButtonUpFlags[] =
|
||||
{
|
||||
0xFF, /* unused */
|
||||
MOUSE_LEFT_BUTTON_DOWN,
|
||||
MOUSE_RIGHT_BUTTON_DOWN,
|
||||
MOUSE_MIDDLE_BUTTON_DOWN,
|
||||
MOUSE_BUTTON_4_DOWN,
|
||||
MOUSE_BUTTON_5_DOWN
|
||||
};
|
||||
|
||||
static USHORT MouHid_ButtonDownFlags[] =
|
||||
{
|
||||
0xFF, /* unused */
|
||||
MOUSE_LEFT_BUTTON_UP,
|
||||
MOUSE_RIGHT_BUTTON_UP,
|
||||
MOUSE_MIDDLE_BUTTON_UP,
|
||||
MOUSE_BUTTON_4_UP,
|
||||
MOUSE_BUTTON_5_UP
|
||||
};
|
||||
|
||||
VOID
|
||||
MouHid_GetButtonMove(
|
||||
IN PMOUHID_DEVICE_EXTENSION DeviceExtension,
|
||||
OUT PLONG LastX,
|
||||
OUT PLONG LastY)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
|
||||
/* init result */
|
||||
*LastX = 0;
|
||||
*LastY = 0;
|
||||
|
||||
/* get scaled usage value x */
|
||||
Status = HidP_GetScaledUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, HIDP_LINK_COLLECTION_UNSPECIFIED, HID_USAGE_GENERIC_X, (PLONG)LastX, DeviceExtension->PreparsedData, DeviceExtension->Report, DeviceExtension->ReportLength);
|
||||
/* FIXME handle error */
|
||||
ASSERT(Status == HIDP_STATUS_SUCCESS);
|
||||
|
||||
/* get scaled usage value y */
|
||||
Status = HidP_GetScaledUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, HIDP_LINK_COLLECTION_UNSPECIFIED, HID_USAGE_GENERIC_Y, (PLONG)LastY, DeviceExtension->PreparsedData, DeviceExtension->Report, DeviceExtension->ReportLength);
|
||||
/* FIXME handle error */
|
||||
ASSERT(Status == HIDP_STATUS_SUCCESS);
|
||||
|
||||
}
|
||||
|
||||
|
||||
VOID
|
||||
MouHid_GetButtonFlags(
|
||||
IN PMOUHID_DEVICE_EXTENSION DeviceExtension,
|
||||
OUT PUSHORT ButtonFlags)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
USAGE Usage;
|
||||
ULONG Index;
|
||||
PUSAGE TempList;
|
||||
ULONG CurrentUsageListLength;
|
||||
|
||||
/* init flags */
|
||||
*ButtonFlags = 0;
|
||||
|
||||
/* get usages */
|
||||
CurrentUsageListLength = DeviceExtension->UsageListLength;
|
||||
Status = HidP_GetUsages(HidP_Input, HID_USAGE_PAGE_BUTTON, HIDP_LINK_COLLECTION_UNSPECIFIED, DeviceExtension->CurrentUsageList, &CurrentUsageListLength, DeviceExtension->PreparsedData, DeviceExtension->Report, DeviceExtension->ReportLength);
|
||||
if (Status != HIDP_STATUS_SUCCESS)
|
||||
{
|
||||
DPRINT1("MouHid_GetButtonFlags failed to get usages with %x\n", Status);
|
||||
return;
|
||||
}
|
||||
|
||||
/* extract usage list difference */
|
||||
Status = HidP_UsageListDifference(DeviceExtension->PreviousUsageList, DeviceExtension->CurrentUsageList, DeviceExtension->BreakUsageList, DeviceExtension->MakeUsageList, DeviceExtension->UsageListLength);
|
||||
if (Status != HIDP_STATUS_SUCCESS)
|
||||
{
|
||||
DPRINT1("MouHid_GetButtonFlags failed to get usages with %x\n", Status);
|
||||
return;
|
||||
}
|
||||
|
||||
if (DeviceExtension->UsageListLength)
|
||||
{
|
||||
Index = 0;
|
||||
do
|
||||
{
|
||||
/* get usage */
|
||||
Usage = DeviceExtension->BreakUsageList[Index];
|
||||
if (!Usage)
|
||||
break;
|
||||
|
||||
if (Usage <= 5)
|
||||
{
|
||||
/* max 5 buttons supported */
|
||||
*ButtonFlags |= MouHid_ButtonDownFlags[Usage];
|
||||
}
|
||||
|
||||
/* move to next index*/
|
||||
Index++;
|
||||
}while(Index < DeviceExtension->UsageListLength);
|
||||
}
|
||||
|
||||
if (DeviceExtension->UsageListLength)
|
||||
{
|
||||
Index = 0;
|
||||
do
|
||||
{
|
||||
/* get usage */
|
||||
Usage = DeviceExtension->MakeUsageList[Index];
|
||||
if (!Usage)
|
||||
break;
|
||||
|
||||
if (Usage <= 5)
|
||||
{
|
||||
/* max 5 buttons supported */
|
||||
*ButtonFlags |= MouHid_ButtonUpFlags[Usage];
|
||||
}
|
||||
|
||||
/* move to next index*/
|
||||
Index++;
|
||||
}while(Index < DeviceExtension->UsageListLength);
|
||||
}
|
||||
|
||||
/* now switch the previous list with current list */
|
||||
TempList = DeviceExtension->CurrentUsageList;
|
||||
DeviceExtension->CurrentUsageList = DeviceExtension->PreviousUsageList;
|
||||
DeviceExtension->PreviousUsageList = TempList;
|
||||
}
|
||||
|
||||
VOID
|
||||
MouHid_DispatchInputData(
|
||||
IN PMOUHID_DEVICE_EXTENSION DeviceExtension,
|
||||
IN PMOUSE_INPUT_DATA InputData)
|
||||
{
|
||||
KIRQL OldIrql;
|
||||
ULONG InputDataConsumed;
|
||||
|
||||
if (!DeviceExtension->ClassService)
|
||||
return;
|
||||
|
||||
/* sanity check */
|
||||
ASSERT(DeviceExtension->ClassService);
|
||||
ASSERT(DeviceExtension->ClassDeviceObject);
|
||||
|
||||
/* raise irql */
|
||||
KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
|
||||
|
||||
/* dispatch input data */
|
||||
(*(PSERVICE_CALLBACK_ROUTINE)DeviceExtension->ClassService)(DeviceExtension->ClassDeviceObject, InputData, InputData + 1, &InputDataConsumed);
|
||||
|
||||
/* lower irql to previous level */
|
||||
KeLowerIrql(OldIrql);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
MouHid_ReadCompletion(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp,
|
||||
IN PVOID Context)
|
||||
{
|
||||
PMOUHID_DEVICE_EXTENSION DeviceExtension;
|
||||
USHORT ButtonFlags;
|
||||
LONG UsageValue;
|
||||
NTSTATUS Status;
|
||||
LONG LastX, LastY;
|
||||
MOUSE_INPUT_DATA MouseInputData;
|
||||
|
||||
/* get device extension */
|
||||
DeviceExtension = (PMOUHID_DEVICE_EXTENSION)Context;
|
||||
|
||||
if (Irp->IoStatus.Status == STATUS_PRIVILEGE_NOT_HELD ||
|
||||
Irp->IoStatus.Status == STATUS_DEVICE_NOT_CONNECTED ||
|
||||
Irp->IoStatus.Status == STATUS_CANCELLED ||
|
||||
DeviceExtension->StopReadReport)
|
||||
{
|
||||
/* failed to read or should be stopped*/
|
||||
DPRINT1("[MOUHID] ReadCompletion terminating read Status %x\n", Irp->IoStatus.Status);
|
||||
|
||||
/* report no longer active */
|
||||
DeviceExtension->ReadReportActive = FALSE;
|
||||
|
||||
/* request stopping of the report cycle */
|
||||
DeviceExtension->StopReadReport = FALSE;
|
||||
|
||||
/* signal completion event */
|
||||
KeSetEvent(&DeviceExtension->ReadCompletionEvent, 0, 0);
|
||||
return STATUS_MORE_PROCESSING_REQUIRED;
|
||||
}
|
||||
|
||||
/* get mouse change flags */
|
||||
MouHid_GetButtonFlags(DeviceExtension, &ButtonFlags);
|
||||
|
||||
/* get mouse change */
|
||||
MouHid_GetButtonMove(DeviceExtension, &LastX, &LastY);
|
||||
|
||||
/* init input data */
|
||||
RtlZeroMemory(&MouseInputData, sizeof(MOUSE_INPUT_DATA));
|
||||
|
||||
/* init input data */
|
||||
MouseInputData.ButtonFlags = ButtonFlags;
|
||||
MouseInputData.LastX = LastX;
|
||||
MouseInputData.LastY = LastY;
|
||||
|
||||
/* detect mouse wheel change */
|
||||
if (DeviceExtension->MouseIdentifier == WHEELMOUSE_HID_HARDWARE)
|
||||
{
|
||||
/* get usage */
|
||||
UsageValue = 0;
|
||||
Status = HidP_GetScaledUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, HIDP_LINK_COLLECTION_UNSPECIFIED, HID_USAGE_GENERIC_WHEEL, &UsageValue, DeviceExtension->PreparsedData, DeviceExtension->Report, DeviceExtension->ReportLength);
|
||||
if (Status == HIDP_STATUS_SUCCESS && UsageValue != 0)
|
||||
{
|
||||
/* store wheel status */
|
||||
MouseInputData.ButtonFlags |= MOUSE_WHEEL;
|
||||
MouseInputData.ButtonData = (USHORT)(UsageValue * WHEEL_DELTA);
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINT("[MOUHID] failed to get wheel status with %x\n", Status);
|
||||
}
|
||||
}
|
||||
|
||||
DPRINT("[MOUHID] LastX %ld LastY %ld Flags %x ButtonData %x\n", MouseInputData.LastX, MouseInputData.LastY, MouseInputData.ButtonFlags, MouseInputData.ButtonData);
|
||||
|
||||
/* dispatch mouse action */
|
||||
MouHid_DispatchInputData(DeviceExtension, &MouseInputData);
|
||||
|
||||
/* re-init read */
|
||||
MouHid_InitiateRead(DeviceExtension);
|
||||
|
||||
/* stop completion */
|
||||
return STATUS_MORE_PROCESSING_REQUIRED;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
MouHid_InitiateRead(
|
||||
IN PMOUHID_DEVICE_EXTENSION DeviceExtension)
|
||||
{
|
||||
PIO_STACK_LOCATION IoStack;
|
||||
NTSTATUS Status;
|
||||
|
||||
/* re-use irp */
|
||||
IoReuseIrp(DeviceExtension->Irp, STATUS_SUCCESS);
|
||||
|
||||
/* init irp */
|
||||
DeviceExtension->Irp->MdlAddress = DeviceExtension->ReportMDL;
|
||||
|
||||
/* get next stack location */
|
||||
IoStack = IoGetNextIrpStackLocation(DeviceExtension->Irp);
|
||||
|
||||
/* init stack location */
|
||||
IoStack->Parameters.Read.Length = DeviceExtension->ReportLength;
|
||||
IoStack->Parameters.Read.Key = 0;
|
||||
IoStack->Parameters.Read.ByteOffset.QuadPart = 0LL;
|
||||
IoStack->MajorFunction = IRP_MJ_READ;
|
||||
IoStack->FileObject = DeviceExtension->FileObject;
|
||||
|
||||
/* set completion routine */
|
||||
IoSetCompletionRoutine(DeviceExtension->Irp, MouHid_ReadCompletion, DeviceExtension, TRUE, TRUE, TRUE);
|
||||
|
||||
/* read is active */
|
||||
DeviceExtension->ReadReportActive = TRUE;
|
||||
|
||||
/* start the read */
|
||||
Status = IoCallDriver(DeviceExtension->NextDeviceObject, DeviceExtension->Irp);
|
||||
|
||||
/* done */
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
MouHid_CreateCompletion(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp,
|
||||
IN PVOID Context)
|
||||
{
|
||||
KeSetEvent((PKEVENT)Context, 0, FALSE);
|
||||
return STATUS_MORE_PROCESSING_REQUIRED;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
MouHid_Create(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
PIO_STACK_LOCATION IoStack;
|
||||
NTSTATUS Status;
|
||||
KEVENT Event;
|
||||
PMOUHID_DEVICE_EXTENSION DeviceExtension;
|
||||
|
||||
DPRINT("MOUHID: IRP_MJ_CREATE\n");
|
||||
|
||||
/* get device extension */
|
||||
DeviceExtension = (PMOUHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
|
||||
/* get stack location */
|
||||
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||
|
||||
/* copy stack location to next */
|
||||
IoCopyCurrentIrpStackLocationToNext(Irp);
|
||||
|
||||
/* init event */
|
||||
KeInitializeEvent(&Event, NotificationEvent, FALSE);
|
||||
|
||||
/* prepare irp */
|
||||
IoSetCompletionRoutine(Irp, MouHid_CreateCompletion, &Event, TRUE, TRUE, TRUE);
|
||||
|
||||
/* call lower driver */
|
||||
Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
|
||||
if (Status == STATUS_PENDING)
|
||||
{
|
||||
/* request pending */
|
||||
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
|
||||
}
|
||||
|
||||
/* check for success */
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* failed */
|
||||
Irp->IoStatus.Status = Status;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* is the driver already in use */
|
||||
if (DeviceExtension->FileObject == NULL)
|
||||
{
|
||||
/* did the caller specify correct attributes */
|
||||
ASSERT(IoStack->Parameters.Create.SecurityContext);
|
||||
if (IoStack->Parameters.Create.SecurityContext->DesiredAccess)
|
||||
{
|
||||
/* store file object */
|
||||
DeviceExtension->FileObject = IoStack->FileObject;
|
||||
|
||||
/* reset event */
|
||||
KeResetEvent(&DeviceExtension->ReadCompletionEvent);
|
||||
|
||||
/* initiating read */
|
||||
Status = MouHid_InitiateRead(DeviceExtension);
|
||||
DPRINT("[MOUHID] MouHid_InitiateRead: status %x\n", Status);
|
||||
if (Status == STATUS_PENDING)
|
||||
{
|
||||
/* report irp is pending */
|
||||
Status = STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* complete request */
|
||||
Irp->IoStatus.Status = Status;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
MouHid_Close(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
PMOUHID_DEVICE_EXTENSION DeviceExtension;
|
||||
|
||||
/* get device extension */
|
||||
DeviceExtension = (PMOUHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
|
||||
DPRINT("[MOUHID] IRP_MJ_CLOSE ReadReportActive %x\n", DeviceExtension->ReadReportActive);
|
||||
|
||||
if (DeviceExtension->ReadReportActive)
|
||||
{
|
||||
/* request stopping of the report cycle */
|
||||
DeviceExtension->StopReadReport = TRUE;
|
||||
|
||||
/* wait until the reports have been read */
|
||||
KeWaitForSingleObject(&DeviceExtension->ReadCompletionEvent, Executive, KernelMode, FALSE, NULL);
|
||||
|
||||
/* cancel irp */
|
||||
IoCancelIrp(DeviceExtension->Irp);
|
||||
}
|
||||
|
||||
DPRINT("[MOUHID] IRP_MJ_CLOSE ReadReportActive %x\n", DeviceExtension->ReadReportActive);
|
||||
|
||||
/* remove file object */
|
||||
DeviceExtension->FileObject = NULL;
|
||||
|
||||
/* skip location */
|
||||
IoSkipCurrentIrpStackLocation(Irp);
|
||||
|
||||
/* pass irp to down the stack */
|
||||
return IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
MouHid_InternalDeviceControl(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
PIO_STACK_LOCATION IoStack;
|
||||
PMOUSE_ATTRIBUTES Attributes;
|
||||
PMOUHID_DEVICE_EXTENSION DeviceExtension;
|
||||
PCONNECT_DATA Data;
|
||||
|
||||
/* get current stack location */
|
||||
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||
|
||||
DPRINT("[MOUHID] InternalDeviceControl %x\n", IoStack->Parameters.DeviceIoControl.IoControlCode);
|
||||
|
||||
/* get device extension */
|
||||
DeviceExtension = (PMOUHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
|
||||
/* handle requests */
|
||||
if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_MOUSE_QUERY_ATTRIBUTES)
|
||||
{
|
||||
/* verify output buffer length */
|
||||
if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(MOUSE_ATTRIBUTES))
|
||||
{
|
||||
/* invalid request */
|
||||
DPRINT1("[MOUHID] IOCTL_MOUSE_QUERY_ATTRIBUTES Buffer too small\n");
|
||||
Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
/* get output buffer */
|
||||
Attributes = (PMOUSE_ATTRIBUTES)Irp->AssociatedIrp.SystemBuffer;
|
||||
|
||||
/* type of mouse */
|
||||
Attributes->MouseIdentifier = DeviceExtension->MouseIdentifier;
|
||||
|
||||
/* number of buttons */
|
||||
Attributes->NumberOfButtons = DeviceExtension->UsageListLength;
|
||||
|
||||
/* sample rate not used for usb */
|
||||
Attributes->SampleRate = 0;
|
||||
|
||||
/* queue length */
|
||||
Attributes->InputDataQueueLength = 2;
|
||||
|
||||
DPRINT("[MOUHID] MouseIdentifier %x\n", Attributes->MouseIdentifier);
|
||||
DPRINT("[MOUHID] NumberOfButtons %x\n", Attributes->NumberOfButtons);
|
||||
DPRINT("[MOUHID] SampleRate %x\n", Attributes->SampleRate);
|
||||
DPRINT("[MOUHID] InputDataQueueLength %x\n", Attributes->InputDataQueueLength);
|
||||
|
||||
/* complete request */
|
||||
Irp->IoStatus.Information = sizeof(MOUSE_ATTRIBUTES);
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_MOUSE_CONNECT)
|
||||
{
|
||||
/* verify input buffer length */
|
||||
if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(CONNECT_DATA))
|
||||
{
|
||||
/* invalid request */
|
||||
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* is it already connected */
|
||||
if (DeviceExtension->ClassService)
|
||||
{
|
||||
/* already connected */
|
||||
Irp->IoStatus.Status = STATUS_SHARING_VIOLATION;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_SHARING_VIOLATION;
|
||||
}
|
||||
|
||||
/* get connect data */
|
||||
Data = (PCONNECT_DATA)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
|
||||
|
||||
/* store connect details */
|
||||
DeviceExtension->ClassDeviceObject = Data->ClassDeviceObject;
|
||||
DeviceExtension->ClassService = Data->ClassService;
|
||||
|
||||
/* completed successfully */
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_MOUSE_DISCONNECT)
|
||||
{
|
||||
/* not supported */
|
||||
Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_MOUSE_ENABLE)
|
||||
{
|
||||
/* not supported */
|
||||
Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_MOUSE_DISABLE)
|
||||
{
|
||||
/* not supported */
|
||||
Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
}
|
||||
|
||||
DPRINT1("[MOUHID] Unknown DeviceControl %x\n", IoStack->Parameters.DeviceIoControl.IoControlCode);
|
||||
/* unknown request not supported */
|
||||
Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
MouHid_DeviceControl(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
PMOUHID_DEVICE_EXTENSION DeviceExtension;
|
||||
|
||||
/* get device extension */
|
||||
DeviceExtension = (PMOUHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
|
||||
/* skip stack location */
|
||||
IoSkipCurrentIrpStackLocation(Irp);
|
||||
|
||||
/* pass and forget */
|
||||
return IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
MouHid_Power(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
MouHid_SubmitRequest(
|
||||
PDEVICE_OBJECT DeviceObject,
|
||||
ULONG IoControlCode,
|
||||
ULONG InputBufferSize,
|
||||
PVOID InputBuffer,
|
||||
ULONG OutputBufferSize,
|
||||
PVOID OutputBuffer)
|
||||
{
|
||||
KEVENT Event;
|
||||
PMOUHID_DEVICE_EXTENSION DeviceExtension;
|
||||
PIRP Irp;
|
||||
NTSTATUS Status;
|
||||
IO_STATUS_BLOCK IoStatus;
|
||||
|
||||
/* get device extension */
|
||||
DeviceExtension = (PMOUHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
|
||||
/* init event */
|
||||
KeInitializeEvent(&Event, NotificationEvent, FALSE);
|
||||
|
||||
/* build request */
|
||||
Irp = IoBuildDeviceIoControlRequest(IoControlCode, DeviceExtension->NextDeviceObject, InputBuffer, InputBufferSize, OutputBuffer, OutputBufferSize, FALSE, &Event, &IoStatus);
|
||||
if (!Irp)
|
||||
{
|
||||
/* no memory */
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
/* send request */
|
||||
Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
|
||||
if (Status == STATUS_PENDING)
|
||||
{
|
||||
/* wait for request to complete */
|
||||
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
|
||||
Status = IoStatus.Status;
|
||||
}
|
||||
|
||||
/* done */
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
MouHid_StartDevice(
|
||||
IN PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
ULONG Buttons;
|
||||
HID_COLLECTION_INFORMATION Information;
|
||||
PVOID PreparsedData;
|
||||
HIDP_CAPS Capabilities;
|
||||
ULONG ValueCapsLength;
|
||||
HIDP_VALUE_CAPS ValueCaps;
|
||||
PMOUHID_DEVICE_EXTENSION DeviceExtension;
|
||||
PUSHORT Buffer;
|
||||
|
||||
/* get device extension */
|
||||
DeviceExtension = (PMOUHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
|
||||
/* query collection information */
|
||||
Status = MouHid_SubmitRequest(DeviceObject, IOCTL_HID_GET_COLLECTION_INFORMATION, 0, NULL, sizeof(HID_COLLECTION_INFORMATION), &Information);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* failed to query collection information */
|
||||
DPRINT1("[MOUHID] failed to obtain collection information with %x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* lets allocate space for preparsed data */
|
||||
PreparsedData = ExAllocatePool(NonPagedPool, Information.DescriptorSize);
|
||||
if (!PreparsedData)
|
||||
{
|
||||
/* no memory */
|
||||
DPRINT1("[MOUHID] no memory size %u\n", Information.DescriptorSize);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
/* now obtain the preparsed data */
|
||||
Status = MouHid_SubmitRequest(DeviceObject, IOCTL_HID_GET_COLLECTION_DESCRIPTOR, 0, NULL, Information.DescriptorSize, PreparsedData);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* failed to get preparsed data */
|
||||
DPRINT1("[MOUHID] failed to obtain collection information with %x\n", Status);
|
||||
ExFreePool(PreparsedData);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* lets get the caps */
|
||||
Status = HidP_GetCaps(PreparsedData, &Capabilities);
|
||||
if (Status != HIDP_STATUS_SUCCESS)
|
||||
{
|
||||
/* failed to get capabilities */
|
||||
DPRINT1("[MOUHID] failed to obtain caps with %x\n", Status);
|
||||
ExFreePool(PreparsedData);
|
||||
return Status;
|
||||
}
|
||||
|
||||
DPRINT("[MOUHID] Usage %x UsagePage %x InputReportLength %lu\n", Capabilities.Usage, Capabilities.UsagePage, Capabilities.InputReportByteLength);
|
||||
|
||||
/* verify capabilities */
|
||||
if ((Capabilities.Usage != HID_USAGE_GENERIC_POINTER && Capabilities.Usage != HID_USAGE_GENERIC_MOUSE) || Capabilities.UsagePage != HID_USAGE_PAGE_GENERIC)
|
||||
{
|
||||
/* not supported */
|
||||
ExFreePool(PreparsedData);
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
/* init input report*/
|
||||
DeviceExtension->ReportLength = Capabilities.InputReportByteLength;
|
||||
ASSERT(DeviceExtension->ReportLength);
|
||||
DeviceExtension->Report = (PCHAR)ExAllocatePool(NonPagedPool, DeviceExtension->ReportLength);
|
||||
ASSERT(DeviceExtension->Report);
|
||||
RtlZeroMemory(DeviceExtension->Report, DeviceExtension->ReportLength);
|
||||
|
||||
/* build mdl */
|
||||
DeviceExtension->ReportMDL = IoAllocateMdl(DeviceExtension->Report, DeviceExtension->ReportLength, FALSE, FALSE, NULL);
|
||||
ASSERT(DeviceExtension->ReportMDL);
|
||||
|
||||
/* init mdl */
|
||||
MmBuildMdlForNonPagedPool(DeviceExtension->ReportMDL);
|
||||
|
||||
/* get max number of buttons */
|
||||
Buttons = HidP_MaxUsageListLength(HidP_Input, HID_USAGE_PAGE_BUTTON, PreparsedData);
|
||||
DPRINT("[MOUHID] Buttons %lu\n", Buttons);
|
||||
ASSERT(Buttons > 0);
|
||||
|
||||
/* now allocate an array for those buttons */
|
||||
Buffer = ExAllocatePool(NonPagedPool, sizeof(USAGE) * 4 * Buttons);
|
||||
if (!Buffer)
|
||||
{
|
||||
/* no memory */
|
||||
ExFreePool(PreparsedData);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
/* init usage lists */
|
||||
RtlZeroMemory(Buffer, sizeof(USAGE) * 4 * Buttons);
|
||||
DeviceExtension->CurrentUsageList = Buffer;
|
||||
Buffer += Buttons;
|
||||
DeviceExtension->PreviousUsageList = Buffer;
|
||||
Buffer += Buttons;
|
||||
DeviceExtension->MakeUsageList = Buffer;
|
||||
Buffer += Buttons;
|
||||
DeviceExtension->BreakUsageList = Buffer;
|
||||
|
||||
/* store number of buttons */
|
||||
DeviceExtension->UsageListLength = (USHORT)Buttons;
|
||||
|
||||
/* store preparsed data */
|
||||
DeviceExtension->PreparsedData = PreparsedData;
|
||||
|
||||
ValueCapsLength = 1;
|
||||
HidP_GetSpecificValueCaps(HidP_Input, HID_USAGE_PAGE_GENERIC, HIDP_LINK_COLLECTION_UNSPECIFIED, HID_USAGE_GENERIC_X, &ValueCaps, &ValueCapsLength, PreparsedData);
|
||||
|
||||
ValueCapsLength = 1;
|
||||
HidP_GetSpecificValueCaps(HidP_Input, HID_USAGE_PAGE_GENERIC, HIDP_LINK_COLLECTION_UNSPECIFIED, HID_USAGE_GENERIC_Y, &ValueCaps, &ValueCapsLength, PreparsedData);
|
||||
|
||||
/* now check for wheel mouse support */
|
||||
ValueCapsLength = 1;
|
||||
Status = HidP_GetSpecificValueCaps(HidP_Input, HID_USAGE_PAGE_GENERIC, HIDP_LINK_COLLECTION_UNSPECIFIED, HID_USAGE_GENERIC_WHEEL, &ValueCaps, &ValueCapsLength, PreparsedData);
|
||||
if (Status == HIDP_STATUS_SUCCESS )
|
||||
{
|
||||
/* mouse has wheel support */
|
||||
DeviceExtension->MouseIdentifier = WHEELMOUSE_HID_HARDWARE;
|
||||
DeviceExtension->WheelUsagePage = ValueCaps.UsagePage;
|
||||
DPRINT("[MOUHID] mouse wheel support detected\n", Status);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* check if the mouse has z-axis */
|
||||
ValueCapsLength = 1;
|
||||
Status = HidP_GetSpecificValueCaps(HidP_Input, HID_USAGE_PAGE_GENERIC, HIDP_LINK_COLLECTION_UNSPECIFIED, HID_USAGE_GENERIC_Z, &ValueCaps, &ValueCapsLength, PreparsedData);
|
||||
if (Status == HIDP_STATUS_SUCCESS && ValueCapsLength == 1)
|
||||
{
|
||||
/* wheel support */
|
||||
DeviceExtension->MouseIdentifier = WHEELMOUSE_HID_HARDWARE;
|
||||
DeviceExtension->WheelUsagePage = ValueCaps.UsagePage;
|
||||
DPRINT("[MOUHID] mouse wheel support detected with z-axis\n", Status);
|
||||
}
|
||||
}
|
||||
|
||||
/* completed successfully */
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
MouHid_StartDeviceCompletion(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp,
|
||||
IN PVOID Context)
|
||||
{
|
||||
KeSetEvent((PKEVENT)Context, 0, FALSE);
|
||||
return STATUS_MORE_PROCESSING_REQUIRED;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
MouHid_Flush(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
PIO_STACK_LOCATION IoStack;
|
||||
PMOUHID_DEVICE_EXTENSION DeviceExtension;
|
||||
|
||||
/* get device extension */
|
||||
DeviceExtension = (PMOUHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
|
||||
/* skip current stack location */
|
||||
IoSkipCurrentIrpStackLocation(Irp);
|
||||
|
||||
/* get next stack location */
|
||||
IoStack = IoGetNextIrpStackLocation(Irp);
|
||||
|
||||
/* change request to hid flush queue request */
|
||||
IoStack->MajorFunction = IRP_MJ_DEVICE_CONTROL;
|
||||
IoStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_HID_FLUSH_QUEUE;
|
||||
|
||||
/* call device */
|
||||
return IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
MouHid_Pnp(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
PIO_STACK_LOCATION IoStack;
|
||||
KEVENT Event;
|
||||
NTSTATUS Status;
|
||||
PMOUHID_DEVICE_EXTENSION DeviceExtension;
|
||||
|
||||
/* get device extension */
|
||||
DeviceExtension = (PMOUHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
|
||||
/* get current irp stack */
|
||||
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||
DPRINT("[MOUHID] IRP_MJ_PNP Request: %x\n", IoStack->MinorFunction);
|
||||
|
||||
if (IoStack->MinorFunction == IRP_MN_STOP_DEVICE ||
|
||||
IoStack->MinorFunction == IRP_MN_CANCEL_REMOVE_DEVICE ||
|
||||
IoStack->MinorFunction == IRP_MN_QUERY_STOP_DEVICE ||
|
||||
IoStack->MinorFunction == IRP_MN_CANCEL_STOP_DEVICE ||
|
||||
IoStack->MinorFunction == IRP_MN_QUERY_REMOVE_DEVICE)
|
||||
{
|
||||
/* indicate success */
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
|
||||
/* skip irp stack location */
|
||||
IoSkipCurrentIrpStackLocation(Irp);
|
||||
|
||||
/* dispatch to lower device */
|
||||
return IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
|
||||
}
|
||||
else if (IoStack->MinorFunction == IRP_MN_REMOVE_DEVICE)
|
||||
{
|
||||
/* FIXME synchronization */
|
||||
|
||||
/* request stop */
|
||||
DeviceExtension->StopReadReport = TRUE;
|
||||
|
||||
/* cancel irp */
|
||||
IoCancelIrp(DeviceExtension->Irp);
|
||||
|
||||
/* indicate success */
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
|
||||
/* skip irp stack location */
|
||||
IoSkipCurrentIrpStackLocation(Irp);
|
||||
|
||||
/* dispatch to lower device */
|
||||
Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
|
||||
|
||||
/* wait for completion of stop event */
|
||||
KeWaitForSingleObject(&DeviceExtension->ReadCompletionEvent, Executive, KernelMode, FALSE, NULL);
|
||||
|
||||
/* free irp */
|
||||
IoFreeIrp(DeviceExtension->Irp);
|
||||
|
||||
/* detach device */
|
||||
IoDetachDevice(DeviceExtension->NextDeviceObject);
|
||||
|
||||
/* delete device */
|
||||
IoDeleteDevice(DeviceObject);
|
||||
|
||||
/* done */
|
||||
return Status;
|
||||
}
|
||||
else if (IoStack->MinorFunction == IRP_MN_START_DEVICE)
|
||||
{
|
||||
/* init event */
|
||||
KeInitializeEvent(&Event, NotificationEvent, FALSE);
|
||||
|
||||
/* copy stack location */
|
||||
IoCopyCurrentIrpStackLocationToNext (Irp);
|
||||
|
||||
/* set completion routine */
|
||||
IoSetCompletionRoutine(Irp, MouHid_StartDeviceCompletion, &Event, TRUE, TRUE, TRUE);
|
||||
Irp->IoStatus.Status = 0;
|
||||
|
||||
/* pass request */
|
||||
Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
|
||||
if (Status == STATUS_PENDING)
|
||||
{
|
||||
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
|
||||
Status = Irp->IoStatus.Status;
|
||||
}
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* failed */
|
||||
Irp->IoStatus.Status = Status;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* lets start the device */
|
||||
Status = MouHid_StartDevice(DeviceObject);
|
||||
DPRINT("MouHid_StartDevice %x\n", Status);
|
||||
|
||||
/* complete request */
|
||||
Irp->IoStatus.Status = Status;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
|
||||
/* done */
|
||||
return Status;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* skip irp stack location */
|
||||
IoSkipCurrentIrpStackLocation(Irp);
|
||||
|
||||
/* dispatch to lower device */
|
||||
return IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
|
||||
}
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
MouHid_AddDevice(
|
||||
IN PDRIVER_OBJECT DriverObject,
|
||||
IN PDEVICE_OBJECT PhysicalDeviceObject)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PDEVICE_OBJECT DeviceObject, NextDeviceObject;
|
||||
PMOUHID_DEVICE_EXTENSION DeviceExtension;
|
||||
POWER_STATE State;
|
||||
|
||||
/* create device object */
|
||||
Status = IoCreateDevice(DriverObject, sizeof(MOUHID_DEVICE_EXTENSION), NULL, FILE_DEVICE_MOUSE, 0, FALSE, &DeviceObject);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* failed to create device object */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* now attach it */
|
||||
NextDeviceObject = IoAttachDeviceToDeviceStack(DeviceObject, PhysicalDeviceObject);
|
||||
if (!NextDeviceObject)
|
||||
{
|
||||
/* failed to attach */
|
||||
IoDeleteDevice(DeviceObject);
|
||||
return STATUS_DEVICE_NOT_CONNECTED;
|
||||
}
|
||||
|
||||
/* get device extension */
|
||||
DeviceExtension = (PMOUHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
|
||||
/* zero extension */
|
||||
RtlZeroMemory(DeviceExtension, sizeof(MOUHID_DEVICE_EXTENSION));
|
||||
|
||||
/* init device extension */
|
||||
DeviceExtension->MouseIdentifier = MOUSE_HID_HARDWARE;
|
||||
DeviceExtension->WheelUsagePage = 0;
|
||||
DeviceExtension->NextDeviceObject = NextDeviceObject;
|
||||
KeInitializeEvent(&DeviceExtension->ReadCompletionEvent, NotificationEvent, FALSE);
|
||||
DeviceExtension->Irp = IoAllocateIrp(NextDeviceObject->StackSize, FALSE);
|
||||
|
||||
/* FIXME handle allocation error */
|
||||
ASSERT(DeviceExtension->Irp);
|
||||
|
||||
/* FIXME query parameter 'FlipFlopWheel', 'WheelScalingFactor' */
|
||||
|
||||
/* set power state to D0 */
|
||||
State.DeviceState = PowerDeviceD0;
|
||||
PoSetPowerState(DeviceObject, DevicePowerState, State);
|
||||
|
||||
/* init device object */
|
||||
DeviceObject->Flags |= DO_BUFFERED_IO | DO_POWER_PAGABLE;
|
||||
DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
|
||||
|
||||
/* completed successfully */
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
MouHid_Unload(
|
||||
IN PDRIVER_OBJECT DriverObject)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
DriverEntry(
|
||||
IN PDRIVER_OBJECT DriverObject,
|
||||
IN PUNICODE_STRING RegPath)
|
||||
{
|
||||
/* FIXME check for parameters 'UseOnlyMice', 'TreatAbsoluteAsRelative', 'TreatAbsolutePointerAsAbsolute' */
|
||||
|
||||
/* initialize driver object */
|
||||
DriverObject->DriverUnload = MouHid_Unload;
|
||||
DriverObject->DriverExtension->AddDevice = MouHid_AddDevice;
|
||||
DriverObject->MajorFunction[IRP_MJ_CREATE] = MouHid_Create;
|
||||
DriverObject->MajorFunction[IRP_MJ_CLOSE] = MouHid_Close;
|
||||
DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = MouHid_Flush;
|
||||
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = MouHid_DeviceControl;
|
||||
DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = MouHid_InternalDeviceControl;
|
||||
DriverObject->MajorFunction[IRP_MJ_POWER] = MouHid_Power;
|
||||
DriverObject->MajorFunction[IRP_MJ_PNP] = MouHid_Pnp;
|
||||
DriverObject->DriverUnload = MouHid_Unload;
|
||||
DriverObject->DriverExtension->AddDevice = MouHid_AddDevice;
|
||||
|
||||
/* done */
|
||||
return STATUS_SUCCESS;
|
||||
}
|
118
reactos/drivers/hid/mouhid/mouhid.h
Normal file
118
reactos/drivers/hid/mouhid/mouhid.h
Normal file
|
@ -0,0 +1,118 @@
|
|||
#pragma once
|
||||
|
||||
#define _HIDPI_NO_FUNCTION_MACROS_
|
||||
#include <ntddk.h>
|
||||
#include <hidclass.h>
|
||||
#include <hidpddi.h>
|
||||
#include <hidpi.h>
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
#include <ntddmou.h>
|
||||
#include <kbdmou.h>
|
||||
#include <debug.h>
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
//
|
||||
// lower device object
|
||||
//
|
||||
PDEVICE_OBJECT NextDeviceObject;
|
||||
|
||||
//
|
||||
// irp which is used for reading input reports
|
||||
//
|
||||
PIRP Irp;
|
||||
|
||||
//
|
||||
// event
|
||||
//
|
||||
KEVENT ReadCompletionEvent;
|
||||
|
||||
//
|
||||
// device object for class callback
|
||||
//
|
||||
PDEVICE_OBJECT ClassDeviceObject;
|
||||
|
||||
//
|
||||
// class callback
|
||||
//
|
||||
PVOID ClassService;
|
||||
|
||||
//
|
||||
// mouse type
|
||||
//
|
||||
USHORT MouseIdentifier;
|
||||
|
||||
//
|
||||
// wheel usage page
|
||||
//
|
||||
USHORT WheelUsagePage;
|
||||
|
||||
//
|
||||
// usage list length
|
||||
//
|
||||
USHORT UsageListLength;
|
||||
|
||||
//
|
||||
// current usage list length
|
||||
//
|
||||
PUSAGE CurrentUsageList;
|
||||
|
||||
//
|
||||
// previous usage list
|
||||
//
|
||||
PUSAGE PreviousUsageList;
|
||||
|
||||
//
|
||||
// removed usage item list
|
||||
//
|
||||
PUSAGE BreakUsageList;
|
||||
|
||||
//
|
||||
// new item usage list
|
||||
//
|
||||
PUSAGE MakeUsageList;
|
||||
|
||||
//
|
||||
// preparsed data
|
||||
//
|
||||
PVOID PreparsedData;
|
||||
|
||||
//
|
||||
// mdl for reading input report
|
||||
//
|
||||
PMDL ReportMDL;
|
||||
|
||||
//
|
||||
// input report buffer
|
||||
//
|
||||
PCHAR Report;
|
||||
|
||||
//
|
||||
// input report length
|
||||
//
|
||||
ULONG ReportLength;
|
||||
|
||||
//
|
||||
// file object the device is reading reports from
|
||||
//
|
||||
PFILE_OBJECT FileObject;
|
||||
|
||||
//
|
||||
// report read is active
|
||||
//
|
||||
UCHAR ReadReportActive;
|
||||
|
||||
//
|
||||
// stop reading flag
|
||||
//
|
||||
UCHAR StopReadReport;
|
||||
|
||||
}MOUHID_DEVICE_EXTENSION, *PMOUHID_DEVICE_EXTENSION;
|
||||
|
||||
#define WHEEL_DELTA 120
|
||||
|
||||
NTSTATUS
|
||||
MouHid_InitiateRead(
|
||||
IN PMOUHID_DEVICE_EXTENSION DeviceExtension);
|
11
reactos/drivers/hid/mouhid/mouhid.rbuild
Normal file
11
reactos/drivers/hid/mouhid/mouhid.rbuild
Normal file
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0"?>
|
||||
<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
|
||||
<module name="mouhid" type="kernelmodedriver" installbase="system32/drivers" installname="mouhid.sys">
|
||||
<define name="DEBUG_MODE" />
|
||||
<include base="ntoskrnl">include</include>
|
||||
<library>ntoskrnl</library>
|
||||
<library>hal</library>
|
||||
<library>hidparse</library>
|
||||
<file>mouhid.c</file>
|
||||
<file>mouhid.rc</file>
|
||||
</module>
|
5
reactos/drivers/hid/mouhid/mouhid.rc
Normal file
5
reactos/drivers/hid/mouhid/mouhid.rc
Normal file
|
@ -0,0 +1,5 @@
|
|||
#define REACTOS_VERSION_DLL
|
||||
#define REACTOS_STR_FILE_DESCRIPTION "Mouse HID Class Driver\0"
|
||||
#define REACTOS_STR_INTERNAL_NAME "mouhid\0"
|
||||
#define REACTOS_STR_ORIGINAL_FILENAME "mouhid.sys\0"
|
||||
#include <reactos/version.rc>
|
|
@ -824,6 +824,72 @@ HandleReadIrp(
|
|||
return Status;
|
||||
}
|
||||
|
||||
static NTSTATUS NTAPI
|
||||
ClassPnp(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
PPORT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
|
||||
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
IO_STATUS_BLOCK Iosb;
|
||||
NTSTATUS Status;
|
||||
|
||||
switch (IrpSp->MinorFunction)
|
||||
{
|
||||
case IRP_MN_START_DEVICE:
|
||||
Status = ForwardIrpAndWait(DeviceObject, Irp);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&DeviceExtension->InterfaceName,
|
||||
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
Status = ZwOpenFile(&DeviceExtension->FileHandle,
|
||||
FILE_READ_DATA,
|
||||
&ObjectAttributes,
|
||||
&Iosb,
|
||||
0,
|
||||
0);
|
||||
if (!NT_SUCCESS(Status))
|
||||
DeviceExtension->FileHandle = NULL;
|
||||
}
|
||||
else
|
||||
DeviceExtension->FileHandle = NULL;
|
||||
Irp->IoStatus.Status = Status;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return Status;
|
||||
|
||||
case IRP_MN_REMOVE_DEVICE:
|
||||
case IRP_MN_STOP_DEVICE:
|
||||
if (DeviceExtension->FileHandle)
|
||||
{
|
||||
ZwClose(DeviceExtension->FileHandle);
|
||||
DeviceExtension->FileHandle = NULL;
|
||||
}
|
||||
Status = STATUS_SUCCESS;
|
||||
break;
|
||||
|
||||
default:
|
||||
Status = Irp->IoStatus.Status;
|
||||
break;
|
||||
}
|
||||
|
||||
Irp->IoStatus.Status = Status;
|
||||
if (NT_SUCCESS(Status) || Status == STATUS_NOT_SUPPORTED)
|
||||
{
|
||||
IoSkipCurrentIrpStackLocation(Irp);
|
||||
return IoCallDriver(DeviceExtension->LowerDevice, Irp);
|
||||
}
|
||||
else
|
||||
{
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
static VOID NTAPI
|
||||
ClassStartIo(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
|
@ -1021,6 +1087,7 @@ DriverEntry(
|
|||
DriverObject->MajorFunction[IRP_MJ_CLOSE] = ClassClose;
|
||||
DriverObject->MajorFunction[IRP_MJ_CLEANUP] = ClassCleanup;
|
||||
DriverObject->MajorFunction[IRP_MJ_READ] = ClassRead;
|
||||
DriverObject->MajorFunction[IRP_MJ_PNP] = ClassPnp;
|
||||
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ClassDeviceControl;
|
||||
DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = ForwardIrpAndForget;
|
||||
DriverObject->DriverStartIo = ClassStartIo;
|
||||
|
|
|
@ -48,6 +48,7 @@ typedef struct _PORT_DEVICE_EXTENSION
|
|||
PORT_DEVICE_STATE PnpState;
|
||||
PDEVICE_OBJECT LowerDevice;
|
||||
PDEVICE_OBJECT ClassDO;
|
||||
HANDLE FileHandle;
|
||||
UNICODE_STRING InterfaceName;
|
||||
} PORT_DEVICE_EXTENSION, *PPORT_DEVICE_EXTENSION;
|
||||
|
||||
|
|
|
@ -800,6 +800,72 @@ HandleReadIrp(
|
|||
return Status;
|
||||
}
|
||||
|
||||
static NTSTATUS NTAPI
|
||||
ClassPnp(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
PPORT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
|
||||
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
IO_STATUS_BLOCK Iosb;
|
||||
NTSTATUS Status;
|
||||
|
||||
switch (IrpSp->MinorFunction)
|
||||
{
|
||||
case IRP_MN_START_DEVICE:
|
||||
Status = ForwardIrpAndWait(DeviceObject, Irp);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&DeviceExtension->InterfaceName,
|
||||
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
Status = ZwOpenFile(&DeviceExtension->FileHandle,
|
||||
FILE_READ_DATA,
|
||||
&ObjectAttributes,
|
||||
&Iosb,
|
||||
0,
|
||||
0);
|
||||
if (!NT_SUCCESS(Status))
|
||||
DeviceExtension->FileHandle = NULL;
|
||||
}
|
||||
else
|
||||
DeviceExtension->FileHandle = NULL;
|
||||
Irp->IoStatus.Status = Status;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return Status;
|
||||
|
||||
case IRP_MN_REMOVE_DEVICE:
|
||||
case IRP_MN_STOP_DEVICE:
|
||||
if (DeviceExtension->FileHandle)
|
||||
{
|
||||
ZwClose(DeviceExtension->FileHandle);
|
||||
DeviceExtension->FileHandle = NULL;
|
||||
}
|
||||
Status = STATUS_SUCCESS;
|
||||
break;
|
||||
|
||||
default:
|
||||
Status = Irp->IoStatus.Status;
|
||||
break;
|
||||
}
|
||||
|
||||
Irp->IoStatus.Status = Status;
|
||||
if (NT_SUCCESS(Status) || Status == STATUS_NOT_SUPPORTED)
|
||||
{
|
||||
IoSkipCurrentIrpStackLocation(Irp);
|
||||
return IoCallDriver(DeviceExtension->LowerDevice, Irp);
|
||||
}
|
||||
else
|
||||
{
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
static VOID NTAPI
|
||||
ClassStartIo(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
|
@ -993,6 +1059,7 @@ DriverEntry(
|
|||
DriverObject->MajorFunction[IRP_MJ_CLOSE] = ClassClose;
|
||||
DriverObject->MajorFunction[IRP_MJ_CLEANUP] = ClassCleanup;
|
||||
DriverObject->MajorFunction[IRP_MJ_READ] = ClassRead;
|
||||
DriverObject->MajorFunction[IRP_MJ_PNP] = ClassPnp;
|
||||
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ClassDeviceControl;
|
||||
DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = ForwardIrpAndForget;
|
||||
DriverObject->DriverStartIo = ClassStartIo;
|
||||
|
|
|
@ -48,6 +48,7 @@ typedef struct _PORT_DEVICE_EXTENSION
|
|||
PORT_DEVICE_STATE PnpState;
|
||||
PDEVICE_OBJECT LowerDevice;
|
||||
PDEVICE_OBJECT ClassDO;
|
||||
HANDLE FileHandle;
|
||||
UNICODE_STRING InterfaceName;
|
||||
} PORT_DEVICE_EXTENSION, *PPORT_DEVICE_EXTENSION;
|
||||
|
||||
|
|
|
@ -2,4 +2,5 @@
|
|||
add_subdirectory(cdrom)
|
||||
add_subdirectory(class2)
|
||||
add_subdirectory(disk)
|
||||
add_subdirectory(disk_new)
|
||||
add_subdirectory(ramdisk)
|
||||
|
|
|
@ -12,6 +12,10 @@
|
|||
#include <include/class2.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* Part of the drive letter hack */
|
||||
#include <ntifs.h>
|
||||
#include <ketypes.h>
|
||||
|
||||
//#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
|
@ -130,6 +134,272 @@ DriverEntry(
|
|||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* The following hack to assign drive letters with a non-PnP storage stack */
|
||||
|
||||
typedef struct _CLASS_DEVICE_INFO {
|
||||
ULONG Partitions;
|
||||
ULONG DeviceNumber;
|
||||
ULONG DriveNumber;
|
||||
PDEVICE_OBJECT LowerDevice;
|
||||
} CLASS_DEVICE_INFO, *PCLASS_DEVICE_INFO;
|
||||
|
||||
typedef struct _CLASS_DRIVER_EXTENSION {
|
||||
ULONG PortNumber;
|
||||
CLASS_INIT_DATA InitializationData;
|
||||
} CLASS_DRIVER_EXTENSION, *PCLASS_DRIVER_EXTENSION;
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
ScsiClassRemoveDriveLetter(PCLASS_DEVICE_INFO DeviceInfo)
|
||||
{
|
||||
WCHAR Buffer1[100];
|
||||
UNICODE_STRING DriveLetterU;
|
||||
ULONG Index;
|
||||
|
||||
DriveLetterU.Buffer = Buffer1;
|
||||
DriveLetterU.MaximumLength = sizeof(Buffer1);
|
||||
|
||||
/* Delete the symbolic link to PhysicalDriveX */
|
||||
DriveLetterU.Length = swprintf(DriveLetterU.Buffer, L"\\??\\PhysicalDrive%d", DeviceInfo->DriveNumber) * sizeof(WCHAR);
|
||||
IoDeleteSymbolicLink(&DriveLetterU);
|
||||
|
||||
DbgPrint("HACK: Deleted symbolic link %wZ\n", &DriveLetterU);
|
||||
|
||||
for (Index = 0; Index < sizeof(ULONG) * 8; Index++)
|
||||
{
|
||||
if (DeviceInfo->Partitions & (1 << Index))
|
||||
{
|
||||
DriveLetterU.Length = swprintf(DriveLetterU.Buffer, L"\\??\\%C:", ('C' + Index)) * sizeof(WCHAR);
|
||||
IoDeleteSymbolicLink(&DriveLetterU);
|
||||
DbgPrint("HACK: Deleted symbolic link %wZ\n", &DriveLetterU);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ScsiClassAssignDriveLetter(PCLASS_DEVICE_INFO DeviceInfo)
|
||||
{
|
||||
WCHAR Buffer1[100];
|
||||
WCHAR Buffer2[100];
|
||||
UNICODE_STRING DriveLetterU, PartitionU;
|
||||
NTSTATUS Status;
|
||||
ULONG Index, PartitionNumber, DeviceNumber, DriveNumber;
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
IO_STATUS_BLOCK Iosb;
|
||||
HANDLE PartitionHandle;
|
||||
|
||||
/* We assume this device does not current have a drive letter */
|
||||
|
||||
Index = 0;
|
||||
DeviceNumber = 0;
|
||||
DriveNumber = 0;
|
||||
PartitionNumber = 1;
|
||||
DriveLetterU.Buffer = Buffer1;
|
||||
DriveLetterU.MaximumLength = sizeof(Buffer1);
|
||||
PartitionU.Buffer = Buffer2;
|
||||
PartitionU.MaximumLength = sizeof(Buffer2);
|
||||
|
||||
/* Determine the correct disk number */
|
||||
do
|
||||
{
|
||||
/* Check that the disk exists */
|
||||
PartitionU.Length = swprintf(PartitionU.Buffer, L"\\Device\\HardDisk%d\\Partition0", DeviceNumber) * sizeof(WCHAR);
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&PartitionU,
|
||||
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
|
||||
NULL,
|
||||
NULL);
|
||||
Status = ZwOpenFile(&PartitionHandle,
|
||||
FILE_READ_ATTRIBUTES,
|
||||
&ObjectAttributes,
|
||||
&Iosb,
|
||||
0,
|
||||
0);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* Return the last one that worked */
|
||||
DeviceNumber--;
|
||||
}
|
||||
else
|
||||
{
|
||||
ZwClose(PartitionHandle);
|
||||
DeviceNumber++;
|
||||
}
|
||||
} while (Status == STATUS_SUCCESS);
|
||||
|
||||
/* Determine the correct drive number */
|
||||
do
|
||||
{
|
||||
/* Check that the drive exists */
|
||||
PartitionU.Length = swprintf(PartitionU.Buffer, L"\\??\\PhysicalDrive%d", DriveNumber) * sizeof(WCHAR);
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&PartitionU,
|
||||
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
|
||||
NULL,
|
||||
NULL);
|
||||
Status = ZwOpenFile(&PartitionHandle,
|
||||
FILE_READ_ATTRIBUTES,
|
||||
&ObjectAttributes,
|
||||
&Iosb,
|
||||
0,
|
||||
0);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
ZwClose(PartitionHandle);
|
||||
DriveNumber++;
|
||||
}
|
||||
} while (Status == STATUS_SUCCESS);
|
||||
|
||||
/* Create the symbolic link to PhysicalDriveX */
|
||||
PartitionU.Length = swprintf(PartitionU.Buffer, L"\\Device\\Harddisk%d\\Partition0", DeviceNumber) * sizeof(WCHAR);
|
||||
DriveLetterU.Length = swprintf(DriveLetterU.Buffer, L"\\??\\PhysicalDrive%d", DriveNumber) * sizeof(WCHAR);
|
||||
|
||||
Status = IoCreateSymbolicLink(&DriveLetterU, &PartitionU);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* Failed to create symbolic link */
|
||||
return Status;
|
||||
}
|
||||
|
||||
DbgPrint("HACK: Created symbolic link %wZ -> %wZ\n", &PartitionU, &DriveLetterU);
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
/* Check that the disk exists */
|
||||
PartitionU.Length = swprintf(PartitionU.Buffer, L"\\Device\\Harddisk%d\\Partition%d", DeviceNumber, PartitionNumber) * sizeof(WCHAR);
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&PartitionU,
|
||||
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
|
||||
NULL,
|
||||
NULL);
|
||||
Status = ZwOpenFile(&PartitionHandle,
|
||||
FILE_READ_ATTRIBUTES,
|
||||
&ObjectAttributes,
|
||||
&Iosb,
|
||||
0,
|
||||
0);
|
||||
if (!NT_SUCCESS(Status))
|
||||
break;
|
||||
else
|
||||
{
|
||||
ZwClose(PartitionHandle);
|
||||
|
||||
/* Assign it a drive letter */
|
||||
do
|
||||
{
|
||||
DriveLetterU.Length = swprintf(DriveLetterU.Buffer, L"\\??\\%C:", ('C' + Index)) * sizeof(WCHAR);
|
||||
|
||||
Status = IoCreateSymbolicLink(&DriveLetterU, &PartitionU);
|
||||
|
||||
Index++;
|
||||
} while (Status != STATUS_SUCCESS);
|
||||
|
||||
DeviceInfo->Partitions |= (1 << (Index - 1));
|
||||
|
||||
DbgPrint("HACK: Created symbolic link %wZ -> %wZ\n", &PartitionU, &DriveLetterU);
|
||||
PartitionNumber++;
|
||||
}
|
||||
}
|
||||
|
||||
DeviceInfo->DeviceNumber = DeviceNumber;
|
||||
DeviceInfo->DriveNumber = DriveNumber;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ScsiClassPlugPlay(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
||||
|
||||
if (IrpSp->MinorFunction == IRP_MN_START_DEVICE)
|
||||
{
|
||||
IoSkipCurrentIrpStackLocation(Irp);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
else if (IrpSp->MinorFunction == IRP_MN_REMOVE_DEVICE)
|
||||
{
|
||||
PCLASS_DEVICE_INFO DeviceInfo = DeviceObject->DeviceExtension;
|
||||
|
||||
ScsiClassRemoveDriveLetter(DeviceInfo);
|
||||
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
|
||||
IoDetachDevice(DeviceInfo->LowerDevice);
|
||||
IoDeleteDevice(DeviceObject);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ScsiClassAddDevice(
|
||||
IN PDRIVER_OBJECT DriverObject,
|
||||
IN PDEVICE_OBJECT PhysicalDeviceObject)
|
||||
{
|
||||
PCLASS_DRIVER_EXTENSION DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject);
|
||||
PCLASS_DEVICE_INFO DeviceInfo;
|
||||
PDEVICE_OBJECT DeviceObject;
|
||||
NTSTATUS Status;
|
||||
|
||||
if (DriverExtension->InitializationData.ClassFindDevices(DriverObject, NULL, &DriverExtension->InitializationData,
|
||||
PhysicalDeviceObject, DriverExtension->PortNumber))
|
||||
{
|
||||
/* Create a device object */
|
||||
Status = IoCreateDevice(DriverObject,
|
||||
sizeof(CLASS_DEVICE_INFO),
|
||||
NULL,
|
||||
FILE_DEVICE_DISK,
|
||||
0,
|
||||
FALSE,
|
||||
&DeviceObject);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
DeviceInfo = DeviceObject->DeviceExtension;
|
||||
RtlZeroMemory(DeviceInfo, sizeof(CLASS_DEVICE_INFO));
|
||||
|
||||
/* Attach it to the PDO */
|
||||
DeviceInfo->LowerDevice = IoAttachDeviceToDeviceStack(DeviceObject, PhysicalDeviceObject);
|
||||
|
||||
/* Check that the kernel has already assigned drive letters */
|
||||
if (KeLoaderBlock == NULL)
|
||||
{
|
||||
/* Assign a drive letter */
|
||||
ScsiClassAssignDriveLetter(DeviceInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The kernel will handle it */
|
||||
}
|
||||
|
||||
/* Move to the next port number */
|
||||
DriverExtension->PortNumber++;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Failed to find device */
|
||||
DbgPrint("FAILED TO FIND DEVICE!\n");
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
/* ---- End hack ---- */
|
||||
|
||||
|
||||
|
||||
ULONG
|
||||
NTAPI
|
||||
|
@ -162,7 +432,6 @@ Return Value:
|
|||
|
||||
|
||||
PDRIVER_OBJECT DriverObject = Argument1;
|
||||
ULONG portNumber = 0;
|
||||
PDEVICE_OBJECT portDeviceObject;
|
||||
NTSTATUS status;
|
||||
STRING deviceNameString;
|
||||
|
@ -170,6 +439,7 @@ Return Value:
|
|||
PFILE_OBJECT fileObject;
|
||||
CCHAR deviceNameBuffer[256];
|
||||
BOOLEAN deviceFound = FALSE;
|
||||
PCLASS_DRIVER_EXTENSION DriverExtension;
|
||||
|
||||
DebugPrint((3,"\n\nSCSI Class Driver\n"));
|
||||
|
||||
|
@ -200,6 +470,16 @@ Return Value:
|
|||
return (ULONG) STATUS_REVISION_MISMATCH;
|
||||
}
|
||||
|
||||
status = IoAllocateDriverObjectExtension(DriverObject,
|
||||
DriverObject,
|
||||
sizeof(CLASS_DRIVER_EXTENSION),
|
||||
(PVOID *)&DriverExtension);
|
||||
if (!NT_SUCCESS(status))
|
||||
return status;
|
||||
|
||||
RtlCopyMemory(&DriverExtension->InitializationData, InitializationData, sizeof(CLASS_INIT_DATA));
|
||||
DriverExtension->PortNumber = 0;
|
||||
|
||||
//
|
||||
// Update driver object with entry points.
|
||||
//
|
||||
|
@ -208,10 +488,12 @@ Return Value:
|
|||
DriverObject->MajorFunction[IRP_MJ_CLOSE] = ScsiClassCreateClose;
|
||||
DriverObject->MajorFunction[IRP_MJ_READ] = ScsiClassReadWrite;
|
||||
DriverObject->MajorFunction[IRP_MJ_WRITE] = ScsiClassReadWrite;
|
||||
DriverObject->MajorFunction[IRP_MJ_PNP] = ScsiClassPlugPlay;
|
||||
DriverObject->MajorFunction[IRP_MJ_SCSI] = ScsiClassInternalIoControl;
|
||||
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ScsiClassDeviceControlDispatch;
|
||||
DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = ScsiClassShutdownFlush;
|
||||
DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = ScsiClassShutdownFlush;
|
||||
DriverObject->DriverExtension->AddDevice = ScsiClassAddDevice;
|
||||
|
||||
if (InitializationData->ClassStartIo) {
|
||||
DriverObject->DriverStartIo = InitializationData->ClassStartIo;
|
||||
|
@ -223,7 +505,7 @@ Return Value:
|
|||
|
||||
do {
|
||||
|
||||
sprintf(deviceNameBuffer, "\\Device\\ScsiPort%lu", portNumber);
|
||||
sprintf(deviceNameBuffer, "\\Device\\ScsiPort%lu", DriverExtension->PortNumber);
|
||||
|
||||
DebugPrint((2, "ScsiClassInitialize: Open Port %s\n", deviceNameBuffer));
|
||||
|
||||
|
@ -249,7 +531,7 @@ Return Value:
|
|||
//
|
||||
|
||||
if (InitializationData->ClassFindDevices(DriverObject, Argument2, InitializationData,
|
||||
portDeviceObject, portNumber)) {
|
||||
portDeviceObject, DriverExtension->PortNumber)) {
|
||||
|
||||
deviceFound = TRUE;
|
||||
}
|
||||
|
@ -259,11 +541,12 @@ Return Value:
|
|||
// Check next SCSI adapter.
|
||||
//
|
||||
|
||||
portNumber++;
|
||||
DriverExtension->PortNumber++;
|
||||
|
||||
} while(NT_SUCCESS(status));
|
||||
|
||||
return deviceFound ? STATUS_SUCCESS : STATUS_NO_SUCH_DEVICE;
|
||||
/* We don't want to fail init just because we don't have devices right now */
|
||||
return STATUS_SUCCESS; /*deviceFound ? STATUS_SUCCESS : STATUS_NO_SUCH_DEVICE;*/
|
||||
}
|
||||
|
||||
|
||||
|
|
12
reactos/drivers/storage/class/disk_new/CMakeLists.txt
Normal file
12
reactos/drivers/storage/class/disk_new/CMakeLists.txt
Normal file
|
@ -0,0 +1,12 @@
|
|||
include_directories(..)
|
||||
|
||||
add_library(disk_new SHARED data.c disk.c diskwmi.c enum.c geometry.c part.c pnp.c disk.rc)
|
||||
|
||||
target_link_libraries(disk_new libcntpr wdmguid)
|
||||
if(NOT MSVC AND ARCH MATCHES i386)
|
||||
add_target_compile_flags(disk_new "-mrtd -fno-builtin -Wno-unused-variable -Wno-pointer-sign")
|
||||
endif()
|
||||
|
||||
set_module_type(disk_new kernelmodedriver)
|
||||
add_importlibs(disk_new classpnp ntoskrnl hal)
|
||||
add_cd_file(TARGET disk_new DESTINATION reactos/system32/drivers NO_CAB FOR all)
|
82
reactos/drivers/storage/class/disk_new/data.c
Normal file
82
reactos/drivers/storage/class/disk_new/data.c
Normal file
|
@ -0,0 +1,82 @@
|
|||
/*++
|
||||
|
||||
Copyright (C) Microsoft Corporation, 1991 - 1999
|
||||
|
||||
Module Name:
|
||||
|
||||
disk.c
|
||||
|
||||
Abstract:
|
||||
|
||||
SCSI disk class driver
|
||||
|
||||
Environment:
|
||||
|
||||
kernel mode only
|
||||
|
||||
Notes:
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#include "disk.h"
|
||||
|
||||
#ifdef ALLOC_DATA_PRAGMA
|
||||
#pragma data_seg("PAGE")
|
||||
#endif
|
||||
|
||||
/*
|
||||
#define HackDisableTaggedQueuing (0x01)
|
||||
#define HackDisableSynchronousTransfers (0x02)
|
||||
#define HackDisableSpinDown (0x04)
|
||||
#define HackDisableWriteCache (0x08)
|
||||
#define HackCauseNotReportableHack (0x10)
|
||||
#define HackRequiresStartUnitCommand (0x20)
|
||||
*/
|
||||
|
||||
CLASSPNP_SCAN_FOR_SPECIAL_INFO DiskBadControllers[] = {
|
||||
{ "COMPAQ" , "PD-1" , NULL, 0x02 },
|
||||
{ "CONNER" , "CP3500" , NULL, 0x02 },
|
||||
{ "FUJITSU" , "M2652S-512" , NULL, 0x01 },
|
||||
{ "HP ", "C1113F " , NULL, 0x20 },
|
||||
// iomegas require START_UNIT commands so be sure to match all of them.
|
||||
{ "iomega" , "jaz" , NULL, 0x30 },
|
||||
{ "iomega" , NULL , NULL, 0x20 },
|
||||
{ "IOMEGA" , "ZIP" , NULL, 0x27 },
|
||||
{ "IOMEGA" , NULL , NULL, 0x20 },
|
||||
{ "MAXTOR" , "MXT-540SL" , "I1.2", 0x01 },
|
||||
{ "MICROP" , "1936-21MW1002002" , NULL, 0x03 },
|
||||
{ "OLIVETTI", "CP3500" , NULL, 0x02 },
|
||||
{ "SEAGATE" , "ST41601N" , "0102", 0x02 },
|
||||
{ "SEAGATE" , "ST3655N" , NULL, 0x08 },
|
||||
{ "SEAGATE" , "ST3390N" , NULL, 0x08 },
|
||||
{ "SEAGATE" , "ST12550N" , NULL, 0x08 },
|
||||
{ "SEAGATE" , "ST32430N" , NULL, 0x08 },
|
||||
{ "SEAGATE" , "ST31230N" , NULL, 0x08 },
|
||||
{ "SEAGATE" , "ST15230N" , NULL, 0x08 },
|
||||
{ "SyQuest" , "SQ5110" , "CHC", 0x03 },
|
||||
{ "TOSHIBA" , "MK538FB" , "60", 0x01 },
|
||||
{ NULL , NULL , NULL, 0x0 }
|
||||
};
|
||||
|
||||
//
|
||||
// ======== ROS DIFF ========
|
||||
// Added MediaTypes in their own brace nesting level
|
||||
// ======== ROS DIFF ========
|
||||
//
|
||||
DISK_MEDIA_TYPES_LIST const DiskMediaTypes[] = {
|
||||
{ "COMPAQ" , "PD-1 LF-1094" , NULL, 1, 1, {PC_5_RW , 0 , 0 , 0 }},
|
||||
{ "HP" , NULL , NULL, 2, 2, {MO_5_WO , MO_5_RW, 0 , 0 }},
|
||||
{ "iomega" , "jaz" , NULL, 1, 1, {IOMEGA_JAZ , 0 , 0 , 0 }},
|
||||
{ "IOMEGA" , "ZIP" , NULL, 1, 1, {IOMEGA_ZIP , 0 , 0 , 0 }},
|
||||
{ "PINNACLE", "Apex 4.6GB" , NULL, 3, 2, {PINNACLE_APEX_5_RW, MO_5_RW, MO_5_WO, 0 }},
|
||||
{ "SONY" , "SMO-F541" , NULL, 2, 2, {MO_5_WO , MO_5_RW, 0 , 0 }},
|
||||
{ "SONY" , "SMO-F551" , NULL, 2, 2, {MO_5_WO , MO_5_RW, 0 , 0 }},
|
||||
{ NULL , NULL , NULL, 0, 0, {0 , 0 , 0 , 0 }}
|
||||
};
|
||||
|
||||
#ifdef ALLOC_DATA_PRAGMA
|
||||
#pragma data_seg()
|
||||
#endif
|
||||
|
6576
reactos/drivers/storage/class/disk_new/disk.c
Normal file
6576
reactos/drivers/storage/class/disk_new/disk.c
Normal file
File diff suppressed because it is too large
Load diff
910
reactos/drivers/storage/class/disk_new/disk.h
Normal file
910
reactos/drivers/storage/class/disk_new/disk.h
Normal file
|
@ -0,0 +1,910 @@
|
|||
/*++
|
||||
|
||||
Copyright (C) Microsoft Corporation, 1991 - 1999
|
||||
|
||||
Module Name:
|
||||
|
||||
disk.c
|
||||
|
||||
Abstract:
|
||||
|
||||
SCSI disk class driver
|
||||
|
||||
Environment:
|
||||
|
||||
kernel mode only
|
||||
|
||||
Notes:
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#undef _WIN32_WINNT
|
||||
#define _WIN32_WINNT 0x0501
|
||||
#define NTDDI_VERSION NTDDI_WINXP
|
||||
|
||||
#include "ntddk.h"
|
||||
#include "scsi.h"
|
||||
#include <wmidata.h>
|
||||
#include "classpnp.h"
|
||||
#if defined(JAPAN) && defined(_X86_)
|
||||
#include "machine.h"
|
||||
#endif
|
||||
|
||||
#include <wmistr.h>
|
||||
|
||||
#if defined(_X86_)
|
||||
#include "mountdev.h"
|
||||
#endif
|
||||
|
||||
#ifdef ExAllocatePool
|
||||
#undef ExAllocatePool
|
||||
#define ExAllocatePool #assert(FALSE)
|
||||
#endif
|
||||
|
||||
#define DISK_TAG_GENERAL ' DcS' // "ScD " - generic tag
|
||||
#define DISK_TAG_SMART 'aDcS' // "ScDa" - SMART allocations
|
||||
#define DISK_TAG_INFO_EXCEPTION 'ADcS' // "ScDA" - Info Exceptions
|
||||
#define DISK_TAG_DISABLE_CACHE 'CDcS' // "ScDC" - disable cache paths
|
||||
#define DISK_TAG_CCONTEXT 'cDcS' // "ScDc" - disk allocated completion context
|
||||
#define DISK_TAG_DISK_GEOM 'GDcS' // "ScDG" - disk geometry buffer
|
||||
#define DISK_TAG_UPDATE_GEOM 'gDcS' // "ScDg" - update disk geometry paths
|
||||
#define DISK_TAG_SENSE_INFO 'IDcS' // "ScDI" - sense info buffers
|
||||
#define DISK_TAG_PNP_ID 'iDcS' // "ScDp" - pnp ids
|
||||
#define DISK_TAG_MODE_DATA 'MDcS' // "ScDM" - mode data buffer
|
||||
#define DISK_CACHE_MBR_CHECK 'mDcS' // "ScDM" - mbr checksum code
|
||||
#define DISK_TAG_NAME 'NDcS' // "ScDN" - disk name code
|
||||
#define DISK_TAG_READ_CAP 'PDcS' // "ScDP" - read capacity buffer
|
||||
#define DISK_TAG_PART_LIST 'pDcS' // "ScDp" - disk partition lists
|
||||
#define DISK_TAG_SRB 'SDcS' // "ScDS" - srb allocation
|
||||
#define DISK_TAG_START 'sDcS' // "ScDs" - start device paths
|
||||
#define DISK_TAG_UPDATE_CAP 'UDcS' // "ScDU" - update capacity path
|
||||
#define DISK_TAG_WI_CONTEXT 'WDcS' // "ScDW" - work-item context
|
||||
|
||||
typedef
|
||||
VOID
|
||||
(*PDISK_UPDATE_PARTITIONS) (
|
||||
IN PDEVICE_OBJECT Fdo,
|
||||
IN OUT PDRIVE_LAYOUT_INFORMATION_EX PartitionList
|
||||
);
|
||||
|
||||
#if defined(_X86_)
|
||||
|
||||
//
|
||||
// Disk device data
|
||||
//
|
||||
|
||||
typedef enum _DISK_GEOMETRY_SOURCE {
|
||||
DiskGeometryUnknown,
|
||||
DiskGeometryFromBios,
|
||||
DiskGeometryFromPort,
|
||||
DiskGeometryFromNec98,
|
||||
DiskGeometryGuessedFromBios,
|
||||
DiskGeometryFromDefault
|
||||
} DISK_GEOMETRY_SOURCE, *PDISK_GEOMETRY_SOURCE;
|
||||
#endif
|
||||
|
||||
//
|
||||
|
||||
typedef struct _DISK_DATA {
|
||||
|
||||
//
|
||||
// This field is the ordinal of a partition as it appears on a disk.
|
||||
//
|
||||
|
||||
ULONG PartitionOrdinal;
|
||||
|
||||
//
|
||||
// How has this disk been partitioned? Either EFI or MBR.
|
||||
//
|
||||
|
||||
PARTITION_STYLE PartitionStyle;
|
||||
|
||||
union {
|
||||
|
||||
struct {
|
||||
|
||||
//
|
||||
// Disk signature (from MBR)
|
||||
//
|
||||
|
||||
ULONG Signature;
|
||||
|
||||
//
|
||||
// MBR checksum
|
||||
//
|
||||
|
||||
ULONG MbrCheckSum;
|
||||
|
||||
//
|
||||
// Number of hidden sectors for BPB.
|
||||
//
|
||||
|
||||
ULONG HiddenSectors;
|
||||
|
||||
//
|
||||
// Partition type of this device object
|
||||
//
|
||||
// This field is set by:
|
||||
//
|
||||
// 1. Initially set according to the partition list entry
|
||||
// partition type returned by IoReadPartitionTable.
|
||||
//
|
||||
// 2. Subsequently set by the
|
||||
// IOCTL_DISK_SET_PARTITION_INFORMATION I/O control
|
||||
// function when IoSetPartitionInformation function
|
||||
// successfully updates the partition type on the disk.
|
||||
//
|
||||
|
||||
UCHAR PartitionType;
|
||||
|
||||
//
|
||||
// Boot indicator - indicates whether this partition is a
|
||||
// bootable (active) partition for this device
|
||||
//
|
||||
// This field is set according to the partition list entry boot
|
||||
// indicator returned by IoReadPartitionTable.
|
||||
//
|
||||
|
||||
BOOLEAN BootIndicator;
|
||||
|
||||
} Mbr;
|
||||
|
||||
struct {
|
||||
|
||||
//
|
||||
// The DiskGUID field from the EFI partition header.
|
||||
//
|
||||
|
||||
GUID DiskId;
|
||||
|
||||
//
|
||||
// Partition type of this device object.
|
||||
//
|
||||
|
||||
GUID PartitionType;
|
||||
|
||||
//
|
||||
// Unique partition identifier for this partition.
|
||||
//
|
||||
|
||||
GUID PartitionId;
|
||||
|
||||
//
|
||||
// EFI partition attributes for this partition.
|
||||
//
|
||||
|
||||
ULONG64 Attributes;
|
||||
|
||||
//
|
||||
// EFI partition name of this partition.
|
||||
//
|
||||
|
||||
WCHAR PartitionName[36];
|
||||
|
||||
} Efi;
|
||||
|
||||
}; // unnamed union
|
||||
|
||||
struct {
|
||||
//
|
||||
// This flag is set when the well known name is created (through
|
||||
// DiskCreateSymbolicLinks) and cleared when destroying it
|
||||
// (by calling DiskDeleteSymbolicLinks).
|
||||
//
|
||||
|
||||
BOOLEAN WellKnownNameCreated : 1;
|
||||
|
||||
//
|
||||
// This flag is set when the PhysicalDriveN link is created (through
|
||||
// DiskCreateSymbolicLinks) and is cleared when destroying it (through
|
||||
// DiskDeleteSymbolicLinks)
|
||||
//
|
||||
|
||||
BOOLEAN PhysicalDriveLinkCreated : 1;
|
||||
|
||||
} LinkStatus;
|
||||
|
||||
//
|
||||
// ReadyStatus - STATUS_SUCCESS indicates that the drive is ready for
|
||||
// use. Any error status is to be returned as an explaination for why
|
||||
// a request is failed.
|
||||
//
|
||||
// This was done solely for the zero-length partition case of having no
|
||||
// media in a removable disk drive. When that occurs, and a read is sent
|
||||
// to the zero-length non-partition-zero PDO that was created, we had to
|
||||
// be able to fail the request with a reasonable value. This may not have
|
||||
// been the best way to do this, but it works.
|
||||
//
|
||||
|
||||
NTSTATUS ReadyStatus;
|
||||
|
||||
//
|
||||
// Routine to be called when updating the disk partitions. This routine
|
||||
// is different for removable and non-removable media and is called by
|
||||
// (among other things) DiskEnumerateDevice
|
||||
//
|
||||
|
||||
PDISK_UPDATE_PARTITIONS UpdatePartitionRoutine;
|
||||
|
||||
//
|
||||
// SCSI address used for SMART operations.
|
||||
//
|
||||
|
||||
SCSI_ADDRESS ScsiAddress;
|
||||
|
||||
//
|
||||
// Event used to synchronize partitioning operations and enumerations.
|
||||
//
|
||||
|
||||
KEVENT PartitioningEvent;
|
||||
|
||||
//
|
||||
// These unicode strings hold the disk and volume interface strings. If
|
||||
// the interfaces were not registered or could not be set then the string
|
||||
// buffer will be NULL.
|
||||
//
|
||||
|
||||
UNICODE_STRING DiskInterfaceString;
|
||||
UNICODE_STRING PartitionInterfaceString;
|
||||
|
||||
//
|
||||
// What type of failure prediction mechanism is available
|
||||
//
|
||||
|
||||
FAILURE_PREDICTION_METHOD FailurePredictionCapability;
|
||||
BOOLEAN AllowFPPerfHit;
|
||||
|
||||
#if defined(_X86_)
|
||||
//
|
||||
// This flag indiciates that a non-default geometry for this drive has
|
||||
// already been determined by the disk driver. This field is ignored
|
||||
// for removable media drives.
|
||||
//
|
||||
|
||||
DISK_GEOMETRY_SOURCE GeometrySource;
|
||||
|
||||
//
|
||||
// If GeometryDetermined is TRUE this will contain the geometry which was
|
||||
// reported by the firmware or by the BIOS. For removable media drives
|
||||
// this will contain the last geometry used when media was present.
|
||||
//
|
||||
|
||||
DISK_GEOMETRY RealGeometry;
|
||||
#endif
|
||||
|
||||
//
|
||||
// Indicates that the cached partition table is valid when set.
|
||||
//
|
||||
|
||||
ULONG CachedPartitionTableValid;
|
||||
|
||||
//
|
||||
// The cached partition table - this is only valid if the previous
|
||||
// flag is set. When invalidated the cached partition table will be
|
||||
// freed and replaced the next time one of the partitioning functions is
|
||||
// called. This allows the error handling routines to invalidate it by
|
||||
// setting the flag and doesn't require that they obtain a lock.
|
||||
//
|
||||
|
||||
PDRIVE_LAYOUT_INFORMATION_EX CachedPartitionTable;
|
||||
|
||||
//
|
||||
// This mutex prevents more than one IOCTL_DISK_VERIFY from being
|
||||
// sent down to the disk. This greatly reduces the possibility of
|
||||
// a Denial-of-Service attack
|
||||
//
|
||||
|
||||
KMUTEX VerifyMutex;
|
||||
|
||||
} DISK_DATA, *PDISK_DATA;
|
||||
|
||||
// Define a general structure of identfing disk controllers with bad
|
||||
// hardware.
|
||||
//
|
||||
|
||||
#define HackDisableTaggedQueuing (0x01)
|
||||
#define HackDisableSynchronousTransfers (0x02)
|
||||
#define HackDisableSpinDown (0x04)
|
||||
#define HackDisableWriteCache (0x08)
|
||||
#define HackCauseNotReportableHack (0x10)
|
||||
#define HackRequiresStartUnitCommand (0x20)
|
||||
#define HackDisableWriteCacheNotSupported (0x40)
|
||||
|
||||
|
||||
#define DiskDeviceParameterSubkey L"Disk"
|
||||
#define DiskDeviceSpecialFlags L"SpecialFlags"
|
||||
#define DiskDeviceUserWriteCacheSetting L"UserWriteCacheSetting"
|
||||
|
||||
|
||||
#define FUNCTIONAL_EXTENSION_SIZE sizeof(FUNCTIONAL_DEVICE_EXTENSION) + sizeof(DISK_DATA)
|
||||
#define PHYSICAL_EXTENSION_SIZE sizeof(PHYSICAL_DEVICE_EXTENSION) + sizeof(DISK_DATA)
|
||||
|
||||
#define MODE_DATA_SIZE 192
|
||||
#define VALUE_BUFFER_SIZE 2048
|
||||
#define SCSI_DISK_TIMEOUT 10
|
||||
#define PARTITION0_LIST_SIZE 4
|
||||
|
||||
#define MAX_MEDIA_TYPES 4
|
||||
typedef struct _DISK_MEDIA_TYPES_LIST {
|
||||
PCHAR VendorId;
|
||||
PCHAR ProductId;
|
||||
PCHAR Revision;
|
||||
const ULONG NumberOfTypes;
|
||||
const ULONG NumberOfSides;
|
||||
const STORAGE_MEDIA_TYPE MediaTypes[MAX_MEDIA_TYPES];
|
||||
} DISK_MEDIA_TYPES_LIST, *PDISK_MEDIA_TYPES_LIST;
|
||||
|
||||
//
|
||||
// WMI reregistration structures used for reregister work item
|
||||
//
|
||||
typedef struct
|
||||
{
|
||||
SINGLE_LIST_ENTRY Next;
|
||||
PDEVICE_OBJECT DeviceObject;
|
||||
PIRP Irp;
|
||||
} DISKREREGREQUEST, *PDISKREREGREQUEST;
|
||||
|
||||
//
|
||||
// Write cache setting as defined by the user
|
||||
//
|
||||
typedef enum _DISK_USER_WRITE_CACHE_SETTING
|
||||
{
|
||||
DiskWriteCacheDisable = 0,
|
||||
DiskWriteCacheEnable = 1,
|
||||
DiskWriteCacheDefault = -1
|
||||
|
||||
} DISK_USER_WRITE_CACHE_SETTING, *PDISK_USER_WRITE_CACHE_SETTING;
|
||||
|
||||
#define MAX_SECTORS_PER_VERIFY 0x200
|
||||
|
||||
//
|
||||
// This is based off 100ns units
|
||||
//
|
||||
#define ONE_MILLI_SECOND ((ULONGLONG)10 * 1000)
|
||||
|
||||
//
|
||||
// Context for the work-item
|
||||
//
|
||||
typedef struct _DISK_VERIFY_WORKITEM_CONTEXT
|
||||
{
|
||||
PIRP Irp;
|
||||
PSCSI_REQUEST_BLOCK Srb;
|
||||
PIO_WORKITEM WorkItem;
|
||||
|
||||
} DISK_VERIFY_WORKITEM_CONTEXT, *PDISK_VERIFY_WORKITEM_CONTEXT;
|
||||
|
||||
//
|
||||
// Poll for Failure Prediction every hour
|
||||
//
|
||||
#define DISK_DEFAULT_FAILURE_POLLING_PERIOD 1 * 60 * 60
|
||||
|
||||
//
|
||||
// Static global lookup tables.
|
||||
//
|
||||
|
||||
extern CLASSPNP_SCAN_FOR_SPECIAL_INFO DiskBadControllers[];
|
||||
extern const DISK_MEDIA_TYPES_LIST DiskMediaTypes[];
|
||||
|
||||
//
|
||||
// Macros
|
||||
//
|
||||
|
||||
//
|
||||
// Routine prototypes.
|
||||
//
|
||||
|
||||
|
||||
NTSTATUS
|
||||
DriverEntry(
|
||||
IN PDRIVER_OBJECT DriverObject,
|
||||
IN PUNICODE_STRING RegistryPath
|
||||
);
|
||||
|
||||
VOID
|
||||
DiskUnload(
|
||||
IN PDRIVER_OBJECT DriverObject
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
DiskAddDevice(
|
||||
IN PDRIVER_OBJECT DriverObject,
|
||||
IN PDEVICE_OBJECT Pdo
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
DiskInitFdo(
|
||||
IN PDEVICE_OBJECT Fdo
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
DiskInitPdo(
|
||||
IN PDEVICE_OBJECT Pdo
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
DiskStartFdo(
|
||||
IN PDEVICE_OBJECT Fdo
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
DiskStartPdo(
|
||||
IN PDEVICE_OBJECT Pdo
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
DiskStopDevice(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN UCHAR Type
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
DiskRemoveDevice(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN UCHAR Type
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
DiskReadWriteVerification(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
DiskDeviceControl(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp
|
||||
);
|
||||
|
||||
VOID
|
||||
DiskFdoProcessError(
|
||||
PDEVICE_OBJECT DeviceObject,
|
||||
PSCSI_REQUEST_BLOCK Srb,
|
||||
NTSTATUS *Status,
|
||||
BOOLEAN *Retry
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
DiskShutdownFlush(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
DiskGetCacheInformation(
|
||||
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
|
||||
IN PDISK_CACHE_INFORMATION CacheInfo
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
DiskSetCacheInformation(
|
||||
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
|
||||
IN PDISK_CACHE_INFORMATION CacheInfo
|
||||
);
|
||||
|
||||
VOID
|
||||
DisableWriteCache(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIO_WORKITEM WorkItem
|
||||
);
|
||||
|
||||
VOID
|
||||
DiskIoctlVerify(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PDISK_VERIFY_WORKITEM_CONTEXT Context
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
DiskModeSelect(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PCHAR ModeSelectBuffer,
|
||||
IN ULONG Length,
|
||||
IN BOOLEAN SavePage
|
||||
);
|
||||
|
||||
//
|
||||
// We need to validate that the self test subcommand is valid and
|
||||
// appropriate. Right now we allow subcommands 0, 1 and 2 which are non
|
||||
// captive mode tests. Once we figure out a way to know if it is safe to
|
||||
// run a captive test then we can allow captive mode tests. Also if the
|
||||
// atapi 5 spec is ever updated to denote that bit 7 is the captive
|
||||
// mode bit, we can allow any request that does not have bit 7 set. Until
|
||||
// that is done we want to be sure
|
||||
//
|
||||
#define DiskIsValidSmartSelfTest(Subcommand) \
|
||||
( ((Subcommand) == SMART_OFFLINE_ROUTINE_OFFLINE) || \
|
||||
((Subcommand) == SMART_SHORT_SELFTEST_OFFLINE) || \
|
||||
((Subcommand) == SMART_EXTENDED_SELFTEST_OFFLINE) )
|
||||
|
||||
|
||||
NTSTATUS
|
||||
DiskPerformSmartCommand(
|
||||
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
|
||||
IN ULONG SrbControlCode,
|
||||
IN UCHAR Command,
|
||||
IN UCHAR Feature,
|
||||
IN UCHAR SectorCount,
|
||||
IN UCHAR SectorNumber,
|
||||
IN OUT PSRB_IO_CONTROL SrbControl,
|
||||
OUT PULONG BufferSize
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
DiskGetInfoExceptionInformation(
|
||||
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
|
||||
OUT PMODE_INFO_EXCEPTIONS ReturnPageData
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
DiskSetInfoExceptionInformation(
|
||||
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
|
||||
IN PMODE_INFO_EXCEPTIONS PageData
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
DiskDetectFailurePrediction(
|
||||
PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
|
||||
PFAILURE_PREDICTION_METHOD FailurePredictCapability
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
EnumerateBusKey(
|
||||
IN PFUNCTIONAL_DEVICE_EXTENSION DeviceExtension,
|
||||
HANDLE BusKey,
|
||||
PULONG DiskNumber
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
DiskCreateFdo(
|
||||
IN PDRIVER_OBJECT DriverObject,
|
||||
IN PDEVICE_OBJECT LowerDeviceObject,
|
||||
IN PULONG DeviceCount,
|
||||
IN BOOLEAN DasdAccessOnly
|
||||
);
|
||||
|
||||
VOID
|
||||
UpdateDeviceObjects(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp
|
||||
);
|
||||
|
||||
VOID
|
||||
DiskSetSpecialHacks(
|
||||
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
|
||||
IN ULONG_PTR Data
|
||||
);
|
||||
|
||||
VOID
|
||||
DiskScanRegistryForSpecial(
|
||||
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
|
||||
);
|
||||
|
||||
VOID
|
||||
ResetBus(
|
||||
IN PDEVICE_OBJECT DeviceObject
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
DiskEnumerateDevice(
|
||||
IN PDEVICE_OBJECT Fdo
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
DiskQueryId(
|
||||
IN PDEVICE_OBJECT Pdo,
|
||||
IN BUS_QUERY_ID_TYPE IdType,
|
||||
IN PUNICODE_STRING UnicodeIdString
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
DiskQueryPnpCapabilities(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PDEVICE_CAPABILITIES Capabilities
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
DiskGenerateDeviceName(
|
||||
IN BOOLEAN IsFdo,
|
||||
IN ULONG DeviceNumber,
|
||||
IN OPTIONAL ULONG PartitionNumber,
|
||||
IN OPTIONAL PLARGE_INTEGER StartingOffset,
|
||||
IN OPTIONAL PLARGE_INTEGER PartitionLength,
|
||||
OUT PUCHAR *RawName
|
||||
);
|
||||
|
||||
VOID
|
||||
DiskCreateSymbolicLinks(
|
||||
IN PDEVICE_OBJECT DeviceObject
|
||||
);
|
||||
|
||||
VOID
|
||||
DiskUpdatePartitions(
|
||||
IN PDEVICE_OBJECT Fdo,
|
||||
IN OUT PDRIVE_LAYOUT_INFORMATION_EX PartitionList
|
||||
);
|
||||
|
||||
VOID
|
||||
DiskUpdateRemovablePartitions(
|
||||
IN PDEVICE_OBJECT Fdo,
|
||||
IN OUT PDRIVE_LAYOUT_INFORMATION_EX PartitionList
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
DiskCreatePdo(
|
||||
IN PDEVICE_OBJECT Fdo,
|
||||
IN ULONG PartitionOrdinal,
|
||||
IN PPARTITION_INFORMATION_EX PartitionEntry,
|
||||
IN PARTITION_STYLE PartitionStyle,
|
||||
OUT PDEVICE_OBJECT *Pdo
|
||||
);
|
||||
|
||||
VOID
|
||||
DiskDeleteSymbolicLinks(
|
||||
IN PDEVICE_OBJECT DeviceObject
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
DiskPdoQueryWmiRegInfo(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
OUT ULONG *RegFlags,
|
||||
OUT PUNICODE_STRING InstanceName
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
DiskPdoQueryWmiDataBlock(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp,
|
||||
IN ULONG GuidIndex,
|
||||
IN ULONG BufferAvail,
|
||||
OUT PUCHAR Buffer
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
DiskPdoSetWmiDataBlock(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp,
|
||||
IN ULONG GuidIndex,
|
||||
IN ULONG BufferSize,
|
||||
IN PUCHAR Buffer
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
DiskPdoSetWmiDataItem(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp,
|
||||
IN ULONG GuidIndex,
|
||||
IN ULONG DataItemId,
|
||||
IN ULONG BufferSize,
|
||||
IN PUCHAR Buffer
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
DiskPdoExecuteWmiMethod(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp,
|
||||
IN ULONG GuidIndex,
|
||||
IN ULONG MethodId,
|
||||
IN ULONG InBufferSize,
|
||||
IN ULONG OutBufferSize,
|
||||
IN PUCHAR Buffer
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
DiskFdoQueryWmiRegInfo(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
OUT ULONG *RegFlags,
|
||||
OUT PUNICODE_STRING InstanceName
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
DiskFdoQueryWmiRegInfoEx(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
OUT ULONG *RegFlags,
|
||||
OUT PUNICODE_STRING InstanceName,
|
||||
OUT PUNICODE_STRING MofName
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
DiskFdoQueryWmiDataBlock(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp,
|
||||
IN ULONG GuidIndex,
|
||||
IN ULONG BufferAvail,
|
||||
OUT PUCHAR Buffer
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
DiskFdoSetWmiDataBlock(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp,
|
||||
IN ULONG GuidIndex,
|
||||
IN ULONG BufferSize,
|
||||
IN PUCHAR Buffer
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
DiskFdoSetWmiDataItem(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp,
|
||||
IN ULONG GuidIndex,
|
||||
IN ULONG DataItemId,
|
||||
IN ULONG BufferSize,
|
||||
IN PUCHAR Buffer
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
DiskFdoExecuteWmiMethod(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp,
|
||||
IN ULONG GuidIndex,
|
||||
IN ULONG MethodId,
|
||||
IN ULONG InBufferSize,
|
||||
IN ULONG OutBufferSize,
|
||||
IN PUCHAR Buffer
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
DiskWmiFunctionControl(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp,
|
||||
IN ULONG GuidIndex,
|
||||
IN CLASSENABLEDISABLEFUNCTION Function,
|
||||
IN BOOLEAN Enable
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
DiskReadFailurePredictStatus(
|
||||
PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
|
||||
PSTORAGE_FAILURE_PREDICT_STATUS DiskSmartStatus
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
DiskReadFailurePredictData(
|
||||
PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
|
||||
PSTORAGE_FAILURE_PREDICT_DATA DiskSmartData
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
DiskEnableDisableFailurePrediction(
|
||||
PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
|
||||
BOOLEAN Enable
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
DiskEnableDisableFailurePredictPolling(
|
||||
PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
|
||||
BOOLEAN Enable,
|
||||
ULONG PollTimeInSeconds
|
||||
);
|
||||
|
||||
VOID
|
||||
DiskAcquirePartitioningLock(
|
||||
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
|
||||
);
|
||||
|
||||
VOID
|
||||
DiskReleasePartitioningLock(
|
||||
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
|
||||
);
|
||||
|
||||
NTSTATUS DiskInitializeReregistration(
|
||||
void
|
||||
);
|
||||
|
||||
extern GUIDREGINFO DiskWmiFdoGuidList[];
|
||||
extern GUIDREGINFO DiskWmiPdoGuidList[];
|
||||
|
||||
#if defined(_X86_)
|
||||
NTSTATUS
|
||||
DiskReadDriveCapacity(
|
||||
IN PDEVICE_OBJECT Fdo
|
||||
);
|
||||
#else
|
||||
#define DiskReadDriveCapacity(Fdo) ClassReadDriveCapacity(Fdo)
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(_X86_)
|
||||
|
||||
#if 0
|
||||
NTSTATUS
|
||||
DiskQuerySuggestedLinkName(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp
|
||||
);
|
||||
#endif
|
||||
|
||||
NTSTATUS
|
||||
DiskSaveDetectInfo(
|
||||
PDRIVER_OBJECT DriverObject
|
||||
);
|
||||
|
||||
VOID
|
||||
DiskCleanupDetectInfo(
|
||||
IN PDRIVER_OBJECT DriverObject
|
||||
);
|
||||
|
||||
VOID
|
||||
DiskDriverReinitialization (
|
||||
IN PDRIVER_OBJECT DriverObject,
|
||||
IN PVOID Nothing,
|
||||
IN ULONG Count
|
||||
);
|
||||
|
||||
#endif
|
||||
|
||||
VOID
|
||||
DiskConvertPartitionToExtended(
|
||||
IN PPARTITION_INFORMATION Partition,
|
||||
OUT PPARTITION_INFORMATION_EX PartitionEx
|
||||
);
|
||||
|
||||
PDRIVE_LAYOUT_INFORMATION_EX
|
||||
DiskConvertLayoutToExtended(
|
||||
IN CONST PDRIVE_LAYOUT_INFORMATION Layout
|
||||
);
|
||||
|
||||
PDRIVE_LAYOUT_INFORMATION
|
||||
DiskConvertExtendedToLayout(
|
||||
IN CONST PDRIVE_LAYOUT_INFORMATION_EX LayoutEx
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
DiskReadPartitionTableEx(
|
||||
IN PFUNCTIONAL_DEVICE_EXTENSION Fdo,
|
||||
IN BOOLEAN BypassCache,
|
||||
OUT PDRIVE_LAYOUT_INFORMATION_EX* DriveLayout
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
DiskWritePartitionTableEx(
|
||||
IN PFUNCTIONAL_DEVICE_EXTENSION Fdo,
|
||||
IN PDRIVE_LAYOUT_INFORMATION_EX DriveLayout
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
DiskSetPartitionInformationEx(
|
||||
IN PFUNCTIONAL_DEVICE_EXTENSION Fdo,
|
||||
IN ULONG PartitionNumber,
|
||||
IN struct _SET_PARTITION_INFORMATION_EX* PartitionInfo
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
DiskSetPartitionInformation(
|
||||
IN PFUNCTIONAL_DEVICE_EXTENSION Fdo,
|
||||
IN ULONG SectorSize,
|
||||
IN ULONG PartitionNumber,
|
||||
IN ULONG PartitionType
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
DiskVerifyPartitionTable(
|
||||
IN PFUNCTIONAL_DEVICE_EXTENSION Fdo,
|
||||
IN BOOLEAN FixErrors
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
DiskInvalidatePartitionTable(
|
||||
IN PFUNCTIONAL_DEVICE_EXTENSION Fdo,
|
||||
IN BOOLEAN PartitionLockHeld
|
||||
);
|
||||
|
||||
#if defined (_X86_)
|
||||
NTSTATUS
|
||||
DiskGetDetectInfo(
|
||||
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
|
||||
OUT PDISK_DETECTION_INFO DetectInfo
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
DiskReadSignature(
|
||||
IN PDEVICE_OBJECT Fdo
|
||||
);
|
||||
|
||||
#else
|
||||
#define DiskGetDetectInfo(FdoExtension, DetectInfo) (STATUS_UNSUCCESSFUL)
|
||||
#endif
|
||||
|
||||
|
||||
#define DiskHashGuid(Guid) (((PULONG) &Guid)[0] ^ ((PULONG) &Guid)[0] ^ ((PULONG) &Guid)[0] ^ ((PULONG) &Guid)[0])
|
||||
|
23
reactos/drivers/storage/class/disk_new/disk.rc
Normal file
23
reactos/drivers/storage/class/disk_new/disk.rc
Normal file
|
@ -0,0 +1,23 @@
|
|||
//+-------------------------------------------------------------------------
|
||||
//
|
||||
// Microsoft Windows
|
||||
//
|
||||
// Copyright (C) Microsoft Corporation, 1996 - 1999
|
||||
//
|
||||
// File: disk.rc
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <ntverp.h>
|
||||
|
||||
#define VER_FILETYPE VFT_DRV
|
||||
#define VER_FILESUBTYPE VFT2_DRV_SYSTEM
|
||||
#define VER_FILEDESCRIPTION_STR "PnP Disk Driver"
|
||||
#define VER_INTERNALNAME_STR "scsidisk.sys"
|
||||
#define VER_ORIGINALFILENAME_STR "scsidisk.sys"
|
||||
#define VER_LANGNEUTRAL
|
||||
|
||||
#include "common.ver"
|
||||
|
96
reactos/drivers/storage/class/disk_new/diskdev.inf
Normal file
96
reactos/drivers/storage/class/disk_new/diskdev.inf
Normal file
|
@ -0,0 +1,96 @@
|
|||
; disk.inf
|
||||
;
|
||||
; Installation inf for the Disk drive adapter.
|
||||
;
|
||||
; SAMPLE INF File for Class Driver
|
||||
; FOR DDK - Driver Development Kit
|
||||
;
|
||||
; (c) Copyright 1999 Microsoft Corp.
|
||||
;
|
||||
|
||||
[Version]
|
||||
Signature="$Windows NT$"
|
||||
Provider=%MS%
|
||||
ClassGUID={4d36e967-e325-11ce-bfc1-08002be10318}
|
||||
Class=DiskDrive
|
||||
; CatalogFile=disk.cat ; Supply your own catalog file
|
||||
; see DDK Doc.
|
||||
DriverVer=08/27/1999
|
||||
|
||||
[DestinationDirs]
|
||||
DefaultDestDir = 12
|
||||
|
||||
;
|
||||
; Driver information
|
||||
;
|
||||
|
||||
[Manufacturer]
|
||||
%MS% = MS.Mfg
|
||||
|
||||
[MS.Mfg]
|
||||
%MS.DeviceDesc0% = disk, GenDisk
|
||||
%MS.DeviceDesc1% = disk, GenOptical
|
||||
|
||||
|
||||
;
|
||||
; General installation section
|
||||
;
|
||||
|
||||
[disk]
|
||||
|
||||
;
|
||||
; File sections
|
||||
;
|
||||
|
||||
|
||||
;
|
||||
; Service Installation
|
||||
;
|
||||
|
||||
[disk.Services]
|
||||
AddService = disk, 0x00000002 , disk_Service_Inst
|
||||
|
||||
[disk_Service_Inst]
|
||||
DisplayName = %disk.SvcDesc%
|
||||
ServiceType = 1 ; SERVICE_KERNEL_DRIVER
|
||||
StartType = 1 ; SERVICE_SYSTEM_START
|
||||
ErrorControl = 0x1 ; SERVICE_ERROR_NORMAL
|
||||
LoadOrderGroup = Pointer Port
|
||||
ServiceBinary = %12%\disk.sys
|
||||
|
||||
|
||||
;
|
||||
; Source file information
|
||||
;
|
||||
|
||||
[SourceDisksNames.x86]
|
||||
1 = %DiskId1%,,,""
|
||||
|
||||
[SourceDisksFiles]
|
||||
; Files for disk Microsoft Corp. Installation Disk #1 (DiskDrive)
|
||||
disk.sys = 1,,
|
||||
|
||||
|
||||
[Strings]
|
||||
|
||||
;
|
||||
; Non-Localizable Strings
|
||||
;
|
||||
|
||||
REG_SZ = 0x00000000
|
||||
REG_MULTI_SZ = 0x00010000
|
||||
REG_EXPAND_SZ = 0x00020000
|
||||
REG_BINARY = 0x00000001
|
||||
REG_DWORD = 0x00010001
|
||||
SERVICEROOT = "System\CurrentControlSet\Services"
|
||||
|
||||
;
|
||||
; Localizable Strings
|
||||
;
|
||||
|
||||
MS.DeviceDesc0 = "Disk drive"
|
||||
MS.DeviceDesc1 = "Optical disk drive"
|
||||
DiskId1 = "Microsoft Corp. Installation Disk #1 (DiskDrive)"
|
||||
MS = "Microsoft Corp."
|
||||
disk.SvcDesc="Disk Drive"
|
||||
|
3434
reactos/drivers/storage/class/disk_new/diskwmi.c
Normal file
3434
reactos/drivers/storage/class/disk_new/diskwmi.c
Normal file
File diff suppressed because it is too large
Load diff
1249
reactos/drivers/storage/class/disk_new/enum.c
Normal file
1249
reactos/drivers/storage/class/disk_new/enum.c
Normal file
File diff suppressed because it is too large
Load diff
1470
reactos/drivers/storage/class/disk_new/geometry.c
Normal file
1470
reactos/drivers/storage/class/disk_new/geometry.c
Normal file
File diff suppressed because it is too large
Load diff
327
reactos/drivers/storage/class/disk_new/part.c
Normal file
327
reactos/drivers/storage/class/disk_new/part.c
Normal file
|
@ -0,0 +1,327 @@
|
|||
/*++
|
||||
|
||||
Copyright (C) Microsoft Corporation, 1991 - 1999
|
||||
|
||||
Module Name:
|
||||
|
||||
disk.c
|
||||
|
||||
Abstract:
|
||||
|
||||
SCSI disk class driver
|
||||
|
||||
Environment:
|
||||
|
||||
kernel mode only
|
||||
|
||||
Notes:
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#include "disk.h"
|
||||
|
||||
#define PtCache ClassDebugExternal1
|
||||
|
||||
#ifdef ALLOC_PRAGMA
|
||||
|
||||
#pragma alloc_text(PAGE, DiskReadPartitionTableEx)
|
||||
#pragma alloc_text(PAGE, DiskWritePartitionTableEx)
|
||||
#pragma alloc_text(PAGE, DiskSetPartitionInformationEx)
|
||||
#endif
|
||||
|
||||
ULONG DiskBreakOnPtInval = FALSE;
|
||||
|
||||
//
|
||||
// By default, 64-bit systems can see GPT disks and 32-bit systems
|
||||
// cannot. This will likely change in the future.
|
||||
//
|
||||
|
||||
#if defined(_WIN64)
|
||||
ULONG DiskDisableGpt = FALSE;
|
||||
#else
|
||||
ULONG DiskDisableGpt = TRUE;
|
||||
#endif
|
||||
|
||||
NTSTATUS
|
||||
DiskReadPartitionTableEx(
|
||||
IN PFUNCTIONAL_DEVICE_EXTENSION Fdo,
|
||||
IN BOOLEAN BypassCache,
|
||||
OUT PDRIVE_LAYOUT_INFORMATION_EX* DriveLayout
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
This routine will return the current layout information for the disk.
|
||||
If the cached information is still valid then it will be returned,
|
||||
otherwise the layout will be retreived from the kernel and cached for
|
||||
future use.
|
||||
|
||||
This routine must be called with the partitioning lock held. The
|
||||
partition list which is returned is not guaranteed to remain valid
|
||||
once the lock has been released.
|
||||
|
||||
Arguments:
|
||||
|
||||
Fdo - a pointer to the FDO for the disk.
|
||||
|
||||
DriveLayout - a location to store a pointer to the drive layout information.
|
||||
|
||||
Return Value:
|
||||
|
||||
STATUS_SUCCESS if successful or an error status indicating what failed.
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
PDISK_DATA diskData = Fdo->CommonExtension.DriverData;
|
||||
NTSTATUS status;
|
||||
PDRIVE_LAYOUT_INFORMATION_EX layoutEx;
|
||||
|
||||
layoutEx = NULL;
|
||||
|
||||
if(BypassCache) {
|
||||
diskData->CachedPartitionTableValid = FALSE;
|
||||
DebugPrint((PtCache, "DiskRPTEx: cache bypassed and invalidated for "
|
||||
"FDO %#p\n", Fdo));
|
||||
}
|
||||
|
||||
//
|
||||
// If the cached partition table is present then return a copy of it.
|
||||
//
|
||||
|
||||
if(diskData->CachedPartitionTableValid == TRUE) {
|
||||
|
||||
ULONG partitionNumber;
|
||||
PDRIVE_LAYOUT_INFORMATION_EX layout = diskData->CachedPartitionTable;
|
||||
|
||||
//
|
||||
// Clear the partition numbers from the list entries
|
||||
//
|
||||
|
||||
for(partitionNumber = 0;
|
||||
partitionNumber < layout->PartitionCount;
|
||||
partitionNumber++) {
|
||||
layout->PartitionEntry[partitionNumber].PartitionNumber = 0;
|
||||
}
|
||||
|
||||
*DriveLayout = diskData->CachedPartitionTable;
|
||||
|
||||
DebugPrint((PtCache, "DiskRPTEx: cached PT returned (%#p) for "
|
||||
"FDO %#p\n",
|
||||
*DriveLayout, Fdo));
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ASSERTMSG("DiskReadPartitionTableEx is not using cached partition table",
|
||||
(DiskBreakOnPtInval == FALSE));
|
||||
|
||||
//
|
||||
// If there's a cached partition table still around then free it.
|
||||
//
|
||||
|
||||
if(diskData->CachedPartitionTable) {
|
||||
DebugPrint((PtCache, "DiskRPTEx: cached PT (%#p) freed for FDO %#p\n",
|
||||
diskData->CachedPartitionTable, Fdo));
|
||||
|
||||
ExFreePool(diskData->CachedPartitionTable);
|
||||
diskData->CachedPartitionTable = NULL;
|
||||
}
|
||||
|
||||
//
|
||||
// By default, X86 disables recognition of GPT disks. Instead we
|
||||
// return the protective MBR partition. Use IoReadPartitionTable
|
||||
// to get this.
|
||||
//
|
||||
|
||||
status = IoReadPartitionTableEx(Fdo->DeviceObject, &layoutEx);
|
||||
|
||||
if (DiskDisableGpt) {
|
||||
PDRIVE_LAYOUT_INFORMATION layout;
|
||||
|
||||
if (NT_SUCCESS (status) &&
|
||||
layoutEx->PartitionStyle == PARTITION_STYLE_GPT) {
|
||||
|
||||
//
|
||||
// ISSUE - 2000/29/08 - math: Remove from final product.
|
||||
// Leave this debug print in for a while until everybody
|
||||
// has had a chance to convert their GPT disks to MBR.
|
||||
//
|
||||
|
||||
DbgPrint ("DISK: Disk %p recognized as a GPT disk on a system without GPT support.\n"
|
||||
" Disk will appear as RAW.\n",
|
||||
Fdo->DeviceObject);
|
||||
|
||||
ExFreePool (layoutEx);
|
||||
status = IoReadPartitionTable(Fdo->DeviceObject,
|
||||
Fdo->DiskGeometry.BytesPerSector,
|
||||
FALSE,
|
||||
&layout);
|
||||
if (NT_SUCCESS (status)) {
|
||||
layoutEx = DiskConvertLayoutToExtended(layout);
|
||||
ExFreePool (layout);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
diskData->CachedPartitionTable = layoutEx;
|
||||
|
||||
//
|
||||
// If the routine fails make sure we don't have a stale partition table
|
||||
// pointer. Otherwise indicate that the table is now valid.
|
||||
//
|
||||
|
||||
if(!NT_SUCCESS(status)) {
|
||||
diskData->CachedPartitionTable = NULL;
|
||||
} else {
|
||||
diskData->CachedPartitionTableValid = TRUE;
|
||||
}
|
||||
|
||||
*DriveLayout = diskData->CachedPartitionTable;
|
||||
|
||||
DebugPrint((PtCache, "DiskRPTEx: returning PT %#p for FDO %#p with status "
|
||||
"%#08lx. PT is %scached\n",
|
||||
*DriveLayout,
|
||||
Fdo,
|
||||
status,
|
||||
(diskData->CachedPartitionTableValid ? "" : "not ")));
|
||||
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
DiskWritePartitionTableEx(
|
||||
IN PFUNCTIONAL_DEVICE_EXTENSION Fdo,
|
||||
IN PDRIVE_LAYOUT_INFORMATION_EX DriveLayout
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
This routine will invalidate the cached partition table. It will then
|
||||
write the new drive layout to disk.
|
||||
|
||||
Arguments:
|
||||
|
||||
Fdo - the FDO for the disk getting the new partition table.
|
||||
|
||||
DriveLayout - the new drive layout.
|
||||
|
||||
Return Value:
|
||||
|
||||
status
|
||||
|
||||
--*/
|
||||
{
|
||||
PDISK_DATA diskData = Fdo->CommonExtension.DriverData;
|
||||
|
||||
//
|
||||
// Invalidate the cached partition table. Do not free it as it may be
|
||||
// the very drive layout that was passed in to us.
|
||||
//
|
||||
|
||||
diskData->CachedPartitionTableValid = FALSE;
|
||||
|
||||
DebugPrint((PtCache, "DiskWPTEx: Invalidating PT cache for FDO %#p\n",
|
||||
Fdo));
|
||||
|
||||
if (DiskDisableGpt) {
|
||||
if (DriveLayout->PartitionStyle == PARTITION_STYLE_GPT) {
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
return IoWritePartitionTableEx(Fdo->DeviceObject, DriveLayout);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
DiskSetPartitionInformationEx(
|
||||
IN PFUNCTIONAL_DEVICE_EXTENSION Fdo,
|
||||
IN ULONG PartitionNumber,
|
||||
IN struct _SET_PARTITION_INFORMATION_EX* PartitionInfo
|
||||
)
|
||||
{
|
||||
PDISK_DATA diskData = Fdo->CommonExtension.DriverData;
|
||||
|
||||
diskData->CachedPartitionTableValid = FALSE;
|
||||
DebugPrint((PtCache, "DiskSPIEx: Invalidating PT cache for FDO %#p\n",
|
||||
Fdo));
|
||||
|
||||
if (DiskDisableGpt) {
|
||||
if (PartitionInfo->PartitionStyle == PARTITION_STYLE_GPT) {
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
return IoSetPartitionInformationEx(Fdo->DeviceObject,
|
||||
PartitionNumber,
|
||||
PartitionInfo);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
DiskSetPartitionInformation(
|
||||
IN PFUNCTIONAL_DEVICE_EXTENSION Fdo,
|
||||
IN ULONG SectorSize,
|
||||
IN ULONG PartitionNumber,
|
||||
IN ULONG PartitionType
|
||||
)
|
||||
{
|
||||
PDISK_DATA diskData = Fdo->CommonExtension.DriverData;
|
||||
|
||||
diskData->CachedPartitionTableValid = FALSE;
|
||||
DebugPrint((PtCache, "DiskSPI: Invalidating PT cache for FDO %#p\n",
|
||||
Fdo));
|
||||
|
||||
return IoSetPartitionInformation(Fdo->DeviceObject,
|
||||
SectorSize,
|
||||
PartitionNumber,
|
||||
PartitionType);
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
DiskInvalidatePartitionTable(
|
||||
IN PFUNCTIONAL_DEVICE_EXTENSION Fdo,
|
||||
IN BOOLEAN PartitionLockHeld
|
||||
)
|
||||
{
|
||||
PDISK_DATA diskData = Fdo->CommonExtension.DriverData;
|
||||
BOOLEAN wasValid;
|
||||
|
||||
wasValid = (BOOLEAN) (diskData->CachedPartitionTableValid ? TRUE : FALSE);
|
||||
diskData->CachedPartitionTableValid = FALSE;
|
||||
|
||||
DebugPrint((PtCache, "DiskIPT: Invalidating PT cache for FDO %#p\n",
|
||||
Fdo));
|
||||
|
||||
if((PartitionLockHeld) && (diskData->CachedPartitionTable != NULL)) {
|
||||
DebugPrint((PtCache, "DiskIPT: Freeing PT cache (%#p) for FDO %#p\n",
|
||||
diskData->CachedPartitionTable, Fdo));
|
||||
ExFreePool(diskData->CachedPartitionTable);
|
||||
diskData->CachedPartitionTable = NULL;
|
||||
}
|
||||
|
||||
return wasValid;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
DiskVerifyPartitionTable(
|
||||
IN PFUNCTIONAL_DEVICE_EXTENSION Fdo,
|
||||
IN BOOLEAN FixErrors
|
||||
)
|
||||
{
|
||||
PDISK_DATA diskData = Fdo->CommonExtension.DriverData;
|
||||
|
||||
if(FixErrors) {
|
||||
diskData->CachedPartitionTableValid = FALSE;
|
||||
DebugPrint((PtCache, "DiskWPTEx: Invalidating PT cache for FDO %#p\n",
|
||||
Fdo));
|
||||
}
|
||||
|
||||
return IoVerifyPartitionTable(Fdo->DeviceObject, FixErrors);
|
||||
}
|
||||
|
1403
reactos/drivers/storage/class/disk_new/pnp.c
Normal file
1403
reactos/drivers/storage/class/disk_new/pnp.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -17,7 +17,7 @@ if(ARCH MATCHES i386)
|
|||
endif()
|
||||
endif()
|
||||
|
||||
spec2def(classpnp.sys class.spec)
|
||||
spec2def(classpnp.sys classpnp.spec)
|
||||
|
||||
list(APPEND SOURCE
|
||||
autorun.c
|
||||
|
@ -35,11 +35,12 @@ list(APPEND SOURCE
|
|||
utils.c
|
||||
xferpkt.c
|
||||
class.rc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/class.def)
|
||||
${CMAKE_CURRENT_BINARY_DIR}/classpnp.def)
|
||||
|
||||
add_library(classpnp SHARED ${SOURCE})
|
||||
add_pch(classpnp classp.h)
|
||||
target_link_libraries(classpnp ${PSEH_LIB} libcntpr)
|
||||
set_module_type(classpnp kernelmodedriver)
|
||||
add_importlibs(classpnp hal ntoskrnl)
|
||||
add_importlib_target(classpnp.spec)
|
||||
add_cd_file(TARGET classpnp DESTINATION reactos/system32/drivers NO_CAB FOR all)
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<!DOCTYPE module SYSTEM "../../../../tools/rbuild/project.dtd">
|
||||
<module name="classpnp" type="kernelmodedriver" installbase="system32/drivers" installname="classpnp.sys">
|
||||
<bootstrap installbase="$(CDOUTPUT)/system32/drivers" />
|
||||
<importlibrary definition="class.spec" />
|
||||
<importlibrary definition="classpnp.spec" />
|
||||
<library>ntoskrnl</library>
|
||||
<library>hal</library>
|
||||
<library>pseh</library>
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
|
||||
if(NOT ${ARCH} MATCHES amd64)
|
||||
add_subdirectory(nt4compat)
|
||||
endif()
|
||||
add_subdirectory(usbccgp)
|
||||
add_subdirectory(usbd)
|
||||
#add_subdirectory(usbehci) The USB branch has usbehci_new
|
||||
#add_subdirectory(usbhub) Compiles, just skipped in trunk
|
||||
#add_subdirectory(usbstor) Compiles, just skipped in trunk
|
||||
add_subdirectory(usbehci)
|
||||
add_subdirectory(usbhub)
|
||||
add_subdirectory(usbohci)
|
||||
add_subdirectory(usbstor)
|
|
@ -1,16 +1,22 @@
|
|||
<?xml version="1.0"?>
|
||||
<!DOCTYPE group SYSTEM "../../tools/rbuild/project.dtd">
|
||||
<group xmlns:xi="http://www.w3.org/2001/XInclude">
|
||||
<directory name="nt4compat">
|
||||
<xi:include href="nt4compat/directory.rbuild" />
|
||||
<directory name="usbccgp">
|
||||
<xi:include href="usbccgp/usbccgp.rbuild" />
|
||||
</directory>
|
||||
<directory name="usbd">
|
||||
<xi:include href="usbd/usbd.rbuild" />
|
||||
</directory>
|
||||
<!--directory name="usbhub">
|
||||
<directory name="usbehci">
|
||||
<xi:include href="usbehci/usbehci.rbuild" />
|
||||
</directory>
|
||||
<directory name="usbhub">
|
||||
<xi:include href="usbhub/usbhub.rbuild" />
|
||||
</directory>
|
||||
<directory name="usbohci">
|
||||
<xi:include href="usbohci/usbohci.rbuild" />
|
||||
</directory>
|
||||
<directory name="usbstor">
|
||||
<xi:include href="usbstor/usbstor.rbuild" />
|
||||
</directory-->
|
||||
</directory>
|
||||
</group>
|
||||
|
|
16
reactos/drivers/usb/usbccgp/CMakeLists.txt
Normal file
16
reactos/drivers/usb/usbccgp/CMakeLists.txt
Normal file
|
@ -0,0 +1,16 @@
|
|||
remove_definitions(-D_WIN32_WINNT=0x502)
|
||||
add_definitions(-D_WIN32_WINNT=0x600)
|
||||
|
||||
|
||||
add_definitions(-DDEBUG_MODE)
|
||||
|
||||
include_directories(${REACTOS_SOURCE_DIR}/ntoskrnl/include)
|
||||
|
||||
add_library(usbccgp SHARED descriptor.c fdo.c function.c misc.c pdo.c usbccgp.c usbccgp.rc)
|
||||
|
||||
target_link_libraries(usbccgp ${PSEH_LIB})
|
||||
|
||||
set_module_type(usbccgp kernelmodedriver)
|
||||
add_importlibs(usbccgp ntoskrnl hal usbd)
|
||||
|
||||
add_cd_file(TARGET usbccgp DESTINATION reactos/system32/drivers NO_CAB FOR all)
|
493
reactos/drivers/usb/usbccgp/descriptor.c
Normal file
493
reactos/drivers/usb/usbccgp/descriptor.c
Normal file
|
@ -0,0 +1,493 @@
|
|||
/*
|
||||
* PROJECT: ReactOS Universal Serial Bus Bulk Enhanced Host Controller Interface
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* FILE: drivers/usb/usbccgp/descriptor.c
|
||||
* PURPOSE: USB device driver.
|
||||
* PROGRAMMERS:
|
||||
* Michael Martin (michael.martin@reactos.org)
|
||||
* Johannes Anderwald (johannes.anderwald@reactos.org)
|
||||
* Cameron Gutman
|
||||
*/
|
||||
|
||||
#include "usbccgp.h"
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
USBCCGP_GetDescriptor(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN UCHAR DescriptorType,
|
||||
IN ULONG DescriptorLength,
|
||||
IN UCHAR DescriptorIndex,
|
||||
IN LANGID LanguageId,
|
||||
OUT PVOID *OutDescriptor)
|
||||
{
|
||||
PURB Urb;
|
||||
NTSTATUS Status;
|
||||
PVOID Descriptor;
|
||||
|
||||
//
|
||||
// sanity checks
|
||||
//
|
||||
ASSERT(DeviceObject);
|
||||
ASSERT(OutDescriptor);
|
||||
ASSERT(DescriptorLength);
|
||||
|
||||
//
|
||||
// first allocate descriptor buffer
|
||||
//
|
||||
Descriptor = AllocateItem(NonPagedPool, DescriptorLength);
|
||||
if (!Descriptor)
|
||||
{
|
||||
//
|
||||
// no memory
|
||||
//
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
//
|
||||
// allocate urb
|
||||
//
|
||||
Urb = (PURB) AllocateItem(NonPagedPool, sizeof(URB));
|
||||
if (!Urb)
|
||||
{
|
||||
//
|
||||
// no memory
|
||||
//
|
||||
FreeItem(Descriptor);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
//
|
||||
// initialize urb
|
||||
//
|
||||
UsbBuildGetDescriptorRequest(Urb,
|
||||
sizeof(Urb->UrbControlDescriptorRequest),
|
||||
DescriptorType,
|
||||
DescriptorIndex,
|
||||
LanguageId,
|
||||
Descriptor,
|
||||
NULL,
|
||||
DescriptorLength,
|
||||
NULL);
|
||||
|
||||
//
|
||||
// submit urb
|
||||
//
|
||||
Status = USBCCGP_SyncUrbRequest(DeviceObject, Urb);
|
||||
|
||||
//
|
||||
// free urb
|
||||
//
|
||||
FreeItem(Urb);
|
||||
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
//
|
||||
// store result
|
||||
//
|
||||
*OutDescriptor = Descriptor;
|
||||
}
|
||||
|
||||
//
|
||||
// done
|
||||
//
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
USBCCGP_GetDescriptors(
|
||||
IN PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PFDO_DEVICE_EXTENSION DeviceExtension;
|
||||
USHORT DescriptorLength;
|
||||
|
||||
//
|
||||
// get device extension
|
||||
//
|
||||
DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
|
||||
//
|
||||
// first get device descriptor
|
||||
//
|
||||
Status = USBCCGP_GetDescriptor(DeviceExtension->NextDeviceObject, USB_DEVICE_DESCRIPTOR_TYPE, sizeof(USB_DEVICE_DESCRIPTOR), 0, 0, (PVOID*)&DeviceExtension->DeviceDescriptor);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
//
|
||||
// failed to get device descriptor
|
||||
//
|
||||
DeviceExtension->DeviceDescriptor = NULL;
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// now get basic configuration descriptor
|
||||
//
|
||||
Status = USBCCGP_GetDescriptor(DeviceExtension->NextDeviceObject, USB_CONFIGURATION_DESCRIPTOR_TYPE, sizeof(USB_CONFIGURATION_DESCRIPTOR), 0, 0, (PVOID*)&DeviceExtension->ConfigurationDescriptor);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
//
|
||||
// failed to get configuration descriptor
|
||||
//
|
||||
FreeItem(DeviceExtension->DeviceDescriptor);
|
||||
DeviceExtension->DeviceDescriptor = NULL;
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// backup length
|
||||
//
|
||||
DescriptorLength = DeviceExtension->ConfigurationDescriptor->wTotalLength;
|
||||
|
||||
//
|
||||
// release basic descriptor
|
||||
//
|
||||
FreeItem(DeviceExtension->ConfigurationDescriptor);
|
||||
DeviceExtension->ConfigurationDescriptor = NULL;
|
||||
|
||||
//
|
||||
// allocate full descriptor
|
||||
//
|
||||
Status = USBCCGP_GetDescriptor(DeviceExtension->NextDeviceObject, USB_CONFIGURATION_DESCRIPTOR_TYPE, DescriptorLength, 0, 0, (PVOID*)&DeviceExtension->ConfigurationDescriptor);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
//
|
||||
// failed to get configuration descriptor
|
||||
//
|
||||
FreeItem(DeviceExtension->DeviceDescriptor);
|
||||
DeviceExtension->DeviceDescriptor = NULL;
|
||||
return Status;
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
|
||||
ULONG
|
||||
CountInterfaceDescriptors(
|
||||
IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor)
|
||||
{
|
||||
PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
|
||||
PVOID CurrentPosition;
|
||||
ULONG Count = 0;
|
||||
|
||||
//
|
||||
// enumerate all interfaces
|
||||
//
|
||||
CurrentPosition = ConfigurationDescriptor;
|
||||
do
|
||||
{
|
||||
//
|
||||
// find next descriptor
|
||||
//
|
||||
InterfaceDescriptor = USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor, CurrentPosition, -1, -1, -1, -1, -1);
|
||||
if (!InterfaceDescriptor)
|
||||
break;
|
||||
|
||||
//
|
||||
// advance to next descriptor
|
||||
//
|
||||
CurrentPosition = (PVOID)((ULONG_PTR)InterfaceDescriptor + InterfaceDescriptor->bLength);
|
||||
|
||||
//
|
||||
// increment descriptor count
|
||||
//
|
||||
Count++;
|
||||
|
||||
}while(TRUE);
|
||||
|
||||
//
|
||||
// done
|
||||
//
|
||||
return Count;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
AllocateInterfaceDescriptorsArray(
|
||||
IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
|
||||
OUT PUSB_INTERFACE_DESCRIPTOR **OutArray)
|
||||
{
|
||||
PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
|
||||
PVOID CurrentPosition;
|
||||
ULONG Count = 0;
|
||||
PUSB_INTERFACE_DESCRIPTOR *Array;
|
||||
|
||||
Count = CountInterfaceDescriptors(ConfigurationDescriptor);
|
||||
ASSERT(Count);
|
||||
|
||||
//
|
||||
// allocate array
|
||||
//
|
||||
Array = AllocateItem(NonPagedPool, sizeof(PUSB_INTERFACE_DESCRIPTOR) * Count);
|
||||
if (!Array)
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
||||
//
|
||||
// enumerate all interfaces
|
||||
//
|
||||
CurrentPosition = ConfigurationDescriptor;
|
||||
Count = 0;
|
||||
do
|
||||
{
|
||||
//
|
||||
// find next descriptor
|
||||
//
|
||||
InterfaceDescriptor = USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor, CurrentPosition, -1, -1, -1, -1, -1);
|
||||
if (!InterfaceDescriptor)
|
||||
break;
|
||||
|
||||
//
|
||||
// store descriptor
|
||||
//
|
||||
Array[Count] = InterfaceDescriptor;
|
||||
Count++;
|
||||
|
||||
//
|
||||
// advance to next descriptor
|
||||
//
|
||||
CurrentPosition = (PVOID)((ULONG_PTR)InterfaceDescriptor + InterfaceDescriptor->bLength);
|
||||
|
||||
}while(TRUE);
|
||||
|
||||
//
|
||||
// store result
|
||||
//
|
||||
*OutArray = Array;
|
||||
|
||||
//
|
||||
// done
|
||||
//
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
USBCCGP_ScanConfigurationDescriptor(
|
||||
IN OUT PFDO_DEVICE_EXTENSION FDODeviceExtension,
|
||||
IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor)
|
||||
{
|
||||
PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
|
||||
ULONG InterfaceIndex = 0;
|
||||
PVOID CurrentPosition;
|
||||
ULONG DescriptorCount;
|
||||
|
||||
//
|
||||
// sanity checks
|
||||
//
|
||||
ASSERT(ConfigurationDescriptor);
|
||||
ASSERT(ConfigurationDescriptor->bNumInterfaces);
|
||||
|
||||
//
|
||||
// count all interface descriptors
|
||||
//
|
||||
DescriptorCount = ConfigurationDescriptor->bNumInterfaces;
|
||||
|
||||
//
|
||||
// allocate array holding the interface descriptors
|
||||
//
|
||||
FDODeviceExtension->InterfaceList = AllocateItem(NonPagedPool, sizeof(USBD_INTERFACE_LIST_ENTRY) * (DescriptorCount + 1));
|
||||
if (!FDODeviceExtension->InterfaceList)
|
||||
{
|
||||
//
|
||||
// no memory
|
||||
//
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
CurrentPosition = ConfigurationDescriptor;
|
||||
do
|
||||
{
|
||||
//
|
||||
// parse configuration descriptor
|
||||
//
|
||||
InterfaceDescriptor = USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor, ConfigurationDescriptor, InterfaceIndex, -1, -1, -1, -1);
|
||||
ASSERT(InterfaceDescriptor);
|
||||
if (InterfaceDescriptor)
|
||||
{
|
||||
//
|
||||
// store in interface list
|
||||
//
|
||||
FDODeviceExtension->InterfaceList[FDODeviceExtension->InterfaceListCount].InterfaceDescriptor = InterfaceDescriptor;
|
||||
FDODeviceExtension->InterfaceListCount++;
|
||||
CurrentPosition = (PVOID)((ULONG_PTR)InterfaceDescriptor + InterfaceDescriptor->bLength);
|
||||
}
|
||||
|
||||
//
|
||||
// move to next interface
|
||||
//
|
||||
InterfaceIndex++;
|
||||
|
||||
}while(InterfaceIndex < DescriptorCount);
|
||||
|
||||
//
|
||||
// sanity check
|
||||
//
|
||||
ASSERT(FDODeviceExtension->InterfaceListCount);
|
||||
|
||||
//
|
||||
// done
|
||||
//
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
VOID
|
||||
DumpConfigurationDescriptor(PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor)
|
||||
{
|
||||
DPRINT1("Dumping ConfigurationDescriptor %x\n", ConfigurationDescriptor);
|
||||
DPRINT1("bLength %x\n", ConfigurationDescriptor->bLength);
|
||||
DPRINT1("bDescriptorType %x\n", ConfigurationDescriptor->bDescriptorType);
|
||||
DPRINT1("wTotalLength %x\n", ConfigurationDescriptor->wTotalLength);
|
||||
DPRINT1("bNumInterfaces %x\n", ConfigurationDescriptor->bNumInterfaces);
|
||||
DPRINT1("bConfigurationValue %x\n", ConfigurationDescriptor->bConfigurationValue);
|
||||
DPRINT1("iConfiguration %x\n", ConfigurationDescriptor->iConfiguration);
|
||||
DPRINT1("bmAttributes %x\n", ConfigurationDescriptor->bmAttributes);
|
||||
DPRINT1("MaxPower %x\n", ConfigurationDescriptor->MaxPower);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
USBCCGP_SelectInterface(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PFDO_DEVICE_EXTENSION DeviceExtension,
|
||||
IN ULONG InterfaceIndex)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PURB Urb;
|
||||
|
||||
//
|
||||
// allocate urb
|
||||
//
|
||||
Urb = AllocateItem(NonPagedPool, GET_SELECT_INTERFACE_REQUEST_SIZE(DeviceExtension->InterfaceList[InterfaceIndex].InterfaceDescriptor->bNumEndpoints));
|
||||
if (!Urb)
|
||||
{
|
||||
//
|
||||
// no memory
|
||||
//
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
//
|
||||
// now prepare interface urb
|
||||
//
|
||||
UsbBuildSelectInterfaceRequest(Urb, GET_SELECT_INTERFACE_REQUEST_SIZE(DeviceExtension->InterfaceList[InterfaceIndex].InterfaceDescriptor->bNumEndpoints), DeviceExtension->ConfigurationHandle, DeviceExtension->InterfaceList[InterfaceIndex].InterfaceDescriptor->bInterfaceNumber, DeviceExtension->InterfaceList[InterfaceIndex].InterfaceDescriptor->bAlternateSetting);
|
||||
|
||||
//
|
||||
// now select the interface
|
||||
//
|
||||
Status = USBCCGP_SyncUrbRequest(DeviceExtension->NextDeviceObject, Urb);
|
||||
|
||||
//
|
||||
// did it succeeed
|
||||
//
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
//
|
||||
// update configuration info
|
||||
//
|
||||
ASSERT(Urb->UrbSelectInterface.Interface.Length == DeviceExtension->InterfaceList[InterfaceIndex].Interface->Length);
|
||||
RtlCopyMemory(DeviceExtension->InterfaceList[InterfaceIndex].Interface, &Urb->UrbSelectInterface.Interface, Urb->UrbSelectInterface.Interface.Length);
|
||||
}
|
||||
|
||||
//
|
||||
// free urb
|
||||
//
|
||||
FreeItem(Urb);
|
||||
|
||||
//
|
||||
// done
|
||||
//
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
USBCCGP_SelectConfiguration(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PFDO_DEVICE_EXTENSION DeviceExtension)
|
||||
{
|
||||
PUSBD_INTERFACE_INFORMATION InterfaceInformation;
|
||||
NTSTATUS Status;
|
||||
PURB Urb;
|
||||
ULONG Index;
|
||||
|
||||
//
|
||||
// now scan configuration descriptors
|
||||
//
|
||||
Status = USBCCGP_ScanConfigurationDescriptor(DeviceExtension, DeviceExtension->ConfigurationDescriptor);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
//
|
||||
// failed to scan
|
||||
//
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// now allocate the urb
|
||||
//
|
||||
Urb = USBD_CreateConfigurationRequestEx(DeviceExtension->ConfigurationDescriptor, DeviceExtension->InterfaceList);
|
||||
if (!Urb)
|
||||
{
|
||||
//
|
||||
// no memory
|
||||
//
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
//
|
||||
// submit urb
|
||||
//
|
||||
Status = USBCCGP_SyncUrbRequest(DeviceExtension->NextDeviceObject, Urb);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
//
|
||||
// failed to set configuration
|
||||
//
|
||||
DPRINT1("USBCCGP_SyncUrbRequest failed to set interface %x\n", Status);
|
||||
ExFreePool(Urb);
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// get interface information
|
||||
//
|
||||
InterfaceInformation = &Urb->UrbSelectConfiguration.Interface;
|
||||
for(Index = 0; Index < DeviceExtension->InterfaceListCount; Index++)
|
||||
{
|
||||
//
|
||||
// allocate buffer to store interface information
|
||||
//
|
||||
DeviceExtension->InterfaceList[Index].Interface = AllocateItem(NonPagedPool, InterfaceInformation->Length);
|
||||
if (!DeviceExtension->InterfaceList[Index].Interface)
|
||||
{
|
||||
//
|
||||
// no memory
|
||||
//
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
//
|
||||
// copy interface information
|
||||
//
|
||||
RtlCopyMemory(DeviceExtension->InterfaceList[Index].Interface, InterfaceInformation, InterfaceInformation->Length);
|
||||
|
||||
//
|
||||
// move to next interface
|
||||
//
|
||||
InterfaceInformation = (PUSBD_INTERFACE_INFORMATION)((ULONG_PTR)InterfaceInformation + InterfaceInformation->Length);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// store pipe handle
|
||||
//
|
||||
DeviceExtension->ConfigurationHandle = Urb->UrbSelectConfiguration.ConfigurationHandle;
|
||||
|
||||
//
|
||||
// free interface list & urb
|
||||
//
|
||||
ExFreePool(Urb);
|
||||
|
||||
//
|
||||
// done
|
||||
//
|
||||
return Status;
|
||||
}
|
||||
|
720
reactos/drivers/usb/usbccgp/fdo.c
Normal file
720
reactos/drivers/usb/usbccgp/fdo.c
Normal file
|
@ -0,0 +1,720 @@
|
|||
/*
|
||||
* PROJECT: ReactOS Universal Serial Bus Bulk Enhanced Host Controller Interface
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* FILE: drivers/usb/usbccgp/fdo.c
|
||||
* PURPOSE: USB device driver.
|
||||
* PROGRAMMERS:
|
||||
* Michael Martin (michael.martin@reactos.org)
|
||||
* Johannes Anderwald (johannes.anderwald@reactos.org)
|
||||
* Cameron Gutman
|
||||
*/
|
||||
|
||||
#include "usbccgp.h"
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
FDO_QueryCapabilitiesCompletionRoutine(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp,
|
||||
IN PVOID Context)
|
||||
{
|
||||
//
|
||||
// set event
|
||||
//
|
||||
KeSetEvent((PRKEVENT)Context, 0, FALSE);
|
||||
|
||||
//
|
||||
// completion is done in the HidClassFDO_QueryCapabilities routine
|
||||
//
|
||||
return STATUS_MORE_PROCESSING_REQUIRED;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
FDO_QueryCapabilities(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN OUT PDEVICE_CAPABILITIES Capabilities)
|
||||
{
|
||||
PIRP Irp;
|
||||
KEVENT Event;
|
||||
NTSTATUS Status;
|
||||
PIO_STACK_LOCATION IoStack;
|
||||
PFDO_DEVICE_EXTENSION FDODeviceExtension;
|
||||
|
||||
//
|
||||
// get device extension
|
||||
//
|
||||
FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
ASSERT(FDODeviceExtension->Common.IsFDO);
|
||||
|
||||
//
|
||||
// init event
|
||||
//
|
||||
KeInitializeEvent(&Event, NotificationEvent, FALSE);
|
||||
|
||||
//
|
||||
// now allocte the irp
|
||||
//
|
||||
Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
|
||||
if (!Irp)
|
||||
{
|
||||
//
|
||||
// no memory
|
||||
//
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
//
|
||||
// get next stack location
|
||||
//
|
||||
IoStack = IoGetNextIrpStackLocation(Irp);
|
||||
|
||||
//
|
||||
// init stack location
|
||||
//
|
||||
IoStack->MajorFunction = IRP_MJ_PNP;
|
||||
IoStack->MinorFunction = IRP_MN_QUERY_CAPABILITIES;
|
||||
IoStack->Parameters.DeviceCapabilities.Capabilities = Capabilities;
|
||||
|
||||
//
|
||||
// set completion routine
|
||||
//
|
||||
IoSetCompletionRoutine(Irp, FDO_QueryCapabilitiesCompletionRoutine, (PVOID)&Event, TRUE, TRUE, TRUE);
|
||||
|
||||
//
|
||||
// init capabilities
|
||||
//
|
||||
RtlZeroMemory(Capabilities, sizeof(DEVICE_CAPABILITIES));
|
||||
Capabilities->Size = sizeof(DEVICE_CAPABILITIES);
|
||||
Capabilities->Version = 1; // FIXME hardcoded constant
|
||||
Capabilities->Address = MAXULONG;
|
||||
Capabilities->UINumber = MAXULONG;
|
||||
|
||||
//
|
||||
// pnp irps have default completion code
|
||||
//
|
||||
Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
|
||||
|
||||
//
|
||||
// call lower device
|
||||
//
|
||||
Status = IoCallDriver(FDODeviceExtension->NextDeviceObject, Irp);
|
||||
if (Status == STATUS_PENDING)
|
||||
{
|
||||
//
|
||||
// wait for completion
|
||||
//
|
||||
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
|
||||
}
|
||||
|
||||
//
|
||||
// get status
|
||||
//
|
||||
Status = Irp->IoStatus.Status;
|
||||
|
||||
//
|
||||
// complete request
|
||||
//
|
||||
IoFreeIrp(Irp);
|
||||
|
||||
//
|
||||
// done
|
||||
//
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
FDO_DeviceRelations(
|
||||
PDEVICE_OBJECT DeviceObject,
|
||||
PIRP Irp)
|
||||
{
|
||||
ULONG DeviceCount = 0;
|
||||
ULONG Index;
|
||||
PDEVICE_RELATIONS DeviceRelations;
|
||||
PIO_STACK_LOCATION IoStack;
|
||||
PFDO_DEVICE_EXTENSION FDODeviceExtension;
|
||||
|
||||
//
|
||||
// get device extension
|
||||
//
|
||||
FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
|
||||
//
|
||||
// get current irp stack location
|
||||
//
|
||||
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||
|
||||
//
|
||||
// check if relation type is BusRelations
|
||||
//
|
||||
if (IoStack->Parameters.QueryDeviceRelations.Type != BusRelations)
|
||||
{
|
||||
//
|
||||
// FDO always only handles bus relations
|
||||
//
|
||||
return USBCCGP_SyncForwardIrp(FDODeviceExtension->NextDeviceObject, Irp);
|
||||
}
|
||||
|
||||
//
|
||||
// go through array and count device objects
|
||||
//
|
||||
for(Index = 0; Index < FDODeviceExtension->FunctionDescriptorCount; Index++)
|
||||
{
|
||||
if (FDODeviceExtension->ChildPDO[Index])
|
||||
{
|
||||
//
|
||||
// child pdo
|
||||
//
|
||||
DeviceCount++;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// allocate device relations
|
||||
//
|
||||
DeviceRelations = (PDEVICE_RELATIONS)AllocateItem(PagedPool, sizeof(DEVICE_RELATIONS) + (DeviceCount > 1 ? (DeviceCount-1) * sizeof(PDEVICE_OBJECT) : 0));
|
||||
if (!DeviceRelations)
|
||||
{
|
||||
//
|
||||
// no memory
|
||||
//
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
//
|
||||
// add device objects
|
||||
//
|
||||
for(Index = 0; Index < FDODeviceExtension->FunctionDescriptorCount; Index++)
|
||||
{
|
||||
if (FDODeviceExtension->ChildPDO[Index])
|
||||
{
|
||||
//
|
||||
// store child pdo
|
||||
//
|
||||
DeviceRelations->Objects[DeviceRelations->Count] = FDODeviceExtension->ChildPDO[Index];
|
||||
|
||||
//
|
||||
// add reference
|
||||
//
|
||||
ObReferenceObject(FDODeviceExtension->ChildPDO[Index]);
|
||||
|
||||
//
|
||||
// increment count
|
||||
//
|
||||
DeviceRelations->Count++;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// store result
|
||||
//
|
||||
Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
|
||||
|
||||
//
|
||||
// request completed successfully
|
||||
//
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
FDO_CreateChildPdo(
|
||||
IN PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PDEVICE_OBJECT PDODeviceObject;
|
||||
PPDO_DEVICE_EXTENSION PDODeviceExtension;
|
||||
PFDO_DEVICE_EXTENSION FDODeviceExtension;
|
||||
ULONG Index;
|
||||
|
||||
//
|
||||
// get device extension
|
||||
//
|
||||
FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
ASSERT(FDODeviceExtension->Common.IsFDO);
|
||||
|
||||
//
|
||||
// lets create array for the child PDO
|
||||
//
|
||||
FDODeviceExtension->ChildPDO = AllocateItem(NonPagedPool, sizeof(PDEVICE_OBJECT) * FDODeviceExtension->FunctionDescriptorCount);
|
||||
if (!FDODeviceExtension->ChildPDO)
|
||||
{
|
||||
//
|
||||
// no memory
|
||||
//
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
//
|
||||
// create pdo for each function
|
||||
//
|
||||
for(Index = 0; Index < FDODeviceExtension->FunctionDescriptorCount; Index++)
|
||||
{
|
||||
//
|
||||
// create the PDO
|
||||
//
|
||||
Status = IoCreateDevice(FDODeviceExtension->DriverObject, sizeof(PDO_DEVICE_EXTENSION), NULL, FILE_DEVICE_USB, FILE_AUTOGENERATED_DEVICE_NAME, FALSE, &PDODeviceObject);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
//
|
||||
// failed to create device object
|
||||
//
|
||||
DPRINT1("IoCreateDevice failed with %x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// store in array
|
||||
//
|
||||
FDODeviceExtension->ChildPDO[Index] = PDODeviceObject;
|
||||
|
||||
//
|
||||
// get device extension
|
||||
//
|
||||
PDODeviceExtension = (PPDO_DEVICE_EXTENSION)PDODeviceObject->DeviceExtension;
|
||||
RtlZeroMemory(PDODeviceExtension, sizeof(PDO_DEVICE_EXTENSION));
|
||||
|
||||
//
|
||||
// init device extension
|
||||
//
|
||||
PDODeviceExtension->Common.IsFDO = FALSE;
|
||||
PDODeviceExtension->FunctionDescriptor = &FDODeviceExtension->FunctionDescriptor[Index];
|
||||
PDODeviceExtension->NextDeviceObject = DeviceObject;
|
||||
PDODeviceExtension->FunctionIndex = Index;
|
||||
PDODeviceExtension->FDODeviceExtension = FDODeviceExtension;
|
||||
PDODeviceExtension->InterfaceList = FDODeviceExtension->InterfaceList;
|
||||
PDODeviceExtension->InterfaceListCount = FDODeviceExtension->InterfaceListCount;
|
||||
PDODeviceExtension->ConfigurationHandle = FDODeviceExtension->ConfigurationHandle;
|
||||
PDODeviceExtension->ConfigurationDescriptor = FDODeviceExtension->ConfigurationDescriptor;
|
||||
RtlCopyMemory(&PDODeviceExtension->Capabilities, &FDODeviceExtension->Capabilities, sizeof(DEVICE_CAPABILITIES));
|
||||
RtlCopyMemory(&PDODeviceExtension->DeviceDescriptor, &FDODeviceExtension->DeviceDescriptor, sizeof(USB_DEVICE_DESCRIPTOR));
|
||||
|
||||
//
|
||||
// patch the stack size
|
||||
//
|
||||
PDODeviceObject->StackSize = DeviceObject->StackSize + 1;
|
||||
|
||||
//
|
||||
// set device flags
|
||||
//
|
||||
PDODeviceObject->Flags |= DO_DIRECT_IO | DO_MAP_IO_BUFFER;
|
||||
|
||||
//
|
||||
// device is initialized
|
||||
//
|
||||
PDODeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
|
||||
}
|
||||
|
||||
//
|
||||
// done
|
||||
//
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
FDO_StartDevice(
|
||||
PDEVICE_OBJECT DeviceObject,
|
||||
PIRP Irp)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PFDO_DEVICE_EXTENSION FDODeviceExtension;
|
||||
|
||||
//
|
||||
// get device extension
|
||||
//
|
||||
FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
ASSERT(FDODeviceExtension->Common.IsFDO);
|
||||
|
||||
//
|
||||
// first start lower device
|
||||
//
|
||||
Status = USBCCGP_SyncForwardIrp(FDODeviceExtension->NextDeviceObject, Irp);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
//
|
||||
// failed to start lower device
|
||||
//
|
||||
DPRINT1("FDO_StartDevice lower device failed to start with %x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
// get descriptors
|
||||
Status = USBCCGP_GetDescriptors(DeviceObject);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
// failed to start lower device
|
||||
DPRINT1("FDO_StartDevice failed to get descriptors with %x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
// get capabilities
|
||||
Status = FDO_QueryCapabilities(DeviceObject, &FDODeviceExtension->Capabilities);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
// failed to start lower device
|
||||
DPRINT1("FDO_StartDevice failed to get capabilities with %x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
// now select the configuration
|
||||
Status = USBCCGP_SelectConfiguration(DeviceObject, FDODeviceExtension);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
// failed to select interface
|
||||
DPRINT1("FDO_StartDevice failed to get capabilities with %x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
// query bus interface
|
||||
USBCCGP_QueryInterface(FDODeviceExtension->NextDeviceObject, &FDODeviceExtension->BusInterface);
|
||||
|
||||
// now enumerate the functions
|
||||
Status = USBCCGP_EnumerateFunctions(DeviceObject);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
// failed to enumerate functions
|
||||
DPRINT1("Failed to enumerate functions with %x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// sanity checks
|
||||
//
|
||||
ASSERT(FDODeviceExtension->FunctionDescriptorCount);
|
||||
ASSERT(FDODeviceExtension->FunctionDescriptor);
|
||||
DumpFunctionDescriptor(FDODeviceExtension->FunctionDescriptor, FDODeviceExtension->FunctionDescriptorCount);
|
||||
|
||||
//
|
||||
// now create the pdo
|
||||
//
|
||||
Status = FDO_CreateChildPdo(DeviceObject);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
//
|
||||
// failed
|
||||
//
|
||||
DPRINT1("FDO_CreateChildPdo failed with %x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// inform pnp manager of new device objects
|
||||
//
|
||||
IoInvalidateDeviceRelations(FDODeviceExtension->PhysicalDeviceObject, BusRelations);
|
||||
|
||||
//
|
||||
// done
|
||||
//
|
||||
DPRINT("[USBCCGP] FDO initialized successfully\n");
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
FDO_HandlePnp(
|
||||
PDEVICE_OBJECT DeviceObject,
|
||||
PIRP Irp)
|
||||
{
|
||||
PIO_STACK_LOCATION IoStack;
|
||||
NTSTATUS Status;
|
||||
PFDO_DEVICE_EXTENSION FDODeviceExtension;
|
||||
|
||||
// get device extension
|
||||
FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
ASSERT(FDODeviceExtension->Common.IsFDO);
|
||||
|
||||
|
||||
// get stack location
|
||||
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||
DPRINT("[USBCCGP] PnP Minor %x\n", IoStack->MinorFunction);
|
||||
switch(IoStack->MinorFunction)
|
||||
{
|
||||
case IRP_MN_REMOVE_DEVICE:
|
||||
{
|
||||
/* Send the IRP down the stack */
|
||||
Status = USBCCGP_SyncForwardIrp(FDODeviceExtension->NextDeviceObject, Irp);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
//
|
||||
// Detach from the device stack
|
||||
//
|
||||
IoDetachDevice(FDODeviceExtension->NextDeviceObject);
|
||||
|
||||
//
|
||||
// Delete the device object
|
||||
//
|
||||
IoDeleteDevice(DeviceObject);
|
||||
}
|
||||
|
||||
//
|
||||
// request completed
|
||||
//
|
||||
break;
|
||||
}
|
||||
case IRP_MN_START_DEVICE:
|
||||
{
|
||||
//
|
||||
// start the device
|
||||
//
|
||||
Status = FDO_StartDevice(DeviceObject, Irp);
|
||||
break;
|
||||
}
|
||||
case IRP_MN_QUERY_DEVICE_RELATIONS:
|
||||
{
|
||||
//
|
||||
// handle device relations
|
||||
//
|
||||
Status = FDO_DeviceRelations(DeviceObject, Irp);
|
||||
break;
|
||||
}
|
||||
case IRP_MN_QUERY_CAPABILITIES:
|
||||
{
|
||||
//
|
||||
// copy capabilities
|
||||
//
|
||||
RtlCopyMemory(IoStack->Parameters.DeviceCapabilities.Capabilities, &FDODeviceExtension->Capabilities, sizeof(DEVICE_CAPABILITIES));
|
||||
Status = USBCCGP_SyncForwardIrp(FDODeviceExtension->NextDeviceObject, Irp);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
//
|
||||
// surprise removal ok
|
||||
//
|
||||
IoStack->Parameters.DeviceCapabilities.Capabilities->SurpriseRemovalOK = TRUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IRP_MN_QUERY_REMOVE_DEVICE:
|
||||
case IRP_MN_QUERY_STOP_DEVICE:
|
||||
{
|
||||
//
|
||||
// sure
|
||||
//
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
|
||||
//
|
||||
// forward irp to next device object
|
||||
//
|
||||
IoSkipCurrentIrpStackLocation(Irp);
|
||||
return IoCallDriver(FDODeviceExtension->NextDeviceObject, Irp);
|
||||
}
|
||||
default:
|
||||
{
|
||||
//
|
||||
// forward irp to next device object
|
||||
//
|
||||
IoSkipCurrentIrpStackLocation(Irp);
|
||||
return IoCallDriver(FDODeviceExtension->NextDeviceObject, Irp);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
// complete request
|
||||
//
|
||||
Irp->IoStatus.Status = Status;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
FDO_HandleResetCyclePort(
|
||||
PDEVICE_OBJECT DeviceObject,
|
||||
PIRP Irp)
|
||||
{
|
||||
PIO_STACK_LOCATION IoStack;
|
||||
NTSTATUS Status;
|
||||
PFDO_DEVICE_EXTENSION FDODeviceExtension;
|
||||
PLIST_ENTRY ListHead, Entry;
|
||||
LIST_ENTRY TempList;
|
||||
PUCHAR ResetActive;
|
||||
PIRP ListIrp;
|
||||
KIRQL OldLevel;
|
||||
|
||||
//
|
||||
// get device extension
|
||||
//
|
||||
FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
ASSERT(FDODeviceExtension->Common.IsFDO);
|
||||
|
||||
// get stack location
|
||||
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||
DPRINT("FDO_HandleResetCyclePort IOCTL %x\n", IoStack->Parameters.DeviceIoControl.IoControlCode);
|
||||
|
||||
if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_USB_RESET_PORT)
|
||||
{
|
||||
//
|
||||
// use reset port list
|
||||
//
|
||||
ListHead = &FDODeviceExtension->ResetPortListHead;
|
||||
ResetActive = &FDODeviceExtension->ResetPortActive;
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// use cycle port list
|
||||
//
|
||||
ListHead = &FDODeviceExtension->CyclePortListHead;
|
||||
ResetActive = &FDODeviceExtension->CyclePortActive;
|
||||
}
|
||||
|
||||
//
|
||||
// acquire lock
|
||||
//
|
||||
KeAcquireSpinLock(&FDODeviceExtension->Lock, &OldLevel);
|
||||
|
||||
if (*ResetActive)
|
||||
{
|
||||
//
|
||||
// insert into pending list
|
||||
//
|
||||
InsertTailList(ListHead, &Irp->Tail.Overlay.ListEntry);
|
||||
|
||||
//
|
||||
// mark irp pending
|
||||
//
|
||||
IoMarkIrpPending(Irp);
|
||||
Status = STATUS_PENDING;
|
||||
|
||||
//
|
||||
// release lock
|
||||
//
|
||||
KeReleaseSpinLock(&FDODeviceExtension->Lock, OldLevel);
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// mark reset active
|
||||
//
|
||||
*ResetActive = TRUE;
|
||||
|
||||
//
|
||||
// release lock
|
||||
//
|
||||
KeReleaseSpinLock(&FDODeviceExtension->Lock, OldLevel);
|
||||
|
||||
//
|
||||
// forward request synchronized
|
||||
//
|
||||
USBCCGP_SyncForwardIrp(FDODeviceExtension->NextDeviceObject, Irp);
|
||||
|
||||
//
|
||||
// reacquire lock
|
||||
//
|
||||
KeAcquireSpinLock(&FDODeviceExtension->Lock, &OldLevel);
|
||||
|
||||
//
|
||||
// mark reset as completed
|
||||
//
|
||||
*ResetActive = FALSE;
|
||||
|
||||
//
|
||||
// move all requests into temporary list
|
||||
//
|
||||
InitializeListHead(&TempList);
|
||||
while(!IsListEmpty(ListHead))
|
||||
{
|
||||
Entry = RemoveHeadList(ListHead);
|
||||
InsertTailList(&TempList, Entry);
|
||||
}
|
||||
|
||||
//
|
||||
// release lock
|
||||
//
|
||||
KeReleaseSpinLock(&FDODeviceExtension->Lock, OldLevel);
|
||||
|
||||
//
|
||||
// complete pending irps
|
||||
//
|
||||
while(!IsListEmpty(&TempList))
|
||||
{
|
||||
Entry = RemoveHeadList(&TempList);
|
||||
ListIrp = (PIRP)CONTAINING_RECORD(Entry, IRP, Tail.Overlay.ListEntry);
|
||||
|
||||
//
|
||||
// complete request with status success
|
||||
//
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
}
|
||||
|
||||
//
|
||||
// status success
|
||||
//
|
||||
Status = STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
|
||||
NTSTATUS
|
||||
FDO_HandleInternalDeviceControl(
|
||||
PDEVICE_OBJECT DeviceObject,
|
||||
PIRP Irp)
|
||||
{
|
||||
PIO_STACK_LOCATION IoStack;
|
||||
NTSTATUS Status;
|
||||
PFDO_DEVICE_EXTENSION FDODeviceExtension;
|
||||
|
||||
//
|
||||
// get device extension
|
||||
//
|
||||
FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
ASSERT(FDODeviceExtension->Common.IsFDO);
|
||||
|
||||
// get stack location
|
||||
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||
|
||||
if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_USB_RESET_PORT ||
|
||||
IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_USB_CYCLE_PORT)
|
||||
{
|
||||
//
|
||||
// handle reset / cycle ports
|
||||
//
|
||||
Status = FDO_HandleResetCyclePort(DeviceObject, Irp);
|
||||
DPRINT("FDO_HandleResetCyclePort Status %x\n", Status);
|
||||
if (Status != STATUS_PENDING)
|
||||
{
|
||||
//
|
||||
// complete request
|
||||
//
|
||||
Irp->IoStatus.Status = Status;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// forward and forget request
|
||||
//
|
||||
IoSkipCurrentIrpStackLocation(Irp);
|
||||
return IoCallDriver(FDODeviceExtension->NextDeviceObject, Irp);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
FDO_Dispatch(
|
||||
PDEVICE_OBJECT DeviceObject,
|
||||
PIRP Irp)
|
||||
{
|
||||
PIO_STACK_LOCATION IoStack;
|
||||
NTSTATUS Status;
|
||||
|
||||
/* get stack location */
|
||||
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||
|
||||
switch(IoStack->MajorFunction)
|
||||
{
|
||||
case IRP_MJ_PNP:
|
||||
return FDO_HandlePnp(DeviceObject, Irp);
|
||||
case IRP_MJ_INTERNAL_DEVICE_CONTROL:
|
||||
return FDO_HandleInternalDeviceControl(DeviceObject, Irp);
|
||||
default:
|
||||
DPRINT1("FDO_Dispatch Function %x not implemented\n", IoStack->MajorFunction);
|
||||
ASSERT(FALSE);
|
||||
Status = Irp->IoStatus.Status;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return Status;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
909
reactos/drivers/usb/usbccgp/function.c
Normal file
909
reactos/drivers/usb/usbccgp/function.c
Normal file
|
@ -0,0 +1,909 @@
|
|||
/*
|
||||
* PROJECT: ReactOS Universal Serial Bus Bulk Enhanced Host Controller Interface
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* FILE: drivers/usb/usbccgp/descriptor.c
|
||||
* PURPOSE: USB device driver.
|
||||
* PROGRAMMERS:
|
||||
* Michael Martin (michael.martin@reactos.org)
|
||||
* Johannes Anderwald (johannes.anderwald@reactos.org)
|
||||
* Cameron Gutman
|
||||
*/
|
||||
|
||||
#include "usbccgp.h"
|
||||
|
||||
NTSTATUS
|
||||
USBCCGP_QueryInterface(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
OUT PUSBC_DEVICE_CONFIGURATION_INTERFACE_V1 BusInterface)
|
||||
{
|
||||
KEVENT Event;
|
||||
NTSTATUS Status;
|
||||
PIRP Irp;
|
||||
IO_STATUS_BLOCK IoStatus;
|
||||
PIO_STACK_LOCATION Stack;
|
||||
|
||||
//
|
||||
// sanity checks
|
||||
//
|
||||
ASSERT(DeviceObject);
|
||||
|
||||
//
|
||||
// initialize event
|
||||
//
|
||||
KeInitializeEvent(&Event, NotificationEvent, FALSE);
|
||||
|
||||
//
|
||||
// init interface
|
||||
//
|
||||
RtlZeroMemory(BusInterface, sizeof(USBC_DEVICE_CONFIGURATION_INTERFACE_V1));
|
||||
BusInterface->Version = USBC_DEVICE_CONFIGURATION_INTERFACE_VERSION_1;
|
||||
BusInterface->Size = sizeof(USBC_DEVICE_CONFIGURATION_INTERFACE_V1);
|
||||
|
||||
//
|
||||
// create irp
|
||||
//
|
||||
Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP,
|
||||
DeviceObject,
|
||||
NULL,
|
||||
0,
|
||||
NULL,
|
||||
&Event,
|
||||
&IoStatus);
|
||||
|
||||
//
|
||||
// was irp built
|
||||
//
|
||||
if (Irp == NULL)
|
||||
{
|
||||
//
|
||||
// no memory
|
||||
//
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
//
|
||||
// initialize request
|
||||
//
|
||||
Stack=IoGetNextIrpStackLocation(Irp);
|
||||
Stack->MajorFunction = IRP_MJ_PNP;
|
||||
Stack->MinorFunction = IRP_MN_QUERY_INTERFACE;
|
||||
Stack->Parameters.QueryInterface.Size = sizeof(BUS_INTERFACE_STANDARD);
|
||||
Stack->Parameters.QueryInterface.InterfaceType = (LPGUID)&USB_BUS_INTERFACE_USBC_CONFIGURATION_GUID;
|
||||
Stack->Parameters.QueryInterface.Version = 2;
|
||||
Stack->Parameters.QueryInterface.Interface = (PINTERFACE)&BusInterface;
|
||||
Stack->Parameters.QueryInterface.InterfaceSpecificData = NULL;
|
||||
Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
|
||||
|
||||
//
|
||||
// call driver
|
||||
//
|
||||
Status= IoCallDriver(DeviceObject, Irp);
|
||||
|
||||
//
|
||||
// did operation complete
|
||||
//
|
||||
if (Status == STATUS_PENDING)
|
||||
{
|
||||
//
|
||||
// wait for completion
|
||||
//
|
||||
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
|
||||
|
||||
//
|
||||
// collect status
|
||||
//
|
||||
Status = IoStatus.Status;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
USBCCGP_CustomEnumWithInterface(
|
||||
IN PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
PFDO_DEVICE_EXTENSION FDODeviceExtension;
|
||||
ULONG FunctionDescriptorBufferLength = 0;
|
||||
NTSTATUS Status;
|
||||
PUSBC_FUNCTION_DESCRIPTOR FunctionDescriptorBuffer = NULL;
|
||||
|
||||
//
|
||||
// get device extension
|
||||
//
|
||||
FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
ASSERT(FDODeviceExtension->Common.IsFDO);
|
||||
|
||||
if (FDODeviceExtension->BusInterface.StartDeviceCallback == NULL)
|
||||
{
|
||||
//
|
||||
// not supported
|
||||
//
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
//
|
||||
// invoke callback
|
||||
//
|
||||
Status = FDODeviceExtension->BusInterface.StartDeviceCallback(FDODeviceExtension->DeviceDescriptor,
|
||||
FDODeviceExtension->ConfigurationDescriptor,
|
||||
&FunctionDescriptorBuffer,
|
||||
&FunctionDescriptorBufferLength,
|
||||
DeviceObject,
|
||||
FDODeviceExtension->PhysicalDeviceObject);
|
||||
|
||||
DPRINT("USBCCGP_CustomEnumWithInterface Status %x\n", Status);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
//
|
||||
// failed
|
||||
//
|
||||
return Status;
|
||||
}
|
||||
|
||||
DPRINT("FunctionDescriptorBufferLength %lu\n", FunctionDescriptorBufferLength);
|
||||
DPRINT("FunctionDescriptorBuffer %p\n", FunctionDescriptorBuffer);
|
||||
|
||||
//
|
||||
// assume length % function buffer size
|
||||
//
|
||||
ASSERT(FunctionDescriptorBufferLength);
|
||||
ASSERT(FunctionDescriptorBufferLength % sizeof(USBC_FUNCTION_DESCRIPTOR) == 0);
|
||||
|
||||
//
|
||||
// store result
|
||||
//
|
||||
FDODeviceExtension->FunctionDescriptor = FunctionDescriptorBuffer;
|
||||
FDODeviceExtension->FunctionDescriptorCount = FunctionDescriptorBufferLength / sizeof(USBC_FUNCTION_DESCRIPTOR);
|
||||
|
||||
//
|
||||
// success
|
||||
//
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ULONG
|
||||
USBCCGP_CountAssociationDescriptors(
|
||||
IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor)
|
||||
{
|
||||
PUSB_INTERFACE_ASSOCIATION_DESCRIPTOR Descriptor;
|
||||
PUCHAR Offset, End;
|
||||
ULONG Count = 0;
|
||||
|
||||
//
|
||||
// init offsets
|
||||
//
|
||||
Offset = (PUCHAR)ConfigurationDescriptor + ConfigurationDescriptor->bLength;
|
||||
End = (PUCHAR)ConfigurationDescriptor + ConfigurationDescriptor->wTotalLength;
|
||||
|
||||
while(Offset < End)
|
||||
{
|
||||
//
|
||||
// get association descriptor
|
||||
//
|
||||
Descriptor = (PUSB_INTERFACE_ASSOCIATION_DESCRIPTOR)Offset;
|
||||
|
||||
if (Descriptor->bLength == sizeof(USB_INTERFACE_ASSOCIATION_DESCRIPTOR) && Descriptor->bDescriptorType == USB_INTERFACE_ASSOCIATION_DESCRIPTOR_TYPE)
|
||||
{
|
||||
//
|
||||
// found descriptor
|
||||
//
|
||||
Count++;
|
||||
}
|
||||
|
||||
//
|
||||
// move to next descriptor
|
||||
//
|
||||
Offset += Descriptor->bLength;
|
||||
}
|
||||
|
||||
//
|
||||
// done
|
||||
//
|
||||
return Count;
|
||||
}
|
||||
|
||||
PUSB_INTERFACE_ASSOCIATION_DESCRIPTOR
|
||||
USBCCGP_GetAssociationDescriptorAtIndex(
|
||||
IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
|
||||
IN ULONG Index)
|
||||
{
|
||||
PUSB_INTERFACE_ASSOCIATION_DESCRIPTOR Descriptor;
|
||||
PUCHAR Offset, End;
|
||||
ULONG Count = 0;
|
||||
|
||||
//
|
||||
// init offsets
|
||||
//
|
||||
Offset = (PUCHAR)ConfigurationDescriptor + ConfigurationDescriptor->bLength;
|
||||
End = (PUCHAR)ConfigurationDescriptor + ConfigurationDescriptor->wTotalLength;
|
||||
|
||||
while(Offset < End)
|
||||
{
|
||||
//
|
||||
// get association descriptor
|
||||
//
|
||||
Descriptor = (PUSB_INTERFACE_ASSOCIATION_DESCRIPTOR)Offset;
|
||||
|
||||
if (Descriptor->bLength == sizeof(USB_INTERFACE_ASSOCIATION_DESCRIPTOR) && Descriptor->bDescriptorType == USB_INTERFACE_ASSOCIATION_DESCRIPTOR_TYPE)
|
||||
{
|
||||
if (Index == Count)
|
||||
{
|
||||
//
|
||||
// found descriptor
|
||||
//
|
||||
return Descriptor;
|
||||
}
|
||||
|
||||
//
|
||||
// not the searched one
|
||||
//
|
||||
Count++;
|
||||
}
|
||||
|
||||
//
|
||||
// move to next descriptor
|
||||
//
|
||||
Offset += Descriptor->bLength;
|
||||
}
|
||||
|
||||
//
|
||||
// failed to find descriptor at the specified index
|
||||
//
|
||||
return NULL;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
USBCCGP_InitInterfaceListOfFunctionDescriptor(
|
||||
IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
|
||||
IN PUSB_INTERFACE_ASSOCIATION_DESCRIPTOR AssociationDescriptor,
|
||||
OUT PUSBC_FUNCTION_DESCRIPTOR FunctionDescriptor)
|
||||
{
|
||||
PUSB_INTERFACE_DESCRIPTOR Descriptor;
|
||||
PUCHAR Offset, End;
|
||||
ULONG Count = 0;
|
||||
|
||||
//
|
||||
// init offsets
|
||||
//
|
||||
Offset = (PUCHAR)AssociationDescriptor + AssociationDescriptor->bLength;
|
||||
End = (PUCHAR)ConfigurationDescriptor + ConfigurationDescriptor->wTotalLength;
|
||||
|
||||
while(Offset < End)
|
||||
{
|
||||
//
|
||||
// get association descriptor
|
||||
//
|
||||
Descriptor = (PUSB_INTERFACE_DESCRIPTOR)Offset;
|
||||
|
||||
if (Descriptor->bLength == sizeof(USB_INTERFACE_DESCRIPTOR) && Descriptor->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE)
|
||||
{
|
||||
//
|
||||
// store interface descriptor
|
||||
//
|
||||
FunctionDescriptor->InterfaceDescriptorList[Count] = Descriptor;
|
||||
Count++;
|
||||
|
||||
if (Count == AssociationDescriptor->bInterfaceCount)
|
||||
{
|
||||
//
|
||||
// got all interfaces
|
||||
//
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
if (Descriptor->bLength == sizeof(USB_INTERFACE_ASSOCIATION_DESCRIPTOR) && Descriptor->bDescriptorType == USB_INTERFACE_ASSOCIATION_DESCRIPTOR_TYPE)
|
||||
{
|
||||
//
|
||||
// WTF? a association descriptor which overlaps the next association descriptor
|
||||
//
|
||||
DPRINT1("Invalid association descriptor\n");
|
||||
ASSERT(FALSE);
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
//
|
||||
// move to next descriptor
|
||||
//
|
||||
Offset += Descriptor->bLength;
|
||||
}
|
||||
|
||||
//
|
||||
// invalid association descriptor
|
||||
//
|
||||
DPRINT1("Invalid association descriptor\n");
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
USBCCGP_InitFunctionDescriptor(
|
||||
IN PFDO_DEVICE_EXTENSION FDODeviceExtension,
|
||||
IN ULONG FunctionNumber,
|
||||
OUT PUSBC_FUNCTION_DESCRIPTOR FunctionDescriptor)
|
||||
{
|
||||
PUSB_INTERFACE_ASSOCIATION_DESCRIPTOR Descriptor;
|
||||
NTSTATUS Status;
|
||||
LPWSTR DescriptionBuffer;
|
||||
WCHAR Buffer[100];
|
||||
ULONG Index;
|
||||
|
||||
// init function number
|
||||
FunctionDescriptor->FunctionNumber = (UCHAR)FunctionNumber;
|
||||
|
||||
// get association descriptor
|
||||
Descriptor = USBCCGP_GetAssociationDescriptorAtIndex(FDODeviceExtension->ConfigurationDescriptor, FunctionNumber);
|
||||
ASSERT(Descriptor);
|
||||
|
||||
// store number interfaces
|
||||
FunctionDescriptor->NumberOfInterfaces = Descriptor->bInterfaceCount;
|
||||
|
||||
// allocate array for interface count
|
||||
FunctionDescriptor->InterfaceDescriptorList = AllocateItem(NonPagedPool, sizeof(PUSB_INTERFACE_DESCRIPTOR) * Descriptor->bInterfaceCount);
|
||||
if (FunctionDescriptor->InterfaceDescriptorList)
|
||||
{
|
||||
//
|
||||
// no memory
|
||||
//
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
// init interface list
|
||||
Status = USBCCGP_InitInterfaceListOfFunctionDescriptor(FDODeviceExtension->ConfigurationDescriptor, Descriptor, FunctionDescriptor);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
//
|
||||
// failed
|
||||
//
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// now init interface description
|
||||
//
|
||||
if (Descriptor->iFunction)
|
||||
{
|
||||
//
|
||||
// get interface description
|
||||
//
|
||||
Status = USBCCGP_GetDescriptor(FDODeviceExtension->NextDeviceObject,
|
||||
USB_STRING_DESCRIPTOR_TYPE,
|
||||
100 * sizeof(WCHAR),
|
||||
Descriptor->iFunction,
|
||||
0x0409, //FIXME
|
||||
(PVOID*)&DescriptionBuffer);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
//
|
||||
// no description
|
||||
//
|
||||
RtlInitUnicodeString(&FunctionDescriptor->FunctionDescription, L"");
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// init description
|
||||
//
|
||||
RtlInitUnicodeString(&FunctionDescriptor->FunctionDescription, DescriptionBuffer);
|
||||
}
|
||||
DPRINT1("FunctionDescription %wZ\n", &FunctionDescriptor->FunctionDescription);
|
||||
}
|
||||
|
||||
//
|
||||
// now init hardware id
|
||||
//
|
||||
Index = swprintf(Buffer, L"USB\\VID_%04x&PID_%04x&Rev_%04x&MI_%02x", FDODeviceExtension->DeviceDescriptor->idVendor,
|
||||
FDODeviceExtension->DeviceDescriptor->idProduct,
|
||||
FDODeviceExtension->DeviceDescriptor->bcdDevice,
|
||||
Descriptor->bFirstInterface) + 1;
|
||||
Index = swprintf(&Buffer[Index], L"USB\\VID_%04x&PID_%04x&MI_%02x", FDODeviceExtension->DeviceDescriptor->idVendor,
|
||||
FDODeviceExtension->DeviceDescriptor->idProduct,
|
||||
Descriptor->bFirstInterface) + 1;
|
||||
|
||||
// allocate result buffer
|
||||
DescriptionBuffer = AllocateItem(NonPagedPool, (Index + 1) * sizeof(WCHAR));
|
||||
if (!DescriptionBuffer)
|
||||
{
|
||||
//
|
||||
// failed to allocate memory
|
||||
//
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
// copy description
|
||||
RtlCopyMemory(DescriptionBuffer, Buffer, Index * sizeof(WCHAR));
|
||||
FunctionDescriptor->HardwareId.Buffer = DescriptionBuffer;
|
||||
FunctionDescriptor->HardwareId.Length = Index * sizeof(WCHAR);
|
||||
FunctionDescriptor->HardwareId.MaximumLength = (Index + 1) * sizeof(WCHAR);
|
||||
|
||||
|
||||
//
|
||||
// now init the compatible id
|
||||
//
|
||||
Index = swprintf(Buffer, L"USB\\Class_%02x&SubClass_%02x&Prot_%02x", Descriptor->bFunctionClass, Descriptor->bFunctionSubClass, Descriptor->bFunctionProtocol) + 1;
|
||||
Index = swprintf(&Buffer[Index], L"USB\\Class_%04x&SubClass_%04x", Descriptor->bFunctionClass, Descriptor->bFunctionSubClass) + 1;
|
||||
Index = swprintf(&Buffer[Index], L"USB\\Class_%04x", Descriptor->bFunctionClass) + 1;
|
||||
|
||||
// allocate result buffer
|
||||
DescriptionBuffer = AllocateItem(NonPagedPool, (Index + 1) * sizeof(WCHAR));
|
||||
if (!DescriptionBuffer)
|
||||
{
|
||||
//
|
||||
// failed to allocate memory
|
||||
//
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
// copy description
|
||||
RtlCopyMemory(DescriptionBuffer, Buffer, Index * sizeof(WCHAR));
|
||||
FunctionDescriptor->CompatibleId.Buffer = DescriptionBuffer;
|
||||
FunctionDescriptor->CompatibleId.Length = Index * sizeof(WCHAR);
|
||||
FunctionDescriptor->CompatibleId.MaximumLength = (Index + 1) * sizeof(WCHAR);
|
||||
|
||||
//
|
||||
// done
|
||||
//
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
USBCCGP_EnumWithAssociationDescriptor(
|
||||
IN PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
ULONG DescriptorCount, Index;
|
||||
PFDO_DEVICE_EXTENSION FDODeviceExtension;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
//
|
||||
// get device extension
|
||||
//
|
||||
FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
ASSERT(FDODeviceExtension->Common.IsFDO);
|
||||
|
||||
//
|
||||
// count association descriptors
|
||||
//
|
||||
DescriptorCount = USBCCGP_CountAssociationDescriptors(FDODeviceExtension->ConfigurationDescriptor);
|
||||
if (!DescriptorCount)
|
||||
{
|
||||
//
|
||||
// no descriptors found
|
||||
//
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
//
|
||||
// allocate function descriptor array
|
||||
//
|
||||
FDODeviceExtension->FunctionDescriptor = AllocateItem(NonPagedPool, sizeof(USBC_FUNCTION_DESCRIPTOR) * DescriptorCount);
|
||||
if (!FDODeviceExtension->FunctionDescriptorCount)
|
||||
{
|
||||
//
|
||||
// no memory
|
||||
//
|
||||
DPRINT1("USBCCGP_EnumWithAssociationDescriptor failed to allocate function descriptor count %x\n", DescriptorCount);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
for(Index = 0; Index < DescriptorCount; Index++)
|
||||
{
|
||||
//
|
||||
// init function descriptors
|
||||
//
|
||||
Status = USBCCGP_InitFunctionDescriptor(FDODeviceExtension, Index, &FDODeviceExtension->FunctionDescriptor[Index]);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
//
|
||||
// failed
|
||||
//
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// store function descriptor count
|
||||
//
|
||||
FDODeviceExtension->FunctionDescriptorCount = DescriptorCount;
|
||||
|
||||
//
|
||||
// done
|
||||
//
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
USBCCG_InitIdsWithInterfaceDescriptor(
|
||||
IN PFDO_DEVICE_EXTENSION FDODeviceExtension,
|
||||
IN PUSB_INTERFACE_DESCRIPTOR Descriptor,
|
||||
IN ULONG FunctionIndex,
|
||||
OUT PUSBC_FUNCTION_DESCRIPTOR FunctionDescriptor)
|
||||
{
|
||||
ULONG Index;
|
||||
WCHAR Buffer[200];
|
||||
LPWSTR DescriptionBuffer;
|
||||
NTSTATUS Status;
|
||||
|
||||
//
|
||||
// now init interface description
|
||||
//
|
||||
if (Descriptor->iInterface)
|
||||
{
|
||||
//
|
||||
// get interface description
|
||||
//
|
||||
Status = USBCCGP_GetDescriptor(FDODeviceExtension->NextDeviceObject,
|
||||
USB_STRING_DESCRIPTOR_TYPE,
|
||||
100 * sizeof(WCHAR),
|
||||
Descriptor->iInterface,
|
||||
0x0409, //FIXME
|
||||
(PVOID*)&DescriptionBuffer);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
//
|
||||
// no description
|
||||
//
|
||||
RtlInitUnicodeString(&FunctionDescriptor->FunctionDescription, L"");
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// init description
|
||||
//
|
||||
RtlInitUnicodeString(&FunctionDescriptor->FunctionDescription, DescriptionBuffer);
|
||||
}
|
||||
DPRINT1("FunctionDescription %wZ\n", &FunctionDescriptor->FunctionDescription);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// now init hardware id
|
||||
//
|
||||
Index = swprintf(Buffer, L"USB\\VID_%04x&PID_%04x&Rev_%04x&MI_%02x", FDODeviceExtension->DeviceDescriptor->idVendor,
|
||||
FDODeviceExtension->DeviceDescriptor->idProduct,
|
||||
FDODeviceExtension->DeviceDescriptor->bcdDevice,
|
||||
FunctionIndex) + 1;
|
||||
Index += swprintf(&Buffer[Index], L"USB\\VID_%04x&PID_%04x&MI_%02x", FDODeviceExtension->DeviceDescriptor->idVendor,
|
||||
FDODeviceExtension->DeviceDescriptor->idProduct,
|
||||
FunctionIndex) + 1;
|
||||
|
||||
// allocate result buffer
|
||||
DescriptionBuffer = AllocateItem(NonPagedPool, (Index + 1) * sizeof(WCHAR));
|
||||
if (!DescriptionBuffer)
|
||||
{
|
||||
//
|
||||
// failed to allocate memory
|
||||
//
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
// copy description
|
||||
RtlCopyMemory(DescriptionBuffer, Buffer, Index * sizeof(WCHAR));
|
||||
FunctionDescriptor->HardwareId.Buffer = DescriptionBuffer;
|
||||
FunctionDescriptor->HardwareId.Length = Index * sizeof(WCHAR);
|
||||
FunctionDescriptor->HardwareId.MaximumLength = (Index + 1) * sizeof(WCHAR);
|
||||
|
||||
//
|
||||
// now init the compatible id
|
||||
//
|
||||
Index = swprintf(Buffer, L"USB\\Class_%02x&SubClass_%02x&Prot_%02x", Descriptor->bInterfaceClass, Descriptor->bInterfaceSubClass, Descriptor->bInterfaceProtocol) + 1;
|
||||
Index += swprintf(&Buffer[Index], L"USB\\Class_%02x&SubClass_%02x", Descriptor->bInterfaceClass, Descriptor->bInterfaceSubClass) + 1;
|
||||
Index += swprintf(&Buffer[Index], L"USB\\Class_%02x", Descriptor->bInterfaceClass) + 1;
|
||||
|
||||
// allocate result buffer
|
||||
DescriptionBuffer = AllocateItem(NonPagedPool, (Index + 1) * sizeof(WCHAR));
|
||||
if (!DescriptionBuffer)
|
||||
{
|
||||
//
|
||||
// failed to allocate memory
|
||||
//
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
// copy description
|
||||
RtlCopyMemory(DescriptionBuffer, Buffer, Index * sizeof(WCHAR));
|
||||
FunctionDescriptor->CompatibleId.Buffer = DescriptionBuffer;
|
||||
FunctionDescriptor->CompatibleId.Length = Index * sizeof(WCHAR);
|
||||
FunctionDescriptor->CompatibleId.MaximumLength = (Index + 1) * sizeof(WCHAR);
|
||||
|
||||
//
|
||||
// done
|
||||
//
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
USBCCGP_LegacyEnum(
|
||||
IN PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
ULONG Index;
|
||||
PFDO_DEVICE_EXTENSION FDODeviceExtension;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
|
||||
|
||||
//
|
||||
// get device extension
|
||||
//
|
||||
FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
ASSERT(FDODeviceExtension->Common.IsFDO);
|
||||
|
||||
//
|
||||
// sanity check
|
||||
//
|
||||
ASSERT(FDODeviceExtension->ConfigurationDescriptor->bNumInterfaces);
|
||||
|
||||
//
|
||||
// allocate function array
|
||||
//
|
||||
FDODeviceExtension->FunctionDescriptor = AllocateItem(NonPagedPool, sizeof(USBC_FUNCTION_DESCRIPTOR) * FDODeviceExtension->ConfigurationDescriptor->bNumInterfaces);
|
||||
if (!FDODeviceExtension->FunctionDescriptor)
|
||||
{
|
||||
//
|
||||
// no memory
|
||||
//
|
||||
DPRINT1("USBCCGP_EnumWithAssociationDescriptor failed to allocate function descriptor %lu\n", FDODeviceExtension->ConfigurationDescriptor->bNumInterfaces);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
//
|
||||
// init function descriptors
|
||||
//
|
||||
for(Index = 0; Index < FDODeviceExtension->ConfigurationDescriptor->bNumInterfaces; Index++)
|
||||
{
|
||||
// get interface descriptor
|
||||
InterfaceDescriptor = USBD_ParseConfigurationDescriptorEx(FDODeviceExtension->ConfigurationDescriptor, FDODeviceExtension->ConfigurationDescriptor, Index, 0, -1, -1, -1);
|
||||
if (InterfaceDescriptor == NULL)
|
||||
{
|
||||
//
|
||||
// failed to find interface descriptor
|
||||
//
|
||||
DPRINT1("[USBCCGP] Failed to find interface descriptor index %lu\n", Index);
|
||||
ASSERT(FALSE);
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
//
|
||||
// init function descriptor
|
||||
//
|
||||
FDODeviceExtension->FunctionDescriptor[Index].FunctionNumber = Index;
|
||||
FDODeviceExtension->FunctionDescriptor[Index].NumberOfInterfaces = 1;
|
||||
FDODeviceExtension->FunctionDescriptor[Index].InterfaceDescriptorList = AllocateItem(NonPagedPool, sizeof(PUSB_INTERFACE_DESCRIPTOR) * 1);
|
||||
if (!FDODeviceExtension->FunctionDescriptor[Index].InterfaceDescriptorList)
|
||||
{
|
||||
//
|
||||
// no memory
|
||||
//
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
//
|
||||
// store interface descriptor
|
||||
//
|
||||
FDODeviceExtension->FunctionDescriptor[Index].InterfaceDescriptorList[0] = InterfaceDescriptor;
|
||||
|
||||
//
|
||||
// now init the device ids
|
||||
//
|
||||
Status = USBCCG_InitIdsWithInterfaceDescriptor(FDODeviceExtension, InterfaceDescriptor, Index, &FDODeviceExtension->FunctionDescriptor[Index]);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
//
|
||||
// failed to init ids
|
||||
//
|
||||
DPRINT1("[USBCCGP] Failed to init ids with %x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// store function count
|
||||
//
|
||||
FDODeviceExtension->FunctionDescriptorCount++;
|
||||
}
|
||||
|
||||
//
|
||||
// done
|
||||
//
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
USBCCGP_EnumWithUnionFunctionDescriptors(
|
||||
IN PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
USBCCGP_EnumWithAudioLegacy(
|
||||
IN PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
ULONG Index;
|
||||
PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor, FirstDescriptor = NULL;
|
||||
PFDO_DEVICE_EXTENSION FDODeviceExtension;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
PVOID StartPosition;
|
||||
|
||||
//
|
||||
// get device extension
|
||||
//
|
||||
FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
ASSERT(FDODeviceExtension->Common.IsFDO);
|
||||
|
||||
|
||||
//
|
||||
// first check if all interfaces belong to the same audio class
|
||||
//
|
||||
StartPosition = FDODeviceExtension->ConfigurationDescriptor;
|
||||
for(Index = 0; Index < CountInterfaceDescriptors(FDODeviceExtension->ConfigurationDescriptor); Index++)
|
||||
{
|
||||
//
|
||||
// get interface descriptor
|
||||
//
|
||||
InterfaceDescriptor = USBD_ParseConfigurationDescriptorEx(FDODeviceExtension->ConfigurationDescriptor, StartPosition, -1, -1, -1, -1, -1);
|
||||
DPRINT1("Index %lu Descriptor %p\n", Index, InterfaceDescriptor);
|
||||
ASSERT(InterfaceDescriptor);
|
||||
|
||||
//
|
||||
// move to next descriptor
|
||||
//
|
||||
StartPosition = (PVOID)((ULONG_PTR)InterfaceDescriptor + InterfaceDescriptor->bLength);
|
||||
|
||||
if (InterfaceDescriptor->bInterfaceClass != 0x1)
|
||||
{
|
||||
//
|
||||
// collection contains non audio class
|
||||
//
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
if (FirstDescriptor == NULL)
|
||||
{
|
||||
//
|
||||
// store interface descriptor
|
||||
//
|
||||
FirstDescriptor = InterfaceDescriptor;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (FirstDescriptor->bInterfaceSubClass == InterfaceDescriptor->bInterfaceSubClass)
|
||||
{
|
||||
//
|
||||
// interface subclass must be different from the first interface
|
||||
//
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// this is an composite audio device
|
||||
//
|
||||
DPRINT("[USBCCGP] Audio Composite Device detected\n");
|
||||
|
||||
//
|
||||
// audio interfaces are all grouped into one single function
|
||||
//
|
||||
FDODeviceExtension->FunctionDescriptor = AllocateItem(NonPagedPool, sizeof(USBC_FUNCTION_DESCRIPTOR));
|
||||
if (!FDODeviceExtension->FunctionDescriptor)
|
||||
{
|
||||
//
|
||||
// no memory
|
||||
//
|
||||
DPRINT1("USBCCGP_EnumWithAssociationDescriptor failed to allocate function descriptor count\n");
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
//
|
||||
// init function number
|
||||
//
|
||||
FDODeviceExtension->FunctionDescriptor[0].FunctionNumber = 0;
|
||||
|
||||
//
|
||||
// store interfaces
|
||||
//
|
||||
Status = AllocateInterfaceDescriptorsArray(FDODeviceExtension->ConfigurationDescriptor, &FDODeviceExtension->FunctionDescriptor[0].InterfaceDescriptorList);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
//
|
||||
// failed to allocate descriptor array
|
||||
//
|
||||
DPRINT1("[USBCCGP] Failed to allocate descriptor array %x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// now init the device ids
|
||||
//
|
||||
Status = USBCCG_InitIdsWithInterfaceDescriptor(FDODeviceExtension, FirstDescriptor, 0, &FDODeviceExtension->FunctionDescriptor[0]);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
//
|
||||
// failed to init ids
|
||||
//
|
||||
DPRINT1("[USBCCGP] Failed to init ids with %x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// number of interfaces
|
||||
//
|
||||
FDODeviceExtension->FunctionDescriptor[0].NumberOfInterfaces = CountInterfaceDescriptors(FDODeviceExtension->ConfigurationDescriptor);
|
||||
|
||||
//
|
||||
// store function count
|
||||
//
|
||||
FDODeviceExtension->FunctionDescriptorCount = 1;
|
||||
|
||||
//
|
||||
// done
|
||||
//
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
USBCCGP_EnumerateFunctions(
|
||||
IN PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PFDO_DEVICE_EXTENSION FDODeviceExtension;
|
||||
|
||||
//
|
||||
// get device extension
|
||||
//
|
||||
FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
ASSERT(FDODeviceExtension->Common.IsFDO);
|
||||
|
||||
//
|
||||
// first try with filter driver
|
||||
//
|
||||
Status = USBCCGP_CustomEnumWithInterface(DeviceObject);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
//
|
||||
// succeeded
|
||||
//
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// enumerate functions with interface association descriptor
|
||||
//
|
||||
Status = USBCCGP_EnumWithAssociationDescriptor(DeviceObject);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
//
|
||||
// succeeded
|
||||
//
|
||||
return Status;
|
||||
}
|
||||
|
||||
#if 0
|
||||
//
|
||||
// try with union function descriptors
|
||||
//
|
||||
Status = USBCCGP_EnumWithUnionFunctionDescriptors(DeviceObject);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
//
|
||||
// succeeded
|
||||
//
|
||||
return Status;
|
||||
}
|
||||
#endif
|
||||
|
||||
//
|
||||
// try with legacy audio methods
|
||||
//
|
||||
Status = USBCCGP_EnumWithAudioLegacy(DeviceObject);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
//
|
||||
// succeeded
|
||||
//
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// try with legacy enumeration
|
||||
//
|
||||
return USBCCGP_LegacyEnum(DeviceObject);
|
||||
}
|
224
reactos/drivers/usb/usbccgp/misc.c
Normal file
224
reactos/drivers/usb/usbccgp/misc.c
Normal file
|
@ -0,0 +1,224 @@
|
|||
/*
|
||||
* PROJECT: ReactOS Universal Serial Bus Bulk Enhanced Host Controller Interface
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* FILE: drivers/usb/usbccgp/misc.c
|
||||
* PURPOSE: USB device driver.
|
||||
* PROGRAMMERS:
|
||||
* Michael Martin (michael.martin@reactos.org)
|
||||
* Johannes Anderwald (johannes.anderwald@reactos.org)
|
||||
* Cameron Gutman
|
||||
*/
|
||||
|
||||
#include "usbccgp.h"
|
||||
|
||||
//
|
||||
// driver verifier
|
||||
//
|
||||
IO_COMPLETION_ROUTINE SyncForwardIrpCompletionRoutine;
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
USBSTOR_SyncForwardIrpCompletionRoutine(
|
||||
PDEVICE_OBJECT DeviceObject,
|
||||
PIRP Irp,
|
||||
PVOID Context)
|
||||
{
|
||||
if (Irp->PendingReturned)
|
||||
{
|
||||
KeSetEvent((PKEVENT)Context, IO_NO_INCREMENT, FALSE);
|
||||
}
|
||||
return STATUS_MORE_PROCESSING_REQUIRED;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
USBCCGP_SyncForwardIrp(
|
||||
PDEVICE_OBJECT DeviceObject,
|
||||
PIRP Irp)
|
||||
{
|
||||
KEVENT Event;
|
||||
NTSTATUS Status;
|
||||
|
||||
//
|
||||
// initialize event
|
||||
//
|
||||
KeInitializeEvent(&Event, NotificationEvent, FALSE);
|
||||
|
||||
//
|
||||
// copy irp stack location
|
||||
//
|
||||
IoCopyCurrentIrpStackLocationToNext(Irp);
|
||||
|
||||
//
|
||||
// set completion routine
|
||||
//
|
||||
IoSetCompletionRoutine(Irp, USBSTOR_SyncForwardIrpCompletionRoutine, &Event, TRUE, TRUE, TRUE);
|
||||
|
||||
|
||||
//
|
||||
// call driver
|
||||
//
|
||||
Status = IoCallDriver(DeviceObject, Irp);
|
||||
|
||||
//
|
||||
// check if pending
|
||||
//
|
||||
if (Status == STATUS_PENDING)
|
||||
{
|
||||
//
|
||||
// wait for the request to finish
|
||||
//
|
||||
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
|
||||
|
||||
//
|
||||
// copy status code
|
||||
//
|
||||
Status = Irp->IoStatus.Status;
|
||||
}
|
||||
|
||||
//
|
||||
// done
|
||||
//
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
USBCCGP_SyncUrbRequest(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
OUT PURB UrbRequest)
|
||||
{
|
||||
PIRP Irp;
|
||||
PIO_STACK_LOCATION IoStack;
|
||||
KEVENT Event;
|
||||
NTSTATUS Status;
|
||||
|
||||
//
|
||||
// allocate irp
|
||||
//
|
||||
Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
|
||||
if (!Irp)
|
||||
{
|
||||
//
|
||||
// no memory
|
||||
//
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
//
|
||||
// initialize event
|
||||
//
|
||||
KeInitializeEvent(&Event, NotificationEvent, FALSE);
|
||||
|
||||
|
||||
//
|
||||
// get next stack location
|
||||
//
|
||||
IoStack = IoGetNextIrpStackLocation(Irp);
|
||||
|
||||
//
|
||||
// initialize stack location
|
||||
//
|
||||
IoStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
|
||||
IoStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
|
||||
IoStack->Parameters.Others.Argument1 = (PVOID)UrbRequest;
|
||||
IoStack->Parameters.DeviceIoControl.InputBufferLength = UrbRequest->UrbHeader.Length;
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
|
||||
//
|
||||
// setup completion routine
|
||||
//
|
||||
IoSetCompletionRoutine(Irp, USBSTOR_SyncForwardIrpCompletionRoutine, &Event, TRUE, TRUE, TRUE);
|
||||
|
||||
//
|
||||
// call driver
|
||||
//
|
||||
Status = IoCallDriver(DeviceObject, Irp);
|
||||
|
||||
//
|
||||
// check if request is pending
|
||||
//
|
||||
if (Status == STATUS_PENDING)
|
||||
{
|
||||
//
|
||||
// wait for completion
|
||||
//
|
||||
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
|
||||
|
||||
//
|
||||
// update status
|
||||
//
|
||||
Status = Irp->IoStatus.Status;
|
||||
}
|
||||
|
||||
//
|
||||
// free irp
|
||||
//
|
||||
IoFreeIrp(Irp);
|
||||
|
||||
//
|
||||
// done
|
||||
//
|
||||
return Status;
|
||||
}
|
||||
|
||||
PVOID
|
||||
AllocateItem(
|
||||
IN POOL_TYPE PoolType,
|
||||
IN ULONG ItemSize)
|
||||
{
|
||||
//
|
||||
// allocate item
|
||||
//
|
||||
PVOID Item = ExAllocatePoolWithTag(PoolType, ItemSize, USBCCPG_TAG);
|
||||
|
||||
if (Item)
|
||||
{
|
||||
//
|
||||
// zero item
|
||||
//
|
||||
RtlZeroMemory(Item, ItemSize);
|
||||
}
|
||||
|
||||
//
|
||||
// return element
|
||||
//
|
||||
return Item;
|
||||
}
|
||||
|
||||
VOID
|
||||
FreeItem(
|
||||
IN PVOID Item)
|
||||
{
|
||||
//
|
||||
// free item
|
||||
//
|
||||
ExFreePoolWithTag(Item, USBCCPG_TAG);
|
||||
}
|
||||
|
||||
VOID
|
||||
DumpFunctionDescriptor(
|
||||
IN PUSBC_FUNCTION_DESCRIPTOR FunctionDescriptor,
|
||||
IN ULONG FunctionDescriptorCount)
|
||||
{
|
||||
ULONG Index, SubIndex;
|
||||
|
||||
|
||||
DPRINT1("FunctionCount %lu\n", FunctionDescriptorCount);
|
||||
for(Index = 0; Index < FunctionDescriptorCount; Index++)
|
||||
{
|
||||
DPRINT1("Function %lu\n", Index);
|
||||
DPRINT1("FunctionNumber %lu\n", FunctionDescriptor[Index].FunctionNumber);
|
||||
DPRINT1("HardwareId %wZ\n", &FunctionDescriptor[Index].HardwareId);
|
||||
DPRINT1("CompatibleId %wZ\n", &FunctionDescriptor[Index].CompatibleId);
|
||||
DPRINT1("FunctionDescription %wZ\n", &FunctionDescriptor[Index].FunctionDescription);
|
||||
DPRINT1("NumInterfaces %lu\n", FunctionDescriptor[Index].NumberOfInterfaces);
|
||||
|
||||
for(SubIndex = 0; SubIndex < FunctionDescriptor[Index].NumberOfInterfaces; SubIndex++)
|
||||
{
|
||||
DPRINT1(" Interface %p\n", FunctionDescriptor[Index].InterfaceDescriptorList[SubIndex]);
|
||||
DPRINT1(" Interface InterfaceNumber %x\n", FunctionDescriptor[Index].InterfaceDescriptorList[SubIndex]->bInterfaceNumber);
|
||||
DPRINT1(" Interface Alternate %x\n", FunctionDescriptor[Index].InterfaceDescriptorList[SubIndex]->bAlternateSetting );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
1002
reactos/drivers/usb/usbccgp/pdo.c
Normal file
1002
reactos/drivers/usb/usbccgp/pdo.c
Normal file
File diff suppressed because it is too large
Load diff
155
reactos/drivers/usb/usbccgp/usbccgp.c
Normal file
155
reactos/drivers/usb/usbccgp/usbccgp.c
Normal file
|
@ -0,0 +1,155 @@
|
|||
/*
|
||||
* PROJECT: ReactOS Universal Serial Bus Bulk Enhanced Host Controller Interface
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* FILE: drivers/usb/usbccgp/usbccgp.c
|
||||
* PURPOSE: USB device driver.
|
||||
* PROGRAMMERS:
|
||||
* Michael Martin (michael.martin@reactos.org)
|
||||
* Johannes Anderwald (johannes.anderwald@reactos.org)
|
||||
* Cameron Gutman
|
||||
*/
|
||||
|
||||
#include "usbccgp.h"
|
||||
|
||||
//
|
||||
// driver verifier
|
||||
//
|
||||
DRIVER_ADD_DEVICE USBCCGP_AddDevice;
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
USBCCGP_AddDevice(
|
||||
PDRIVER_OBJECT DriverObject,
|
||||
PDEVICE_OBJECT PhysicalDeviceObject)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PDEVICE_OBJECT DeviceObject;
|
||||
PFDO_DEVICE_EXTENSION FDODeviceExtension;
|
||||
|
||||
// lets create the device
|
||||
Status = IoCreateDevice(DriverObject, sizeof(FDO_DEVICE_EXTENSION), NULL, FILE_DEVICE_USB, FILE_AUTOGENERATED_DEVICE_NAME, FALSE, &DeviceObject);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
// failed to create device
|
||||
DPRINT1("USBCCGP_AddDevice failed to create device with %x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
// get device extension
|
||||
FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
|
||||
// init device extension
|
||||
RtlZeroMemory(FDODeviceExtension, sizeof(FDO_DEVICE_EXTENSION));
|
||||
FDODeviceExtension->Common.IsFDO = TRUE;
|
||||
FDODeviceExtension->DriverObject = DriverObject;
|
||||
FDODeviceExtension->PhysicalDeviceObject = PhysicalDeviceObject;
|
||||
InitializeListHead(&FDODeviceExtension->ResetPortListHead);
|
||||
InitializeListHead(&FDODeviceExtension->CyclePortListHead);
|
||||
KeInitializeSpinLock(&FDODeviceExtension->Lock);
|
||||
|
||||
FDODeviceExtension->NextDeviceObject = IoAttachDeviceToDeviceStack(DeviceObject, PhysicalDeviceObject);
|
||||
if (!FDODeviceExtension->NextDeviceObject)
|
||||
{
|
||||
// failed to attach
|
||||
DPRINT1("USBCCGP_AddDevice failed to attach device\n");
|
||||
IoDeleteDevice(DeviceObject);
|
||||
return STATUS_DEVICE_REMOVED;
|
||||
}
|
||||
|
||||
// set device flags
|
||||
DeviceObject->Flags |= DO_BUFFERED_IO | DO_POWER_PAGABLE;
|
||||
|
||||
// device is initialized
|
||||
DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
|
||||
|
||||
// device initialized
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
USBCCGP_CreateClose(
|
||||
PDEVICE_OBJECT DeviceObject,
|
||||
PIRP Irp)
|
||||
{
|
||||
PCOMMON_DEVICE_EXTENSION DeviceExtension;
|
||||
PFDO_DEVICE_EXTENSION FDODeviceExtension;
|
||||
|
||||
// get common device extension
|
||||
DeviceExtension = (PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
|
||||
// is it a fdo
|
||||
if (DeviceExtension->IsFDO)
|
||||
{
|
||||
// forward and forget
|
||||
IoSkipCurrentIrpStackLocation(Irp);
|
||||
|
||||
// get fdo
|
||||
FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
|
||||
// call lower driver
|
||||
return IoCallDriver(FDODeviceExtension->NextDeviceObject, Irp);
|
||||
}
|
||||
else
|
||||
{
|
||||
// pdo not supported
|
||||
Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
USBCCGP_Dispatch(
|
||||
PDEVICE_OBJECT DeviceObject,
|
||||
PIRP Irp)
|
||||
{
|
||||
PCOMMON_DEVICE_EXTENSION DeviceExtension;
|
||||
PIO_STACK_LOCATION IoStack;
|
||||
|
||||
// get common device extension
|
||||
DeviceExtension = (PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
|
||||
// get current stack location
|
||||
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||
|
||||
if (IoStack->MajorFunction == IRP_MJ_CREATE || IoStack->MajorFunction == IRP_MJ_CLOSE)
|
||||
{
|
||||
// dispatch to default handler
|
||||
return USBCCGP_CreateClose(DeviceObject, Irp);
|
||||
}
|
||||
|
||||
if (DeviceExtension->IsFDO)
|
||||
{
|
||||
// handle request for FDO
|
||||
return FDO_Dispatch(DeviceObject, Irp);
|
||||
}
|
||||
else
|
||||
{
|
||||
// handle request for PDO
|
||||
return PDO_Dispatch(DeviceObject, Irp);
|
||||
}
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
DriverEntry(
|
||||
PDRIVER_OBJECT DriverObject,
|
||||
PUNICODE_STRING RegistryPath)
|
||||
{
|
||||
|
||||
// initialize driver object
|
||||
DPRINT("[USBCCGP] DriverEntry\n");
|
||||
DriverObject->DriverExtension->AddDevice = USBCCGP_AddDevice;
|
||||
DriverObject->MajorFunction[IRP_MJ_CREATE] = USBCCGP_Dispatch;
|
||||
DriverObject->MajorFunction[IRP_MJ_CLOSE] = USBCCGP_Dispatch;
|
||||
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = USBCCGP_Dispatch;
|
||||
DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = USBCCGP_Dispatch;
|
||||
DriverObject->MajorFunction[IRP_MJ_POWER] = USBCCGP_Dispatch;
|
||||
DriverObject->MajorFunction[IRP_MJ_PNP] = USBCCGP_Dispatch;
|
||||
|
||||
// FIMXE query GenericCompositeUSBDeviceString
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
148
reactos/drivers/usb/usbccgp/usbccgp.h
Normal file
148
reactos/drivers/usb/usbccgp/usbccgp.h
Normal file
|
@ -0,0 +1,148 @@
|
|||
#ifndef USBEHCI_H__
|
||||
#define USBEHCI_H__
|
||||
|
||||
#include <ntddk.h>
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
#include <initguid.h>
|
||||
#include <hubbusif.h>
|
||||
#include <usbbusif.h>
|
||||
#include <usbioctl.h>
|
||||
#include <usbdlib.h>
|
||||
|
||||
//
|
||||
// FIXME:
|
||||
// #include <usbprotocoldefs.h>
|
||||
//
|
||||
#include <usb.h>
|
||||
#include <stdio.h>
|
||||
#include <wdmguid.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
BOOLEAN IsFDO; // is device a FDO or PDO
|
||||
}COMMON_DEVICE_EXTENSION, *PCOMMON_DEVICE_EXTENSION;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
COMMON_DEVICE_EXTENSION Common; // shared with PDO
|
||||
PDRIVER_OBJECT DriverObject; // driver object
|
||||
PDEVICE_OBJECT PhysicalDeviceObject; // physical device object
|
||||
PDEVICE_OBJECT NextDeviceObject; // lower device object
|
||||
PUSB_DEVICE_DESCRIPTOR DeviceDescriptor; // usb device descriptor
|
||||
PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor; // usb configuration descriptor
|
||||
DEVICE_CAPABILITIES Capabilities; // device capabilities
|
||||
PUSBD_INTERFACE_LIST_ENTRY InterfaceList; // interface list
|
||||
ULONG InterfaceListCount; // interface list count
|
||||
USBD_CONFIGURATION_HANDLE ConfigurationHandle; // configuration handle
|
||||
USBC_DEVICE_CONFIGURATION_INTERFACE_V1 BusInterface; // bus custom enumeration interface
|
||||
PUSBC_FUNCTION_DESCRIPTOR FunctionDescriptor; // usb function descriptor
|
||||
ULONG FunctionDescriptorCount; // number of function descriptor
|
||||
PDEVICE_OBJECT * ChildPDO; // child pdos
|
||||
LIST_ENTRY ResetPortListHead; // reset port list head
|
||||
LIST_ENTRY CyclePortListHead; // cycle port list head
|
||||
UCHAR ResetPortActive; // reset port active
|
||||
UCHAR CyclePortActive; // cycle port active
|
||||
KSPIN_LOCK Lock; // reset / cycle port list lock
|
||||
}FDO_DEVICE_EXTENSION, *PFDO_DEVICE_EXTENSION;
|
||||
|
||||
#define USBCCPG_TAG 'cbsu'
|
||||
|
||||
typedef struct
|
||||
{
|
||||
COMMON_DEVICE_EXTENSION Common; // shared with FDO
|
||||
PUSBC_FUNCTION_DESCRIPTOR FunctionDescriptor; // function descriptor
|
||||
PDEVICE_OBJECT NextDeviceObject; // next device object
|
||||
DEVICE_CAPABILITIES Capabilities; // device capabilities
|
||||
ULONG FunctionIndex; // function index
|
||||
USB_DEVICE_DESCRIPTOR DeviceDescriptor; // usb device descriptor
|
||||
PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor; // usb configuration descriptor
|
||||
USBD_CONFIGURATION_HANDLE ConfigurationHandle; // configuration handle
|
||||
PUSBD_INTERFACE_LIST_ENTRY InterfaceList; // interface list
|
||||
ULONG InterfaceListCount; // interface list count
|
||||
PFDO_DEVICE_EXTENSION FDODeviceExtension; // pointer to fdo's pdo list
|
||||
}PDO_DEVICE_EXTENSION, *PPDO_DEVICE_EXTENSION;
|
||||
|
||||
/* descriptor.c */
|
||||
|
||||
NTSTATUS
|
||||
USBCCGP_GetDescriptors(
|
||||
IN PDEVICE_OBJECT DeviceObject);
|
||||
|
||||
NTSTATUS
|
||||
USBCCGP_SelectConfiguration(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PFDO_DEVICE_EXTENSION DeviceExtension);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
USBCCGP_GetDescriptor(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN UCHAR DescriptorType,
|
||||
IN ULONG DescriptorLength,
|
||||
IN UCHAR DescriptorIndex,
|
||||
IN LANGID LanguageId,
|
||||
OUT PVOID *OutDescriptor);
|
||||
|
||||
ULONG
|
||||
CountInterfaceDescriptors(
|
||||
IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor);
|
||||
|
||||
NTSTATUS
|
||||
AllocateInterfaceDescriptorsArray(
|
||||
IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
|
||||
OUT PUSB_INTERFACE_DESCRIPTOR **OutArray);
|
||||
|
||||
/* misc.c */
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
USBCCGP_SyncForwardIrp(
|
||||
PDEVICE_OBJECT DeviceObject,
|
||||
PIRP Irp);
|
||||
|
||||
NTSTATUS
|
||||
USBCCGP_SyncUrbRequest(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
OUT PURB UrbRequest);
|
||||
|
||||
PVOID
|
||||
AllocateItem(
|
||||
IN POOL_TYPE PoolType,
|
||||
IN ULONG ItemSize);
|
||||
|
||||
VOID
|
||||
FreeItem(
|
||||
IN PVOID Item);
|
||||
|
||||
VOID
|
||||
DumpFunctionDescriptor(
|
||||
IN PUSBC_FUNCTION_DESCRIPTOR FunctionDescriptor,
|
||||
IN ULONG FunctionDescriptorCount);
|
||||
|
||||
/* fdo.c */
|
||||
|
||||
NTSTATUS
|
||||
FDO_Dispatch(
|
||||
PDEVICE_OBJECT DeviceObject,
|
||||
PIRP Irp);
|
||||
|
||||
/* pdo.c */
|
||||
|
||||
NTSTATUS
|
||||
PDO_Dispatch(
|
||||
PDEVICE_OBJECT DeviceObject,
|
||||
PIRP Irp);
|
||||
|
||||
/* function.c */
|
||||
|
||||
NTSTATUS
|
||||
USBCCGP_QueryInterface(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
OUT PUSBC_DEVICE_CONFIGURATION_INTERFACE_V1 BusInterface);
|
||||
|
||||
NTSTATUS
|
||||
USBCCGP_EnumerateFunctions(
|
||||
IN PDEVICE_OBJECT DeviceObject);
|
||||
|
||||
#endif
|
19
reactos/drivers/usb/usbccgp/usbccgp.rbuild
Normal file
19
reactos/drivers/usb/usbccgp/usbccgp.rbuild
Normal file
|
@ -0,0 +1,19 @@
|
|||
<?xml version="1.0"?>
|
||||
<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
|
||||
<module name="usbccgp" type="kernelmodedriver" installbase="system32/drivers" installname="usbccgp.sys">
|
||||
<bootstrap installbase="$(CDOUTPUT)/system32/drivers" />
|
||||
<redefine name="_WIN32_WINNT">0x600</redefine>
|
||||
<define name="DEBUG_MODE" />
|
||||
<include base="ntoskrnl">include</include>
|
||||
<library>ntoskrnl</library>
|
||||
<library>hal</library>
|
||||
<library>usbd</library>
|
||||
<library>pseh</library>
|
||||
<file>descriptor.c</file>
|
||||
<file>fdo.c</file>
|
||||
<file>function.c</file>
|
||||
<file>misc.c</file>
|
||||
<file>pdo.c</file>
|
||||
<file>usbccgp.c</file>
|
||||
<file>usbccgp.rc</file>
|
||||
</module>
|
5
reactos/drivers/usb/usbccgp/usbccgp.rc
Normal file
5
reactos/drivers/usb/usbccgp/usbccgp.rc
Normal file
|
@ -0,0 +1,5 @@
|
|||
#define REACTOS_VERSION_DLL
|
||||
#define REACTOS_STR_FILE_DESCRIPTION "USBCCGP Driver\0"
|
||||
#define REACTOS_STR_INTERNAL_NAME "usccpg\0"
|
||||
#define REACTOS_STR_ORIGINAL_FILENAME "usbccpg.sys\0"
|
||||
#include <reactos/version.rc>
|
|
@ -9,3 +9,5 @@ add_library(usbd SHARED
|
|||
set_module_type(usbd kernelmodedriver)
|
||||
add_importlibs(usbd ntoskrnl hal)
|
||||
add_importlib_target(usbd.spec)
|
||||
|
||||
add_cd_file(TARGET usbd DESTINATION reactos/system32/drivers NO_CAB FOR all)
|
|
@ -32,9 +32,10 @@
|
|||
* USBD_GetPdoRegistryParameters (implemented)
|
||||
*/
|
||||
|
||||
#include <wdm.h>
|
||||
#include <ntddk.h>
|
||||
#include <usbdi.h>
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
#ifndef PLUGPLAY_REGKEY_DRIVER
|
||||
#define PLUGPLAY_REGKEY_DRIVER 2
|
||||
#endif
|
||||
|
@ -102,6 +103,7 @@ USBD_Debug_LogEntry(PCHAR Name, ULONG_PTR Info1, ULONG_PTR Info2,
|
|||
PVOID NTAPI
|
||||
USBD_AllocateDeviceName(ULONG Unknown)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -139,6 +141,7 @@ USBD_CalculateUsbBandwidth(
|
|||
ULONG NTAPI
|
||||
USBD_Dispatch(ULONG Unknown1, ULONG Unknown2, ULONG Unknown3, ULONG Unknown4)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -148,6 +151,7 @@ USBD_Dispatch(ULONG Unknown1, ULONG Unknown2, ULONG Unknown3, ULONG Unknown4)
|
|||
VOID NTAPI
|
||||
USBD_FreeDeviceMutex(PVOID Unknown)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -156,6 +160,7 @@ USBD_FreeDeviceMutex(PVOID Unknown)
|
|||
VOID NTAPI
|
||||
USBD_FreeDeviceName(PVOID Unknown)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -164,6 +169,7 @@ USBD_FreeDeviceName(PVOID Unknown)
|
|||
VOID NTAPI
|
||||
USBD_WaitDeviceMutex(PVOID Unknown)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -172,6 +178,7 @@ USBD_WaitDeviceMutex(PVOID Unknown)
|
|||
ULONG NTAPI
|
||||
USBD_GetSuspendPowerState(ULONG Unknown1)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -182,6 +189,7 @@ NTSTATUS NTAPI
|
|||
USBD_InitializeDevice(ULONG Unknown1, ULONG Unknown2, ULONG Unknown3,
|
||||
ULONG Unknown4, ULONG Unknown5, ULONG Unknown6)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
|
@ -193,6 +201,7 @@ USBD_RegisterHostController(ULONG Unknown1, ULONG Unknown2, ULONG Unknown3,
|
|||
ULONG Unknown4, ULONG Unknown5, ULONG Unknown6, ULONG Unknown7,
|
||||
ULONG Unknown8, ULONG Unknown9, ULONG Unknown10)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
|
@ -202,6 +211,7 @@ USBD_RegisterHostController(ULONG Unknown1, ULONG Unknown2, ULONG Unknown3,
|
|||
NTSTATUS NTAPI
|
||||
USBD_GetDeviceInformation(ULONG Unknown1, ULONG Unknown2, ULONG Unknown3)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
|
@ -212,6 +222,7 @@ NTSTATUS NTAPI
|
|||
USBD_CreateDevice(ULONG Unknown1, ULONG Unknown2, ULONG Unknown3,
|
||||
ULONG Unknown4, ULONG Unknown5)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
|
@ -221,6 +232,7 @@ USBD_CreateDevice(ULONG Unknown1, ULONG Unknown2, ULONG Unknown3,
|
|||
NTSTATUS NTAPI
|
||||
USBD_RemoveDevice(ULONG Unknown1, ULONG Unknown2, ULONG Unknown3)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
|
@ -230,6 +242,7 @@ USBD_RemoveDevice(ULONG Unknown1, ULONG Unknown2, ULONG Unknown3)
|
|||
VOID NTAPI
|
||||
USBD_CompleteRequest(ULONG Unknown1, ULONG Unknown2)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -241,6 +254,7 @@ USBD_RegisterHcFilter(
|
|||
PDEVICE_OBJECT FilterDeviceObject
|
||||
)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -249,6 +263,7 @@ USBD_RegisterHcFilter(
|
|||
VOID NTAPI
|
||||
USBD_SetSuspendPowerState(ULONG Unknown1, ULONG Unknown2)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -257,6 +272,7 @@ USBD_SetSuspendPowerState(ULONG Unknown1, ULONG Unknown2)
|
|||
NTSTATUS NTAPI
|
||||
USBD_MakePdoName(ULONG Unknown1, ULONG Unknown2)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
|
@ -269,6 +285,7 @@ USBD_QueryBusTime(
|
|||
PULONG CurrentFrame
|
||||
)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
|
@ -283,7 +300,7 @@ USBD_GetUSBDIVersion(
|
|||
if (Version != NULL)
|
||||
{
|
||||
Version->USBDI_Version = USBDI_VERSION;
|
||||
Version->Supported_USB_Version = 0x100;
|
||||
Version->Supported_USB_Version = 0x200;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -293,6 +310,7 @@ USBD_GetUSBDIVersion(
|
|||
NTSTATUS NTAPI
|
||||
USBD_RestoreDevice(ULONG Unknown1, ULONG Unknown2, ULONG Unknown3)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
|
@ -303,6 +321,7 @@ VOID NTAPI
|
|||
USBD_RegisterHcDeviceCapabilities(ULONG Unknown1, ULONG Unknown2,
|
||||
ULONG Unknown3)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -410,16 +429,39 @@ USBD_ParseDescriptors(
|
|||
LONG DescriptorType
|
||||
)
|
||||
{
|
||||
PUSB_COMMON_DESCRIPTOR PComDes = StartPosition;
|
||||
PUSB_COMMON_DESCRIPTOR CommonDescriptor;
|
||||
|
||||
while(PComDes)
|
||||
/* use start position */
|
||||
CommonDescriptor = (PUSB_COMMON_DESCRIPTOR)StartPosition;
|
||||
|
||||
|
||||
/* find next available descriptor */
|
||||
while(CommonDescriptor)
|
||||
{
|
||||
if (PComDes >= (PUSB_COMMON_DESCRIPTOR)
|
||||
((PLONG)DescriptorBuffer + TotalLength) ) break;
|
||||
if (PComDes->bDescriptorType == DescriptorType) return PComDes;
|
||||
if (PComDes->bLength == 0) break;
|
||||
PComDes = (PUSB_COMMON_DESCRIPTOR)((ULONG_PTR)PComDes + PComDes->bLength);
|
||||
if ((ULONG_PTR)CommonDescriptor >= ((ULONG_PTR)DescriptorBuffer + TotalLength))
|
||||
{
|
||||
/* end reached */
|
||||
DPRINT("End reached %p\n", CommonDescriptor);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DPRINT("CommonDescriptor Type %x Length %x\n", CommonDescriptor->bDescriptorType, CommonDescriptor->bLength);
|
||||
|
||||
/* is the requested one */
|
||||
if (CommonDescriptor->bDescriptorType == DescriptorType)
|
||||
{
|
||||
/* it is */
|
||||
return CommonDescriptor;
|
||||
}
|
||||
|
||||
/* sanity check */
|
||||
ASSERT(CommonDescriptor->bLength);
|
||||
|
||||
/* move to next descriptor */
|
||||
CommonDescriptor = (PUSB_COMMON_DESCRIPTOR)((ULONG_PTR)CommonDescriptor + CommonDescriptor->bLength);
|
||||
}
|
||||
|
||||
/* no descriptor found */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -438,45 +480,97 @@ USBD_ParseConfigurationDescriptorEx(
|
|||
LONG InterfaceProtocol
|
||||
)
|
||||
{
|
||||
int x = 0;
|
||||
PUSB_INTERFACE_DESCRIPTOR UsbInterfaceDesc = StartPosition;
|
||||
BOOLEAN Found;
|
||||
PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
|
||||
|
||||
while(UsbInterfaceDesc)
|
||||
/* set to start position */
|
||||
InterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR)StartPosition;
|
||||
|
||||
DPRINT("USBD_ParseConfigurationDescriptorEx\n");
|
||||
DPRINT("ConfigurationDescriptor %p Length %lu\n", ConfigurationDescriptor, ConfigurationDescriptor->wTotalLength);
|
||||
DPRINT("CurrentOffset %p Offset %lu\n", StartPosition, ((ULONG_PTR)StartPosition - (ULONG_PTR)ConfigurationDescriptor));
|
||||
|
||||
while(InterfaceDescriptor)
|
||||
{
|
||||
UsbInterfaceDesc = (PUSB_INTERFACE_DESCRIPTOR)
|
||||
USBD_ParseDescriptors(ConfigurationDescriptor,
|
||||
ConfigurationDescriptor->wTotalLength,
|
||||
UsbInterfaceDesc,
|
||||
USB_INTERFACE_DESCRIPTOR_TYPE);
|
||||
/* get interface descriptor */
|
||||
InterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR) USBD_ParseDescriptors(ConfigurationDescriptor, ConfigurationDescriptor->wTotalLength, InterfaceDescriptor, USB_INTERFACE_DESCRIPTOR_TYPE);
|
||||
if (!InterfaceDescriptor)
|
||||
{
|
||||
/* no more descriptors available */
|
||||
break;
|
||||
}
|
||||
|
||||
if (!UsbInterfaceDesc) break;
|
||||
DPRINT("InterfaceDescriptor %p InterfaceNumber %x AlternateSetting %x Length %lu\n", InterfaceDescriptor, InterfaceDescriptor->bInterfaceNumber, InterfaceDescriptor->bAlternateSetting, InterfaceDescriptor->bLength);
|
||||
|
||||
/* set found */
|
||||
Found = TRUE;
|
||||
|
||||
/* is there an interface number provided */
|
||||
if(InterfaceNumber != -1)
|
||||
{
|
||||
if(InterfaceNumber != UsbInterfaceDesc->bInterfaceNumber) x = 1;
|
||||
if(InterfaceNumber != InterfaceDescriptor->bInterfaceNumber)
|
||||
{
|
||||
/* interface number does not match */
|
||||
Found = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* is there an alternate setting provided */
|
||||
if(AlternateSetting != -1)
|
||||
{
|
||||
if(AlternateSetting != UsbInterfaceDesc->bAlternateSetting) x = 1;
|
||||
if(AlternateSetting != InterfaceDescriptor->bAlternateSetting)
|
||||
{
|
||||
/* alternate setting does not match */
|
||||
Found = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* match on interface class */
|
||||
if(InterfaceClass != -1)
|
||||
{
|
||||
if(InterfaceClass != UsbInterfaceDesc->bInterfaceClass) x = 1;
|
||||
if(InterfaceClass != InterfaceDescriptor->bInterfaceClass)
|
||||
{
|
||||
/* no match with interface class criteria */
|
||||
Found = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* match on interface sub class */
|
||||
if(InterfaceSubClass != -1)
|
||||
{
|
||||
if(InterfaceSubClass != UsbInterfaceDesc->bInterfaceSubClass) x = 1;
|
||||
if(InterfaceSubClass != InterfaceDescriptor->bInterfaceSubClass)
|
||||
{
|
||||
/* no interface sub class match */
|
||||
Found = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* interface protocol criteria */
|
||||
if(InterfaceProtocol != -1)
|
||||
{
|
||||
if(InterfaceProtocol != UsbInterfaceDesc->bInterfaceProtocol) x = 1;
|
||||
if(InterfaceProtocol != InterfaceDescriptor->bInterfaceProtocol)
|
||||
{
|
||||
/* no interface protocol match */
|
||||
Found = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!x) return UsbInterfaceDesc;
|
||||
|
||||
if (UsbInterfaceDesc->bLength == 0) break;
|
||||
UsbInterfaceDesc = UsbInterfaceDesc + UsbInterfaceDesc->bLength;
|
||||
if (Found)
|
||||
{
|
||||
/* the choosen one */
|
||||
return InterfaceDescriptor;
|
||||
}
|
||||
|
||||
/* sanity check */
|
||||
ASSERT(InterfaceDescriptor->bLength);
|
||||
|
||||
/* move to next descriptor */
|
||||
InterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR)((ULONG_PTR)InterfaceDescriptor + InterfaceDescriptor->bLength);
|
||||
}
|
||||
|
||||
DPRINT("No Descriptor With InterfaceNumber %ld AlternateSetting %ld InterfaceClass %ld InterfaceSubClass %ld InterfaceProtocol %ld found\n", InterfaceNumber,
|
||||
AlternateSetting, InterfaceClass, InterfaceSubClass, InterfaceProtocol);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -511,28 +605,58 @@ USBD_GetPdoRegistryParameter(
|
|||
NTSTATUS Status;
|
||||
HANDLE DevInstRegKey;
|
||||
|
||||
/* Open the device key */
|
||||
Status = IoOpenDeviceRegistryKey(PhysicalDeviceObject,
|
||||
PLUGPLAY_REGKEY_DRIVER, STANDARD_RIGHTS_ALL, &DevInstRegKey);
|
||||
PLUGPLAY_REGKEY_DEVICE, STANDARD_RIGHTS_ALL, &DevInstRegKey);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
PKEY_VALUE_FULL_INFORMATION FullInfo;
|
||||
PKEY_VALUE_PARTIAL_INFORMATION PartialInfo;
|
||||
UNICODE_STRING ValueName;
|
||||
ULONG Length;
|
||||
|
||||
RtlInitUnicodeString(&ValueName, KeyName);
|
||||
Length = ParameterLength + KeyNameLength + sizeof(KEY_VALUE_FULL_INFORMATION);
|
||||
FullInfo = ExAllocatePool(PagedPool, Length);
|
||||
if (FullInfo)
|
||||
/* Initialize the unicode string based on caller data */
|
||||
ValueName.Buffer = KeyName;
|
||||
ValueName.Length = ValueName.MaximumLength = KeyNameLength;
|
||||
|
||||
Length = ParameterLength + sizeof(KEY_VALUE_PARTIAL_INFORMATION);
|
||||
PartialInfo = ExAllocatePool(PagedPool, Length);
|
||||
if (PartialInfo)
|
||||
{
|
||||
Status = ZwQueryValueKey(DevInstRegKey, &ValueName,
|
||||
KeyValueFullInformation, FullInfo, Length, &Length);
|
||||
KeyValuePartialInformation, PartialInfo, Length, &Length);
|
||||
if (Status == STATUS_BUFFER_OVERFLOW || Status == STATUS_BUFFER_TOO_SMALL)
|
||||
{
|
||||
/* The caller doesn't want all the data */
|
||||
ExFreePool(PartialInfo);
|
||||
PartialInfo = ExAllocatePool(PagedPool, Length);
|
||||
if (PartialInfo)
|
||||
{
|
||||
Status = ZwQueryValueKey(DevInstRegKey, &ValueName,
|
||||
KeyValuePartialInformation, PartialInfo, Length, &Length);
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = STATUS_NO_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* Compute the length to copy back */
|
||||
if (ParameterLength < PartialInfo->DataLength)
|
||||
Length = ParameterLength;
|
||||
else
|
||||
Length = PartialInfo->DataLength;
|
||||
|
||||
RtlCopyMemory(Parameter,
|
||||
((PUCHAR)FullInfo) + FullInfo->DataOffset,
|
||||
ParameterLength /*FullInfo->DataLength*/);
|
||||
PartialInfo->Data,
|
||||
Length);
|
||||
}
|
||||
|
||||
if (PartialInfo)
|
||||
{
|
||||
ExFreePool(PartialInfo);
|
||||
}
|
||||
ExFreePool(FullInfo);
|
||||
} else
|
||||
Status = STATUS_NO_MEMORY;
|
||||
ZwClose(DevInstRegKey);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<?xml version="1.0"?>
|
||||
<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
|
||||
<module name="usbd" type="kernelmodedriver" installbase="system32/drivers" installname="usbd.sys">
|
||||
<bootstrap installbase="$(CDOUTPUT)/system32/drivers" />
|
||||
<importlibrary definition="usbd.spec" />
|
||||
<library>ntoskrnl</library>
|
||||
<library>hal</library>
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
@ stdcall USBD_Debug_GetHeap(long long long long)
|
||||
@ stdcall USBD_Debug_RetHeap(ptr long long)
|
||||
@ stdcall USBD_Debug_LogEntry(ptr ptr ptr ptr)
|
||||
@ stdcall USBD_CalculateUsbBandwidth(long long long)
|
||||
@ stdcall USBD_CreateConfigurationRequestEx(ptr ptr)
|
||||
@ stdcall USBD_CreateConfigurationRequest(ptr ptr)
|
||||
@ stdcall USBD_GetInterfaceLength(ptr ptr)
|
||||
@ stdcall USBD_ParseConfigurationDescriptor(ptr long long)
|
||||
@ stdcall USBD_ParseConfigurationDescriptorEx(ptr ptr long long long long long)
|
||||
@ stdcall USBD_ParseDescriptors(ptr long ptr long)
|
||||
;USBD_GetPdoRegistryParameters
|
||||
@ stdcall USBD_GetPdoRegistryParameter(ptr ptr long ptr long)
|
||||
@ stdcall USBD_GetUSBDIVersion(ptr)
|
||||
@ stdcall USBD_QueryBusTime(ptr ptr)
|
|
@ -1,21 +1,34 @@
|
|||
|
||||
list(APPEND SOURCE
|
||||
usbehci.c
|
||||
hardware.c
|
||||
physmem.c
|
||||
hwiface.c
|
||||
transfer.c
|
||||
fdo.c
|
||||
pdo.c
|
||||
common.c
|
||||
misc.c
|
||||
irp.c
|
||||
usbiffn.c
|
||||
set_cpp()
|
||||
|
||||
remove_definitions(-D_WIN32_WINNT=0x502)
|
||||
add_definitions(-D_WIN32_WINNT=0x600)
|
||||
|
||||
add_library(usbehci SHARED
|
||||
usbehci.cpp
|
||||
usb_device.cpp
|
||||
usb_request.cpp
|
||||
usb_queue.cpp
|
||||
hcd_controller.cpp
|
||||
hardware.cpp
|
||||
misc.cpp
|
||||
purecall.cpp
|
||||
hub_controller.cpp
|
||||
memory_manager.cpp
|
||||
usbehci.rc)
|
||||
|
||||
add_library(usbehci SHARED ${SOURCE})
|
||||
target_link_libraries(usbehci
|
||||
libcntpr
|
||||
${PSEH_LIB})
|
||||
|
||||
if(MSVC)
|
||||
set_target_properties(usbehci PROPERTIES COMPILE_FLAGS "/GR-")
|
||||
else()
|
||||
target_link_libraries(usbehci -lgcc)
|
||||
set_target_properties(usbehci PROPERTIES COMPILE_FLAGS "-fno-exceptions -fno-rtti")
|
||||
endif(MSVC)
|
||||
|
||||
set_module_type(usbehci kernelmodedriver)
|
||||
add_importlibs(usbehci ntoskrnl hal)
|
||||
|
||||
add_cab_target(usbehci 2)
|
||||
add_cd_file(TARGET usbehci DESTINATION reactos/system32/drivers NO_CAB FOR all)
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue