[CMAKE]
[reactos.git] / drivers / usb / nt4compat / usbdriver / gendrv.c
1 /**
2 * gendrv.c - USB driver stack project for Windows NT 4.0
3 *
4 * Copyright (c) 2002-2004 Zhiming mypublic99@yahoo.com
5 *
6 * This program/include file is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as published
8 * by the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program/include file is distributed in the hope that it will be
12 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
13 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program (in the main directory of the distribution, the file
18 * COPYING); if not, write to the Free Software Foundation,Inc., 59 Temple
19 * Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22 //this driver is part of the dev manager responsible to manage non-driver device
23 #include "usbdriver.h"
24 #include "gendrv.h"
25
26 #define if_dev( dev_obj ) \
27 ( ( ( ( PGENDRV_DEVICE_EXTENSION)dev_obj->DeviceExtension )->pdriver->driver_desc.flags & USB_DRIVER_FLAG_IF_CAPABLE ) != 0 )
28
29 #define GENDRV_EXIT_DISPATCH( dev_OBJ, staTUS, iRp ) \
30 {\
31 iRp->IoStatus.Status = staTUS;\
32 if( staTUS != STATUS_PENDING)\
33 {\
34 IoCompleteRequest( iRp, IO_NO_INCREMENT);\
35 return staTUS;\
36 }\
37 IoMarkIrpPending( iRp );\
38 IoStartPacket( dev_OBJ, iRp, NULL, gendrv_cancel_queued_irp ); \
39 return STATUS_PENDING;\
40 }
41
42 #define GENDRV_COMPLETE_START_IO( dev_OBJ, staTUS, iRP ) \
43 {\
44 iRP->IoStatus.Status = staTUS;\
45 if( staTUS != STATUS_PENDING )\
46 {\
47 IoStartNextPacket( dev_OBJ, TRUE );\
48 IoCompleteRequest( iRP, IO_NO_INCREMENT );\
49 }\
50 return;\
51 }
52
53 extern POBJECT_TYPE NTSYSAPI IoDriverObjectType;
54
55 extern VOID disp_urb_completion(PURB purb, PVOID context);
56
57
58 VOID disp_noio_urb_completion(PURB purb, PVOID context);
59
60 NTSYSAPI NTSTATUS NTAPI ZwLoadDriver(IN PUNICODE_STRING DriverServiceName);
61
62 NTSYSAPI NTSTATUS NTAPI ZwClose(IN HANDLE Handle);
63
64 NTSYSAPI
65 NTSTATUS
66 NTAPI
67 ObOpenObjectByName(IN POBJECT_ATTRIBUTES ObjectAttributes,
68 IN POBJECT_TYPE ObjectType OPTIONAL,
69 IN KPROCESSOR_MODE AccessMode,
70 IN OUT PACCESS_STATE AccessState OPTIONAL,
71 IN ACCESS_MASK DesiredAccess OPTIONAL,
72 IN OUT PVOID ParseContext OPTIONAL, OUT PHANDLE Handle);
73
74 BOOLEAN gendrv_if_driver_destroy(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver);
75
76 VOID gendrv_set_cfg_completion(PURB purb, PVOID context);
77
78 BOOLEAN gendrv_connect(PDEV_CONNECT_DATA param, DEV_HANDLE dev_handle);
79
80 BOOLEAN gendrv_stop(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle);
81
82 BOOLEAN gendrv_disconnect(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle);
83
84 VOID gendrv_startio(IN PDEVICE_OBJECT dev_obj, IN PIRP irp);
85
86 VOID NTAPI gendrv_cancel_queued_irp(PDEVICE_OBJECT pdev_obj, PIRP pirp);
87
88 VOID gendrv_release_ext_drvr_entry(PGENDRV_DRVR_EXTENSION pdrvr_ext, PGENDRV_EXT_DRVR_ENTRY pentry);
89
90 VOID gendrv_clean_up_queued_irps(PDEVICE_OBJECT dev_obj);
91
92 PGENDRV_EXT_DRVR_ENTRY gendrv_alloc_ext_drvr_entry(PGENDRV_DRVR_EXTENSION pdrvr_ext);
93
94 PDRIVER_OBJECT gendrv_open_ext_driver(PUNICODE_STRING unicode_string);
95
96 NTSTATUS
97 gendrv_get_key_value(IN HANDLE KeyHandle, IN PWSTR ValueName, OUT PKEY_VALUE_FULL_INFORMATION * Information);
98
99 NTSTATUS
100 gendrv_open_reg_key(OUT PHANDLE handle,
101 IN HANDLE base_handle OPTIONAL,
102 IN PUNICODE_STRING keyname, IN ACCESS_MASK desired_access, IN BOOLEAN create);
103
104 BOOLEAN gendrv_do_disconnect(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE if_handle, BOOLEAN is_if);
105
106 BOOLEAN gendrv_do_stop(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle, BOOLEAN is_if);
107
108 NTSTATUS gendrv_send_pnp_msg(ULONG msg, PDEVICE_OBJECT pdev_obj, PVOID pctx);
109
110 BOOLEAN gendrv_delete_device(PUSB_DEV_MANAGER dev_mgr, PDEVICE_OBJECT dev_obj);
111
112 PDEVICE_OBJECT gendrv_create_device(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER gen_drvr, DEV_HANDLE dev_handle);
113
114 PDRIVER_OBJECT gendrv_load_ext_drvr(PGENDRV_DRVR_EXTENSION pdrvr_ext, PUSB_DESC_HEADER pdesc);
115
116 PDRIVER_OBJECT gendrv_find_drvr_by_key(PGENDRV_DRVR_EXTENSION pdrvr_ext, ULONG key);
117
118 ULONG gendrv_make_key(PUSB_DESC_HEADER pdesc);
119
120 BOOLEAN
121 gendrv_driver_init(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver)
122 {
123 PGENDRV_DRVR_EXTENSION pdrvr_ext;
124
125 if (dev_mgr == NULL || pdriver == NULL)
126 return FALSE;
127
128 pdriver->driver_desc.flags = USB_DRIVER_FLAG_DEV_CAPABLE;
129 pdriver->driver_desc.vendor_id = 0xffff; // USB Vendor ID
130 pdriver->driver_desc.product_id = 0xffff; // USB Product ID.
131 pdriver->driver_desc.release_num = 0x100; // Release Number of Device
132
133 pdriver->driver_desc.config_val = 0; // Configuration Value
134 pdriver->driver_desc.if_num = 0; // Interface Number
135 pdriver->driver_desc.if_class = 0xff; // Interface Class
136 pdriver->driver_desc.if_sub_class = 0xff; // Interface SubClass
137 pdriver->driver_desc.if_protocol = 0xff; // Interface Protocol
138
139 pdriver->driver_desc.driver_name = "USB generic dev driver"; // Driver name for Name Registry
140 pdriver->driver_desc.dev_class = USB_CLASS_VENDOR_SPEC;
141 pdriver->driver_desc.dev_sub_class = 0; // Device Subclass
142 pdriver->driver_desc.dev_protocol = 0; // Protocol Info.
143
144 pdriver->driver_ext = usb_alloc_mem(NonPagedPool, sizeof(GENDRV_DRVR_EXTENSION));
145 if (!pdriver->driver_ext)
146 {
147 usb_dbg_print(DBGLVL_MAXIMUM, ("gendrv_driver_init(): memory allocation failed!\n"));
148 return FALSE;
149 }
150
151 pdriver->driver_ext_size = sizeof(GENDRV_DRVR_EXTENSION);
152
153 RtlZeroMemory(pdriver->driver_ext, pdriver->driver_ext_size);
154 pdrvr_ext = (PGENDRV_DRVR_EXTENSION) pdriver->driver_ext;
155
156 // InitializeListHead( &pdrvr_ext->dev_list );
157 InitializeListHead(&pdrvr_ext->ext_drvr_list);
158 pdrvr_ext->ext_drvr_count = 0;
159 ExInitializeFastMutex(&pdrvr_ext->drvr_ext_mutex);
160
161 pdriver->disp_tbl.version = 1;
162 pdriver->disp_tbl.dev_connect = gendrv_connect;
163 pdriver->disp_tbl.dev_disconnect = gendrv_disconnect;
164 pdriver->disp_tbl.dev_stop = gendrv_stop;
165 pdriver->disp_tbl.dev_reserved = NULL;
166
167 return TRUE;
168 }
169
170 BOOLEAN
171 gendrv_driver_destroy(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver)
172 {
173 return gendrv_if_driver_destroy(dev_mgr, pdriver);
174 }
175
176 BOOLEAN
177 gendrv_connect(PDEV_CONNECT_DATA param, DEV_HANDLE dev_handle)
178 {
179 PURB purb;
180 PUSB_CTRL_SETUP_PACKET psetup;
181 NTSTATUS status;
182 PUCHAR buf;
183 LONG i;
184 PUSB_CONFIGURATION_DESC pconfig_desc;
185 PUSB_DEV_MANAGER dev_mgr;
186
187 if (param == NULL || dev_handle == 0)
188 return FALSE;
189
190 dev_mgr = param->dev_mgr;
191
192 // let's set the configuration
193 purb = usb_alloc_mem(NonPagedPool, sizeof(URB));
194 if (purb == NULL)
195 return FALSE;
196
197 buf = usb_alloc_mem(NonPagedPool, 512);
198 if (buf == NULL)
199 {
200 usb_dbg_print(DBGLVL_MAXIMUM, ("gendrv_connect(): can not alloc buf\n"));
201 usb_free_mem(purb);
202 return FALSE;
203 }
204
205 // before we set the configuration, let's search to find if there
206 // exist interfaces we supported
207 psetup = (PUSB_CTRL_SETUP_PACKET) (purb)->setup_packet;
208 urb_init((purb));
209 purb->endp_handle = dev_handle | 0xffff;
210 purb->data_buffer = buf;
211 purb->data_length = 512;
212 purb->completion = NULL; // this is an immediate request, no completion required
213 purb->context = NULL;
214 purb->reference = 0;
215 psetup->bmRequestType = 0x80;
216 psetup->bRequest = USB_REQ_GET_DESCRIPTOR;
217 psetup->wValue = USB_DT_CONFIG << 8;
218 psetup->wIndex = 0;
219 psetup->wLength = 512;
220
221 status = usb_submit_urb(dev_mgr, purb);
222 if (status == STATUS_PENDING)
223 {
224 TRAP();
225 usb_free_mem(buf);
226 usb_free_mem(purb);
227 return FALSE;
228 }
229
230 // check the config desc valid
231 pconfig_desc = (PUSB_CONFIGURATION_DESC) buf;
232 if (pconfig_desc->wTotalLength > 512)
233 {
234 usb_free_mem(buf);
235 usb_free_mem(purb);
236 usb_dbg_print(DBGLVL_MAXIMUM, ("gendrv_connect(): error, bad configuration desc\n"));
237 return FALSE;
238 }
239
240 i = pconfig_desc->bConfigurationValue;
241 usb_free_mem(buf);
242 buf = NULL;
243
244 //set the configuration
245 urb_init(purb);
246 purb->endp_handle = dev_handle | 0xffff;
247 purb->data_buffer = NULL;
248 purb->data_length = 0;
249 purb->completion = gendrv_set_cfg_completion;
250 purb->context = dev_mgr;
251 purb->reference = (ULONG) param->pdriver;
252 psetup->bmRequestType = 0;
253 psetup->bRequest = USB_REQ_SET_CONFIGURATION;
254 psetup->wValue = (USHORT) i;
255 psetup->wIndex = 0;
256 psetup->wLength = 0;
257
258 usb_dbg_print(DBGLVL_MAXIMUM, ("gendrv_connect(): start config the device, cfgval=%d\n", i));
259 status = usb_submit_urb(dev_mgr, purb);
260
261 if (status != STATUS_PENDING)
262 {
263 usb_free_mem(purb);
264
265 if (status == STATUS_SUCCESS)
266 return TRUE;
267
268 return FALSE;
269 }
270
271 return TRUE;
272 }
273
274 BOOLEAN
275 gendrv_event_select_driver(PUSB_DEV pdev, //always null. we do not use this param
276 ULONG event, ULONG context, ULONG param)
277 {
278 //
279 // try to search the registry to find one driver.
280 // if found, create the PDO, load the driver.
281 // and call its AddDevice.
282 //
283 LONG i;
284 PUSB_DRIVER pdrvr;
285 PGENDRV_DRVR_EXTENSION pdrvr_ext;
286 PGENDRV_EXT_DRVR_ENTRY pentry;
287 PGENDRV_DEVICE_EXTENSION pdev_ext;
288 PUSB_CONFIGURATION_DESC pconfig_desc;
289 PUSB_DEV_MANAGER dev_mgr;
290
291 PDEVICE_OBJECT pdev_obj;
292 PDRIVER_OBJECT pdrvr_obj;
293 PLIST_ENTRY pthis, pnext;
294
295 USE_BASIC_NON_PENDING_IRQL;
296
297 UNREFERENCED_PARAMETER(context);
298 UNREFERENCED_PARAMETER(event);
299
300 if (pdev == NULL)
301 return FALSE;
302
303 usb_dbg_print(DBGLVL_MAXIMUM, ("gendrv_event_select_driver(): entering...\n"));
304
305 pdrvr = (PUSB_DRIVER) param;
306 //original code: pconfig_desc = (PUSB_CONFIGURATION_DESC) pdev->desc_buf[sizeof(USB_DEVICE_DESC)];
307 pconfig_desc = (PUSB_CONFIGURATION_DESC) &pdev->desc_buf[sizeof(USB_DEVICE_DESC)];
308 pdrvr_ext = (PGENDRV_DRVR_EXTENSION) pdrvr->driver_ext;
309
310 //
311 // well, let's do the hard work to see if there is a class driver
312 // for this device.
313 // in the event routine, we have no need to check if the device is zomb or
314 // not, it must be alive there.
315 //
316 i = gendrv_make_key((PUSB_DESC_HEADER) pdev->pusb_dev_desc);
317 if (i == -1)
318 {
319 return FALSE;
320 }
321
322 pdrvr_obj = gendrv_find_drvr_by_key(pdrvr_ext, (ULONG) i);
323 if (!pdrvr_obj)
324 {
325 if ((pdrvr_obj = gendrv_load_ext_drvr(pdrvr_ext, (PUSB_DESC_HEADER) pdev->pusb_dev_desc)) == NULL)
326 return FALSE;
327 }
328
329 dev_mgr = dev_mgr_from_dev(pdev);
330 pdev_obj = gendrv_create_device(dev_mgr, pdrvr, usb_make_handle(pdev->dev_id, 0, 0));
331 if (pdev_obj == NULL)
332 {
333 goto ERROR_OUT;
334 }
335
336 lock_dev(pdev, FALSE);
337 if (dev_state(pdev) == USB_DEV_STATE_ZOMB ||
338 dev_mgr_set_driver(dev_mgr, usb_make_handle(pdev->dev_id, 0, 0), pdrvr, pdev) == FALSE)
339 {
340 unlock_dev(pdev, FALSE);
341 gendrv_delete_device(dev_mgr, pdev_obj);
342 goto ERROR_OUT;
343 }
344
345 if (pdev->usb_config)
346 {
347 pdev->dev_obj = pdev_obj;
348 }
349
350 unlock_dev(pdev, FALSE);
351
352 pdev_ext = (PGENDRV_DEVICE_EXTENSION) pdev_obj->DeviceExtension;
353 pdev_ext->desc_buf = usb_alloc_mem(NonPagedPool, 512);
354 if (!pdev_ext->desc_buf)
355 {
356 usb_dbg_print(DBGLVL_MAXIMUM, ("gendrv_event_select_driver(): memory allocation failed!\n"));
357 goto ERROR_OUT;
358 }
359
360 RtlCopyMemory(pdev_ext->desc_buf, pconfig_desc, 512);
361
362 // insert the device to the dev_list
363 ExAcquireFastMutex(&pdrvr_ext->drvr_ext_mutex);
364 ListFirst(&pdrvr_ext->ext_drvr_list, pthis);
365 pentry = NULL;
366 while (pthis)
367 {
368 pentry = (PGENDRV_EXT_DRVR_ENTRY) pthis;
369 if (pentry->pext_drvr == pdrvr_obj)
370 break;
371 ListNext(&pdrvr_ext->ext_drvr_list, pthis, pnext);
372 pthis = pnext;
373 pentry = NULL;
374 }
375 ASSERT(pentry);
376 InsertTailList(&pentry->dev_list, &pdev_ext->dev_obj_link);
377 pdev_ext->ext_drvr_entry = pentry;
378 pentry->ref_count++;
379 ExReleaseFastMutex(&pdrvr_ext->drvr_ext_mutex);
380
381 // notify the class driver, some device comes
382 gendrv_send_pnp_msg(GENDRV_MSG_ADDDEVICE, pdev_obj, pdrvr_obj);
383 usb_unlock_dev(pdev);
384 return TRUE;
385
386 ERROR_OUT:
387
388 usb_unlock_dev(pdev);
389 return FALSE;
390 }
391
392 VOID
393 gendrv_set_cfg_completion(PURB purb, PVOID context)
394 {
395 DEV_HANDLE dev_handle;
396 PUSB_DEV_MANAGER dev_mgr;
397 PUSB_DRIVER pdriver;
398 NTSTATUS status;
399 PUSB_DEV pdev;
400 PUSB_EVENT pevent;
401 USE_BASIC_NON_PENDING_IRQL;
402
403 if (purb == NULL || context == NULL)
404 return;
405
406 dev_handle = purb->endp_handle & ~0xffff;
407 dev_mgr = (PUSB_DEV_MANAGER) context;
408 pdriver = (PUSB_DRIVER) purb->reference;
409
410 if (purb->status != STATUS_SUCCESS)
411 {
412 usb_free_mem(purb);
413 return;
414 }
415
416 usb_free_mem(purb);
417 purb = NULL;
418
419 // set the dev state
420 status = usb_query_and_lock_dev(dev_mgr, dev_handle, &pdev);
421 if (status != STATUS_SUCCESS)
422 {
423 usb_unlock_dev(pdev);
424 return;
425 }
426 usb_unlock_dev(pdev); // safe to release the pdev ref since we are in urb completion
427
428
429 KeAcquireSpinLockAtDpcLevel(&dev_mgr->event_list_lock);
430 lock_dev(pdev, TRUE);
431
432 if (dev_state(pdev) >= USB_DEV_STATE_BEFORE_ZOMB)
433 {
434 unlock_dev(pdev, TRUE);
435 KeReleaseSpinLockFromDpcLevel(&dev_mgr->event_list_lock);
436 return;
437 }
438
439 if (dev_mgr_set_driver(dev_mgr, dev_handle, pdriver, pdev) == FALSE)
440 {
441 unlock_dev(pdev, TRUE);
442 KeReleaseSpinLockFromDpcLevel(&dev_mgr->event_list_lock);
443 return;
444 }
445
446 //transit the state to configured
447 pdev->flags &= ~USB_DEV_STATE_MASK;
448 pdev->flags |= USB_DEV_STATE_CONFIGURED;
449
450 pevent = alloc_event(&dev_mgr->event_pool, 1);
451 if (pevent == NULL)
452 {
453 unlock_dev(pdev, TRUE);
454 KeReleaseSpinLockFromDpcLevel(&dev_mgr->event_list_lock);
455 return;
456 }
457
458 pevent->flags = USB_EVENT_FLAG_ACTIVE;
459 pevent->event = USB_EVENT_DEFAULT;
460 pevent->pdev = pdev;
461 pevent->context = 0;
462 pevent->param = (ULONG) pdriver;
463 pevent->pnext = 0; //vertical queue for serialized operation
464 pevent->process_event = (PROCESS_EVENT) gendrv_event_select_driver;
465 pevent->process_queue = event_list_default_process_queue;
466
467 InsertTailList(&dev_mgr->event_list, &pevent->event_link);
468 KeSetEvent(&dev_mgr->wake_up_event, 0, FALSE);
469 unlock_dev(pdev, TRUE);
470 KeReleaseSpinLockFromDpcLevel(&dev_mgr->event_list_lock);
471
472 return;
473 }
474
475
476 BOOLEAN
477 gendrv_stop(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle)
478 {
479 if (dev_mgr == NULL)
480 return FALSE;
481 return gendrv_do_stop(dev_mgr, dev_handle, FALSE);
482 }
483
484 BOOLEAN
485 gendrv_disconnect(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle)
486 {
487 if (dev_mgr == NULL)
488 return FALSE;
489 return gendrv_do_disconnect(dev_mgr, dev_handle, FALSE);
490 }
491
492 BOOLEAN
493 gendrv_build_reg_string(PUSB_DESC_HEADER pdesc, PUNICODE_STRING pus)
494 {
495
496 CHAR desc_str[128];
497 STRING atemp;
498
499 if (pdesc == NULL || pus == NULL)
500 return FALSE;
501
502 if (pdesc->bDescriptorType == USB_DT_DEVICE)
503 {
504 PUSB_DEVICE_DESC pdev_desc;
505 pdev_desc = (PUSB_DEVICE_DESC) pdesc;
506 sprintf(desc_str, "%sv_%04x&p_%04x",
507 "\\Registry\\Machine\\System\\CurrentControlSet\\Services\\ehci\\device\\",
508 pdev_desc->idVendor, pdev_desc->idProduct);
509 }
510 else if (pdesc->bDescriptorType == USB_DT_INTERFACE)
511 {
512 PUSB_INTERFACE_DESC pif_desc;
513 pif_desc = (PUSB_INTERFACE_DESC) pdesc;
514 sprintf(desc_str, "%sc_%04x&s_%04x&p_%04x",
515 "\\Registry\\Machine\\System\\CurrentControlSet\\Services\\ehci\\interface\\",
516 pif_desc->bInterfaceClass, pif_desc->bInterfaceSubClass, pif_desc->bInterfaceProtocol);
517 }
518 else
519 return FALSE;
520
521 RtlInitString(&atemp, desc_str);
522 RtlAnsiStringToUnicodeString(pus, &atemp, TRUE);
523 return TRUE;
524 }
525
526 ULONG
527 gendrv_make_key(PUSB_DESC_HEADER pdesc)
528 {
529 PUSB_DEVICE_DESC pdev_desc;
530 PUSB_INTERFACE_DESC pif_desc;
531
532 if (pdesc == NULL)
533 return (ULONG) - 1;
534 if (pdesc->bDescriptorType == USB_DT_DEVICE)
535 {
536 pdev_desc = (PUSB_DEVICE_DESC) pdesc;
537 return ((((ULONG) pdev_desc->idVendor) << 16) | pdev_desc->idProduct);
538 }
539 else if (pdesc->bDescriptorType == USB_DT_INTERFACE)
540 {
541 pif_desc = (PUSB_INTERFACE_DESC) pdesc;
542 return ((((ULONG) pif_desc->bInterfaceClass) << 16) |
543 (((ULONG) pif_desc->bInterfaceSubClass) << 8) | ((ULONG) pif_desc->bInterfaceProtocol));
544 }
545 return (ULONG) - 1;
546 }
547
548 PDRIVER_OBJECT
549 gendrv_find_drvr_by_key(PGENDRV_DRVR_EXTENSION pdrvr_ext, ULONG key)
550 {
551 PGENDRV_EXT_DRVR_ENTRY pentry;
552 PLIST_ENTRY pthis, pnext;
553 if (pdrvr_ext == NULL || key == (ULONG) - 1)
554 return NULL;
555
556 ExAcquireFastMutex(&pdrvr_ext->drvr_ext_mutex);
557 ListFirst(&pdrvr_ext->ext_drvr_list, pthis);
558 while (pthis)
559 {
560 pentry = (PGENDRV_EXT_DRVR_ENTRY) pthis;
561 if (pentry->drvr_key == key)
562 {
563 ExReleaseFastMutex(&pdrvr_ext->drvr_ext_mutex);
564 return pentry->pext_drvr;
565 }
566 ListNext(&pdrvr_ext->ext_drvr_list, pthis, pnext);
567 pthis = pnext;
568 }
569 ExReleaseFastMutex(&pdrvr_ext->drvr_ext_mutex);
570
571 return NULL;
572 }
573
574 PDRIVER_OBJECT
575 gendrv_load_ext_drvr(PGENDRV_DRVR_EXTENSION pdrvr_ext, PUSB_DESC_HEADER pdesc)
576 {
577 PDRIVER_OBJECT pdrvr_obj;
578 PGENDRV_EXT_DRVR_ENTRY pentry;
579 UNICODE_STRING usz, svc_name, svc_key, utemp;
580 PKEY_VALUE_FULL_INFORMATION val_info;
581 PWCHAR val_buf;
582 HANDLE handle;
583 NTSTATUS status;
584
585 if (pdrvr_ext == NULL || pdesc == NULL)
586 return NULL;
587
588 // try to search and load driver from outside
589 handle = NULL;
590 RtlZeroMemory(&svc_key, sizeof(svc_key));
591 val_info = NULL;
592 RtlInitUnicodeString(&usz, L"");
593 gendrv_build_reg_string(pdesc, &usz);
594 DbgPrint("UHCI: Trying to load driver %wZ\n", &usz);
595 if (gendrv_open_reg_key(&handle, NULL, &usz, KEY_READ, FALSE) != STATUS_SUCCESS)
596 {
597 goto ERROR_OUT;
598 }
599 if (gendrv_get_key_value(handle, L"service", &val_info) != STATUS_SUCCESS)
600 {
601 goto ERROR_OUT;
602 }
603
604 if (val_info->DataLength > 32)
605 goto ERROR_OUT;
606
607 val_buf = (PWCHAR) (((PBYTE) val_info) + val_info->DataOffset);
608 svc_key.Length = 0, svc_key.MaximumLength = 255;
609 svc_key.Buffer = usb_alloc_mem(NonPagedPool, 256);
610
611 RtlInitUnicodeString(&utemp, L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
612 RtlAppendUnicodeStringToString(&svc_key, &utemp);
613 RtlInitUnicodeString(&svc_name, val_buf);
614 RtlAppendUnicodeStringToString(&svc_key, &svc_name);
615
616 status = ZwLoadDriver(&svc_key);
617 if (status != STATUS_SUCCESS)
618 goto ERROR_OUT;
619
620 svc_key.Length = 0;
621 RtlZeroMemory(svc_key.Buffer, 128);
622 RtlInitUnicodeString(&svc_key, L"\\Driver\\");
623 RtlAppendUnicodeStringToString(&svc_key, &svc_name);
624 pdrvr_obj = gendrv_open_ext_driver(&svc_key);
625 if (pdrvr_obj == NULL)
626 goto ERROR_OUT;
627
628 ExAcquireFastMutex(&pdrvr_ext->drvr_ext_mutex);
629
630 // insert the driver to the drvr list
631 pentry = gendrv_alloc_ext_drvr_entry(pdrvr_ext);
632 if (pentry == NULL)
633 {
634 ExReleaseFastMutex(&pdrvr_ext->drvr_ext_mutex);
635 ObDereferenceObject(pdrvr_obj);
636 goto ERROR_OUT;
637 }
638 pentry->pext_drvr = pdrvr_obj;
639 InsertTailList(&pdrvr_ext->ext_drvr_list, &pentry->drvr_link);
640 pdrvr_ext->ext_drvr_count++;
641 ExReleaseFastMutex(&pdrvr_ext->drvr_ext_mutex);
642 ZwClose(handle);
643 return pdrvr_obj;
644
645 ERROR_OUT:
646 RtlFreeUnicodeString(&usz);
647 if (val_info != NULL)
648 {
649 usb_free_mem(val_info);
650 val_info = NULL;
651 }
652 if (svc_key.Buffer)
653 usb_free_mem(svc_key.Buffer);
654
655 if (handle)
656 ZwClose(handle);
657
658 return NULL;
659 }
660
661 VOID
662 gendrv_release_drvr(PGENDRV_DRVR_EXTENSION pdrvr_ext, PDRIVER_OBJECT pdrvr_obj)
663 {
664 PLIST_ENTRY pthis, pnext;
665 PGENDRV_EXT_DRVR_ENTRY pentry;
666
667 if (pdrvr_ext == NULL || pdrvr_obj == NULL)
668 return;
669 ExAcquireFastMutex(&pdrvr_ext->drvr_ext_mutex);
670 ListFirst(&pdrvr_ext->ext_drvr_list, pthis);
671 while (pthis)
672 {
673 pentry = (PGENDRV_EXT_DRVR_ENTRY) pthis;
674 if (pentry->pext_drvr == pdrvr_obj)
675 {
676 ASSERT(pentry->ref_count);
677 ExReleaseFastMutex(&pdrvr_ext->drvr_ext_mutex);
678 return;
679 }
680 ListNext(&pdrvr_ext->ext_drvr_list, pthis, pnext);
681 pthis = pnext;
682 }
683 ExReleaseFastMutex(&pdrvr_ext->drvr_ext_mutex);
684 }
685
686 NTSTATUS
687 gendrv_send_pnp_msg(ULONG msg, PDEVICE_OBJECT pdev_obj, PVOID pctx)
688 {
689 if (pdev_obj == NULL)
690 return STATUS_INVALID_PARAMETER;
691
692 switch (msg)
693 {
694 case GENDRV_MSG_ADDDEVICE:
695 {
696 PDRIVER_OBJECT pdrvr_obj;
697 if (pctx == NULL)
698 return STATUS_INVALID_PARAMETER;
699 pdrvr_obj = (PDRIVER_OBJECT) pctx;
700 if (pdrvr_obj->DriverExtension)
701 {
702 return pdrvr_obj->DriverExtension->AddDevice(pdrvr_obj, pdev_obj);
703 }
704 return STATUS_IO_DEVICE_ERROR;
705 }
706 case GENDRV_MSG_STOPDEVICE:
707 case GENDRV_MSG_DISCDEVICE:
708 {
709 NTSTATUS status;
710 IO_STACK_LOCATION *irpstack;
711 IRP *irp;
712 // IRP_MJ_PNP_POWER
713 irp = IoAllocateIrp(2, FALSE);
714 if (irp == NULL)
715 return STATUS_NO_MEMORY;
716
717 irpstack = IoGetNextIrpStackLocation(irp);
718 irpstack->MajorFunction = IRP_MJ_PNP_POWER;
719 irpstack->MinorFunction =
720 (msg == GENDRV_MSG_STOPDEVICE) ? IRP_MN_STOP_DEVICE : IRP_MN_REMOVE_DEVICE;
721 status = IoCallDriver(pdev_obj, irp);
722 ASSERT(status != STATUS_PENDING);
723 status = irp->IoStatus.Status;
724 IoFreeIrp(irp);
725 return STATUS_MORE_PROCESSING_REQUIRED;
726 }
727 }
728 return STATUS_INVALID_PARAMETER;
729 }
730
731
732 BOOLEAN
733 gendrv_if_connect(PDEV_CONNECT_DATA params, DEV_HANDLE if_handle)
734 {
735 //
736 // try to search the registry to find one driver.
737 // if found, create the PDO, load the driver.
738 // and call its AddDevice.
739 //
740 LONG if_idx, i;
741 NTSTATUS status;
742 PUSB_DEV pdev;
743 PUSB_DRIVER pdrvr;
744 PUSB_INTERFACE_DESC pif_desc;
745 PGENDRV_DEVICE_EXTENSION pdev_ext;
746 PUSB_CONFIGURATION_DESC pconfig_desc;
747 PUSB_DEV_MANAGER dev_mgr;
748 PGENDRV_DRVR_EXTENSION pdrvr_ext;
749 PGENDRV_EXT_DRVR_ENTRY pentry;
750
751 PDEVICE_OBJECT pdev_obj;
752 PDRIVER_OBJECT pdrvr_obj;
753 PLIST_ENTRY pthis, pnext;
754 USE_BASIC_NON_PENDING_IRQL;
755
756 pdev = NULL;
757 usb_dbg_print(DBGLVL_MAXIMUM, ("gendrv_if_connect(): entering...\n"));
758
759 if (params == NULL)
760 return FALSE;
761
762 dev_mgr = params->dev_mgr;
763 pdrvr = params->pdriver;
764 pdrvr_ext = (PGENDRV_DRVR_EXTENSION) pdrvr->driver_ext;
765
766 status = usb_query_and_lock_dev(dev_mgr, if_handle, &pdev);
767 if (status != STATUS_SUCCESS)
768 {
769 goto ERROR_OUT;
770 }
771 // obtain the pointer to the config desc, the dev won't go away in this routine
772 pconfig_desc = pdev->usb_config->pusb_config_desc; //
773 usb_unlock_dev(pdev);
774 pdev = NULL;
775
776 if_idx = if_idx_from_handle(if_handle);
777 pif_desc = (PUSB_INTERFACE_DESC) (&pconfig_desc[1]);
778
779 for(i = 0; i < if_idx; i++)
780 {
781 //search for our if
782 if (usb_skip_if_and_altif((PUCHAR *) & pif_desc) == FALSE)
783 break;
784 }
785 if (pif_desc == NULL)
786 return FALSE;
787
788 //
789 // well, let's do the hard work to see if there is a class driver
790 // for this device.
791 //
792 i = gendrv_make_key((PUSB_DESC_HEADER) pif_desc);
793 if (i == -1)
794 {
795 return FALSE;
796 }
797
798 pdrvr_obj = gendrv_find_drvr_by_key(pdrvr_ext, (ULONG) i);
799 if (!pdrvr_obj)
800 {
801 if ((pdrvr_obj = gendrv_load_ext_drvr(pdrvr_ext, (PUSB_DESC_HEADER) pif_desc)) == NULL)
802 return FALSE;
803 }
804
805
806 pdev_obj = gendrv_create_device(dev_mgr, pdrvr, if_handle);
807 if (pdev_obj == NULL)
808 {
809 goto ERROR_OUT;
810 }
811
812 lock_dev(pdev, FALSE);
813 if (dev_state(pdev) == USB_DEV_STATE_ZOMB ||
814 dev_mgr_set_if_driver(dev_mgr, if_handle, pdrvr, pdev) == FALSE)
815 {
816 unlock_dev(pdev, FALSE);
817 gendrv_delete_device(dev_mgr, pdev_obj);
818 goto ERROR_OUT;
819 }
820
821 if (pdev->usb_config)
822 {
823 pdev->usb_config->interf[if_idx].if_ext = pdev_obj;
824 pdev->usb_config->interf[if_idx].if_ext_size = 0;
825 }
826
827 unlock_dev(pdev, FALSE);
828
829 pdev_ext = (PGENDRV_DEVICE_EXTENSION) pdev_obj->DeviceExtension;
830 pdev_ext->desc_buf = usb_alloc_mem(NonPagedPool, 512);
831 if (!pdev_ext->desc_buf)
832 {
833 usb_dbg_print(DBGLVL_MAXIMUM, ("gendrv_if_connect(): memory allocation failed!\n"));
834 goto ERROR_OUT;
835 }
836
837 RtlCopyMemory(pdev_ext->desc_buf, pconfig_desc, 512);
838 pdev_ext->if_ctx.pif_desc =
839 (PUSB_INTERFACE_DESC) & pdev_ext->desc_buf[(PBYTE) pif_desc - (PBYTE) pconfig_desc];
840
841 // insert the device to the dev_list
842 ExAcquireFastMutex(&pdrvr_ext->drvr_ext_mutex);
843 ListFirst(&pdrvr_ext->ext_drvr_list, pthis);
844 pentry = NULL;
845 while (pthis)
846 {
847 pentry = (PGENDRV_EXT_DRVR_ENTRY) pthis;
848 if (pentry->pext_drvr == pdrvr_obj)
849 break;
850 ListNext(&pdrvr_ext->ext_drvr_list, pthis, pnext);
851 pthis = pnext;
852 pentry = NULL;
853 }
854 ASSERT(pentry);
855 InsertTailList(&pentry->dev_list, &pdev_ext->dev_obj_link);
856 pdev_ext->ext_drvr_entry = pentry;
857 pentry->ref_count++;
858 ExReleaseFastMutex(&pdrvr_ext->drvr_ext_mutex);
859
860 // notify the class driver, some device comes
861 gendrv_send_pnp_msg(GENDRV_MSG_ADDDEVICE, pdev_obj, pdrvr_obj);
862 usb_unlock_dev(pdev);
863 return TRUE;
864
865 ERROR_OUT:
866
867 usb_unlock_dev(pdev);
868 return FALSE;
869 }
870
871 BOOLEAN
872 gendrv_do_stop(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle, BOOLEAN is_if)
873 {
874 PUSB_DEV pdev;
875 PDEVICE_OBJECT pdev_obj;
876 ULONG if_idx;
877
878 if (dev_mgr == NULL)
879 return FALSE;
880
881 // clean up the irps
882 if_idx = if_idx_from_handle(dev_handle);
883 if (usb_query_and_lock_dev(dev_mgr, dev_handle, &pdev) != STATUS_SUCCESS)
884 {
885 return FALSE;
886 }
887 if (is_if && pdev->usb_config)
888 pdev_obj = (PDEVICE_OBJECT) pdev->usb_config->interf[if_idx].if_ext;
889 else
890 pdev_obj = pdev->dev_obj;
891
892 gendrv_clean_up_queued_irps(pdev_obj);
893 usb_unlock_dev(pdev);
894
895 // send message to class drivers.
896 gendrv_send_pnp_msg(GENDRV_MSG_STOPDEVICE, pdev_obj, NULL);
897
898 return TRUE;
899 }
900
901 BOOLEAN
902 gendrv_if_stop(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle)
903 {
904 if (dev_mgr == NULL)
905 return FALSE;
906
907 return gendrv_do_stop(dev_mgr, dev_handle, TRUE);
908 }
909
910 BOOLEAN
911 gendrv_do_disconnect(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE if_handle, BOOLEAN is_if)
912 {
913 PUSB_DEV pdev;
914 PDEVICE_OBJECT dev_obj = NULL;
915 NTSTATUS status;
916 PUSB_DRIVER pdrvr;
917 PGENDRV_DRVR_EXTENSION pdrvr_ext = NULL;
918 PGENDRV_DEVICE_EXTENSION pdev_ext = NULL;
919 ULONG if_idx;
920
921 status = usb_query_and_lock_dev(dev_mgr, if_handle, &pdev);
922 if (pdev == NULL)
923 {
924 return FALSE;
925 }
926 if (status == STATUS_SUCCESS)
927 {
928 // must be a bug
929 TRAP();
930 }
931 if_idx = if_idx_from_handle(if_handle);
932 if (pdev->usb_config)
933 {
934 if (is_if)
935 {
936 pdrvr = pdev->usb_config->interf[if_idx].pif_drv;
937 dev_obj = (PDEVICE_OBJECT) pdev->usb_config->interf[if_idx].if_ext;
938 }
939 else
940 {
941 pdrvr = pdev->dev_driver;
942 dev_obj = pdev->dev_obj;
943 }
944
945 if (dev_obj == NULL)
946 {
947 // it means no driver was found for the device and thus no device object created
948 // we just do nothing here
949 return TRUE;
950 }
951
952 pdrvr_ext = (PGENDRV_DRVR_EXTENSION) pdrvr->driver_ext;
953 pdev_ext = (PGENDRV_DEVICE_EXTENSION) dev_obj->DeviceExtension;
954 }
955 else
956 TRAP();
957 pdev = NULL;
958
959 // remove the device from the list
960 ExAcquireFastMutex(&pdrvr_ext->drvr_ext_mutex);
961 RemoveEntryList(&pdev_ext->dev_obj_link);
962 pdev_ext->ext_drvr_entry->ref_count--;
963 ExReleaseFastMutex(&pdrvr_ext->drvr_ext_mutex);
964
965 // send message to class driver
966 gendrv_send_pnp_msg(GENDRV_MSG_DISCDEVICE, dev_obj, NULL);
967 // delete the device object
968 gendrv_delete_device(dev_mgr, dev_obj);
969 return TRUE;
970 }
971
972 BOOLEAN
973 gendrv_if_disconnect(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE if_handle)
974 {
975 return gendrv_do_disconnect(dev_mgr, if_handle, TRUE);
976 }
977
978 BOOLEAN
979 gendrv_if_driver_init(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver)
980 {
981 PGENDRV_DRVR_EXTENSION pdrvr_ext;
982 if (dev_mgr == NULL || pdriver == NULL)
983 return FALSE;
984
985 pdriver->driver_desc.flags = USB_DRIVER_FLAG_IF_CAPABLE;
986 pdriver->driver_desc.vendor_id = 0x0000; // USB Vendor ID
987 pdriver->driver_desc.product_id = 0x0000; // USB Product ID.
988 pdriver->driver_desc.release_num = 0x100; // Release Number of Device
989
990 pdriver->driver_desc.config_val = 0; // Configuration Value
991 pdriver->driver_desc.if_num = 0; // Interface Number
992 pdriver->driver_desc.if_class = 0x0; // Interface Class
993 pdriver->driver_desc.if_sub_class = 0x0; // Interface SubClass
994 pdriver->driver_desc.if_protocol = 0x0; // Interface Protocol
995
996 pdriver->driver_desc.driver_name = "USB generic interface driver"; // Driver name for Name Registry
997 pdriver->driver_desc.dev_class = 0;
998 pdriver->driver_desc.dev_sub_class = 0; // Device Subclass
999 pdriver->driver_desc.dev_protocol = 0; // Protocol Info.
1000
1001 //we have no extra data sturcture currently
1002
1003 pdriver->disp_tbl.version = 1;
1004 pdriver->disp_tbl.dev_connect = gendrv_if_connect;
1005 pdriver->disp_tbl.dev_disconnect = gendrv_if_disconnect;
1006 pdriver->disp_tbl.dev_stop = gendrv_if_stop;
1007 pdriver->disp_tbl.dev_reserved = NULL;
1008
1009 pdriver->driver_ext = usb_alloc_mem(NonPagedPool, sizeof(GENDRV_DRVR_EXTENSION));
1010 if (!pdriver->driver_ext) return FALSE;
1011
1012 pdriver->driver_ext_size = sizeof(GENDRV_DRVR_EXTENSION);
1013
1014 RtlZeroMemory(pdriver->driver_ext, pdriver->driver_ext_size);
1015 pdrvr_ext = (PGENDRV_DRVR_EXTENSION) pdriver->driver_ext;
1016
1017 // InitializeListHead( &pdrvr_ext->dev_list );
1018 InitializeListHead(&pdrvr_ext->ext_drvr_list);
1019 pdrvr_ext->ext_drvr_count = 0;
1020 ExInitializeFastMutex(&pdrvr_ext->drvr_ext_mutex);
1021
1022 return TRUE;
1023 }
1024
1025 BOOLEAN
1026 gendrv_if_driver_destroy(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver)
1027 {
1028 PGENDRV_DRVR_EXTENSION pdrvr_ext;
1029 PLIST_ENTRY pthis;
1030 PGENDRV_EXT_DRVR_ENTRY pentry;
1031 if (dev_mgr == NULL || pdriver == NULL)
1032 return FALSE;
1033
1034 if (pdriver->driver_ext)
1035 {
1036 // should we lock it?
1037 // ExAcquireFastMutex( &pdrvr_ext->drvr_ext_mutex );
1038 pdrvr_ext = (PGENDRV_DRVR_EXTENSION) pdriver->driver_ext;
1039 if (pdrvr_ext->ext_drvr_count)
1040 {
1041 while (IsListEmpty(&pdrvr_ext->ext_drvr_list))
1042 {
1043 pthis = RemoveHeadList(&pdrvr_ext->ext_drvr_list);
1044 pentry = (PGENDRV_EXT_DRVR_ENTRY) pthis;
1045 if (pentry->pext_drvr)
1046 {
1047 if (pentry->ref_count)
1048 {
1049 // FIXME: really fail?
1050 continue;
1051 }
1052 ObDereferenceObject(pentry->pext_drvr);
1053 gendrv_release_ext_drvr_entry(pdrvr_ext, pentry);
1054 }
1055 }
1056 pdrvr_ext->ext_drvr_count = 0;
1057 }
1058
1059 usb_free_mem(pdriver->driver_ext);
1060 pdriver->driver_ext = NULL;
1061 pdriver->driver_ext_size = 0;
1062 }
1063 return TRUE;
1064 }
1065
1066 PDRIVER_OBJECT
1067 gendrv_open_ext_driver(PUNICODE_STRING unicode_string)
1068 {
1069 NTSTATUS status;
1070 OBJECT_ATTRIBUTES oa;
1071 HANDLE drvr_handle;
1072 UNICODE_STRING oname;
1073 PDRIVER_OBJECT pdrvr = NULL;
1074
1075 RtlZeroMemory(&oa, sizeof(oa));
1076 oa.Length = sizeof(oa);
1077 oa.ObjectName = &oname;
1078 oa.Attributes = OBJ_CASE_INSENSITIVE;
1079 RtlInitUnicodeString(&oname, L"");
1080 RtlAppendUnicodeStringToString(&oname, unicode_string);
1081
1082 status = ObOpenObjectByName(&oa, IoDriverObjectType, // object type
1083 KernelMode, // access mode
1084 NULL, // access state
1085 FILE_READ_DATA, // STANDARD_RIGHTS_READ, access right
1086 NULL,
1087 &drvr_handle);
1088
1089 if (status != STATUS_SUCCESS)
1090 {
1091 return NULL;
1092 }
1093 ObReferenceObjectByHandle(drvr_handle,
1094 FILE_READ_DATA,
1095 IoDriverObjectType,
1096 KernelMode,
1097 (PVOID)&pdrvr,
1098 NULL); // OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL
1099
1100 ZwClose(drvr_handle);
1101 return pdrvr;
1102 }
1103
1104 BOOLEAN
1105 gendrv_close_ext_driver(PDRIVER_OBJECT pdrvr)
1106 {
1107 if (pdrvr == NULL)
1108 return FALSE;
1109 ObDereferenceObject(pdrvr);
1110 return TRUE;
1111 }
1112
1113 NTSTATUS
1114 gendrv_dispatch(PDEVICE_OBJECT dev_obj, PIRP irp)
1115 {
1116 IO_STACK_LOCATION *irpstack;
1117 PUSB_DEV_MANAGER dev_mgr;
1118 PDEVEXT_HEADER ext_hdr;
1119 NTSTATUS status;
1120
1121 if (dev_obj == NULL || irp == NULL)
1122 return STATUS_INVALID_PARAMETER;
1123
1124 ext_hdr = dev_obj->DeviceExtension;
1125 dev_mgr = ext_hdr->dev_mgr;
1126
1127 irpstack = IoGetNextIrpStackLocation(irp);
1128 switch (irpstack->MajorFunction)
1129 {
1130 case IRP_MJ_PNP_POWER:
1131 {
1132 irp->IoStatus.Information = 0;
1133 GENDRV_EXIT_DISPATCH(dev_obj, STATUS_SUCCESS, irp);
1134 }
1135 case IRP_MJ_INTERNAL_DEVICE_CONTROL:
1136 {
1137 status = STATUS_NOT_SUPPORTED;
1138 if (irpstack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SUBMIT_URB_RD ||
1139 irpstack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SUBMIT_URB_WR ||
1140 irpstack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SUBMIT_URB_NOIO)
1141 {
1142 PURB purb;
1143 DEV_HANDLE endp_handle;
1144 PGENDRV_DEVICE_EXTENSION pdev_ext;
1145
1146 pdev_ext = dev_obj->DeviceExtension;
1147 if (irpstack->Parameters.DeviceIoControl.InputBufferLength < sizeof(URB))
1148 {
1149 GENDRV_EXIT_DISPATCH(dev_obj, STATUS_INVALID_PARAMETER, irp);
1150 }
1151
1152 purb = (PURB) irp->AssociatedIrp.SystemBuffer;
1153 endp_handle = purb->endp_handle;
1154 if (purb->data_buffer == NULL || purb->data_length == 0)
1155 {
1156 if (irpstack->Parameters.DeviceIoControl.IoControlCode != IOCTL_SUBMIT_URB_NOIO)
1157 {
1158 GENDRV_EXIT_DISPATCH(dev_obj, STATUS_INVALID_PARAMETER, irp);
1159 }
1160 }
1161 if (!default_endp_handle(endp_handle))
1162 {
1163 //no permit to other interface if interface dev
1164 if (if_dev(dev_obj) && if_idx_from_handle(endp_handle) != pdev_ext->if_ctx.if_idx)
1165 GENDRV_EXIT_DISPATCH(dev_obj, STATUS_INVALID_PARAMETER, irp);
1166 }
1167
1168 GENDRV_EXIT_DISPATCH(dev_obj, STATUS_PENDING, irp);
1169 }
1170 else if (irpstack->Parameters.DeviceIoControl.IoControlCode == IOCTL_GET_DEV_DESC)
1171 {
1172 // this is a synchronous call, route to dev_mgr_dispatch
1173 return dev_mgr_dispatch(dev_mgr, irp);
1174 }
1175 else if (irpstack->Parameters.DeviceIoControl.IoControlCode == IOCTL_GET_DEV_HANDLE)
1176 {
1177 PGENDRV_DEVICE_EXTENSION pdev_ext;
1178 pdev_ext = dev_obj->DeviceExtension;
1179 if (irpstack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(LONG))
1180 GENDRV_EXIT_DISPATCH(dev_obj, STATUS_INVALID_PARAMETER, irp);
1181
1182 *((PLONG) irp->AssociatedIrp.SystemBuffer) = pdev_ext->dev_handle;
1183 irp->IoStatus.Information = sizeof(LONG);
1184 GENDRV_EXIT_DISPATCH(dev_obj, STATUS_SUCCESS, irp);
1185 }
1186 GENDRV_EXIT_DISPATCH(dev_obj, STATUS_NOT_SUPPORTED, irp);
1187 }
1188 case IRP_MJ_DEVICE_CONTROL:
1189 {
1190 status = STATUS_NOT_SUPPORTED;
1191 if (irpstack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SUBMIT_URB_RD ||
1192 irpstack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SUBMIT_URB_WR ||
1193 irpstack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SUBMIT_URB_NOIO)
1194 {
1195 PURB purb;
1196 DEV_HANDLE endp_handle;
1197 PGENDRV_DEVICE_EXTENSION pdev_ext;
1198
1199 pdev_ext = dev_obj->DeviceExtension;
1200 if (irpstack->Parameters.DeviceIoControl.InputBufferLength < sizeof(URB))
1201 {
1202 GENDRV_EXIT_DISPATCH(dev_obj, STATUS_INVALID_PARAMETER, irp);
1203 }
1204
1205 purb = (PURB) irp->AssociatedIrp.SystemBuffer;
1206 endp_handle = purb->endp_handle;
1207 if (!default_endp_handle(endp_handle))
1208 {
1209 //no permit to other interface if interface dev
1210 if (if_dev(dev_obj) && if_idx_from_handle(endp_handle) != pdev_ext->if_ctx.if_idx)
1211 GENDRV_EXIT_DISPATCH(dev_obj, STATUS_INVALID_PARAMETER, irp);
1212 }
1213
1214 GENDRV_EXIT_DISPATCH(dev_obj, STATUS_PENDING, irp);
1215 }
1216 else if (irpstack->Parameters.DeviceIoControl.IoControlCode == IOCTL_GET_DEV_DESC)
1217 {
1218 // this is a synchronous call, route to dev_mgr_dispatch
1219 return dev_mgr_dispatch(dev_mgr, irp);
1220 }
1221 else if (irpstack->Parameters.DeviceIoControl.IoControlCode == IOCTL_GET_DEV_HANDLE)
1222 {
1223 PGENDRV_DEVICE_EXTENSION pdev_ext;
1224 pdev_ext = dev_obj->DeviceExtension;
1225 if (irpstack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(LONG))
1226 GENDRV_EXIT_DISPATCH(dev_obj, STATUS_INVALID_PARAMETER, irp);
1227
1228 *((PLONG) irp->AssociatedIrp.SystemBuffer) = pdev_ext->dev_handle;
1229 irp->IoStatus.Information = sizeof(LONG);
1230 GENDRV_EXIT_DISPATCH(dev_obj, STATUS_SUCCESS, irp);
1231 }
1232 GENDRV_EXIT_DISPATCH(dev_obj, STATUS_NOT_SUPPORTED, irp);
1233 }
1234 }
1235 irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
1236 irp->IoStatus.Information = 0;
1237 IoCompleteRequest(irp, IO_NO_INCREMENT);
1238
1239 return STATUS_NOT_SUPPORTED;
1240 }
1241
1242 BOOLEAN
1243 gendrv_init_dev_ext_hdr(PDEVICE_OBJECT dev_obj, PUSB_DEV_MANAGER dev_mgr)
1244 {
1245 PDEVEXT_HEADER dev_hdr = NULL;
1246 if (dev_obj == NULL || dev_mgr == NULL)
1247 return FALSE;
1248
1249 dev_hdr = (PDEVEXT_HEADER) dev_obj->DeviceExtension;
1250 dev_hdr->type = NTDEV_TYPE_CLIENT_DEV;
1251 dev_hdr->dispatch = gendrv_dispatch;
1252 dev_hdr->start_io = (PDRIVER_STARTIO) gendrv_startio;
1253 return TRUE;
1254 }
1255
1256 PDEVICE_OBJECT
1257 gendrv_create_device(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER gen_drvr, DEV_HANDLE dev_handle)
1258 {
1259 BOOLEAN is_if;
1260 PDEVICE_OBJECT pdev;
1261 PGENDRV_DEVICE_EXTENSION pdev_ext;
1262 ULONG dev_id;
1263 PGENDRV_DRVR_EXTENSION pdrvr_ext;
1264 CHAR dev_name[64];
1265 STRING string;
1266 UNICODE_STRING name_string, symb_link;
1267 NTSTATUS status;
1268
1269 if (dev_mgr == NULL || gen_drvr == NULL || dev_handle == 0)
1270 return NULL;
1271
1272 is_if = (gen_drvr->driver_desc.flags & USB_DRIVER_FLAG_IF_CAPABLE) ? 1 : 0;
1273 usb_dbg_print(DBGLVL_MAXIMUM, ("gendrv_create_device(): entering...\n"));
1274 pdrvr_ext = (PGENDRV_DRVR_EXTENSION) gen_drvr->driver_ext;
1275 dev_id = (UCHAR) dev_id_from_handle(dev_handle);
1276
1277 if (is_if == FALSE)
1278 sprintf(dev_name, "\\Device\\gendev_%d", (int)dev_id);
1279 else
1280 sprintf(dev_name, "\\Device\\genifdev_%d", (int)dev_id);
1281
1282 RtlInitString(&string, dev_name);
1283 RtlAnsiStringToUnicodeString(&name_string, &string, TRUE);
1284 pdev = NULL;
1285
1286 status = IoCreateDevice(dev_mgr->usb_driver_obj,
1287 sizeof(GENDRV_DEVICE_EXTENSION), &name_string, FILE_USB_DEV_TYPE, 0, TRUE, &pdev);
1288
1289 if (status == STATUS_SUCCESS)
1290 {
1291 //
1292 // We do direct io
1293 //
1294 pdev->Flags |= DO_DIRECT_IO;
1295
1296 pdev->Flags &= ~DO_DEVICE_INITIALIZING;
1297 pdev->StackSize = 2; //one for fdo, one for file device obj
1298
1299 pdev_ext = (PGENDRV_DEVICE_EXTENSION) pdev->DeviceExtension;
1300
1301 //may be accessed by other thread
1302
1303 gendrv_init_dev_ext_hdr(pdev, dev_mgr);
1304
1305 pdev_ext->dev_id = (UCHAR) dev_id;
1306 pdev_ext->pdo = pdev;
1307 pdev_ext->dev_handle = dev_handle;
1308 pdev_ext->dev_mgr = dev_mgr;
1309 pdev_ext->pdriver = gen_drvr;
1310
1311 if (is_if == FALSE)
1312 sprintf(dev_name, "\\DosDevices\\gendev%d", (int)dev_id);
1313 else
1314 sprintf(dev_name, "\\DosDevices\\genifdev%d", (int)dev_id);
1315
1316 RtlInitString(&string, dev_name);
1317 RtlAnsiStringToUnicodeString(&symb_link, &string, TRUE);
1318 IoCreateSymbolicLink(&symb_link, &name_string);
1319 RtlFreeUnicodeString(&symb_link);
1320 KeInitializeEvent(&pdev_ext->sync_event, SynchronizationEvent, FALSE);
1321 KeInitializeSpinLock(&pdev_ext->dev_lock);
1322
1323 }
1324 RtlFreeUnicodeString(&name_string);
1325 return pdev;
1326 }
1327
1328
1329
1330 VOID
1331 gendrv_deferred_delete_device(PVOID context)
1332 {
1333 PDEVICE_OBJECT dev_obj;
1334 PGENDRV_DEVICE_EXTENSION pdev_ext;
1335 PGENDRV_DRVR_EXTENSION pdrvr_ext;
1336 LARGE_INTEGER interval;
1337
1338 if (context == NULL)
1339 return;
1340
1341 dev_obj = (PDEVICE_OBJECT) context;
1342 pdev_ext = dev_obj->DeviceExtension;
1343 pdrvr_ext = (PGENDRV_DRVR_EXTENSION) pdev_ext->pdriver->driver_ext;
1344
1345 interval.QuadPart = -20000; //two ms
1346
1347 for(;;)
1348 {
1349 if (dev_obj->ReferenceCount)
1350 KeDelayExecutionThread(KernelMode, TRUE, &interval);
1351 else
1352 {
1353 KeDelayExecutionThread(KernelMode, TRUE, &interval);
1354 if (dev_obj->ReferenceCount == 0)
1355 break;
1356 }
1357 }
1358 usb_dbg_print(DBGLVL_MAXIMUM, ("gendrv_deferred_delete_device(): delete device, 0x%x\n", dev_obj));
1359
1360 ExAcquireFastMutex(&pdrvr_ext->drvr_ext_mutex);
1361 RemoveEntryList(&pdev_ext->dev_obj_link);
1362 pdev_ext->ext_drvr_entry->ref_count--;
1363 ExReleaseFastMutex(&pdrvr_ext->drvr_ext_mutex);
1364
1365 IoDeleteDevice(dev_obj);
1366 return;
1367 }
1368
1369 BOOLEAN
1370 gendrv_delete_device(PUSB_DEV_MANAGER dev_mgr, PDEVICE_OBJECT dev_obj)
1371 {
1372 BOOLEAN is_if;
1373 PUSB_DRIVER pdrvr;
1374 PGENDRV_DEVICE_EXTENSION pdev_ext;
1375 CHAR dev_name[64];
1376 STRING string;
1377 UNICODE_STRING symb_link;
1378 PGENDRV_DRVR_EXTENSION pdrvr_ext;
1379
1380 if (dev_mgr == NULL || dev_obj == 0)
1381 return FALSE;
1382
1383 pdev_ext = (PGENDRV_DEVICE_EXTENSION) dev_obj->DeviceExtension;
1384 pdrvr = pdev_ext->pdriver;
1385 pdrvr_ext = (PGENDRV_DRVR_EXTENSION) pdrvr->driver_ext;
1386 is_if = (BOOLEAN) if_dev(dev_obj);
1387 if (is_if == FALSE)
1388 sprintf(dev_name, "\\DosDevices\\gendev%d", (int)pdev_ext->dev_id);
1389 else
1390 sprintf(dev_name, "\\DosDevices\\genifdev%d", (int)pdev_ext->dev_id);
1391
1392 RtlInitString(&string, dev_name);
1393 RtlAnsiStringToUnicodeString(&symb_link, &string, TRUE);
1394 IoDeleteSymbolicLink(&symb_link);
1395 RtlFreeUnicodeString(&symb_link);
1396
1397 if (pdev_ext->desc_buf)
1398 {
1399 usb_dbg_print(DBGLVL_MAXIMUM, ("gendrv_delete_device(): delete desc_buf\n"));
1400 usb_free_mem(pdev_ext->desc_buf);
1401 pdev_ext->desc_buf = NULL;
1402
1403 }
1404
1405 if (dev_obj->ReferenceCount == 0)
1406 {
1407 ExAcquireFastMutex(&pdrvr_ext->drvr_ext_mutex);
1408 RemoveEntryList(&pdev_ext->dev_obj_link);
1409 pdev_ext->ext_drvr_entry->ref_count--; //the ext_drvr_entry is actually in pdrvr_ext, so lock it.
1410 ExReleaseFastMutex(&pdrvr_ext->drvr_ext_mutex);
1411
1412 IoDeleteDevice(dev_obj);
1413 return TRUE;
1414 }
1415
1416 // borrow from umss's work routine
1417 return umss_schedule_workitem(dev_obj, gendrv_deferred_delete_device, NULL, 0);
1418 }
1419
1420 // must have the drvr_ext_mutex acquired.
1421 PGENDRV_EXT_DRVR_ENTRY
1422 gendrv_alloc_ext_drvr_entry(PGENDRV_DRVR_EXTENSION pdrvr_ext)
1423 {
1424 LONG i;
1425 if (pdrvr_ext == NULL)
1426 return NULL;
1427 if (pdrvr_ext->ext_drvr_count == GENDRV_MAX_EXT_DRVR)
1428 return NULL;
1429 for(i = 0; i < GENDRV_MAX_EXT_DRVR; i++)
1430 {
1431 if (pdrvr_ext->ext_drvr_array[i].drvr_link.Flink == NULL &&
1432 pdrvr_ext->ext_drvr_array[i].drvr_link.Blink == NULL)
1433 {
1434 return &pdrvr_ext->ext_drvr_array[i];
1435 }
1436 }
1437 return NULL;
1438 }
1439
1440 // must have the drvr_ext_mutex acquired.
1441 VOID
1442 gendrv_release_ext_drvr_entry(PGENDRV_DRVR_EXTENSION pdrvr_ext, PGENDRV_EXT_DRVR_ENTRY pentry)
1443 {
1444 if (pdrvr_ext == NULL || pentry == NULL)
1445 return;
1446 RtlZeroMemory(pentry, sizeof(GENDRV_EXT_DRVR_ENTRY));
1447 InitializeListHead(&pentry->dev_list);
1448 return;
1449 }
1450
1451 NTSTATUS
1452 gendrv_open_reg_key(OUT PHANDLE handle,
1453 IN HANDLE base_handle OPTIONAL,
1454 IN PUNICODE_STRING keyname, IN ACCESS_MASK desired_access, IN BOOLEAN create)
1455 /*++
1456
1457 Routine Description:
1458
1459 Opens or creates a VOLATILE registry key using the name passed in based
1460 at the BaseHandle node.
1461
1462 Arguments:
1463
1464 Handle - Pointer to the handle which will contain the registry key that
1465 was opened.
1466
1467 BaseHandle - Handle to the base path from which the key must be opened.
1468
1469 KeyName - Name of the Key that must be opened/created.
1470
1471 DesiredAccess - Specifies the desired access that the caller needs to
1472 the key.
1473
1474 Create - Determines if the key is to be created if it does not exist.
1475
1476 Return Value:
1477
1478 The function value is the final status of the operation.
1479
1480 --*/
1481 {
1482 OBJECT_ATTRIBUTES object_attr;
1483 ULONG disposition;
1484
1485 //
1486 // Initialize the object for the key.
1487 //
1488
1489 InitializeObjectAttributes(&object_attr,
1490 keyname, OBJ_CASE_INSENSITIVE, base_handle, (PSECURITY_DESCRIPTOR) NULL);
1491
1492 //
1493 // Create the key or open it, as appropriate based on the caller's
1494 // wishes.
1495 //
1496
1497 if (create)
1498 {
1499 return ZwCreateKey(handle,
1500 desired_access,
1501 &object_attr, 0, (PUNICODE_STRING) NULL, REG_OPTION_VOLATILE, &disposition);
1502 }
1503 else
1504 {
1505 return ZwOpenKey(handle, desired_access, &object_attr);
1506 }
1507 return STATUS_INVALID_PARAMETER;
1508 }
1509
1510 NTSTATUS
1511 gendrv_get_key_value(IN HANDLE KeyHandle, IN PWSTR ValueName, OUT PKEY_VALUE_FULL_INFORMATION * Information)
1512 /*++
1513
1514 Routine Description:
1515
1516 This routine is invoked to retrieve the data for a registry key's value.
1517 This is done by querying the value of the key with a zero-length buffer
1518 to determine the size of the value, and then allocating a buffer and
1519 actually querying the value into the buffer.
1520
1521 It is the responsibility of the caller to free the buffer.
1522
1523 Arguments:
1524
1525 KeyHandle - Supplies the key handle whose value is to be queried
1526
1527 ValueName - Supplies the null-terminated Unicode name of the value.
1528
1529 Information - Returns a pointer to the allocated data buffer.
1530
1531 Return Value:
1532
1533 The function value is the final status of the query operation.
1534
1535 --*/
1536 {
1537 UNICODE_STRING unicodeString;
1538 NTSTATUS status;
1539 PKEY_VALUE_FULL_INFORMATION infoBuffer;
1540 ULONG keyValueLength;
1541
1542 PAGED_CODE();
1543
1544 RtlInitUnicodeString(&unicodeString, ValueName);
1545
1546 //
1547 // Figure out how big the data value is so that a buffer of the
1548 // appropriate size can be allocated.
1549 //
1550
1551 status = ZwQueryValueKey(KeyHandle,
1552 &unicodeString, KeyValueFullInformation, (PVOID) NULL, 0, &keyValueLength);
1553 if (status != STATUS_BUFFER_OVERFLOW && status != STATUS_BUFFER_TOO_SMALL)
1554 {
1555 return status;
1556 }
1557
1558 //
1559 // Allocate a buffer large enough to contain the entire key data value.
1560 //
1561
1562 infoBuffer = usb_alloc_mem(NonPagedPool, keyValueLength);
1563 if (!infoBuffer)
1564 {
1565 return STATUS_INSUFFICIENT_RESOURCES;
1566 }
1567
1568 //
1569 // Query the data for the key value.
1570 //
1571
1572 status = ZwQueryValueKey(KeyHandle,
1573 &unicodeString,
1574 KeyValueFullInformation, infoBuffer, keyValueLength, &keyValueLength);
1575 if (!NT_SUCCESS(status))
1576 {
1577 usb_free_mem(infoBuffer);
1578 return status;
1579 }
1580
1581 //
1582 // Everything worked, so simply return the address of the allocated
1583 // buffer to the caller, who is now responsible for freeing it.
1584 //
1585
1586 *Information = infoBuffer;
1587 return STATUS_SUCCESS;
1588 }
1589
1590 VOID
1591 gendrv_startio(IN PDEVICE_OBJECT dev_obj, IN PIRP irp)
1592 {
1593 PIO_STACK_LOCATION irp_stack;
1594 ULONG ctrl_code;
1595 PUSB_DEV_MANAGER dev_mgr;
1596 USE_NON_PENDING_IRQL;
1597
1598 if (dev_obj == NULL || irp == NULL)
1599 return;
1600
1601 // standard process from walter oney
1602 IoAcquireCancelSpinLock(&old_irql);
1603 if (irp != dev_obj->CurrentIrp || irp->Cancel)
1604 {
1605 // already move on to other irp
1606 IoReleaseCancelSpinLock(old_irql);
1607 return;
1608 }
1609 else
1610 {
1611 (void)IoSetCancelRoutine(irp, NULL);
1612 }
1613 IoReleaseCancelSpinLock(old_irql);
1614
1615 irp->IoStatus.Information = 0;
1616
1617 irp_stack = IoGetCurrentIrpStackLocation(irp);
1618 ctrl_code = irp_stack->Parameters.DeviceIoControl.IoControlCode;
1619 dev_mgr = ((PDEVEXT_HEADER) dev_obj->DeviceExtension)->dev_mgr;
1620
1621 if (irp_stack->MajorFunction != IRP_MJ_DEVICE_CONTROL &&
1622 irp_stack->MajorFunction != IRP_MJ_INTERNAL_DEVICE_CONTROL)
1623 {
1624 GENDRV_COMPLETE_START_IO(dev_obj, STATUS_INVALID_DEVICE_REQUEST, irp);
1625 }
1626
1627 switch (ctrl_code)
1628 {
1629 case IOCTL_SUBMIT_URB_RD:
1630 case IOCTL_SUBMIT_URB_NOIO:
1631 case IOCTL_SUBMIT_URB_WR:
1632 {
1633 PURB purb;
1634 ULONG endp_idx, if_idx, user_buffer_length = 0;
1635 PUCHAR user_buffer = NULL;
1636 PUSB_DEV pdev;
1637 DEV_HANDLE endp_handle;
1638 PUSB_ENDPOINT pendp;
1639
1640 NTSTATUS status;
1641
1642 if (irp_stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(URB))
1643 {
1644 GENDRV_COMPLETE_START_IO(dev_obj, STATUS_INVALID_PARAMETER, irp);
1645 }
1646
1647 purb = (PURB) irp->AssociatedIrp.SystemBuffer;
1648 if (ctrl_code == IOCTL_SUBMIT_URB_RD || ctrl_code == IOCTL_SUBMIT_URB_WR)
1649 {
1650 if (irp_stack->MajorFunction == IRP_MJ_DEVICE_CONTROL)
1651 {
1652 user_buffer = MmGetSystemAddressForMdl(irp->MdlAddress);
1653 user_buffer_length = irp_stack->Parameters.DeviceIoControl.OutputBufferLength;
1654 if (user_buffer_length == 0)
1655 GENDRV_COMPLETE_START_IO(dev_obj, STATUS_INVALID_PARAMETER, irp);
1656 }
1657 else
1658 {
1659 if (purb->data_buffer == NULL || purb->data_length == 0)
1660 GENDRV_COMPLETE_START_IO(dev_obj, STATUS_INVALID_PARAMETER, irp);
1661 user_buffer = purb->data_buffer;
1662 user_buffer_length = purb->data_length;
1663 }
1664 }
1665
1666 purb->reference = 0;
1667 endp_handle = purb->endp_handle;
1668
1669 if (usb_query_and_lock_dev(dev_mgr, endp_handle & ~0xffff, &pdev) != STATUS_SUCCESS)
1670 {
1671 GENDRV_COMPLETE_START_IO(dev_obj, STATUS_IO_DEVICE_ERROR, irp);
1672 }
1673
1674 lock_dev(pdev, FALSE);
1675 if (dev_state(pdev) == USB_DEV_STATE_ZOMB || (dev_state(pdev) < USB_DEV_STATE_ADDRESSED))
1676
1677 {
1678 status = STATUS_INVALID_DEVICE_STATE;
1679 goto ERROR_OUT1;
1680 }
1681
1682 if (dev_state(pdev) == USB_DEV_STATE_ADDRESSED && !default_endp_handle(endp_handle))
1683 {
1684 status = STATUS_DEVICE_NOT_READY;
1685 goto ERROR_OUT1;
1686 }
1687
1688 if_idx = if_idx_from_handle(endp_handle);
1689 endp_idx = endp_idx_from_handle(endp_handle);
1690
1691 //if_idx exceeds the upper limit
1692 if (pdev->usb_config)
1693 {
1694 if (if_idx >= pdev->usb_config->if_count
1695 || endp_idx >= pdev->usb_config->interf[if_idx].endp_count)
1696 {
1697 if (!default_endp_handle(endp_handle))
1698 {
1699 status = STATUS_INVALID_DEVICE_STATE;
1700 goto ERROR_OUT1;
1701 }
1702 }
1703 }
1704
1705 endp_from_handle(pdev, endp_handle, pendp);
1706
1707 // FIXME: don't know what evil will let loose
1708 if (endp_type(pendp) != USB_ENDPOINT_XFER_CONTROL)
1709 {
1710 if (user_buffer_length > 16)
1711 {
1712 status = STATUS_INVALID_PARAMETER;
1713 goto ERROR_OUT1;
1714 }
1715 }
1716
1717 purb->pirp = irp;
1718 purb->context = dev_mgr;
1719 purb->reference = ctrl_code;
1720
1721 if (ctrl_code == IOCTL_SUBMIT_URB_RD || ctrl_code == IOCTL_SUBMIT_URB_WR)
1722 {
1723 purb->data_buffer = user_buffer;
1724 purb->data_length = user_buffer_length;
1725 purb->completion = disp_urb_completion;
1726 }
1727 else
1728 {
1729 purb->completion = disp_noio_urb_completion;
1730 }
1731
1732 unlock_dev(pdev, FALSE);
1733
1734 //
1735 // we have to register irp before the urb is scheduled to
1736 // avoid race condition.
1737 //
1738 ASSERT(dev_mgr_register_irp(dev_mgr, irp, purb));
1739 //
1740 // the irp can not be canceled at this point, since it is
1741 // now the current irp and not in any urb queue. dev_mgr_cancel_irp
1742 // can not find it and simply return.
1743 //
1744 // FIXME: there is a time window that the irp is registered and
1745 // the urb is not queued. In the meantime, the cancel
1746 // request may come and cause the irp removed from the irp
1747 // queue while fail to cancel due to urb not in any urb queue .
1748 // Thus from that point on, the irp can not be canceled till it
1749 // is completed or hanging there forever.
1750 //
1751 status = usb_submit_urb(dev_mgr, purb);
1752 if (status != STATUS_PENDING)
1753 {
1754 // unmark the pending bit
1755 IoGetCurrentIrpStackLocation((irp))->Control &= ~SL_PENDING_RETURNED;
1756 dev_mgr_remove_irp(dev_mgr, irp);
1757 }
1758 usb_unlock_dev(pdev);
1759 if (status != STATUS_PENDING)
1760 {
1761 irp->IoStatus.Status = status;
1762 GENDRV_COMPLETE_START_IO(dev_obj, status, irp);
1763 }
1764 return;
1765
1766 ERROR_OUT1:
1767 unlock_dev(pdev, FALSE);
1768 usb_unlock_dev(pdev);
1769 irp->IoStatus.Information = 0;
1770 GENDRV_COMPLETE_START_IO(dev_obj, status, irp);
1771 }
1772 }
1773 GENDRV_COMPLETE_START_IO(dev_obj, STATUS_INVALID_DEVICE_REQUEST, irp);
1774 }
1775
1776 VOID
1777 gendrv_clean_up_queued_irps(PDEVICE_OBJECT dev_obj)
1778 {
1779 // called when device may not function or about to be removed, need cleanup
1780 KIRQL cancelIrql;
1781 PIRP irp, cur_irp;
1782 PKDEVICE_QUEUE_ENTRY packet;
1783 LIST_ENTRY cancel_irps, *pthis;
1784
1785 //
1786 // cancel all the irps in the queue
1787 //
1788 if (dev_obj == NULL)
1789 return;
1790
1791 InitializeListHead(&cancel_irps);
1792
1793 // remove the irps from device queue
1794 IoAcquireCancelSpinLock(&cancelIrql);
1795 cur_irp = dev_obj->CurrentIrp;
1796 while ((packet = KeRemoveDeviceQueue(&dev_obj->DeviceQueue)))
1797 {
1798 irp = struct_ptr(packet, IRP, Tail.Overlay.DeviceQueueEntry);
1799 InsertTailList(&cancel_irps, &irp->Tail.Overlay.DeviceQueueEntry.DeviceListEntry);
1800 }
1801 IoReleaseCancelSpinLock(cancelIrql);
1802
1803 // cancel the irps in process
1804 // we did not cancel the current irp, it will be done by hcd when
1805 // disconnect is detected.
1806 // remove_irp_from_list( &dev_mgr->irp_list, cur_irp, dev_mgr );
1807
1808 while (IsListEmpty(&cancel_irps) == FALSE)
1809 {
1810 pthis = RemoveHeadList(&cancel_irps);
1811 irp = struct_ptr(pthis, IRP, Tail.Overlay.DeviceQueueEntry.DeviceListEntry);
1812 irp->IoStatus.Information = 0;
1813 irp->IoStatus.Status = STATUS_CANCELLED;
1814 IoCompleteRequest(irp, IO_NO_INCREMENT);
1815 }
1816 return;
1817 }
1818
1819 VOID
1820 NTAPI
1821 gendrv_cancel_queued_irp(PDEVICE_OBJECT dev_obj, PIRP pirp)
1822 {
1823 // cancel routine for irps queued in the device queue
1824 PUSB_DEV_MANAGER dev_mgr;
1825 PDEVEXT_HEADER pdev_ext_hdr;
1826
1827 pdev_ext_hdr = (PDEVEXT_HEADER) dev_obj->DeviceExtension;
1828 dev_mgr = pdev_ext_hdr->dev_mgr;
1829
1830 if (dev_obj->CurrentIrp == pirp)
1831 {
1832 // just before start_io set the cancel routine to null
1833 IoReleaseCancelSpinLock(pirp->CancelIrql);
1834 // we did not IoStartNextPacket, leave it for dev_mgr_cancel_irp, that
1835 // is user have to call CancelIo again.
1836 return;
1837 }
1838
1839 KeRemoveEntryDeviceQueue(&dev_obj->DeviceQueue, &pirp->Tail.Overlay.DeviceQueueEntry);
1840 IoReleaseCancelSpinLock(pirp->CancelIrql);
1841
1842 pirp->IoStatus.Information = 0;
1843 pirp->IoStatus.Status = STATUS_CANCELLED;
1844 IoCompleteRequest(pirp, IO_NO_INCREMENT);
1845 // the device queue is moved on, no need to call IoStartNextPacket
1846 return;
1847 }