1 /*
2  * COPYRIGHT:       See COPYING in the top level directory
3  * PROJECT:         ReactOS Kernel Streaming
4  * FILE:            drivers/wdm/audio/legacy/wdmaud/deviface.c
5  * PURPOSE:         System Audio graph builder
6  * PROGRAMMER:      Andrew Greenwood
7  *                  Johannes Anderwald
8  */
9 
10 #include "wdmaud.h"
11 
12 #define NDEBUG
13 #include <debug.h>
14 
15 const GUID KSPROPSETID_Sysaudio                 = {0xCBE3FAA0L, 0xCC75, 0x11D0, {0xB4, 0x65, 0x00, 0x00, 0x1A, 0x18, 0x18, 0xE6}};
16 
17 NTSTATUS
18 WdmAudControlOpen(
19     IN  PDEVICE_OBJECT DeviceObject,
20     IN  PIRP Irp,
21     IN  PWDMAUD_DEVICE_INFO DeviceInfo,
22     IN  PWDMAUD_CLIENT ClientInfo)
23 {
24     if (DeviceInfo->DeviceType == MIXER_DEVICE_TYPE)
25     {
26         return WdmAudControlOpenMixer(DeviceObject, Irp, DeviceInfo, ClientInfo);
27     }
28 
29     if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE || DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE)
30     {
31         return WdmAudControlOpenWave(DeviceObject, Irp, DeviceInfo, ClientInfo);
32     }
33 
34     if (DeviceInfo->DeviceType == MIDI_OUT_DEVICE_TYPE || DeviceInfo->DeviceType == MIDI_IN_DEVICE_TYPE)
35     {
36         return WdmAudControlOpenMidi(DeviceObject, Irp, DeviceInfo, ClientInfo);
37     }
38 
39 
40     return SetIrpIoStatus(Irp, STATUS_NOT_SUPPORTED, sizeof(WDMAUD_DEVICE_INFO));
41 }
42 
43 NTSTATUS
44 WdmAudControlDeviceType(
45     IN  PDEVICE_OBJECT DeviceObject,
46     IN  PIRP Irp,
47     IN  PWDMAUD_DEVICE_INFO DeviceInfo,
48     IN  PWDMAUD_CLIENT ClientInfo)
49 {
50     ULONG Result = 0;
51 
52     if (DeviceInfo->DeviceType == MIXER_DEVICE_TYPE)
53     {
54         Result = WdmAudGetMixerDeviceCount();
55     }
56     else if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE)
57     {
58         Result = WdmAudGetWaveOutDeviceCount();
59     }
60     else if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE)
61     {
62         Result = WdmAudGetWaveInDeviceCount();
63     }
64     else if (DeviceInfo->DeviceType == MIDI_IN_DEVICE_TYPE)
65     {
66         Result = WdmAudGetMidiInDeviceCount();
67     }
68     else if (DeviceInfo->DeviceType == MIDI_OUT_DEVICE_TYPE)
69     {
70         Result = WdmAudGetMidiOutDeviceCount();
71     }
72 
73 
74     /* store result count */
75     DeviceInfo->DeviceCount = Result;
76 
77     DPRINT("WdmAudControlDeviceType Devices %u\n", DeviceInfo->DeviceCount);
78     return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
79 }
80 
81 NTSTATUS
82 WdmAudControlDeviceState(
83     IN  PDEVICE_OBJECT DeviceObject,
84     IN  PIRP Irp,
85     IN  PWDMAUD_DEVICE_INFO DeviceInfo,
86     IN  PWDMAUD_CLIENT ClientInfo)
87 {
88     KSPROPERTY Property;
89     KSSTATE State;
90     NTSTATUS Status;
91     ULONG BytesReturned;
92     PFILE_OBJECT FileObject;
93 
94     DPRINT("WdmAudControlDeviceState\n");
95 
96     Status = ObReferenceObjectByHandle(DeviceInfo->hDevice, GENERIC_READ | GENERIC_WRITE, *IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
97     if (!NT_SUCCESS(Status))
98     {
99         DPRINT1("Error: invalid device handle provided %p Type %x\n", DeviceInfo->hDevice, DeviceInfo->DeviceType);
100         return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
101     }
102 
103     Property.Set = KSPROPSETID_Connection;
104     Property.Id = KSPROPERTY_CONNECTION_STATE;
105     Property.Flags = KSPROPERTY_TYPE_SET;
106 
107     State = DeviceInfo->u.State;
108 
109     Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&State, sizeof(KSSTATE), &BytesReturned);
110 
111     ObDereferenceObject(FileObject);
112 
113     DPRINT("WdmAudControlDeviceState Status %x\n", Status);
114     return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO));
115 }
116 
117 NTSTATUS
118 WdmAudCapabilities(
119     IN  PDEVICE_OBJECT DeviceObject,
120     IN  PIRP Irp,
121     IN  PWDMAUD_DEVICE_INFO DeviceInfo,
122     IN  PWDMAUD_CLIENT ClientInfo)
123 {
124     PWDMAUD_DEVICE_EXTENSION DeviceExtension;
125     NTSTATUS Status = STATUS_UNSUCCESSFUL;
126 
127     DPRINT("WdmAudCapabilities entered\n");
128 
129     DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
130 
131     if (DeviceInfo->DeviceType == MIXER_DEVICE_TYPE)
132     {
133         Status = WdmAudMixerCapabilities(DeviceObject, DeviceInfo, ClientInfo, DeviceExtension);
134     }
135     else if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE || DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE)
136     {
137         Status = WdmAudWaveCapabilities(DeviceObject, DeviceInfo, ClientInfo, DeviceExtension);
138     }
139     else if (DeviceInfo->DeviceType == MIDI_IN_DEVICE_TYPE || DeviceInfo->DeviceType == MIDI_OUT_DEVICE_TYPE)
140     {
141         Status = WdmAudMidiCapabilities(DeviceObject, DeviceInfo, ClientInfo, DeviceExtension);
142     }
143 
144     return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO));
145 }
146 
147 NTSTATUS
148 NTAPI
149 WdmAudIoctlClose(
150     IN  PDEVICE_OBJECT DeviceObject,
151     IN  PIRP Irp,
152     IN  PWDMAUD_DEVICE_INFO DeviceInfo,
153     IN  PWDMAUD_CLIENT ClientInfo)
154 {
155     ULONG Index;
156 
157     for(Index = 0; Index < ClientInfo->NumPins; Index++)
158     {
159         if (ClientInfo->hPins[Index].Handle == DeviceInfo->hDevice && ClientInfo->hPins[Index].Type != MIXER_DEVICE_TYPE)
160         {
161             DPRINT1("Closing device %p\n", DeviceInfo->hDevice);
162             ZwClose(DeviceInfo->hDevice);
163             ClientInfo->hPins[Index].Handle = NULL;
164             SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
165             return STATUS_SUCCESS;
166         }
167         else if (ClientInfo->hPins[Index].Handle == DeviceInfo->hDevice && ClientInfo->hPins[Index].Type == MIXER_DEVICE_TYPE)
168         {
169             DPRINT1("Closing mixer %p\n", DeviceInfo->hDevice);
170             return WdmAudControlCloseMixer(DeviceObject, Irp, DeviceInfo, ClientInfo, Index);
171         }
172     }
173 
174     SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, sizeof(WDMAUD_DEVICE_INFO));
175     return STATUS_INVALID_PARAMETER;
176 }
177 
178 NTSTATUS
179 NTAPI
180 WdmAudFrameSize(
181     IN  PDEVICE_OBJECT DeviceObject,
182     IN  PIRP Irp,
183     IN  PWDMAUD_DEVICE_INFO DeviceInfo,
184     IN  PWDMAUD_CLIENT ClientInfo)
185 {
186     PFILE_OBJECT FileObject;
187     KSPROPERTY Property;
188     ULONG BytesReturned;
189     KSALLOCATOR_FRAMING Framing;
190     NTSTATUS Status;
191 
192     /* Get sysaudio pin file object */
193     Status = ObReferenceObjectByHandle(DeviceInfo->hDevice, GENERIC_WRITE, *IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
194     if (!NT_SUCCESS(Status))
195     {
196         DPRINT1("Invalid buffer handle %p\n", DeviceInfo->hDevice);
197         return SetIrpIoStatus(Irp, Status, 0);
198     }
199 
200     /* Setup get framing request */
201     Property.Id = KSPROPERTY_CONNECTION_ALLOCATORFRAMING;
202     Property.Flags = KSPROPERTY_TYPE_GET;
203     Property.Set = KSPROPSETID_Connection;
204 
205     Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&Framing, sizeof(KSALLOCATOR_FRAMING), &BytesReturned);
206     /* Did we succeed */
207     if (NT_SUCCESS(Status))
208     {
209         /* Store framesize */
210         DeviceInfo->u.FrameSize = Framing.FrameSize;
211     }
212 
213     /* Release file object */
214     ObDereferenceObject(FileObject);
215 
216     return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO));
217 
218 }
219 
220 NTSTATUS
221 NTAPI
222 WdmAudGetDeviceInterface(
223     IN  PDEVICE_OBJECT DeviceObject,
224     IN  PIRP Irp,
225     IN  PWDMAUD_DEVICE_INFO DeviceInfo)
226 {
227     NTSTATUS Status;
228     LPWSTR Device;
229     ULONG Size, Length;
230 
231     /* get device interface string input length */
232     Size = DeviceInfo->u.Interface.DeviceInterfaceStringSize;
233 
234    /* get mixer info */
235    Status = WdmAudGetPnpNameByIndexAndType(DeviceInfo->DeviceIndex, DeviceInfo->DeviceType, &Device);
236 
237    /* check for success */
238    if (!NT_SUCCESS(Status))
239    {
240         /* invalid device id */
241         return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO));
242    }
243 
244    /* calculate length */
245    Length = (wcslen(Device)+1) * sizeof(WCHAR);
246 
247     if (!Size)
248     {
249         /* store device interface size */
250         DeviceInfo->u.Interface.DeviceInterfaceStringSize = Length;
251     }
252     else if (Size < Length)
253     {
254         /* buffer too small */
255         DeviceInfo->u.Interface.DeviceInterfaceStringSize = Length;
256         return SetIrpIoStatus(Irp, STATUS_BUFFER_OVERFLOW, sizeof(WDMAUD_DEVICE_INFO));
257     }
258     else
259     {
260         //FIXME SEH
261         RtlMoveMemory(DeviceInfo->u.Interface.DeviceInterfaceString, Device, Length);
262     }
263 
264     FreeItem(Device);
265     return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
266 }
267 
268 NTSTATUS
269 NTAPI
270 WdmAudResetStream(
271     IN  PDEVICE_OBJECT DeviceObject,
272     IN  PIRP Irp,
273     IN  PWDMAUD_DEVICE_INFO DeviceInfo)
274 {
275     KSRESET ResetStream;
276     NTSTATUS Status;
277     ULONG BytesReturned;
278     PFILE_OBJECT FileObject;
279 
280     DPRINT("WdmAudResetStream\n");
281 
282     Status = ObReferenceObjectByHandle(DeviceInfo->hDevice, GENERIC_READ | GENERIC_WRITE, *IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
283     if (!NT_SUCCESS(Status))
284     {
285         DPRINT1("Error: invalid device handle provided %p Type %x\n", DeviceInfo->hDevice, DeviceInfo->DeviceType);
286         return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
287     }
288 
289     ResetStream = DeviceInfo->u.ResetStream;
290     ASSERT(ResetStream == KSRESET_BEGIN || ResetStream == KSRESET_END);
291 
292     Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_RESET_STATE, (PVOID)&ResetStream, sizeof(KSRESET), NULL, 0, &BytesReturned);
293 
294     ObDereferenceObject(FileObject);
295 
296     DPRINT("WdmAudResetStream Status %x\n", Status);
297     return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO));
298 }
299 
300 NTSTATUS
301 NTAPI
302 WdmAudDeviceControl(
303     IN  PDEVICE_OBJECT DeviceObject,
304     IN  PIRP Irp)
305 {
306     PIO_STACK_LOCATION IoStack;
307     PWDMAUD_DEVICE_INFO DeviceInfo;
308     PWDMAUD_CLIENT ClientInfo;
309 
310     IoStack = IoGetCurrentIrpStackLocation(Irp);
311 
312     DPRINT("WdmAudDeviceControl entered\n");
313 
314     if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(WDMAUD_DEVICE_INFO))
315     {
316         /* invalid parameter */
317         DPRINT1("Input buffer too small size %u expected %u\n", IoStack->Parameters.DeviceIoControl.InputBufferLength, sizeof(WDMAUD_DEVICE_INFO));
318         return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, 0);
319     }
320 
321     DeviceInfo = (PWDMAUD_DEVICE_INFO)Irp->AssociatedIrp.SystemBuffer;
322 
323     if (DeviceInfo->DeviceType < MIN_SOUND_DEVICE_TYPE || DeviceInfo->DeviceType > MAX_SOUND_DEVICE_TYPE)
324     {
325         /* invalid parameter */
326         DPRINT1("Error: device type not set\n");
327         return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, 0);
328     }
329 
330     if (!IoStack->FileObject || !IoStack->FileObject->FsContext)
331     {
332         /* file object parameter */
333         DPRINT1("Error: file object is not attached\n");
334         return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
335     }
336     ClientInfo = (PWDMAUD_CLIENT)IoStack->FileObject->FsContext;
337 
338     DPRINT("WdmAudDeviceControl entered\n");
339 
340     switch(IoStack->Parameters.DeviceIoControl.IoControlCode)
341     {
342         case IOCTL_OPEN_WDMAUD:
343             return WdmAudControlOpen(DeviceObject, Irp, DeviceInfo, ClientInfo);
344         case IOCTL_GETNUMDEVS_TYPE:
345             return WdmAudControlDeviceType(DeviceObject, Irp, DeviceInfo, ClientInfo);
346         case IOCTL_SETDEVICE_STATE:
347             return WdmAudControlDeviceState(DeviceObject, Irp, DeviceInfo, ClientInfo);
348         case IOCTL_GETCAPABILITIES:
349             return WdmAudCapabilities(DeviceObject, Irp, DeviceInfo, ClientInfo);
350         case IOCTL_CLOSE_WDMAUD:
351             return WdmAudIoctlClose(DeviceObject, Irp, DeviceInfo, ClientInfo);
352         case IOCTL_GETFRAMESIZE:
353             return WdmAudFrameSize(DeviceObject, Irp, DeviceInfo, ClientInfo);
354         case IOCTL_GETLINEINFO:
355             return WdmAudGetLineInfo(DeviceObject, Irp, DeviceInfo, ClientInfo);
356         case IOCTL_GETLINECONTROLS:
357             return WdmAudGetLineControls(DeviceObject, Irp, DeviceInfo, ClientInfo);
358         case IOCTL_SETCONTROLDETAILS:
359             return WdmAudSetControlDetails(DeviceObject, Irp, DeviceInfo, ClientInfo);
360         case IOCTL_GETCONTROLDETAILS:
361             return WdmAudGetControlDetails(DeviceObject, Irp, DeviceInfo, ClientInfo);
362         case IOCTL_QUERYDEVICEINTERFACESTRING:
363             return WdmAudGetDeviceInterface(DeviceObject, Irp, DeviceInfo);
364         case IOCTL_GET_MIXER_EVENT:
365             return WdmAudGetMixerEvent(DeviceObject, Irp, DeviceInfo, ClientInfo);
366         case IOCTL_RESET_STREAM:
367             return WdmAudResetStream(DeviceObject, Irp, DeviceInfo);
368         case IOCTL_GETPOS:
369             return WdmAudGetPosition(DeviceObject, Irp, DeviceInfo);
370         case IOCTL_GETDEVID:
371         case IOCTL_GETVOLUME:
372         case IOCTL_SETVOLUME:
373 
374            DPRINT1("Unhandled %x\n", IoStack->Parameters.DeviceIoControl.IoControlCode);
375            break;
376     }
377 
378     return SetIrpIoStatus(Irp, STATUS_NOT_IMPLEMENTED, 0);
379 }
380 
381 NTSTATUS
382 NTAPI
383 IoCompletion (
384     PDEVICE_OBJECT DeviceObject,
385     PIRP Irp,
386     PVOID Ctx)
387 {
388     PKSSTREAM_HEADER Header;
389     PMDL Mdl, NextMdl;
390     PWDMAUD_COMPLETION_CONTEXT Context = (PWDMAUD_COMPLETION_CONTEXT)Ctx;
391 
392     /* get stream header */
393     Header = (PKSSTREAM_HEADER)Irp->AssociatedIrp.SystemBuffer;
394 
395     /* sanity check */
396     ASSERT(Header);
397 
398     /* time to free all allocated mdls */
399     Mdl = Irp->MdlAddress;
400 
401     while(Mdl)
402     {
403         /* get next mdl */
404         NextMdl = Mdl->Next;
405 
406         /* unlock pages */
407         MmUnlockPages(Mdl);
408 
409         /* grab next mdl */
410         Mdl = NextMdl;
411     }
412     //IoFreeMdl(Mdl);
413     /* clear mdl list */
414     Irp->MdlAddress = Context->Mdl;
415 
416 
417 
418     DPRINT("IoCompletion Irp %p IoStatus %lx Information %lx\n", Irp, Irp->IoStatus.Status, Irp->IoStatus.Information);
419 
420     if (!NT_SUCCESS(Irp->IoStatus.Status))
421     {
422         /* failed */
423         Irp->IoStatus.Information = 0;
424     }
425 
426     /* dereference file object */
427     ObDereferenceObject(Context->FileObject);
428 
429     /* free context */
430     FreeItem(Context);
431 
432     return STATUS_SUCCESS;
433 }
434 
435 NTSTATUS
436 NTAPI
437 WdmAudReadWrite(
438     IN  PDEVICE_OBJECT DeviceObject,
439     IN  PIRP Irp)
440 {
441     NTSTATUS Status;
442     PWDMAUD_DEVICE_INFO DeviceInfo;
443     PFILE_OBJECT FileObject;
444     PIO_STACK_LOCATION IoStack;
445     ULONG Length;
446     PMDL Mdl;
447     BOOLEAN Read = TRUE;
448     PWDMAUD_COMPLETION_CONTEXT Context;
449 
450     /* allocate completion context */
451     Context = AllocateItem(NonPagedPool, sizeof(WDMAUD_COMPLETION_CONTEXT));
452 
453     if (!Context)
454     {
455         /* not enough memory */
456         Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
457         IoCompleteRequest(Irp, IO_NO_INCREMENT);
458 
459         /* done */
460         return STATUS_INSUFFICIENT_RESOURCES;
461     }
462 
463     /* get current irp stack location */
464     IoStack = IoGetCurrentIrpStackLocation(Irp);
465 
466     /* store the input buffer in UserBuffer - as KsProbeStreamIrp operates on IRP_MJ_DEVICE_CONTROL */
467     Irp->UserBuffer = MmGetMdlVirtualAddress(Irp->MdlAddress);
468 
469     /* sanity check */
470     ASSERT(Irp->UserBuffer);
471 
472     /* get the length of the request length */
473     Length = IoStack->Parameters.Write.Length;
474 
475     /* store outputbuffer length */
476     IoStack->Parameters.DeviceIoControl.OutputBufferLength = Length;
477 
478     /* setup context */
479     Context->Length = Length;
480     Context->Function = (IoStack->MajorFunction == IRP_MJ_WRITE ? IOCTL_KS_WRITE_STREAM : IOCTL_KS_READ_STREAM);
481     Context->Mdl = Irp->MdlAddress;
482 
483     /* store mdl address */
484     Mdl = Irp->MdlAddress;
485 
486     /* remove mdladdress as KsProbeStreamIrp will interpret it as an already probed audio buffer */
487     Irp->MdlAddress = NULL;
488 
489     if (IoStack->MajorFunction == IRP_MJ_WRITE)
490     {
491         /* probe the write stream irp */
492         Read = FALSE;
493         Status = KsProbeStreamIrp(Irp, KSPROBE_STREAMWRITE | KSPROBE_ALLOCATEMDL | KSPROBE_PROBEANDLOCK, Length);
494     }
495     else
496     {
497         /* probe the read stream irp */
498         Status = KsProbeStreamIrp(Irp, KSPROBE_STREAMREAD | KSPROBE_ALLOCATEMDL | KSPROBE_PROBEANDLOCK, Length);
499     }
500 
501     if (!NT_SUCCESS(Status))
502     {
503         DPRINT1("KsProbeStreamIrp failed with Status %x Cancel %u\n", Status, Irp->Cancel);
504         Irp->MdlAddress = Mdl;
505         FreeItem(Context);
506         return SetIrpIoStatus(Irp, Status, 0);
507     }
508 
509     /* get device info */
510     DeviceInfo = (PWDMAUD_DEVICE_INFO)Irp->AssociatedIrp.SystemBuffer;
511     ASSERT(DeviceInfo);
512 
513     /* now get sysaudio file object */
514     Status = ObReferenceObjectByHandle(DeviceInfo->hDevice, GENERIC_WRITE, *IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
515     if (!NT_SUCCESS(Status))
516     {
517         DPRINT1("Invalid pin handle %p\n", DeviceInfo->hDevice);
518         Irp->MdlAddress = Mdl;
519         FreeItem(Context);
520         return SetIrpIoStatus(Irp, Status, 0);
521     }
522 
523     /* store file object whose reference is released in the completion callback */
524     Context->FileObject = FileObject;
525 
526     /* skip current irp stack location */
527     IoSkipCurrentIrpStackLocation(Irp);
528 
529     /* get next stack location */
530     IoStack = IoGetNextIrpStackLocation(Irp);
531 
532     /* prepare stack location */
533     IoStack->FileObject = FileObject;
534     IoStack->Parameters.Write.Length = Length;
535     IoStack->MajorFunction = IRP_MJ_WRITE;
536     IoStack->Parameters.DeviceIoControl.IoControlCode = (Read ? IOCTL_KS_READ_STREAM : IOCTL_KS_WRITE_STREAM);
537     IoSetCompletionRoutine(Irp, IoCompletion, (PVOID)Context, TRUE, TRUE, TRUE);
538 
539     /* mark irp as pending */
540 //    IoMarkIrpPending(Irp);
541     /* call the driver */
542     Status = IoCallDriver(IoGetRelatedDeviceObject(FileObject), Irp);
543     return Status;
544 }
545