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