usbhub.sys: add stubbed usbhub.sys
Damjan Jovanovic
damjan.jov at gmail.com
Sun Apr 11 15:57:49 CDT 2010
On Thu, Mar 25, 2010 at 9:06 PM, Alexandre Julliard <julliard at winehq.org> wrote:
> Damjan Jovanovic <damjan.jov at gmail.com> writes:
>
>> I don't know enough about writing kernel drivers yet to decide this
>> (and several other things), so I think it's best I hack at it until I
>> have it working, then I'll start submitting patches again.
>>
>> In the meanwhile, is the use of libusb-1.0 in Wine ok? Or should I use
>> libusb-0.1 or some other library?
>
> I think 1.0 is fine, but I'd like to see some code using it first.
>
> --
> Alexandre Julliard
> julliard at winehq.org
>
I've hacked at this enough to get some basic USB I/O working, so now I
have a better idea of what's necessary.
I like usbhub.sys separate from usbd.sys because:
* The service is called Usbhub in the registry, drivers might depend
on the service, and having the service load usbd.sys instead of
usbhub.sys is confusing.
* usbd.sys isn't part of the device stack in any way, it's just a
utility library used to do miscellaneous things like parse USB
descriptors. Putting I/O code in there would be confusing.
* Windows from 2000 onwards uses usbhub.sys for device stack
management and I/O. No Windows version uses usbd.sys like that.
* If we don't want dlls that export nothing, mountmgr.sys also exports
nothing, so it should be part of ntoskrnl.exe by the same logic.
* There will no more usbXXX.sys files for basic USB after usbhub.sys.
We might eventually want higher-level device class drivers
(usbstor.sys, usbprint.sys) and Microsoft-provided generic drivers
(usbscan.sys) though.
* The driver doesn't load first and load usbd.sys via an import which
creates a device stack, usbhub.sys loads first and then loads drivers
(into the same process) on-demand, as their USB devices are plugged
in.
A *very hacked* patch is attached, if you want to see how libusb-1.0
is used. It only works just enough for the driver to read descriptors
from the device and send a few basic I/O requests.
I'd like to start sending real patches soon, so can I add a separate
usbhub.sys or do I have to stick with usbd.sys? And is libusb-1.0 ok?
Thank you
Damjan Jovanovic
-------------- next part --------------
diff --git a/configure.ac b/configure.ac
index 142d32a..6080b0f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -69,6 +69,7 @@ AC_ARG_WITH(png, AS_HELP_STRING([--without-png],[do not use PNG]),
AC_ARG_WITH(pthread, AS_HELP_STRING([--without-pthread],[do not use the pthread library]),
[if test "x$withval" = "xno"; then ac_cv_header_pthread_h=no; fi])
AC_ARG_WITH(sane, AS_HELP_STRING([--without-sane],[do not use SANE (scanner support)]))
+AC_ARG_WITH(usb, AS_HELP_STRING([--without-usb],[do not use libusb]))
AC_ARG_WITH(tiff, AS_HELP_STRING([--without-tiff],[do not use TIFF]),
[if test "x$withval" = "xno"; then ac_cv_header_tiffio_h=no; fi])
AC_ARG_WITH(v4l, AS_HELP_STRING([--without-v4l],[do not use v4l1 (v4l support)]))
@@ -1162,6 +1163,28 @@ fi
WINE_NOTICE_WITH(sane,[test "x$ac_cv_lib_soname_sane" = "x"],
[libsane ${notice_platform}development files not found, scanners won't be supported.])
+dnl *** Check for libusb-1.0 ****
+AC_SUBST(LIBUSBINCL,"")
+AC_SUBST(LIBUSBLIBS,"")
+if test "x$with_usb" != "xno"
+then
+ ac_save_CPPFLAGS="$CPPFLAGS"
+ if test "$PKG_CONFIG" != "false"
+ then
+ ac_usb_libs="`$PKG_CONFIG --libs libusb-1.0 2>/dev/null`"
+ ac_usb_cflags="`$PKG_CONFIG --cflags libusb-1.0 2>/dev/null`"
+ CPPFLAGS="$CPPFLAGS $ac_usb_cflags"
+ fi
+ AC_CHECK_HEADER(libusb.h,
+ [AC_CHECK_LIB(usb-1.0,libusb_init,
+ [AC_DEFINE(HAVE_LIBUSB, 1, [Define if you have the libusb-1.0 library and header])
+ LIBUSBLIBS="$ac_usb_libs"
+ LIBUSBINCL="$ac_usb_cflags"],,$ac_usb_libs)])
+ CPPFLAGS="$ac_save_CPPFLAGS"
+fi
+WINE_NOTICE_WITH(usb,[test "x$ac_cv_lib_usb_1_0_libusb_init" != "xyes"],
+ [libusb-1.0 ${notice_platform}development files not found, USB won't be supported.])
+
dnl **** Check for libv4l1 ****
if test "x$with_v4l" != "xno"
then
@@ -2543,6 +2566,7 @@ WINE_CONFIG_DLL(url,,[url])
WINE_CONFIG_DLL(urlmon,,[urlmon])
WINE_CONFIG_TEST(dlls/urlmon/tests)
WINE_CONFIG_DLL(usbd.sys,,[usbd.sys])
+WINE_CONFIG_DLL(usbhub.sys,,[usbhub.sys])
WINE_CONFIG_DLL(user.exe16,enable_win16)
WINE_CONFIG_DLL(user32,,[user32])
WINE_CONFIG_TEST(dlls/user32/tests)
diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c
index 7a5af73..0f77660 100644
--- a/dlls/ntoskrnl.exe/ntoskrnl.c
+++ b/dlls/ntoskrnl.exe/ntoskrnl.c
@@ -632,14 +632,9 @@ NTSTATUS WINAPI IoGetDeviceObjectPointer( UNICODE_STRING *name, ACCESS_MASK acc
/***********************************************************************
- * IofCallDriver (NTOSKRNL.EXE.@)
+ * IoCallDriver (NTOSKRNL.EXE.@)
*/
-#ifdef DEFINE_FASTCALL2_ENTRYPOINT
-DEFINE_FASTCALL2_ENTRYPOINT( IofCallDriver )
-NTSTATUS WINAPI __regs_IofCallDriver( DEVICE_OBJECT *device, IRP *irp )
-#else
-NTSTATUS WINAPI IofCallDriver( DEVICE_OBJECT *device, IRP *irp )
-#endif
+NTSTATUS WINAPI IoCallDriver( DEVICE_OBJECT *device, IRP *irp )
{
PDRIVER_DISPATCH dispatch;
IO_STACK_LOCATION *irpsp;
@@ -650,6 +645,8 @@ NTSTATUS WINAPI IofCallDriver( DEVICE_OBJECT *device, IRP *irp )
--irp->CurrentLocation;
irpsp = --irp->Tail.Overlay.s.u2.CurrentStackLocation;
dispatch = device->DriverObject->MajorFunction[irpsp->MajorFunction];
+if (dispatch == NULL) { FIXME("AVOIDING CRASH DUE TO UNIMPLEMENTED MAJOR FUNCTION 0x%X\n", irpsp->MajorFunction); return STATUS_SUCCESS; }
+FIXME("calling the driver at %p, function 0x%X !!!\n", dispatch, irpsp->MajorFunction);
status = dispatch( device, irp );
return status;
@@ -657,6 +654,21 @@ NTSTATUS WINAPI IofCallDriver( DEVICE_OBJECT *device, IRP *irp )
/***********************************************************************
+ * IofCallDriver (NTOSKRNL.EXE.@)
+ */
+#ifdef DEFINE_FASTCALL2_ENTRYPOINT
+DEFINE_FASTCALL2_ENTRYPOINT( IofCallDriver )
+NTSTATUS WINAPI __regs_IofCallDriver( DEVICE_OBJECT *device, IRP *irp )
+#else
+NTSTATUS WINAPI IofCallDriver( DEVICE_OBJECT *device, IRP *irp )
+#endif
+{
+ TRACE( "%p %p\n", device, irp );
+ return IoCallDriver( device, irp );
+}
+
+
+/***********************************************************************
* IoGetRelatedDeviceObject (NTOSKRNL.EXE.@)
*/
PDEVICE_OBJECT WINAPI IoGetRelatedDeviceObject( PFILE_OBJECT obj )
@@ -679,6 +691,20 @@ PCONFIGURATION_INFORMATION WINAPI IoGetConfigurationInformation(void)
/***********************************************************************
+ * IoGetDeviceProperty (NTOSKRNL.EXE.@)
+ */
+NTSTATUS WINAPI IoGetDeviceProperty( PDEVICE_OBJECT DeviceObject,
+ int DeviceProperty,
+ ULONG BufferLength,
+ PVOID PropertyBuffer,
+ PULONG ResultLength )
+{
+ FIXME( "%p %d %u %p %p:stub\n", DeviceObject, DeviceProperty, BufferLength, PropertyBuffer, ResultLength );
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+
+/***********************************************************************
* IoIsWdmVersionAvailable (NTOSKRNL.EXE.@)
*/
NTSTATUS WINAPI IoIsWdmVersionAvailable(UCHAR MajorVersion, UCHAR MinorVersion)
@@ -757,6 +783,20 @@ NTSTATUS WINAPI IoQueryDeviceDescription(PINTERFACE_TYPE itype, PULONG bus, PCON
/***********************************************************************
+ * IoRegisterDeviceInterface (NTOSKRNL.EXE.@)
+ */
+NTSTATUS WINAPI IoRegisterDeviceInterface( PDEVICE_OBJECT obj, const GUID *interface_class_guid,
+ PUNICODE_STRING reference_string, PUNICODE_STRING symlink_name )
+{
+ static const WCHAR devicepath[] = {'D','E','V',0};
+ FIXME( "(%p, %s, %p, %p)\n", obj, debugstr_guid(interface_class_guid),
+ reference_string, symlink_name );
+ RtlCreateUnicodeString( symlink_name, devicepath );
+ return STATUS_SUCCESS;//NOT_IMPLEMENTED;
+}
+
+
+/***********************************************************************
* IoRegisterDriverReinitialization (NTOSKRNL.EXE.@)
*/
void WINAPI IoRegisterDriverReinitialization( PDRIVER_OBJECT obj, PDRIVER_REINITIALIZE reinit, PVOID context )
@@ -1167,6 +1207,16 @@ LONG WINAPI KeReleaseSemaphore( PRKSEMAPHORE Semaphore, KPRIORITY Increment,
/***********************************************************************
+ * KeResetEvent (NTOSKRNL.EXE.@)
+ */
+LONG WINAPI KeResetEvent( PRKEVENT Event )
+{
+ FIXME("(%p): stub\n", Event);
+ return 0;
+}
+
+
+/***********************************************************************
* KeQueryTimeIncrement (NTOSKRNL.EXE.@)
*/
ULONG WINAPI KeQueryTimeIncrement(void)
@@ -1176,6 +1226,16 @@ ULONG WINAPI KeQueryTimeIncrement(void)
/***********************************************************************
+ * KeSetEvent (NTOSKRNL.EXE.@)
+ */
+LONG WINAPI KeSetEvent( PRKEVENT Event, KPRIORITY Increment, BOOLEAN Wait )
+{
+ FIXME("(%p, %d, %d): stub\n", Event, Increment, Wait);
+ return 0;
+}
+
+
+/***********************************************************************
* KeSetPriorityThread (NTOSKRNL.EXE.@)
*/
KPRIORITY WINAPI KeSetPriorityThread( PKTHREAD Thread, KPRIORITY Priority )
diff --git a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec
index 993de77..ceb02a4 100644
--- a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec
+++ b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec
@@ -323,7 +323,7 @@
@ stdcall IoBuildDeviceIoControlRequest(long ptr ptr long ptr long long ptr ptr)
@ stub IoBuildPartialMdl
@ stub IoBuildSynchronousFsdRequest
-@ stub IoCallDriver
+@ stdcall IoCallDriver(ptr ptr)
@ stub IoCancelFileOpen
@ stub IoCancelIrp
@ stub IoCheckDesiredAccess
@@ -383,7 +383,7 @@
@ stub IoGetDeviceInterfaceAlias
@ stub IoGetDeviceInterfaces
@ stdcall IoGetDeviceObjectPointer(ptr long ptr ptr)
-@ stub IoGetDeviceProperty
+@ stdcall IoGetDeviceProperty(ptr long long ptr ptr)
@ stub IoGetDeviceToVerify
@ stub IoGetDiskDeviceObject
@ stub IoGetDmaAdapter
@@ -425,7 +425,7 @@
@ stub IoReadPartitionTableEx
@ stub IoReadTransferCount
@ stub IoRegisterBootDriverReinitialization
-@ stub IoRegisterDeviceInterface
+@ stdcall IoRegisterDeviceInterface(ptr ptr ptr ptr)
@ stdcall IoRegisterDriverReinitialization(ptr ptr ptr)
@ stdcall IoRegisterFileSystem(ptr)
@ stub IoRegisterFsRegistrationChange
@@ -597,7 +597,7 @@
@ stub KeRemoveQueue
@ stub KeRemoveQueueDpc
@ stub KeRemoveSystemServiceTable
-@ stub KeResetEvent
+@ stdcall KeResetEvent(ptr)
@ stub KeRestoreFloatingPointState
@ stub KeRevertToUserAffinityThread
@ stub KeRundownQueue
@@ -607,7 +607,7 @@
@ stub KeSetAffinityThread
@ stub KeSetBasePriorityThread
@ stub KeSetDmaIoCoherency
-@ stub KeSetEvent
+@ stdcall KeSetEvent(ptr long long)
@ stub KeSetEventBoostPriority
@ stub KeSetIdealProcessorThread
@ stub KeSetImportanceDpc
diff --git a/dlls/usbhub.sys/Makefile.in b/dlls/usbhub.sys/Makefile.in
new file mode 100644
index 0000000..56f7a38
--- /dev/null
+++ b/dlls/usbhub.sys/Makefile.in
@@ -0,0 +1,14 @@
+TOPSRCDIR = @top_srcdir@
+TOPOBJDIR = ../..
+SRCDIR = @srcdir@
+VPATH = @srcdir@
+MODULE = usbhub.sys
+IMPORTS = kernel32 ntoskrnl.exe ntdll advapi32 setupapi
+EXTRADLLFLAGS = -Wb,--subsystem,native
+EXTRAINCL = @LIBUSBINCL@
+EXTRALIBS = @LIBUSBLIBS@
+
+C_SRCS = \
+ usbhub.c
+
+ at MAKE_DLL_RULES@
diff --git a/dlls/usbhub.sys/usbhub.c b/dlls/usbhub.sys/usbhub.c
new file mode 100644
index 0000000..0cc8c61
--- /dev/null
+++ b/dlls/usbhub.sys/usbhub.c
@@ -0,0 +1,763 @@
+/*
+ * Copyright 2010 Damjan Jovanovic
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "config.h"
+
+// FIXME
+#include "wine/port.h"
+#include <stdio.h>
+
+#include <stdarg.h>
+
+#define NONAMELESSUNION
+#define NONAMELESSSTRUCT
+
+#include "ntstatus.h"
+#define WIN32_NO_STATUS
+#include "windef.h"
+#include "winbase.h"
+#include "winternl.h"
+#include "winioctl.h"
+#include "winreg.h"
+#include "winuser.h"
+#include "setupapi.h"
+#include "cfgmgr32.h"
+#include "ddk/wdm.h"
+#include "ddk/usb.h"
+#include "ddk/usbioctl.h"
+#include "wine/unicode.h"
+#include "wine/debug.h"
+
+#ifdef HAVE_LIBUSB
+#include <libusb.h>
+
+static libusb_context *context;
+#endif
+
+WINE_DEFAULT_DEBUG_CHANNEL(usbhub);
+
+#ifdef HAVE_LIBUSB
+
+typedef struct {
+ libusb_device *device;
+ libusb_device_handle *handle;
+} WineUsbDeviceExtension;
+
+static DRIVER_OBJECT *usbhub_driver;
+// FIXME
+ DRIVER_EXTENSION driver_extension;
+ DRIVER_OBJECT driver_obj;
+
+static USBD_STATUS libusb_to_usbd_status(int ret)
+{
+ switch (ret)
+ {
+ case LIBUSB_SUCCESS:
+ return USBD_STATUS_SUCCESS;
+ case LIBUSB_ERROR_IO:
+ return USBD_STATUS_INTERNAL_HC_ERROR;
+ case LIBUSB_ERROR_INVALID_PARAM:
+ return USBD_STATUS_INVALID_PARAMETER;
+ case LIBUSB_ERROR_ACCESS:
+ return USBD_STATUS_INTERNAL_HC_ERROR;
+ case LIBUSB_ERROR_NO_DEVICE:
+ return USBD_STATUS_DEVICE_GONE;
+ case LIBUSB_ERROR_NOT_FOUND:
+ return USBD_STATUS_INTERNAL_HC_ERROR;
+ case LIBUSB_ERROR_BUSY:
+ return USBD_STATUS_ERROR_BUSY;
+ case LIBUSB_ERROR_TIMEOUT:
+ return USBD_STATUS_TIMEOUT;
+ case LIBUSB_ERROR_OVERFLOW:
+ /* http://www.cypress.com/?rID=37596 */
+ return USBD_STATUS_BUFFER_OVERRUN;
+ case LIBUSB_ERROR_PIPE:
+ return USBD_STATUS_STALL_PID;
+ case LIBUSB_ERROR_INTERRUPTED:
+ return USBD_STATUS_INTERNAL_HC_ERROR;
+ case LIBUSB_ERROR_NO_MEM:
+ return USBD_STATUS_NO_MEMORY;
+ case LIBUSB_ERROR_NOT_SUPPORTED:
+ return USBD_STATUS_NOT_SUPPORTED;
+ }
+ return USBD_STATUS_INTERNAL_HC_ERROR;
+}
+
+static NTSTATUS usb_vendor_class_control_request( URB *urb, UCHAR typeAndRecipient, WineUsbDeviceExtension *device_extension )
+{
+ UCHAR requestType;
+ UCHAR *buffer;
+ int ret;
+
+ requestType = typeAndRecipient;
+ if (urb->u.UrbControlVendorClassRequest.TransferFlags & USBD_TRANSFER_DIRECTION_IN)
+ requestType |= 0x80;
+ if (requestType & urb->u.UrbControlVendorClassRequest.RequestTypeReservedBits)
+ {
+ FIXME( "buggy driver wants to set reserved bits 0x%02X in USB control request, aborting I/O, please report\n",
+ requestType & urb->u.UrbControlVendorClassRequest.RequestTypeReservedBits);
+ urb->u.UrbHeader.Status = USBD_STATUS_INVALID_PARAMETER;
+ return STATUS_INVALID_PARAMETER;
+ }
+ requestType |= urb->u.UrbControlVendorClassRequest.RequestTypeReservedBits;
+
+ buffer = urb->u.UrbControlVendorClassRequest.TransferBuffer;
+ if (buffer == NULL)
+ buffer = urb->u.UrbControlVendorClassRequest.TransferBufferMDL->MappedSystemVa;
+ if (buffer == NULL)
+ {
+ urb->u.UrbHeader.Status = USBD_STATUS_INVALID_PARAMETER;
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ ret = libusb_control_transfer( device_extension->handle, requestType,
+ urb->u.UrbControlVendorClassRequest.Request,
+ urb->u.UrbControlVendorClassRequest.Value,
+ urb->u.UrbControlVendorClassRequest.Index,
+ buffer, urb->u.UrbControlVendorClassRequest.TransferBufferLength, 0 );
+ if (ret >= 0)
+ {
+ urb->u.UrbControlVendorClassRequest.TransferBufferLength = ret;
+ urb->u.UrbHeader.Status = USBD_STATUS_SUCCESS;
+ return STATUS_SUCCESS;
+ }
+ else
+ {
+ urb->u.UrbHeader.Status = libusb_to_usbd_status( ret );
+ return STATUS_UNSUCCESSFUL;
+ }
+}
+
+static NTSTATUS submit_urb( URB *urb, WineUsbDeviceExtension *device_extension )
+{
+ NTSTATUS status = STATUS_NOT_IMPLEMENTED;
+ int ret;
+
+ switch (urb->u.UrbHeader.Function)
+ {
+ case URB_FUNCTION_SELECT_CONFIGURATION:
+ {
+ TRACE( "URB_FUNCTION_SELECT_CONFIGURATION\n" );
+ break;
+ }
+ case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE:
+ {
+ unsigned char *buffer;
+ TRACE( "URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE\n" );
+
+ buffer = urb->u.UrbControlDescriptorRequest.TransferBuffer;
+ if (buffer == NULL)
+ buffer = urb->u.UrbControlDescriptorRequest.TransferBufferMDL->MappedSystemVa;
+ if (buffer == NULL)
+ {
+ urb->u.UrbHeader.Status = USBD_STATUS_INVALID_PARAMETER;
+ status = STATUS_INVALID_PARAMETER;
+ break;
+ }
+
+ switch (urb->u.UrbControlDescriptorRequest.DescriptorType)
+ {
+ case USB_DEVICE_DESCRIPTOR_TYPE:
+ {
+ struct libusb_device_descriptor device_descriptor;
+ TRACE( "USB_DEVICE_DESCRIPTOR_TYPE\n" );
+ ret = libusb_get_device_descriptor( device_extension->device, &device_descriptor );
+ if (ret == LIBUSB_SUCCESS)
+ {
+ ULONG size = urb->u.UrbControlDescriptorRequest.TransferBufferLength;
+ if (size > sizeof(device_descriptor))
+ size = sizeof(device_descriptor);
+ memcpy( buffer, &device_descriptor, size );
+ urb->u.UrbHeader.Status = USBD_STATUS_SUCCESS;
+ status = STATUS_SUCCESS;
+ }
+ else
+ {
+ ERR( "libusb error %d getting device descriptor\n", ret );
+ urb->u.UrbHeader.Status = libusb_to_usbd_status( ret );
+ status = STATUS_UNSUCCESSFUL;
+ }
+ break;
+ }
+ case USB_CONFIGURATION_DESCRIPTOR_TYPE:
+ {
+ struct libusb_config_descriptor *config_descriptor;
+ TRACE( "USB_CONFIGURATION_DESCRIPTOR_TYPE\n" );
+ ret = libusb_get_active_config_descriptor( device_extension->device, &config_descriptor );
+ if (ret == LIBUSB_SUCCESS)
+ {
+ ULONG remaining = urb->u.UrbControlDescriptorRequest.TransferBufferLength;
+ int i;
+ size_t size = sizeof(USB_CONFIGURATION_DESCRIPTOR);
+ if (size > remaining)
+ size = remaining;
+ memcpy( buffer, config_descriptor, size );
+ buffer += size;
+ remaining -= size;
+ size = config_descriptor->extra_length;
+ if (size > remaining)
+ size = remaining;
+ memcpy( buffer, config_descriptor->extra, size );
+ buffer += size;
+ remaining -= size;
+ for (i = 0; i < config_descriptor->bNumInterfaces; i++)
+ {
+ int j;
+ size = sizeof(USB_INTERFACE_DESCRIPTOR);
+ if (size > remaining)
+ size = remaining;
+ memcpy( buffer, &config_descriptor->interface[i].altsetting[0], size );
+ buffer += size;
+ remaining -= size;
+ size = config_descriptor->interface[i].altsetting[0].extra_length;
+ if (size > remaining)
+ size = remaining;
+ memcpy( buffer, &config_descriptor->interface[i].altsetting[0].extra, size );
+ buffer += size;
+ remaining -= size;
+ for (j = 0; j < config_descriptor->interface[i].altsetting[0].bNumEndpoints; j++)
+ {
+ size = sizeof(USB_ENDPOINT_DESCRIPTOR);
+ if (size > remaining)
+ size = remaining;
+ memcpy( buffer, &config_descriptor->interface[i].altsetting[0].endpoint[j], size );
+ buffer += size;
+ remaining -= size;
+ size = config_descriptor->interface[i].altsetting[0].endpoint[j].extra_length;
+ if (size > remaining)
+ size = remaining;
+ memcpy( buffer, &config_descriptor->interface[i].altsetting[0].endpoint[j].extra, size );
+ buffer += size;
+ remaining -= size;
+ }
+ }
+ urb->u.UrbHeader.Status = USBD_STATUS_SUCCESS;
+ status = STATUS_SUCCESS;
+ libusb_free_config_descriptor( config_descriptor );
+ }
+ else
+ {
+ ERR( "libusb error %d getting configuration descriptor\n", ret );
+ urb->u.UrbHeader.Status = libusb_to_usbd_status( ret );
+ status = STATUS_UNSUCCESSFUL;
+ }
+ break;
+ }
+ case USB_STRING_DESCRIPTOR_TYPE:
+ FIXME( "USB_STRING_DESCRIPTOR_TYPE: stub\n" );
+ urb->u.UrbHeader.Status = STATUS_NOT_SUPPORTED;
+ status = STATUS_NOT_IMPLEMENTED;
+ break;
+ default:
+ FIXME( "unknown USB descriptor type %d\n", urb->u.UrbControlDescriptorRequest.DescriptorType );
+ urb->u.UrbHeader.Status = USBD_STATUS_NOT_SUPPORTED;
+ status = STATUS_NOT_IMPLEMENTED;
+ }
+ break;
+ }
+ case URB_FUNCTION_VENDOR_DEVICE:
+ {
+ TRACE( "URB_FUNCTION_VENDOR_DEVICE\n" );
+ status = usb_vendor_class_control_request( urb, 0x40, device_extension );
+ break;
+ }
+ default:
+ FIXME( "unimplemented URB function %d\n", urb->u.UrbHeader.Function );
+ urb->u.UrbHeader.Status = USBD_STATUS_NOT_SUPPORTED;
+ status = STATUS_NOT_IMPLEMENTED;
+ break;
+ }
+ return status;
+}
+
+static NTSTATUS WINAPI usbhub_internal_ioctl( DEVICE_OBJECT *device, IRP *irp )
+{
+ IO_STACK_LOCATION *irpsp;
+ URB *urb = NULL;
+ WineUsbDeviceExtension *deviceExtension;
+ NTSTATUS status = STATUS_NOT_IMPLEMENTED;
+
+ TRACE( "(%p, %p)\n", device, irp );
+
+ deviceExtension = device->DeviceExtension;
+ irp->IoStatus.Information = 0;
+ irpsp = IoGetCurrentIrpStackLocation( irp );
+
+ switch (irpsp->Parameters.DeviceIoControl.IoControlCode)
+ {
+ case IOCTL_INTERNAL_USB_SUBMIT_URB:
+ urb = irpsp->Parameters.Others.Argument1;
+ status = submit_urb( urb, deviceExtension );
+ break;
+ default:
+ FIXME( "ioctl code 0x%08X is unimplemented\n", irpsp->Parameters.DeviceIoControl.IoControlCode );
+ if (urb)
+ urb->u.UrbHeader.Status = USBD_STATUS_NOT_SUPPORTED;
+ status = STATUS_NOT_IMPLEMENTED;
+ }
+
+ irp->IoStatus.u.Status = status;
+ IoCompleteRequest( irp, IO_NO_INCREMENT );
+ return status;
+}
+
+static BOOL is_any_usb_interface_unclaimed( libusb_device *device, libusb_device_handle *handle )
+{
+ struct libusb_config_descriptor *config_desc = NULL;
+ int i;
+ BOOL anyInterfaceUnclaimed = FALSE;
+ int ret;
+
+ ret = libusb_get_active_config_descriptor( device, &config_desc );
+ if (ret != LIBUSB_SUCCESS)
+ {
+ ERR( "could not get active configuration's descriptor\n" );
+ goto done;
+ }
+
+ for (i = 0; i < config_desc->bNumInterfaces; i++)
+ {
+ struct libusb_interface_descriptor interface_desc =
+ config_desc->interface[i].altsetting[0];
+ ret = libusb_kernel_driver_active( handle, interface_desc.bInterfaceNumber );
+ if (ret == 0)
+ {
+ anyInterfaceUnclaimed = TRUE;
+ break;
+ }
+ else if (ret == 1)
+ ;
+ else
+ {
+ ERR( "checking for active kernel driver for USB interface failed with %d\n", ret );
+ goto done;
+ }
+ }
+ /* It's still theoretically possible a user-space driver has claimed interfaces we think are free,
+ * but the problem also exists between other user-space drivers, with no clear solution.
+ */
+
+done:
+ libusb_free_config_descriptor( config_desc );
+ return anyInterfaceUnclaimed;
+}
+
+/* find the LDR_MODULE corresponding to the driver module */
+static LDR_MODULE *find_ldr_module( HMODULE module )
+{
+ LIST_ENTRY *entry, *list = &NtCurrentTeb()->Peb->LdrData->InMemoryOrderModuleList;
+
+ for (entry = list->Flink; entry != list; entry = entry->Flink)
+ {
+ LDR_MODULE *ldr = CONTAINING_RECORD(entry, LDR_MODULE, InMemoryOrderModuleList);
+ if (ldr->BaseAddress == module) return ldr;
+ if (ldr->BaseAddress > (void *)module) break;
+ }
+ return NULL;
+}
+
+/* load the driver module file */
+static HMODULE load_driver_module( const WCHAR *name )
+{
+ IMAGE_NT_HEADERS *nt;
+ const IMAGE_IMPORT_DESCRIPTOR *imports;
+ size_t page_size = getpagesize();
+ int i, delta;
+ ULONG size;
+ HMODULE module = LoadLibraryW( name );
+
+ if (!module) return NULL;
+ nt = RtlImageNtHeader( module );
+
+ if (!(delta = (char *)module - (char *)nt->OptionalHeader.ImageBase)) return module;
+
+ /* the loader does not apply relocations to non page-aligned binaries or executables,
+ * we have to do it ourselves */
+
+ if (nt->OptionalHeader.SectionAlignment < page_size ||
+ !(nt->FileHeader.Characteristics & IMAGE_FILE_DLL))
+ {
+ DWORD old;
+ IMAGE_BASE_RELOCATION *rel, *end;
+
+ if ((rel = RtlImageDirectoryEntryToData( module, TRUE, IMAGE_DIRECTORY_ENTRY_BASERELOC, &size )))
+ {
+ WINE_TRACE( "%s: relocating from %p to %p\n",
+ wine_dbgstr_w(name), (char *)module - delta, module );
+ end = (IMAGE_BASE_RELOCATION *)((char *)rel + size);
+ while (rel < end && rel->SizeOfBlock)
+ {
+ void *page = (char *)module + rel->VirtualAddress;
+ VirtualProtect( page, page_size, PAGE_EXECUTE_READWRITE, &old );
+ rel = LdrProcessRelocationBlock( page, (rel->SizeOfBlock - sizeof(*rel)) / sizeof(USHORT),
+ (USHORT *)(rel + 1), delta );
+ if (old != PAGE_EXECUTE_READWRITE) VirtualProtect( page, page_size, old, NULL );
+ if (!rel) goto error;
+ }
+ /* make sure we don't try again */
+ nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = 0;
+ }
+ }
+
+ /* make sure imports are relocated too */
+ if ((imports = RtlImageDirectoryEntryToData( module, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &size )))
+ {
+ for (i = 0; imports[i].Name && imports[i].FirstThunk; i++)
+ {
+ char *name = (char *)module + imports[i].Name;
+ WCHAR buffer[32], *p = buffer;
+
+ while (p < buffer + 32) if (!(*p++ = *name++)) break;
+ if (p <= buffer + 32) FreeLibrary( load_driver_module( buffer ) );
+ }
+ }
+
+ return module;
+
+error:
+ FreeLibrary( module );
+ return NULL;
+}
+
+/* call the driver init entry point */
+static NTSTATUS init_driver( WCHAR *driver_name, HMODULE module, UNICODE_STRING *keyname )
+{
+ unsigned int i;
+ NTSTATUS status;
+ const IMAGE_NT_HEADERS *nt = RtlImageNtHeader( module );
+
+ if (!nt->OptionalHeader.AddressOfEntryPoint) return STATUS_SUCCESS;
+
+ driver_obj.Size = sizeof(driver_obj);
+ driver_obj.DriverSection = find_ldr_module( module );
+ driver_obj.DriverInit = (PDRIVER_INITIALIZE)((char *)module + nt->OptionalHeader.AddressOfEntryPoint);
+ driver_obj.DriverExtension = &driver_extension;
+
+ driver_extension.DriverObject = &driver_obj;
+ driver_extension.ServiceKeyName = *keyname;
+
+// if (WINE_TRACE_ON(relay))
+ WINE_DPRINTF( "%04x:Call driver init %p (obj=%p,str=%s)\n", GetCurrentThreadId(),
+ driver_obj.DriverInit, &driver_obj, wine_dbgstr_w(keyname->Buffer) );
+
+ status = driver_obj.DriverInit( &driver_obj, keyname );
+
+// if (WINE_TRACE_ON(relay))
+ WINE_DPRINTF( "%04x:Ret driver init %p (obj=%p,str=%s) retval=%08x\n", GetCurrentThreadId(),
+ driver_obj.DriverInit, &driver_obj, wine_dbgstr_w(keyname->Buffer), status );
+ WINE_TRACE( "init done for %s obj %p\n", wine_dbgstr_w(driver_name), &driver_obj );
+ WINE_TRACE( "- DriverInit = %p\n", driver_obj.DriverInit );
+ WINE_TRACE( "- DriverStartIo = %p\n", driver_obj.DriverStartIo );
+ WINE_TRACE( "- DriverUnload = %p\n", driver_obj.DriverUnload );
+ for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
+ WINE_TRACE( "- MajorFunction[%d] = %p\n", i, driver_obj.MajorFunction[i] );
+
+ return status;
+}
+/* load the .sys module for a device driver */
+static HMODULE load_driver(WCHAR *driver_name)
+{
+ static const WCHAR driversW[] = {'\\','d','r','i','v','e','r','s','\\',0};
+ static const WCHAR postfixW[] = {'.','s','y','s',0};
+ static const WCHAR ntprefixW[] = {'\\','?','?','\\',0};
+ static const WCHAR ImagePathW[] = {'I','m','a','g','e','P','a','t','h',0};
+ static const WCHAR servicesW[] = {'\\','R','e','g','i','s','t','r','y',
+ '\\','M','a','c','h','i','n','e',
+ '\\','S','y','s','t','e','m',
+ '\\','C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t',
+ '\\','S','e','r','v','i','c','e','s','\\',0};
+
+ UNICODE_STRING keypath;
+ HMODULE module;
+ LPWSTR path = NULL, str;
+ DWORD type, size;
+ HKEY driver_hkey;
+
+ str = HeapAlloc( GetProcessHeap(), 0, sizeof(servicesW) + strlenW(driver_name)*sizeof(WCHAR) );
+ lstrcpyW( str, servicesW );
+ lstrcatW( str, driver_name );
+
+ if (RegOpenKeyW( HKEY_LOCAL_MACHINE, str + 18 /* skip \registry\machine */, &driver_hkey ))
+ {
+ WINE_ERR( "cannot open key %s, err=%u\n", wine_dbgstr_w(str), GetLastError() );
+ HeapFree( GetProcessHeap(), 0, str);
+ return NULL;
+ }
+ RtlInitUnicodeString( &keypath, str );
+
+ /* read the executable path from memory */
+ size = 0;
+ if (!RegQueryValueExW( driver_hkey, ImagePathW, NULL, &type, NULL, &size ))
+ {
+ str = HeapAlloc( GetProcessHeap(), 0, size );
+ if (!RegQueryValueExW( driver_hkey, ImagePathW, NULL, &type, (LPBYTE)str, &size ))
+ {
+ size = ExpandEnvironmentStringsW(str,NULL,0);
+ path = HeapAlloc(GetProcessHeap(),0,size*sizeof(WCHAR));
+ ExpandEnvironmentStringsW(str,path,size);
+ }
+ HeapFree( GetProcessHeap(), 0, str );
+ if (!path) return NULL;
+ }
+ else
+ {
+ /* default is to use the driver name + ".sys" */
+ WCHAR buffer[MAX_PATH];
+ GetSystemDirectoryW(buffer, MAX_PATH);
+ path = HeapAlloc(GetProcessHeap(),0,
+ (strlenW(buffer) + strlenW(driversW) + strlenW(driver_name) + strlenW(postfixW) + 1)
+ *sizeof(WCHAR));
+ lstrcpyW(path, buffer);
+ lstrcatW(path, driversW);
+ lstrcatW(path, driver_name);
+ lstrcatW(path, postfixW);
+ }
+
+ /* GameGuard uses an NT-style path name */
+ str = path;
+ if (!strncmpW( path, ntprefixW, 4 )) str += 4;
+
+ WINE_TRACE( "loading driver %s\n", wine_dbgstr_w(str) );
+
+ module = load_driver_module( str );
+ HeapFree( GetProcessHeap(), 0, path );
+ if (!module) return NULL;
+
+ init_driver( driver_name, module, &keypath );
+ return module;
+}
+
+
+static void start_service( WCHAR *service, libusb_device *device, libusb_device_handle *handle )
+{
+ HMODULE module;
+ module = load_driver(service);
+ if (module)
+ {
+ DEVICE_OBJECT *device_object;
+ NTSTATUS status;
+
+ FIXME("loaded driver\n");
+ status = IoCreateDevice( usbhub_driver, sizeof(WineUsbDeviceExtension), NULL, FILE_DEVICE_UNKNOWN, 0, FALSE, &device_object );
+ if (status == STATUS_SUCCESS)
+ {
+ NTSTATUS (WINAPI *AddDevice)( PDRIVER_OBJECT, PDEVICE_OBJECT ) =
+ driver_obj.DriverExtension->AddDevice;
+ ((WineUsbDeviceExtension*)device_object->DeviceExtension)->device = device;
+ ((WineUsbDeviceExtension*)device_object->DeviceExtension)->handle = handle;
+ FIXME("calling add device at %p\n", AddDevice);
+ status = AddDevice( &driver_obj, device_object );
+ FIXME("add device gave 0x%X\n", status);
+ if (status == STATUS_SUCCESS)
+ {
+ if (driver_obj.MajorFunction[IRP_MJ_PNP] == NULL)
+ FIXME("MJ_PNP not supported\n");
+ else
+ {
+ PIRP irp;
+ irp = IoAllocateIrp( device_object->StackSize, FALSE );
+ if (irp)
+ {
+ IO_STACK_LOCATION *irpsp;
+ irpsp = IoGetNextIrpStackLocation( irp );
+ irp->RequestorMode = KernelMode;
+ irpsp->MajorFunction = IRP_MJ_PNP;
+ irpsp->MinorFunction = IRP_MN_START_DEVICE;
+ irpsp->DeviceObject = device_object;
+device_object->CurrentIrp = irp;
+device_object->DriverObject = usbhub_driver;
+irp->IoStatus.u.Status = STATUS_NOT_SUPPORTED;
+ status = IoCallDriver( device_object->AttachedDevice, irp );
+ FIXME("IoCallDriver gave 0x%x\n", status);
+ IoFreeIrp( irp );
+ }
+ else
+ FIXME("IoAllocateIrp failed\n");
+ }
+ }
+ }
+ else
+ ERR("IoCreateDevice failed, status 0x%X\n", status);
+ }
+ else
+ ERR("loading driver failed\n");
+}
+
+static void load_usb_driver( libusb_device *device, libusb_device_handle *handle )
+{
+ static const WCHAR usbW[] = {'U','S','B',0};
+ int ret;
+ struct libusb_device_descriptor dev_desc;
+ DWORD i;
+ BOOL found = FALSE;
+ HDEVINFO devices = INVALID_HANDLE_VALUE;
+ SP_DEVINFO_DATA devinfo;
+
+ ret = libusb_get_device_descriptor( device, &dev_desc );
+ if (ret != LIBUSB_SUCCESS)
+ {
+ ERR( "getting USB device descriptor failed, error %d\n", ret );
+ goto end;
+ }
+
+ /* Windows could create an enum key here,
+ * but we do all that from winecfg
+ * and only when asked */
+ devices = SetupDiGetClassDevsW( NULL, usbW, NULL, DIGCF_ALLCLASSES );
+ if (devices == INVALID_HANDLE_VALUE)
+ {
+ ERR( "listing USB devices failed with error %d\n", GetLastError() );
+ goto end;
+ }
+
+ memset( &devinfo, 0, sizeof(devinfo) );
+ devinfo.cbSize = sizeof(devinfo);
+ for (i = 0; SetupDiEnumDeviceInfo( devices, i, &devinfo ); i++)
+ {
+ CHAR deviceId[MAX_DEVICE_ID_LEN];
+ if (SetupDiGetDeviceInstanceIdA( devices, &devinfo, deviceId, MAX_DEVICE_ID_LEN, NULL ))
+ {
+#if 0
+ static const WCHAR pattern[] = {
+ 'U','S','B','\\','V','I','D','_','%','0','4','X','&',
+ 'P','I','D','_','%','0','4','X',0
+ };
+#endif
+ int vendorId, productId;
+ if (sscanf( deviceId, "USB\\VID_%04X&PID_%04X", &vendorId, &productId ) == 2 &&
+ dev_desc.idVendor == vendorId && dev_desc.idProduct == productId)
+ {
+ WCHAR *service;
+ DWORD size = 0;
+ SetupDiGetDeviceRegistryPropertyW( devices, &devinfo, SPDRP_SERVICE,
+ NULL, NULL, 0, &size );
+ service = HeapAlloc( GetProcessHeap(), 0, size );
+ if (service)
+ {
+ if (SetupDiGetDeviceRegistryPropertyW( devices, &devinfo, SPDRP_SERVICE,
+ NULL, (PBYTE)service, size, &size ))
+ {
+ start_service( service, device, handle );
+ }
+ else
+ ERR(" error %d reading service name\n", GetLastError() );
+ HeapFree( GetProcessHeap(), 0, service );
+ }
+ }
+ }
+ else
+ ERR( "couldn't get device instance id, error %d\n", GetLastError() );
+ }
+ if (!found && GetLastError() != ERROR_NO_MORE_ITEMS)
+ ERR( "enumerating USB devices failed with error %d\n", GetLastError() );
+
+end:
+ if (devices != INVALID_HANDLE_VALUE)
+ SetupDiDestroyDeviceInfoList( devices );
+}
+
+static void add_usb_device( libusb_device *device )
+{
+ int ret;
+ libusb_device_handle *handle;
+
+ ret = libusb_open( device, &handle );
+ if (ret == LIBUSB_SUCCESS)
+ {
+ if (is_any_usb_interface_unclaimed( device, handle ))
+ {
+FIXME("found free device\n");
+ load_usb_driver( device, handle );
+ }
+ libusb_close( handle );
+ }
+ else
+ ERR("could not open libusb device, error %d\n", ret);
+}
+
+static DWORD WINAPI detect_usb_devices( LPVOID arg )
+{
+ /* HAL is deprecated,
+ * its official replacements - devkit and udev - are 100% Linux-only (wow, progress!),
+ * libusb-1.0 plans to support device hotplugging from version 1.1,
+ * so we have to poll for now.
+ */
+ while (1)
+ {
+ libusb_device **list;
+ ssize_t size;
+ size = libusb_get_device_list( context, &list );
+ if (size >= 0)
+ {
+ int i;
+ for (i = 0; i < size; i++)
+ {
+ add_usb_device( list[i] );
+ }
+ libusb_free_device_list( list, 1 );
+ }
+ else
+ ERR( "libusb_get_device_list failed with error %d\n", size );
+ Sleep( 1000 );
+//FIXME:
+break;
+
+ }
+ return 0;
+}
+
+static VOID WINAPI usbhub_unload( DRIVER_OBJECT *driver )
+{
+ TRACE( "(%p)\n", driver );
+ libusb_exit( context );
+}
+
+#endif
+
+NTSTATUS WINAPI DriverEntry( DRIVER_OBJECT *driver, UNICODE_STRING *path )
+{
+ int ret = 0;
+ NTSTATUS status = STATUS_SUCCESS;
+
+ TRACE( "(%p, %s)\n", driver, debugstr_w(path->Buffer) );
+
+#ifdef HAVE_LIBUSB
+ ret = libusb_init( &context );
+ if (ret == LIBUSB_SUCCESS)
+ {
+ if (CreateThread( NULL, 0, detect_usb_devices, NULL, 0, NULL ) != NULL)
+ {
+ driver->DriverUnload = usbhub_unload;
+ driver->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = usbhub_internal_ioctl;
+ usbhub_driver = driver;
+ }
+ else
+ {
+ ERR( "couldn't create thread to detect USB devices, error %d\n", GetLastError() );
+ status = STATUS_UNSUCCESSFUL;
+ }
+ }
+ else
+ {
+ ERR( "libusb_init() failed with %d\n", ret );
+ status = STATUS_UNSUCCESSFUL;
+ }
+#endif
+
+ return status;
+}
diff --git a/dlls/usbhub.sys/usbhub.sys.spec b/dlls/usbhub.sys/usbhub.sys.spec
new file mode 100644
index 0000000..e69de29
diff --git a/include/ddk/usb.h b/include/ddk/usb.h
index af1c10d..0093478 100644
--- a/include/ddk/usb.h
+++ b/include/ddk/usb.h
@@ -103,6 +103,7 @@ typedef PVOID USBD_INTERFACE_HANDLE;
#define USBD_STATUS_BABBLE_DETECTED ((USBD_STATUS)0xC0000012)
#define USBD_STATUS_DATA_BUFFER_ERROR ((USBD_STATUS)0xC0000013)
#define USBD_STATUS_ENDPOINT_HALTED ((USBD_STATUS)0xC0000030)
+#define USBD_STATUS_NO_MEMORY ((USBD_STATUS)0x80000100)
#define USBD_STATUS_INVALID_URB_FUNCTION ((USBD_STATUS)0x80000200)
#define USBD_STATUS_INVALID_PARAMETER ((USBD_STATUS)0x80000300)
#define USBD_STATUS_ERROR_BUSY ((USBD_STATUS)0x80000400)
diff --git a/include/ddk/usbioctl.h b/include/ddk/usbioctl.h
new file mode 100644
index 0000000..8fcce74
--- /dev/null
+++ b/include/ddk/usbioctl.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) Damjan Jovanovic
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef __DDK_USBIOCTL_H__
+#define __DDK_USBIOCTL_H__
+
+#include "ntddk.h"
+#include "usbiodef.h"
+
+#define IOCTL_INTERNAL_USB_SUBMIT_URB \
+ CTL_CODE(FILE_DEVICE_USB, USB_SUBMIT_URB, METHOD_NEITHER, FILE_ANY_ACCESS)
+
+#endif
diff --git a/include/ddk/usbiodef.h b/include/ddk/usbiodef.h
new file mode 100644
index 0000000..0c34cdd
--- /dev/null
+++ b/include/ddk/usbiodef.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) Damjan Jovanovic
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef __DDK_USBIODEF_H__
+#define __DDK_USBIODEF_H__
+
+#include "ntddk.h"
+
+#define USB_SUBMIT_URB 0
+
+#define FILE_DEVICE_USB FILE_DEVICE_UNKNOWN
+
+#endif
diff --git a/include/ddk/wdm.h b/include/ddk/wdm.h
index 102dda8..89c9805 100644
--- a/include/ddk/wdm.h
+++ b/include/ddk/wdm.h
@@ -1024,14 +1024,18 @@ NTSTATUS WINAPI ObCloseHandle(IN HANDLE handle);
#ifdef NONAMELESSUNION
# ifdef NONAMELESSSTRUCT
# define IoGetCurrentIrpStackLocation(_Irp) ((_Irp)->Tail.Overlay.s.u2.CurrentStackLocation)
+# define IoGetNextIrpStackLocation(_Irp) ((_Irp)->Tail.Overlay.s.u2.CurrentStackLocation - 1)
# else
# define IoGetCurrentIrpStackLocation(_Irp) ((_Irp)->Tail.Overlay.u2.CurrentStackLocation)
+# define IoGetNextIrpStackLocation(_Irp) ((_Irp)->Tail.Overlay.u2.CurrentStackLocation - 1)
# endif
#else
# ifdef NONAMELESSSTRUCT
# define IoGetCurrentIrpStackLocation(_Irp) ((_Irp)->Tail.Overlay.s.CurrentStackLocation)
+# define IoGetNextIrpStackLocation(_Irp) ((_Irp)->Tail.Overlay.s.CurrentStackLocation - 1)
# else
# define IoGetCurrentIrpStackLocation(_Irp) ((_Irp)->Tail.Overlay.CurrentStackLocation)
+# define IoGetNextIrpStackLocation(_Irp) ((_Irp)->Tail.Overlay.CurrentStackLocation - 1)
# endif
#endif
@@ -1059,6 +1063,7 @@ void WINAPI ExFreePoolWithTag(PVOID,ULONG);
NTSTATUS WINAPI IoAllocateDriverObjectExtension(PDRIVER_OBJECT,PVOID,ULONG,PVOID*);
PVOID WINAPI IoAllocateErrorLogEntry(PVOID,UCHAR);
PIRP WINAPI IoAllocateIrp(CCHAR,BOOLEAN);
+NTSTATUS WINAPI IoCallDriver(DEVICE_OBJECT*,IRP*);
VOID WINAPI IoCompleteRequest(IRP*,UCHAR);
NTSTATUS WINAPI IoCreateDevice(DRIVER_OBJECT*,ULONG,UNICODE_STRING*,DEVICE_TYPE,ULONG,BOOLEAN,DEVICE_OBJECT**);
NTSTATUS WINAPI IoCreateDriver(UNICODE_STRING*,PDRIVER_INITIALIZE);
More information about the wine-devel
mailing list