Sync tools to 45592
[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 #include "wdmaud.h"
10
11 const GUID KSPROPSETID_Pin = {0x8C134960L, 0x51AD, 0x11CF, {0x87, 0x8A, 0x94, 0xF8, 0x01, 0xC1, 0x00, 0x00}};
12 const GUID KSPROPSETID_Connection = {0x1D58C920L, 0xAC9B, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
13 const GUID KSPROPSETID_Sysaudio = {0xCBE3FAA0L, 0xCC75, 0x11D0, {0xB4, 0x65, 0x00, 0x00, 0x1A, 0x18, 0x18, 0xE6}};
14 const GUID KSPROPSETID_General = {0x1464EDA5L, 0x6A8F, 0x11D1, {0x9A, 0xA7, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
15 const GUID KSINTERFACESETID_Standard = {0x1A8766A0L, 0x62CE, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
16 const GUID KSMEDIUMSETID_Standard = {0x4747B320L, 0x62CE, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
17 const GUID KSDATAFORMAT_TYPE_AUDIO = {0x73647561L, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
18 const GUID KSDATAFORMAT_SUBTYPE_PCM = {0x00000001L, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
19 const GUID KSDATAFORMAT_SPECIFIER_WAVEFORMATEX = {0x05589f81L, 0xc356, 0x11ce, {0xbf, 0x01, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a}};
20 const GUID KSPROPSETID_Topology = {0x720D4AC0L, 0x7533, 0x11D0, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
21
22
23 NTSTATUS
24 WdmAudControlOpen(
25 IN PDEVICE_OBJECT DeviceObject,
26 IN PIRP Irp,
27 IN PWDMAUD_DEVICE_INFO DeviceInfo,
28 IN PWDMAUD_CLIENT ClientInfo)
29 {
30 if (DeviceInfo->DeviceType == MIXER_DEVICE_TYPE)
31 {
32 return WdmAudControlOpenMixer(DeviceObject, Irp, DeviceInfo, ClientInfo);
33 }
34
35 if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE || DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE)
36 {
37 return WdmAudControlOpenWave(DeviceObject, Irp, DeviceInfo, ClientInfo);
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 = DeviceExtension->MixerInfoCount;
59 }
60 else if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE)
61 {
62 Result = DeviceExtension->WaveOutDeviceCount;
63 }
64 else if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE)
65 {
66 Result = DeviceExtension->WaveInDeviceCount;
67 }
68
69 /* store result count */
70 DeviceInfo->DeviceCount = Result;
71
72 DPRINT("WdmAudControlDeviceType Status %x Devices %u\n", Status, DeviceInfo->DeviceCount);
73 return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
74 }
75
76 NTSTATUS
77 WdmAudControlDeviceState(
78 IN PDEVICE_OBJECT DeviceObject,
79 IN PIRP Irp,
80 IN PWDMAUD_DEVICE_INFO DeviceInfo,
81 IN PWDMAUD_CLIENT ClientInfo)
82 {
83 KSPROPERTY Property;
84 KSSTATE State;
85 NTSTATUS Status;
86 ULONG BytesReturned;
87 PFILE_OBJECT FileObject;
88
89 DPRINT("WdmAudControlDeviceState\n");
90
91 Status = ObReferenceObjectByHandle(DeviceInfo->hDevice, GENERIC_READ | GENERIC_WRITE, IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
92 if (!NT_SUCCESS(Status))
93 {
94 DPRINT1("Error: invalid device handle provided %p Type %x\n", DeviceInfo->hDevice, DeviceInfo->DeviceType);
95 return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
96 }
97
98 Property.Set = KSPROPSETID_Connection;
99 Property.Id = KSPROPERTY_CONNECTION_STATE;
100 Property.Flags = KSPROPERTY_TYPE_SET;
101
102 State = DeviceInfo->u.State;
103
104 Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&State, sizeof(KSSTATE), &BytesReturned);
105
106 ObDereferenceObject(FileObject);
107
108 DPRINT("WdmAudControlDeviceState Status %x\n", Status);
109 return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO));
110 }
111
112 NTSTATUS
113 WdmAudCapabilities(
114 IN PDEVICE_OBJECT DeviceObject,
115 IN PIRP Irp,
116 IN PWDMAUD_DEVICE_INFO DeviceInfo,
117 IN PWDMAUD_CLIENT ClientInfo)
118 {
119 PWDMAUD_DEVICE_EXTENSION DeviceExtension;
120 NTSTATUS Status = STATUS_UNSUCCESSFUL;
121
122 DPRINT("WdmAudCapabilities entered\n");
123
124 DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
125
126 if (DeviceInfo->DeviceType == MIXER_DEVICE_TYPE)
127 {
128 Status = WdmAudMixerCapabilities(DeviceObject, DeviceInfo, ClientInfo, DeviceExtension);
129 }
130 else if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE || DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE)
131 {
132 Status = WdmAudWaveCapabilities(DeviceObject, DeviceInfo, ClientInfo, DeviceExtension);
133 }
134
135 return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO));
136 }
137
138 NTSTATUS
139 NTAPI
140 WdmAudIoctlClose(
141 IN PDEVICE_OBJECT DeviceObject,
142 IN PIRP Irp,
143 IN PWDMAUD_DEVICE_INFO DeviceInfo,
144 IN PWDMAUD_CLIENT ClientInfo)
145 {
146 ULONG Index;
147
148 for(Index = 0; Index < ClientInfo->NumPins; Index++)
149 {
150 if (ClientInfo->hPins[Index].Handle == DeviceInfo->hDevice && ClientInfo->hPins[Index].Type != MIXER_DEVICE_TYPE)
151 {
152 DPRINT1("Closing device %p\n", DeviceInfo->hDevice);
153 ZwClose(DeviceInfo->hDevice);
154 ClientInfo->hPins[Index].Handle = NULL;
155 SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
156 return STATUS_SUCCESS;
157 }
158 else if (ClientInfo->hPins[Index].Handle == DeviceInfo->hDevice && ClientInfo->hPins[Index].Type == MIXER_DEVICE_TYPE)
159 {
160 if (ClientInfo->hPins[Index].NotifyEvent)
161 {
162 ObDereferenceObject(ClientInfo->hPins[Index].NotifyEvent);
163 ClientInfo->hPins[Index].NotifyEvent = NULL;
164 }
165 }
166 }
167
168 SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, sizeof(WDMAUD_DEVICE_INFO));
169 return STATUS_INVALID_PARAMETER;
170 }
171
172 NTSTATUS
173 NTAPI
174 WdmAudFrameSize(
175 IN PDEVICE_OBJECT DeviceObject,
176 IN PIRP Irp,
177 IN PWDMAUD_DEVICE_INFO DeviceInfo,
178 IN PWDMAUD_CLIENT ClientInfo)
179 {
180 PFILE_OBJECT FileObject;
181 KSPROPERTY Property;
182 ULONG BytesReturned;
183 KSALLOCATOR_FRAMING Framing;
184 NTSTATUS Status;
185
186 /* Get sysaudio pin file object */
187 Status = ObReferenceObjectByHandle(DeviceInfo->hDevice, GENERIC_WRITE, IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
188 if (!NT_SUCCESS(Status))
189 {
190 DPRINT1("Invalid buffer handle %p\n", DeviceInfo->hDevice);
191 return SetIrpIoStatus(Irp, Status, 0);
192 }
193
194 /* Setup get framing request */
195 Property.Id = KSPROPERTY_CONNECTION_ALLOCATORFRAMING;
196 Property.Flags = KSPROPERTY_TYPE_GET;
197 Property.Set = KSPROPSETID_Connection;
198
199 Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&Framing, sizeof(KSALLOCATOR_FRAMING), &BytesReturned);
200 /* Did we succeed */
201 if (NT_SUCCESS(Status))
202 {
203 /* Store framesize */
204 DeviceInfo->u.FrameSize = Framing.FrameSize;
205 }
206
207 /* Release file object */
208 ObDereferenceObject(FileObject);
209
210 return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO));
211
212 }
213
214 NTSTATUS
215 NTAPI
216 WdmAudGetDeviceInterface(
217 IN PDEVICE_OBJECT DeviceObject,
218 IN PIRP Irp,
219 IN PWDMAUD_DEVICE_INFO DeviceInfo)
220 {
221 PWDMAUD_DEVICE_EXTENSION DeviceExtension;
222 NTSTATUS Status;
223 LPWSTR Device;
224 LPWAVE_INFO WaveInfo;
225 ULONG Size, Length;
226
227 /* get device extension */
228 DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
229
230 /* get device interface string input length */
231 Size = DeviceInfo->u.Interface.DeviceInterfaceStringSize;
232
233 if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE || DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE)
234 {
235 /* get wave info */
236 Status = GetWaveInfoByIndexAndType(DeviceObject, DeviceInfo->DeviceIndex, DeviceInfo->DeviceType, &WaveInfo);
237
238 /* check for success */
239 if (!NT_SUCCESS(Status))
240 {
241 /* invalid device id */
242 return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO));
243 }
244
245 Status = GetSysAudioDevicePnpName(DeviceObject, WaveInfo->FilterId, &Device);
246 /* check for success */
247 if (!NT_SUCCESS(Status))
248 {
249 /* invalid device id */
250 return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO));
251 }
252
253 /* calculate length */
254 Length = (wcslen(Device)+1) * sizeof(WCHAR);
255
256 if (!Size)
257 {
258 /* store device interface size */
259 DeviceInfo->u.Interface.DeviceInterfaceStringSize = Length;
260 }
261 else if (Size < Length)
262 {
263 /* buffer too small */
264 DeviceInfo->u.Interface.DeviceInterfaceStringSize = Length;
265 return SetIrpIoStatus(Irp, STATUS_BUFFER_OVERFLOW, sizeof(WDMAUD_DEVICE_INFO));
266 }
267 else
268 {
269 //FIXME SEH
270 RtlMoveMemory(DeviceInfo->u.Interface.DeviceInterfaceString, Device, Length);
271 }
272
273 ExFreePool(Device);
274 return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
275 }
276 else if (DeviceInfo->DeviceType == MIXER_DEVICE_TYPE)
277 {
278 if (DeviceInfo->DeviceIndex >= DeviceExtension->MixerInfoCount)
279 {
280 /* invalid device id */
281 return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, sizeof(WDMAUD_DEVICE_INFO));
282 }
283
284 Status = GetSysAudioDevicePnpName(DeviceObject, DeviceExtension->MixerInfo[DeviceInfo->DeviceIndex].DeviceIndex, &Device);
285 /* check for success */
286 if (!NT_SUCCESS(Status))
287 {
288 /* invalid device id */
289 return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO));
290 }
291
292 /* calculate length */
293 Length = (wcslen(Device)+1) * sizeof(WCHAR);
294
295 if (!Size)
296 {
297 /* store device interface size */
298 DeviceInfo->u.Interface.DeviceInterfaceStringSize = Length;
299 }
300 else if (Size < Length)
301 {
302 /* buffer too small */
303 DeviceInfo->u.Interface.DeviceInterfaceStringSize = Length;
304 return SetIrpIoStatus(Irp, STATUS_BUFFER_OVERFLOW, sizeof(WDMAUD_DEVICE_INFO));
305 }
306 else
307 {
308 //FIXME SEH
309 RtlMoveMemory(DeviceInfo->u.Interface.DeviceInterfaceString, Device, Length);
310 }
311
312 ExFreePool(Device);
313 return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
314 }
315
316 return SetIrpIoStatus(Irp, STATUS_INVALID_DEVICE_REQUEST, sizeof(WDMAUD_DEVICE_INFO));
317 }
318
319 NTSTATUS
320 NTAPI
321 WdmAudResetStream(
322 IN PDEVICE_OBJECT DeviceObject,
323 IN PIRP Irp,
324 IN PWDMAUD_DEVICE_INFO DeviceInfo)
325 {
326 KSRESET ResetStream;
327 NTSTATUS Status;
328 ULONG BytesReturned;
329 PFILE_OBJECT FileObject;
330
331 DPRINT("WdmAudResetStream\n");
332
333 Status = ObReferenceObjectByHandle(DeviceInfo->hDevice, GENERIC_READ | GENERIC_WRITE, IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
334 if (!NT_SUCCESS(Status))
335 {
336 DPRINT1("Error: invalid device handle provided %p Type %x\n", DeviceInfo->hDevice, DeviceInfo->DeviceType);
337 return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
338 }
339
340 ResetStream = DeviceInfo->u.ResetStream;
341 ASSERT(ResetStream == KSRESET_BEGIN || ResetStream == KSRESET_END);
342
343 Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_RESET_STATE, (PVOID)&ResetStream, sizeof(KSRESET), NULL, 0, &BytesReturned);
344
345 ObDereferenceObject(FileObject);
346
347 DPRINT("WdmAudResetStream Status %x\n", Status);
348 return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO));
349 }
350
351 NTSTATUS
352 NTAPI
353 WdmAudDeviceControl(
354 IN PDEVICE_OBJECT DeviceObject,
355 IN PIRP Irp)
356 {
357 PIO_STACK_LOCATION IoStack;
358 PWDMAUD_DEVICE_INFO DeviceInfo;
359 PWDMAUD_CLIENT ClientInfo;
360
361 IoStack = IoGetCurrentIrpStackLocation(Irp);
362
363 DPRINT("WdmAudDeviceControl entered\n");
364
365 if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(WDMAUD_DEVICE_INFO))
366 {
367 /* invalid parameter */
368 DPRINT1("Input buffer too small size %u expected %u\n", IoStack->Parameters.DeviceIoControl.InputBufferLength, sizeof(WDMAUD_DEVICE_INFO));
369 return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, 0);
370 }
371
372 DeviceInfo = (PWDMAUD_DEVICE_INFO)Irp->AssociatedIrp.SystemBuffer;
373
374 if (DeviceInfo->DeviceType < MIN_SOUND_DEVICE_TYPE || DeviceInfo->DeviceType > MAX_SOUND_DEVICE_TYPE)
375 {
376 /* invalid parameter */
377 DPRINT1("Error: device type not set\n");
378 return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, 0);
379 }
380
381 if (!IoStack->FileObject)
382 {
383 /* file object parameter */
384 DPRINT1("Error: file object is not attached\n");
385 return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
386 }
387 ClientInfo = (PWDMAUD_CLIENT)IoStack->FileObject->FsContext;
388
389 DPRINT("WdmAudDeviceControl entered\n");
390
391 switch(IoStack->Parameters.DeviceIoControl.IoControlCode)
392 {
393 case IOCTL_OPEN_WDMAUD:
394 return WdmAudControlOpen(DeviceObject, Irp, DeviceInfo, ClientInfo);
395 case IOCTL_GETNUMDEVS_TYPE:
396 return WdmAudControlDeviceType(DeviceObject, Irp, DeviceInfo, ClientInfo);
397 case IOCTL_SETDEVICE_STATE:
398 return WdmAudControlDeviceState(DeviceObject, Irp, DeviceInfo, ClientInfo);
399 case IOCTL_GETCAPABILITIES:
400 return WdmAudCapabilities(DeviceObject, Irp, DeviceInfo, ClientInfo);
401 case IOCTL_CLOSE_WDMAUD:
402 return WdmAudIoctlClose(DeviceObject, Irp, DeviceInfo, ClientInfo);
403 case IOCTL_GETFRAMESIZE:
404 return WdmAudFrameSize(DeviceObject, Irp, DeviceInfo, ClientInfo);
405 case IOCTL_GETLINEINFO:
406 return WdmAudGetLineInfo(DeviceObject, Irp, DeviceInfo, ClientInfo);
407 case IOCTL_GETLINECONTROLS:
408 return WdmAudGetLineControls(DeviceObject, Irp, DeviceInfo, ClientInfo);
409 case IOCTL_SETCONTROLDETAILS:
410 return WdmAudSetControlDetails(DeviceObject, Irp, DeviceInfo, ClientInfo);
411 case IOCTL_GETCONTROLDETAILS:
412 return WdmAudGetControlDetails(DeviceObject, Irp, DeviceInfo, ClientInfo);
413 case IOCTL_QUERYDEVICEINTERFACESTRING:
414 return WdmAudGetDeviceInterface(DeviceObject, Irp, DeviceInfo);
415 case IOCTL_GET_MIXER_EVENT:
416 return WdmAudGetMixerEvent(DeviceObject, Irp, DeviceInfo, ClientInfo);
417 case IOCTL_RESET_STREAM:
418 return WdmAudResetStream(DeviceObject, Irp, DeviceInfo);
419 case IOCTL_GETPOS:
420 case IOCTL_GETDEVID:
421 case IOCTL_GETVOLUME:
422 case IOCTL_SETVOLUME:
423
424 DPRINT1("Unhandeled %x\n", IoStack->Parameters.DeviceIoControl.IoControlCode);
425 break;
426 }
427
428 return SetIrpIoStatus(Irp, STATUS_NOT_IMPLEMENTED, 0);
429 }
430
431
432 NTSTATUS
433 NTAPI
434 WdmAudReadWrite(
435 IN PDEVICE_OBJECT DeviceObject,
436 IN PIRP Irp)
437 {
438 NTSTATUS Status;
439 PWDMAUD_DEVICE_INFO DeviceInfo;
440 PFILE_OBJECT FileObject;
441 PIO_STACK_LOCATION IoStack;
442 ULONG Length;
443 PMDL Mdl;
444 BOOLEAN Read = TRUE;
445
446 /* get current irp stack location */
447 IoStack = IoGetCurrentIrpStackLocation(Irp);
448
449 /* store the input buffer in UserBuffer - as KsProbeStreamIrp operates on IRP_MJ_DEVICE_CONTROL */
450 Irp->UserBuffer = MmGetMdlVirtualAddress(Irp->MdlAddress);
451
452 /* sanity check */
453 ASSERT(Irp->UserBuffer);
454
455 /* get the length of the request length */
456 Length = IoStack->Parameters.Write.Length;
457
458 /* store outputbuffer length */
459 IoStack->Parameters.DeviceIoControl.OutputBufferLength = Length;
460
461 /* store mdl address */
462 Mdl = Irp->MdlAddress;
463
464 /* remove mdladdress as KsProbeStreamIrp will interprete it as an already probed audio buffer */
465 Irp->MdlAddress = NULL;
466
467 /* check for success */
468
469 if (IoStack->MajorFunction == IRP_MJ_WRITE)
470 {
471 /* probe the write stream irp */
472 Read = FALSE;
473 Status = KsProbeStreamIrp(Irp, KSPROBE_STREAMWRITE | KSPROBE_ALLOCATEMDL | KSPROBE_PROBEANDLOCK, Length);
474 }
475 else
476 {
477 /* probe the read stream irp */
478 Status = KsProbeStreamIrp(Irp, KSPROBE_STREAMREAD | KSPROBE_ALLOCATEMDL | KSPROBE_PROBEANDLOCK, Length);
479 }
480
481 /* now free the mdl */
482 IoFreeMdl(Mdl);
483
484 if (!NT_SUCCESS(Status))
485 {
486 DPRINT1("KsProbeStreamIrp failed with Status %x Cancel %u\n", Status, Irp->Cancel);
487 return SetIrpIoStatus(Irp, Status, 0);
488 }
489
490 /* get device info */
491 DeviceInfo = (PWDMAUD_DEVICE_INFO)Irp->AssociatedIrp.SystemBuffer;
492 ASSERT(DeviceInfo);
493
494 /* now get sysaudio file object */
495 Status = ObReferenceObjectByHandle(DeviceInfo->hDevice, GENERIC_WRITE, IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
496 if (!NT_SUCCESS(Status))
497 {
498 DPRINT1("Invalid pin handle %p\n", DeviceInfo->hDevice);
499 return SetIrpIoStatus(Irp, Status, 0);
500 }
501
502 /* skip current irp stack location */
503 IoSkipCurrentIrpStackLocation(Irp);
504
505 /* get next stack location */
506 IoStack = IoGetNextIrpStackLocation(Irp);
507
508 if (Read)
509 {
510 IoStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_KS_READ_STREAM;
511 }
512 else
513 {
514 IoStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_KS_WRITE_STREAM;
515 }
516
517 /* attach file object */
518 IoStack->FileObject = FileObject;
519 IoStack->Parameters.Write.Length = Length;
520 IoStack->MajorFunction = IRP_MJ_WRITE;
521
522 /* mark irp as pending */
523 // IoMarkIrpPending(Irp);
524 /* call the driver */
525 Status = IoCallDriver(IoGetRelatedDeviceObject(FileObject), Irp);
526
527 /* dereference file object */
528 ObDereferenceObject(FileObject);
529
530 return Status;
531 }