- 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:
Cameron Gutman 2012-02-12 04:59:51 +00:00
commit 022f4b2ce5
192 changed files with 74821 additions and 2501 deletions

View file

@ -2811,7 +2811,7 @@ InstallDevice(PCWSTR DeviceInstance, BOOL ShowWizard)
&DeviceKey) == ERROR_SUCCESS)
{
if (RegQueryValueExW(DeviceKey,
L"ClassGUID",
L"Class",
NULL,
NULL,
NULL,

View file

@ -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))

View file

@ -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;

View file

@ -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;
}

View file

@ -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)"

View file

@ -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)"

View file

@ -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

View file

@ -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

View file

@ -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 */

View file

@ -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
*/

View file

@ -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)

View file

@ -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++;

View file

@ -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;
}

View file

@ -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;

View file

@ -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);

View file

@ -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)

View file

@ -127,7 +127,6 @@ PciFdoIrpQueryRemoveDevice(IN PIRP Irp,
IN PPCI_FDO_EXTENSION DeviceExtension)
{
UNIMPLEMENTED;
while (TRUE);
return STATUS_NOT_SUPPORTED;
}

View file

@ -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;
}

View file

@ -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>

View file

@ -0,0 +1,2 @@
add_subdirectory(mountmgr)

View 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>

View 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)

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View 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_ */

File diff suppressed because it is too large Load diff

View 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>

View 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>

View 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);
}
}

View 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;
}

File diff suppressed because it is too large Load diff

View 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;
}

View file

@ -0,0 +1,5 @@
add_subdirectory(hidclass)
add_subdirectory(hidparse)
add_subdirectory(hidusb)
add_subdirectory(kbdhid)
add_subdirectory(mouhid)

View 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>

View 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)

View 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);
}
}
}

File diff suppressed because it is too large Load diff

View 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>

View 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>

View file

@ -0,0 +1,4 @@
@ stdcall -private DllInitialize(long)
@ stdcall -private DllUnload()
@ stdcall HidRegisterMinidriver(ptr)

View 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;
}

View 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 */

View 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)

View 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;
}

View 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>

View 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>

View 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>

View 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)

View 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)

File diff suppressed because it is too large Load diff

View 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

View 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>

View 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>

View 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)

View 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;
}

View 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);

View 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>

View 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>

View 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)

View 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;
}

View 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);

View 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>

View 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>

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -2,4 +2,5 @@
add_subdirectory(cdrom)
add_subdirectory(class2)
add_subdirectory(disk)
add_subdirectory(disk_new)
add_subdirectory(ramdisk)

View file

@ -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;*/
}

View 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)

View 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

File diff suppressed because it is too large Load diff

View 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])

View 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"

View 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"

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View 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);
}

File diff suppressed because it is too large Load diff

View file

@ -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)

View file

@ -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>

View file

@ -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)

View file

@ -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>

View 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)

View 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;
}

View 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;
}
}

View 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);
}

View 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 );
}
}
}

File diff suppressed because it is too large Load diff

View 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;
}

View 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

View 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>

View 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>

View file

@ -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)

View file

@ -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);

View file

@ -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>

View file

@ -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)

View file

@ -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