advapi32/tests: Fix invalid read in test.
[wine/multimedia.git] / dlls / usbd.sys / usbd.c
blob80fd02e0868b3c1c45ac94026155557361377576
1 /*
2 * Copyright (C) 2010 Damjan Jovanovic
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #include <stdarg.h>
21 #define NONAMELESSUNION
22 #define NONAMELESSSTRUCT
24 #include "ntstatus.h"
25 #define WIN32_NO_STATUS
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winternl.h"
29 #include "ddk/wdm.h"
30 #include "ddk/usb.h"
31 #include "ddk/usbdlib.h"
32 #include "wine/debug.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(usbd);
36 PURB WINAPI USBD_CreateConfigurationRequest(
37 PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor, PUSHORT Siz )
39 URB *urb = NULL;
40 USBD_INTERFACE_LIST_ENTRY *interfaceList;
41 ULONG interfaceListSize;
42 USB_INTERFACE_DESCRIPTOR *interfaceDesc;
43 int i;
45 TRACE( "(%p, %p)\n", ConfigurationDescriptor, Siz );
47 /* http://www.microsoft.com/whdc/archive/usbfaq.mspx
48 * claims USBD_CreateConfigurationRequest doesn't support > 1 interface,
49 * but is this on Windows 98 only or all versions?
52 *Siz = 0;
53 interfaceListSize = (ConfigurationDescriptor->bNumInterfaces + 1) * sizeof(USBD_INTERFACE_LIST_ENTRY);
54 interfaceList = ExAllocatePool( NonPagedPool, interfaceListSize );
55 if (interfaceList)
57 RtlZeroMemory( interfaceList, interfaceListSize );
58 interfaceDesc = (PUSB_INTERFACE_DESCRIPTOR) USBD_ParseDescriptors(
59 ConfigurationDescriptor, ConfigurationDescriptor->wTotalLength,
60 ConfigurationDescriptor, USB_INTERFACE_DESCRIPTOR_TYPE );
61 for (i = 0; i < ConfigurationDescriptor->bNumInterfaces && interfaceDesc != NULL; i++)
63 interfaceList[i].InterfaceDescriptor = interfaceDesc;
64 interfaceDesc = (PUSB_INTERFACE_DESCRIPTOR) USBD_ParseDescriptors(
65 ConfigurationDescriptor, ConfigurationDescriptor->wTotalLength,
66 interfaceDesc + 1, USB_INTERFACE_DESCRIPTOR_TYPE );
68 urb = USBD_CreateConfigurationRequestEx( ConfigurationDescriptor, interfaceList );
69 if (urb)
70 *Siz = urb->u.UrbHeader.Length;
71 ExFreePool( interfaceList );
73 return urb;
76 PURB WINAPI USBD_CreateConfigurationRequestEx(
77 PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
78 PUSBD_INTERFACE_LIST_ENTRY InterfaceList )
80 URB *urb;
81 ULONG size = 0;
82 USBD_INTERFACE_LIST_ENTRY *interfaceEntry;
83 ULONG interfaceCount = 0;
85 TRACE( "(%p, %p)\n", ConfigurationDescriptor, InterfaceList );
87 size = sizeof(struct _URB_SELECT_CONFIGURATION);
88 for (interfaceEntry = InterfaceList; interfaceEntry->InterfaceDescriptor; interfaceEntry++)
90 ++interfaceCount;
91 size += (interfaceEntry->InterfaceDescriptor->bNumEndpoints - 1) *
92 sizeof(USBD_PIPE_INFORMATION);
94 size += (interfaceCount - 1) * sizeof(USBD_INTERFACE_INFORMATION);
96 urb = ExAllocatePool( NonPagedPool, size );
97 if (urb)
99 USBD_INTERFACE_INFORMATION *interfaceInfo;
101 RtlZeroMemory( urb, size );
102 urb->u.UrbSelectConfiguration.Hdr.Length = size;
103 urb->u.UrbSelectConfiguration.Hdr.Function = URB_FUNCTION_SELECT_CONFIGURATION;
104 urb->u.UrbSelectConfiguration.ConfigurationDescriptor = ConfigurationDescriptor;
105 interfaceInfo = &urb->u.UrbSelectConfiguration.Interface;
106 for (interfaceEntry = InterfaceList; interfaceEntry->InterfaceDescriptor; interfaceEntry++)
108 int i;
109 USB_INTERFACE_DESCRIPTOR *currentInterface;
110 USB_ENDPOINT_DESCRIPTOR *endpointDescriptor;
111 interfaceInfo->InterfaceNumber = interfaceEntry->InterfaceDescriptor->bInterfaceNumber;
112 interfaceInfo->AlternateSetting = interfaceEntry->InterfaceDescriptor->bAlternateSetting;
113 interfaceInfo->Class = interfaceEntry->InterfaceDescriptor->bInterfaceClass;
114 interfaceInfo->SubClass = interfaceEntry->InterfaceDescriptor->bInterfaceSubClass;
115 interfaceInfo->Protocol = interfaceEntry->InterfaceDescriptor->bInterfaceProtocol;
116 interfaceInfo->NumberOfPipes = interfaceEntry->InterfaceDescriptor->bNumEndpoints;
117 currentInterface = USBD_ParseConfigurationDescriptorEx(
118 ConfigurationDescriptor, ConfigurationDescriptor,
119 interfaceEntry->InterfaceDescriptor->bInterfaceNumber, -1, -1, -1, -1 );
120 endpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR) USBD_ParseDescriptors(
121 ConfigurationDescriptor, ConfigurationDescriptor->wTotalLength,
122 currentInterface, USB_ENDPOINT_DESCRIPTOR_TYPE );
123 for (i = 0; i < interfaceInfo->NumberOfPipes && endpointDescriptor; i++)
125 interfaceInfo->Pipes[i].MaximumPacketSize = endpointDescriptor->wMaxPacketSize;
126 interfaceInfo->Pipes[i].EndpointAddress = endpointDescriptor->bEndpointAddress;
127 interfaceInfo->Pipes[i].Interval = endpointDescriptor->bInterval;
128 switch (endpointDescriptor->bmAttributes & USB_ENDPOINT_TYPE_MASK)
130 case USB_ENDPOINT_TYPE_CONTROL:
131 interfaceInfo->Pipes[i].PipeType = UsbdPipeTypeControl;
132 break;
133 case USB_ENDPOINT_TYPE_BULK:
134 interfaceInfo->Pipes[i].PipeType = UsbdPipeTypeBulk;
135 break;
136 case USB_ENDPOINT_TYPE_INTERRUPT:
137 interfaceInfo->Pipes[i].PipeType = UsbdPipeTypeInterrupt;
138 break;
139 case USB_ENDPOINT_TYPE_ISOCHRONOUS:
140 interfaceInfo->Pipes[i].PipeType = UsbdPipeTypeIsochronous;
141 break;
143 endpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR) USBD_ParseDescriptors(
144 ConfigurationDescriptor, ConfigurationDescriptor->wTotalLength,
145 endpointDescriptor + 1, USB_ENDPOINT_DESCRIPTOR_TYPE );
147 interfaceInfo->Length = sizeof(USBD_INTERFACE_INFORMATION) +
148 (i - 1) * sizeof(USBD_PIPE_INFORMATION);
149 interfaceEntry->Interface = interfaceInfo;
150 interfaceInfo = (USBD_INTERFACE_INFORMATION*)(((char*)interfaceInfo)+interfaceInfo->Length);
153 return urb;
156 VOID WINAPI USBD_GetUSBDIVersion(
157 PUSBD_VERSION_INFORMATION VersionInformation )
159 TRACE( "(%p)\n", VersionInformation );
160 /* Emulate Windows 2000 (= 0x300) for now */
161 VersionInformation->USBDI_Version = 0x300;
162 VersionInformation->Supported_USB_Version = 0x200;
165 PUSB_INTERFACE_DESCRIPTOR WINAPI USBD_ParseConfigurationDescriptorEx(
166 PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
167 PVOID StartPosition, LONG InterfaceNumber,
168 LONG AlternateSetting, LONG InterfaceClass,
169 LONG InterfaceSubClass, LONG InterfaceProtocol )
171 /* http://blogs.msdn.com/usbcoreblog/archive/2009/12/12/
172 * what-is-the-right-way-to-validate-and-parse-configuration-descriptors.aspx
175 PUSB_INTERFACE_DESCRIPTOR interface;
177 TRACE( "(%p, %p, %d, %d, %d, %d, %d)\n", ConfigurationDescriptor,
178 StartPosition, InterfaceNumber, AlternateSetting,
179 InterfaceClass, InterfaceSubClass, InterfaceProtocol );
181 interface = (PUSB_INTERFACE_DESCRIPTOR) USBD_ParseDescriptors(
182 ConfigurationDescriptor, ConfigurationDescriptor->wTotalLength,
183 StartPosition, USB_INTERFACE_DESCRIPTOR_TYPE );
184 while (interface != NULL)
186 if ((InterfaceNumber == -1 || interface->bInterfaceNumber == InterfaceNumber) &&
187 (AlternateSetting == -1 || interface->bAlternateSetting == AlternateSetting) &&
188 (InterfaceClass == -1 || interface->bInterfaceClass == InterfaceClass) &&
189 (InterfaceSubClass == -1 || interface->bInterfaceSubClass == InterfaceSubClass) &&
190 (InterfaceProtocol == -1 || interface->bInterfaceProtocol == InterfaceProtocol))
192 return interface;
194 interface = (PUSB_INTERFACE_DESCRIPTOR) USBD_ParseDescriptors(
195 ConfigurationDescriptor, ConfigurationDescriptor->wTotalLength,
196 interface + 1, USB_INTERFACE_DESCRIPTOR_TYPE );
198 return NULL;
201 PUSB_COMMON_DESCRIPTOR WINAPI USBD_ParseDescriptors(
202 PVOID DescriptorBuffer,
203 ULONG TotalLength,
204 PVOID StartPosition,
205 LONG DescriptorType )
207 PUSB_COMMON_DESCRIPTOR common;
209 TRACE( "(%p, %u, %p, %d)\n", DescriptorBuffer, TotalLength, StartPosition, DescriptorType );
211 for (common = (PUSB_COMMON_DESCRIPTOR)DescriptorBuffer;
212 ((char*)common) + sizeof(USB_COMMON_DESCRIPTOR) <= ((char*)DescriptorBuffer) + TotalLength;
213 common = (PUSB_COMMON_DESCRIPTOR)(((char*)common) + common->bLength))
215 if (StartPosition <= (PVOID)common && common->bDescriptorType == DescriptorType)
216 return common;
218 return NULL;
221 ULONG WINAPI USBD_GetInterfaceLength(
222 PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor,
223 PUCHAR BufferEnd )
225 PUSB_COMMON_DESCRIPTOR common;
226 ULONG total = InterfaceDescriptor->bLength;
228 TRACE( "(%p, %p)\n", InterfaceDescriptor, BufferEnd );
230 for (common = (PUSB_COMMON_DESCRIPTOR)(InterfaceDescriptor + 1);
231 (((PUCHAR)common) + sizeof(USB_COMMON_DESCRIPTOR)) <= BufferEnd &&
232 common->bDescriptorType != USB_INTERFACE_DESCRIPTOR_TYPE;
233 common = (PUSB_COMMON_DESCRIPTOR)(((char*)common) + common->bLength))
235 total += common->bLength;
237 return total;
240 NTSTATUS WINAPI DriverEntry( DRIVER_OBJECT *driver, UNICODE_STRING *path )
242 TRACE( "(%p, %s)\n", driver, debugstr_w(path->Buffer) );
243 return STATUS_SUCCESS;