[USBHUB]
[reactos.git] / drivers / usb / usbhub_new / pdo.c
1 /*
2 * PROJECT: ReactOS Universal Serial Bus Hub Driver
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: drivers/usb/usbhub/fdo.c
5 * PURPOSE: Handle PDO
6 * PROGRAMMERS:
7 * Hervé Poussineau (hpoussin@reactos.org)
8 * Michael Martin (michael.martin@reactos.org)
9 * Johannes Anderwald (johannes.anderwald@reactos.org)
10 */
11
12 #include "usbhub.h"
13
14 #define IO_METHOD_FROM_CTL_CODE(ctlCode) (ctlCode&0x00000003)
15
16 NTSTATUS
17 UrbCompletion(
18 PDEVICE_OBJECT DeviceObject,
19 PIRP Irp,
20 PVOID Context)
21 {
22 PIRP OriginalIrp;
23 DPRINT("Entered Urb Completion\n");
24
25 //
26 // Get the original Irp
27 //
28 OriginalIrp = (PIRP)Context;
29
30 //
31 // Update it to match what was returned for the IRP that was passed to RootHub
32 //
33 OriginalIrp->IoStatus.Status = Irp->IoStatus.Status;
34 OriginalIrp->IoStatus.Information = Irp->IoStatus.Information;
35 DPRINT("Status %x, Information %x\n", Irp->IoStatus.Status, Irp->IoStatus.Information);
36
37 //
38 // Complete the original Irp
39 //
40 IoCompleteRequest(OriginalIrp, IO_NO_INCREMENT);
41
42 //
43 // Return this status so the IO Manager doesnt mess with the Irp
44 //
45 return STATUS_MORE_PROCESSING_REQUIRED;
46 }
47
48 NTSTATUS
49 FowardUrbToRootHub(
50 PDEVICE_OBJECT RootHubDeviceObject,
51 IN ULONG IoControlCode,
52 PIRP Irp,
53 OUT PVOID OutParameter1,
54 OUT PVOID OutParameter2)
55 {
56 NTSTATUS Status;
57 PIRP ForwardIrp;
58 IO_STATUS_BLOCK IoStatus;
59 PIO_STACK_LOCATION ForwardStack, CurrentStack;
60 PURB Urb;
61
62 //
63 // Get the current stack location for the Irp
64 //
65 CurrentStack = IoGetCurrentIrpStackLocation(Irp);
66 ASSERT(CurrentStack);
67
68 //
69 // Pull the Urb from that stack, it will be reused in the Irp sent to RootHub
70 //
71 Urb = (PURB)CurrentStack->Parameters.Others.Argument1;
72 ASSERT(Urb);
73
74 //
75 // Create the Irp to forward to RootHub
76 //
77 ForwardIrp = IoBuildAsynchronousFsdRequest(IRP_MJ_SHUTDOWN,
78 RootHubDeviceObject,
79 NULL,
80 0,
81 0,
82 &IoStatus);
83 if (!ForwardIrp)
84 {
85 DPRINT1("Failed to allocate IRP\n");
86 return STATUS_INSUFFICIENT_RESOURCES;
87 }
88
89 //
90 // Get the new Irps next stack
91 //
92 ForwardStack = IoGetNextIrpStackLocation(ForwardIrp);
93
94 //
95 // Copy the stack for the current irp into the next stack of new irp
96 //
97 RtlCopyMemory(ForwardStack, CurrentStack, sizeof(IO_STACK_LOCATION));
98
99 IoStatus.Status = STATUS_NOT_SUPPORTED;
100 IoStatus.Information = 0;
101
102 //
103 // Mark the Irp from upper driver as pending
104 //
105 IoMarkIrpPending(Irp);
106
107 //
108 // Now set the completion routine for the new Irp.
109 //
110 IoSetCompletionRoutine(ForwardIrp,
111 (PIO_COMPLETION_ROUTINE)UrbCompletion,
112 Irp,
113 TRUE,
114 TRUE,
115 TRUE);
116
117 Status = IoCallDriver(RootHubDeviceObject, ForwardIrp);
118
119 //
120 // Always return pending as the completion routine will take care of it
121 //
122 return STATUS_PENDING;
123 }
124
125 NTSTATUS
126 USBHUB_PdoHandleInternalDeviceControl(
127 IN PDEVICE_OBJECT DeviceObject,
128 IN PIRP Irp)
129 {
130 NTSTATUS Status;
131 PIO_STACK_LOCATION Stack;
132 ULONG_PTR Information = 0;
133 PHUB_DEVICE_EXTENSION HubDeviceExtension;
134 PHUB_CHILDDEVICE_EXTENSION ChildDeviceExtension;
135 PDEVICE_OBJECT RootHubDeviceObject;
136 PURB Urb;
137
138 //DPRINT1("UsbhubInternalDeviceControlPdo(%x) called\n", DeviceObject);
139
140 //
141 // get current stack location
142 //
143 Stack = IoGetCurrentIrpStackLocation(Irp);
144 ASSERT(Stack);
145
146 //
147 // Set default status
148 //
149 Status = Irp->IoStatus.Status;
150
151 ChildDeviceExtension = (PHUB_CHILDDEVICE_EXTENSION)DeviceObject->DeviceExtension;
152 ASSERT(ChildDeviceExtension->Common.IsFDO == FALSE);
153 HubDeviceExtension = (PHUB_DEVICE_EXTENSION)ChildDeviceExtension->ParentDeviceObject->DeviceExtension;
154 RootHubDeviceObject = HubDeviceExtension->RootHubPhysicalDeviceObject;
155
156 switch (Stack->Parameters.DeviceIoControl.IoControlCode)
157 {
158 case IOCTL_INTERNAL_USB_GET_PARENT_HUB_INFO:
159 {
160 PHUB_DEVICE_EXTENSION DeviceExtension;
161
162 DPRINT1("IOCTL_INTERNAL_USB_GET_PARENT_HUB_INFO\n");
163 if (Irp->AssociatedIrp.SystemBuffer == NULL
164 || Stack->Parameters.DeviceIoControl.OutputBufferLength != sizeof(PVOID))
165 {
166 Status = STATUS_INVALID_PARAMETER;
167 }
168 else
169 {
170 PVOID* pHubPointer;
171 DeviceExtension = (PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
172
173 pHubPointer = (PVOID*)Irp->AssociatedIrp.SystemBuffer;
174 // FIXME
175 *pHubPointer = NULL;
176 Information = sizeof(PVOID);
177 Status = STATUS_SUCCESS;
178 }
179 break;
180 }
181 case IOCTL_INTERNAL_USB_SUBMIT_URB:
182 {
183 //DPRINT1("IOCTL_INTERNAL_USB_SUBMIT_URB\n");
184
185 //
186 // Get the Urb
187 //
188 Urb = (PURB)Stack->Parameters.Others.Argument1;
189 ASSERT(Urb);
190
191 //
192 // Set the real device handle
193 //
194 //DPRINT("UsbdDeviceHandle %x, ChildDeviceHandle %x\n", Urb->UrbHeader.UsbdDeviceHandle, ChildDeviceExtension->UsbDeviceHandle);
195
196 Urb->UrbHeader.UsbdDeviceHandle = ChildDeviceExtension->UsbDeviceHandle;
197
198 //
199 // Submit to RootHub
200 //
201 switch (Urb->UrbHeader.Function)
202 {
203 //
204 // Debugging only
205 //
206 case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE:
207 DPRINT1("URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE\n");
208 break;
209 case URB_FUNCTION_CLASS_DEVICE:
210 DPRINT1("URB_FUNCTION_CLASS_DEVICE\n");
211 break;
212 case URB_FUNCTION_GET_STATUS_FROM_DEVICE:
213 DPRINT1("URB_FUNCTION_GET_STATUS_FROM_DEVICE\n");
214 break;
215 case URB_FUNCTION_SELECT_CONFIGURATION:
216 DPRINT1("URB_FUNCTION_SELECT_CONFIGURATION\n");
217 break;
218 case URB_FUNCTION_SELECT_INTERFACE:
219 DPRINT1("URB_FUNCTION_SELECT_INTERFACE\n");
220 break;
221 case URB_FUNCTION_CLASS_OTHER:
222 DPRINT1("URB_FUNCTION_CLASS_OTHER\n");
223 break;
224 case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:
225 {
226 /*
227 DPRINT1("URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER\n");
228 DPRINT1("PipeHandle %x\n", Urb->UrbBulkOrInterruptTransfer.PipeHandle);
229 DPRINT1("TransferFlags %x\n", Urb->UrbBulkOrInterruptTransfer.TransferFlags);
230 DPRINT1("Buffer %x\n", Urb->UrbBulkOrInterruptTransfer.TransferBuffer);
231 DPRINT1("BufferMDL %x\n", Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL);
232 DPRINT1("Length %x\n", Urb->UrbBulkOrInterruptTransfer.TransferBufferLength);
233 DPRINT1("UrbLink %x\n", Urb->UrbBulkOrInterruptTransfer.UrbLink);
234 DPRINT1("hca %x\n", Urb->UrbBulkOrInterruptTransfer.hca);
235 if (Urb->UrbBulkOrInterruptTransfer.TransferFlags == USBD_SHORT_TRANSFER_OK)
236 {
237 }
238 */
239 break;
240
241 }
242 case URB_FUNCTION_CLASS_INTERFACE:
243 DPRINT1("URB_FUNCTION_CLASS_INTERFACE\n");
244 break;
245 default:
246 DPRINT1("IOCTL_INTERNAL_USB_SUBMIT_URB Function %x NOT IMPLEMENTED\n", Urb->UrbHeader.Function);
247 break;
248 }
249 Urb->UrbHeader.UsbdDeviceHandle = ChildDeviceExtension->UsbDeviceHandle;
250 //DPRINT1("Stack->CompletionRoutine %x\n", Stack->CompletionRoutine);
251 //
252 // Send the request to RootHub
253 //
254 Status = FowardUrbToRootHub(RootHubDeviceObject, IOCTL_INTERNAL_USB_SUBMIT_URB, Irp, Urb, NULL);
255 return Status;
256 break;
257 }
258 //
259 // FIXME: Can these be sent to RootHub?
260 //
261 case IOCTL_INTERNAL_USB_RESET_PORT:
262 DPRINT1("IOCTL_INTERNAL_USB_RESET_PORT\n");
263 break;
264 case IOCTL_INTERNAL_USB_GET_PORT_STATUS:
265 {
266 PORT_STATUS_CHANGE PortStatus;
267 LONG PortId;
268 PUCHAR PortStatusBits;
269
270 PortStatusBits = (PUCHAR)Stack->Parameters.Others.Argument1;
271 //
272 // USBD_PORT_ENABLED (bit 0) or USBD_PORT_CONNECTED (bit 1)
273 //
274 DPRINT1("IOCTL_INTERNAL_USB_GET_PORT_STATUS\n");
275 DPRINT1("Arg1 %x\n", *PortStatusBits);
276 *PortStatusBits = 0;
277 if (Stack->Parameters.Others.Argument1)
278 {
279 for (PortId = 1; PortId <= HubDeviceExtension->UsbExtHubInfo.NumberOfPorts; PortId++)
280 {
281 Status = GetPortStatusAndChange(RootHubDeviceObject, PortId, &PortStatus);
282 if (NT_SUCCESS(Status))
283 {
284 DPRINT1("Connect %x\n", ((PortStatus.Status & USB_PORT_STATUS_CONNECT) << 1) << ((PortId - 1) * 2));
285 DPRINT1("Enable %x\n", ((PortStatus.Status & USB_PORT_STATUS_ENABLE) >> 1) << ((PortId - 1) * 2));
286 *PortStatusBits +=
287 (((PortStatus.Status & USB_PORT_STATUS_CONNECT) << 1) << ((PortId - 1) * 2)) +
288 (((PortStatus.Status & USB_PORT_STATUS_ENABLE) >> 1) << ((PortId - 1) * 2));
289
290 }
291 }
292 }
293
294 DPRINT1("Arg1 %x\n", *PortStatusBits);
295 Status = STATUS_SUCCESS;
296 break;
297 }
298 case IOCTL_INTERNAL_USB_ENABLE_PORT:
299 DPRINT1("IOCTL_INTERNAL_USB_ENABLE_PORT\n");
300 break;
301 case IOCTL_INTERNAL_USB_CYCLE_PORT:
302 DPRINT1("IOCTL_INTERNAL_USB_CYCLE_PORT\n");
303 break;
304 case IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE:
305 DPRINT1("IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE\n");
306 break;
307 default:
308 {
309 DPRINT1("Unknown IOCTL code 0x%lx\n", Stack->Parameters.DeviceIoControl.IoControlCode);
310 Information = Irp->IoStatus.Information;
311 Status = Irp->IoStatus.Status;
312 }
313 }
314
315 if (Status != STATUS_PENDING)
316 {
317 Irp->IoStatus.Information = Information;
318 Irp->IoStatus.Status = Status;
319 IoCompleteRequest(Irp, IO_NO_INCREMENT);
320 }
321 return Status;
322 }
323
324 NTSTATUS
325 USBHUB_PdoStartDevice(
326 IN PDEVICE_OBJECT DeviceObject,
327 IN PIRP Irp)
328 {
329 PHUB_CHILDDEVICE_EXTENSION ChildDeviceExtension;
330 //NTSTATUS Status;
331 DPRINT1("USBHUB_PdoStartDevice %x\n", DeviceObject);
332 ChildDeviceExtension = (PHUB_CHILDDEVICE_EXTENSION)DeviceObject->DeviceExtension;
333
334 //
335 // This should be a PDO
336 //
337 ASSERT(ChildDeviceExtension->Common.IsFDO == FALSE);
338
339 //
340 // FIXME: Fow now assume success
341 //
342
343 UNIMPLEMENTED
344 return STATUS_SUCCESS;
345 }
346
347 NTSTATUS
348 USBHUB_PdoQueryId(
349 IN PDEVICE_OBJECT DeviceObject,
350 IN PIRP Irp,
351 OUT ULONG_PTR* Information)
352 {
353 PHUB_CHILDDEVICE_EXTENSION ChildDeviceExtension;
354 ULONG IdType;
355 PUNICODE_STRING SourceString = NULL;
356 PWCHAR ReturnString = NULL;
357 NTSTATUS Status = STATUS_SUCCESS;
358
359 IdType = IoGetCurrentIrpStackLocation(Irp)->Parameters.QueryId.IdType;
360 ChildDeviceExtension = (PHUB_CHILDDEVICE_EXTENSION)DeviceObject->DeviceExtension;
361
362 switch (IdType)
363 {
364 case BusQueryDeviceID:
365 {
366 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryDeviceID\n");
367 SourceString = &ChildDeviceExtension->usDeviceId;
368 break;
369 }
370 case BusQueryHardwareIDs:
371 {
372 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryHardwareIDs\n");
373 SourceString = &ChildDeviceExtension->usHardwareIds;
374 break;
375 }
376 case BusQueryCompatibleIDs:
377 {
378 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryCompatibleIDs\n");
379 SourceString = &ChildDeviceExtension->usCompatibleIds;
380 break;
381 }
382 case BusQueryInstanceID:
383 {
384 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryInstanceID\n");
385 SourceString = &ChildDeviceExtension->usInstanceId;
386 break;
387 }
388 default:
389 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_ID / unknown query id type 0x%lx\n", IdType);
390 return STATUS_NOT_SUPPORTED;
391 }
392
393 if (SourceString)
394 {
395 ReturnString = ExAllocatePool(PagedPool, SourceString->Length);
396 RtlCopyMemory(ReturnString, SourceString->Buffer, SourceString->Length);
397 DPRINT1("%S\n", ReturnString);
398 }
399
400 *Information = (ULONG_PTR)ReturnString;
401
402 return Status;
403 }
404
405 NTSTATUS
406 USBHUB_PdoQueryDeviceText(
407 IN PDEVICE_OBJECT DeviceObject,
408 IN PIRP Irp,
409 OUT ULONG_PTR* Information)
410 {
411 PHUB_CHILDDEVICE_EXTENSION ChildDeviceExtension;
412 DEVICE_TEXT_TYPE DeviceTextType;
413 PUNICODE_STRING SourceString = NULL;
414 PWCHAR ReturnString = NULL;
415 NTSTATUS Status = STATUS_SUCCESS;
416 LCID LocaleId;
417
418 DeviceTextType = IoGetCurrentIrpStackLocation(Irp)->Parameters.QueryDeviceText.DeviceTextType;
419 LocaleId = IoGetCurrentIrpStackLocation(Irp)->Parameters.QueryDeviceText.LocaleId;
420 ChildDeviceExtension = (PHUB_CHILDDEVICE_EXTENSION)DeviceObject->DeviceExtension;
421
422 //
423 // FIXME: LocaleId
424 //
425
426 switch (DeviceTextType)
427 {
428 case DeviceTextDescription:
429 case DeviceTextLocationInformation:
430 {
431 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / DeviceTextDescription\n");
432
433 //
434 // does the device provide a text description
435 //
436 if (ChildDeviceExtension->usTextDescription->Buffer && ChildDeviceExtension->usTextDescription->Length)
437 {
438 //
439 // use device text
440 //
441 SourceString = &ChildDeviceExtension->usTextDescription;
442 }
443 break;
444 }
445 default:
446 {
447 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / unknown device text type 0x%lx\n", DeviceTextType);
448 Status = STATUS_NOT_SUPPORTED;
449 break;
450 }
451 }
452
453 if (SourceString)
454 {
455 ReturnString = ExAllocatePool(PagedPool, SourceString->Length);
456 RtlCopyMemory(ReturnString, SourceString->Buffer, SourceString->Length);
457 DPRINT1("%S\n", ReturnString);
458 *Information = (ULONG_PTR)ReturnString;
459 }
460
461 return Status;
462 }
463
464 NTSTATUS
465 USBHUB_PdoHandlePnp(
466 IN PDEVICE_OBJECT DeviceObject,
467 IN PIRP Irp)
468 {
469 NTSTATUS Status;
470 ULONG MinorFunction;
471 PIO_STACK_LOCATION Stack;
472 ULONG_PTR Information = 0;
473 PHUB_CHILDDEVICE_EXTENSION UsbChildExtension;
474
475 UsbChildExtension = (PHUB_CHILDDEVICE_EXTENSION)DeviceObject->DeviceExtension;
476 Stack = IoGetCurrentIrpStackLocation(Irp);
477 MinorFunction = Stack->MinorFunction;
478
479 switch (MinorFunction)
480 {
481 case IRP_MN_START_DEVICE:
482 {
483 DPRINT1("IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
484 Status = USBHUB_PdoStartDevice(DeviceObject, Irp);
485 break;
486 }
487 case IRP_MN_QUERY_CAPABILITIES:
488 {
489 PDEVICE_CAPABILITIES DeviceCapabilities;
490 ULONG i;
491 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_CAPABILITIES\n");
492
493 DeviceCapabilities = (PDEVICE_CAPABILITIES)Stack->Parameters.DeviceCapabilities.Capabilities;
494 // FIXME: capabilities can change with connected device
495 DeviceCapabilities->LockSupported = FALSE;
496 DeviceCapabilities->EjectSupported = FALSE;
497 DeviceCapabilities->Removable = TRUE;
498 DeviceCapabilities->DockDevice = FALSE;
499 DeviceCapabilities->UniqueID = FALSE;
500 DeviceCapabilities->SilentInstall = FALSE;
501 DeviceCapabilities->RawDeviceOK = FALSE;
502 DeviceCapabilities->SurpriseRemovalOK = FALSE;
503 DeviceCapabilities->HardwareDisabled = FALSE;
504 //DeviceCapabilities->NoDisplayInUI = FALSE;
505 DeviceCapabilities->Address = UsbChildExtension->PortNumber;
506 DeviceCapabilities->UINumber = 0;
507 DeviceCapabilities->DeviceState[0] = PowerDeviceD0;
508 for (i = 0; i < PowerSystemMaximum; i++)
509 DeviceCapabilities->DeviceState[i] = PowerDeviceD3;
510 //DeviceCapabilities->DeviceWake = PowerDeviceUndefined;
511 DeviceCapabilities->D1Latency = 0;
512 DeviceCapabilities->D2Latency = 0;
513 DeviceCapabilities->D3Latency = 0;
514 Status = STATUS_SUCCESS;
515 break;
516 }
517 case IRP_MN_QUERY_RESOURCES:
518 {
519 PCM_RESOURCE_LIST ResourceList;
520
521 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_RESOURCES\n");
522 ResourceList = ExAllocatePool(PagedPool, sizeof(CM_RESOURCE_LIST));
523 if (!ResourceList)
524 {
525 DPRINT1("ExAllocatePool() failed\n");
526 Status = STATUS_INSUFFICIENT_RESOURCES;
527 }
528 else
529 {
530 ResourceList->Count = 0;
531 Information = (ULONG_PTR)ResourceList;
532 Status = STATUS_SUCCESS;
533 }
534 break;
535 }
536 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
537 {
538 PIO_RESOURCE_REQUIREMENTS_LIST ResourceList;
539 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n");
540 ResourceList = ExAllocatePool(PagedPool, sizeof(IO_RESOURCE_REQUIREMENTS_LIST));
541 if (!ResourceList)
542 {
543 DPRINT1("ExAllocatePool() failed\n");
544 Status = STATUS_INSUFFICIENT_RESOURCES;
545 }
546 else
547 {
548 RtlZeroMemory(ResourceList, sizeof(IO_RESOURCE_REQUIREMENTS_LIST));
549 ResourceList->ListSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST);
550 ResourceList->AlternativeLists = 1;
551 ResourceList->List->Version = 1;
552 ResourceList->List->Revision = 1;
553 ResourceList->List->Count = 0;
554 Information = (ULONG_PTR)ResourceList;
555 Status = STATUS_SUCCESS;
556 }
557 break;
558 }
559 case IRP_MN_QUERY_DEVICE_TEXT:
560 {
561 Status = USBHUB_PdoQueryDeviceText(DeviceObject, Irp, &Information);
562 break;
563 }
564 case IRP_MN_QUERY_ID:
565 {
566 Status = USBHUB_PdoQueryId(DeviceObject, Irp, &Information);
567 break;
568 }
569 case IRP_MN_QUERY_BUS_INFORMATION:
570 {
571 PPNP_BUS_INFORMATION BusInfo;
572 BusInfo = (PPNP_BUS_INFORMATION)ExAllocatePool(PagedPool, sizeof(PNP_BUS_INFORMATION));
573 RtlCopyMemory(&BusInfo->BusTypeGuid,
574 &GUID_BUS_TYPE_USB,
575 sizeof(BusInfo->BusTypeGuid));
576 BusInfo->LegacyBusType = PNPBus;
577 // FIXME
578 BusInfo->BusNumber = 0;
579 Information = (ULONG_PTR)BusInfo;
580 Status = STATUS_SUCCESS;
581 break;
582 }
583 case IRP_MN_REMOVE_DEVICE:
584 {
585 //
586 // FIXME
587 //
588 Status = STATUS_SUCCESS;
589 break;
590 }
591 default:
592 {
593 DPRINT1("PDO IRP_MJ_PNP / unknown minor function 0x%lx\n", MinorFunction);
594 Information = Irp->IoStatus.Information;
595 Status = Irp->IoStatus.Status;
596 }
597 }
598
599 Irp->IoStatus.Information = Information;
600 Irp->IoStatus.Status = Status;
601 IoCompleteRequest(Irp, IO_NO_INCREMENT);
602 return Status;
603 }
604