- Remove dead code
[reactos.git] / reactos / drivers / wdm / audio / backpln / portcls / port_wavert.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel Streaming
4 * FILE: drivers/wdm/audio/backpln/portcls/port_wavert.c
5 * PURPOSE: WaveRT Port Driver
6 * PROGRAMMER: Johannes Anderwald
7 */
8
9 #include "private.h"
10
11 typedef struct
12 {
13 IPortWaveRTVtbl *lpVtbl;
14 IPortEventsVtbl *lpVbtlPortEvents;
15 IUnregisterSubdeviceVtbl *lpVtblUnregisterSubdevice;
16 IUnregisterPhysicalConnectionVtbl *lpVtblPhysicalConnection;
17 IPortEventsVtbl *lpVtblPortEvents;
18 ISubdeviceVtbl *lpVtblSubDevice;
19
20 LONG ref;
21
22 BOOL bInitialized;
23 PDEVICE_OBJECT pDeviceObject;
24 PMINIPORTWAVERT pMiniport;
25 PRESOURCELIST pResourceList;
26 PPINCOUNT pPinCount;
27 PPOWERNOTIFY pPowerNotify;
28 PPCFILTER_DESCRIPTOR pDescriptor;
29 PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor;
30 IPortFilterWaveRT * Filter;
31 }IPortWaveRTImpl;
32
33 static GUID InterfaceGuids[3] =
34 {
35 {
36 /// KSCATEGORY_RENDER
37 0x65E8773EL, 0x8F56, 0x11D0, {0xA3, 0xB9, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}
38 },
39 {
40 /// KSCATEGORY_CAPTURE
41 0x65E8773DL, 0x8F56, 0x11D0, {0xA3, 0xB9, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}
42 },
43 {
44 /// KS_CATEGORY_AUDIO
45 0x6994AD04, 0x93EF, 0x11D0, {0xA3, 0xCC, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}
46 }
47 };
48
49 DEFINE_KSPROPERTY_TOPOLOGYSET(PortFilterWaveRTTopologySet, TopologyPropertyHandler);
50 DEFINE_KSPROPERTY_PINPROPOSEDATAFORMAT(PortFilterWaveRTPinSet, PinPropertyHandler, PinPropertyHandler, PinPropertyHandler);
51
52 KSPROPERTY_SET WaveRTPropertySet[] =
53 {
54 {
55 &KSPROPSETID_Topology,
56 sizeof(PortFilterWaveRTTopologySet) / sizeof(KSPROPERTY_ITEM),
57 (const KSPROPERTY_ITEM*)&PortFilterWaveRTTopologySet,
58 0,
59 NULL
60 },
61 {
62 &KSPROPSETID_Pin,
63 sizeof(PortFilterWaveRTPinSet) / sizeof(KSPROPERTY_ITEM),
64 (const KSPROPERTY_ITEM*)&PortFilterWaveRTPinSet,
65 0,
66 NULL
67 }
68 };
69
70 //KSEVENTSETID_LoopedStreaming, Type = KSEVENT_LOOPEDSTREAMING_POSITION
71 //KSEVENTSETID_Connection, Type = KSEVENT_CONNECTION_ENDOFSTREAM,
72
73
74
75 #if 0
76 static const KSIDENTIFIER Identifiers[] =
77 {
78 {
79 &KSINTERFACESETID_Standard,
80 0,
81 0
82 },
83 {
84 &KSINTERFACESETID_Standard,
85 1,
86 0
87 }
88 };
89 #endif
90
91 //---------------------------------------------------------------
92 // IPortEvents
93 //
94
95 static
96 NTSTATUS
97 NTAPI
98 IPortEvents_fnQueryInterface(
99 IPortEvents* iface,
100 IN REFIID refiid,
101 OUT PVOID* Output)
102 {
103 IPortWaveRTImpl * This = (IPortWaveRTImpl*)CONTAINING_RECORD(iface, IPortWaveRTImpl, lpVtblPortEvents);
104
105 DPRINT("IPortEvents_fnQueryInterface entered\n");
106
107 if (IsEqualGUIDAligned(refiid, &IID_IPortEvents) ||
108 IsEqualGUIDAligned(refiid, &IID_IUnknown))
109 {
110 *Output = &This->lpVbtlPortEvents;
111 InterlockedIncrement(&This->ref);
112 return STATUS_SUCCESS;
113 }
114 return STATUS_UNSUCCESSFUL;
115 }
116
117 static
118 ULONG
119 NTAPI
120 IPortEvents_fnAddRef(
121 IPortEvents* iface)
122 {
123 IPortWaveRTImpl * This = (IPortWaveRTImpl*)CONTAINING_RECORD(iface, IPortWaveRTImpl, lpVtblPortEvents);
124 DPRINT("IPortEvents_fnQueryInterface entered\n");
125 return InterlockedIncrement(&This->ref);
126 }
127
128 static
129 ULONG
130 NTAPI
131 IPortEvents_fnRelease(
132 IPortEvents* iface)
133 {
134 IPortWaveRTImpl * This = (IPortWaveRTImpl*)CONTAINING_RECORD(iface, IPortWaveRTImpl, lpVtblPortEvents);
135
136 DPRINT("IPortEvents_fnRelease entered\n");
137 InterlockedDecrement(&This->ref);
138
139 if (This->ref == 0)
140 {
141 FreeItem(This, TAG_PORTCLASS);
142 return 0;
143 }
144 /* Return new reference count */
145 return This->ref;
146 }
147
148 static
149 void
150 NTAPI
151 IPortEvents_fnAddEventToEventList(
152 IPortEvents* iface,
153 IN PKSEVENT_ENTRY EventEntry)
154 {
155 UNIMPLEMENTED
156 }
157
158
159 static
160 void
161 NTAPI
162 IPortEvents_fnGenerateEventList(
163 IPortEvents* iface,
164 IN GUID* Set OPTIONAL,
165 IN ULONG EventId,
166 IN BOOL PinEvent,
167 IN ULONG PinId,
168 IN BOOL NodeEvent,
169 IN ULONG NodeId)
170 {
171 UNIMPLEMENTED
172 }
173
174 static IPortEventsVtbl vt_IPortEvents =
175 {
176 IPortEvents_fnQueryInterface,
177 IPortEvents_fnAddRef,
178 IPortEvents_fnRelease,
179 IPortEvents_fnAddEventToEventList,
180 IPortEvents_fnGenerateEventList
181 };
182
183 //---------------------------------------------------------------
184 // IUnknown interface functions
185 //
186
187 NTSTATUS
188 NTAPI
189 IPortWaveRT_fnQueryInterface(
190 IPortWaveRT* iface,
191 IN REFIID refiid,
192 OUT PVOID* Output)
193 {
194 UNICODE_STRING GuidString;
195 IPortWaveRTImpl * This = (IPortWaveRTImpl*)iface;
196
197 if (IsEqualGUIDAligned(refiid, &IID_IPortWaveRT) ||
198 IsEqualGUIDAligned(refiid, &IID_IUnknown))
199 {
200 *Output = &This->lpVtbl;
201 InterlockedIncrement(&This->ref);
202 return STATUS_SUCCESS;
203 }
204 else if (IsEqualGUIDAligned(refiid, &IID_IPortEvents))
205 {
206 *Output = &This->lpVtblPortEvents;
207 InterlockedIncrement(&This->ref);
208 return STATUS_SUCCESS;
209 }
210 else if (IsEqualGUIDAligned(refiid, &IID_ISubdevice))
211 {
212 *Output = &This->lpVtblSubDevice;
213 InterlockedIncrement(&This->ref);
214 return STATUS_SUCCESS;
215 }
216 else if (IsEqualGUIDAligned(refiid, &IID_IPortClsVersion))
217 {
218 return NewPortClsVersion((PPORTCLSVERSION*)Output);
219 }
220 else if (IsEqualGUIDAligned(refiid, &IID_IDrmPort) ||
221 IsEqualGUIDAligned(refiid, &IID_IDrmPort2))
222 {
223 return NewIDrmPort((PDRMPORT2*)Output);
224 }
225 else if (IsEqualGUIDAligned(refiid, &IID_IUnregisterSubdevice))
226 {
227 return NewIUnregisterSubdevice((PUNREGISTERSUBDEVICE*)Output);
228 }
229 else if (IsEqualGUIDAligned(refiid, &IID_IUnregisterPhysicalConnection))
230 {
231 return NewIUnregisterPhysicalConnection((PUNREGISTERPHYSICALCONNECTION*)Output);
232 }
233
234 if (RtlStringFromGUID(refiid, &GuidString) == STATUS_SUCCESS)
235 {
236 DPRINT1("IPortWaveRT_fnQueryInterface no interface!!! iface %S\n", GuidString.Buffer);
237 RtlFreeUnicodeString(&GuidString);
238 }
239
240 return STATUS_UNSUCCESSFUL;
241 }
242
243 ULONG
244 NTAPI
245 IPortWaveRT_fnAddRef(
246 IPortWaveRT* iface)
247 {
248 IPortWaveRTImpl * This = (IPortWaveRTImpl*)iface;
249
250 return InterlockedIncrement(&This->ref);
251 }
252
253 ULONG
254 NTAPI
255 IPortWaveRT_fnRelease(
256 IPortWaveRT* iface)
257 {
258 IPortWaveRTImpl * This = (IPortWaveRTImpl*)iface;
259
260 InterlockedDecrement(&This->ref);
261
262 if (This->ref == 0)
263 {
264 if (This->bInitialized)
265 {
266 This->pMiniport->lpVtbl->Release(This->pMiniport);
267 }
268 if (This->pPinCount)
269 This->pPinCount->lpVtbl->Release(This->pPinCount);
270
271 if (This->pPowerNotify)
272 This->pPowerNotify->lpVtbl->Release(This->pPowerNotify);
273
274 FreeItem(This, TAG_PORTCLASS);
275 return 0;
276 }
277 /* Return new reference count */
278 return This->ref;
279 }
280
281
282 //---------------------------------------------------------------
283 // IPort interface functions
284 //
285
286 NTSTATUS
287 NTAPI
288 IPortWaveRT_fnGetDeviceProperty(
289 IN IPortWaveRT * iface,
290 IN DEVICE_REGISTRY_PROPERTY DeviceRegistryProperty,
291 IN ULONG BufferLength,
292 OUT PVOID PropertyBuffer,
293 OUT PULONG ReturnLength)
294 {
295 IPortWaveRTImpl * This = (IPortWaveRTImpl*)iface;
296 ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
297
298 if (!This->bInitialized)
299 {
300 DPRINT("IPortWaveRT_fnNewRegistryKey called w/o initiazed\n");
301 return STATUS_UNSUCCESSFUL;
302 }
303
304 return IoGetDeviceProperty(This->pDeviceObject, DeviceRegistryProperty, BufferLength, PropertyBuffer, ReturnLength);
305 }
306
307 NTSTATUS
308 NTAPI
309 IPortWaveRT_fnInit(
310 IN IPortWaveRT * iface,
311 IN PDEVICE_OBJECT DeviceObject,
312 IN PIRP Irp,
313 IN PUNKNOWN UnknownMiniport,
314 IN PUNKNOWN UnknownAdapter OPTIONAL,
315 IN PRESOURCELIST ResourceList)
316 {
317 IMiniportWaveRT * Miniport;
318 NTSTATUS Status;
319 PPINCOUNT PinCount;
320 PPOWERNOTIFY PowerNotify;
321 IPortWaveRTImpl * This = (IPortWaveRTImpl*)iface;
322
323 DPRINT("IPortWaveRT_Init entered %p\n", This);
324 ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
325
326 if (This->bInitialized)
327 {
328 DPRINT("IPortWaveRT_Init called again\n");
329 return STATUS_SUCCESS;
330 }
331
332 Status = UnknownMiniport->lpVtbl->QueryInterface(UnknownMiniport, &IID_IMiniportWaveRT, (PVOID*)&Miniport);
333 if (!NT_SUCCESS(Status))
334 {
335 DPRINT("IPortWaveRT_Init called with invalid IMiniport adapter\n");
336 return STATUS_INVALID_PARAMETER;
337 }
338
339 /* Initialize port object */
340 This->pMiniport = Miniport;
341 This->pDeviceObject = DeviceObject;
342 This->bInitialized = TRUE;
343 This->pResourceList = ResourceList;
344
345 /* increment reference on miniport adapter */
346 Miniport->lpVtbl->AddRef(Miniport);
347
348 Status = Miniport->lpVtbl->Init(Miniport, UnknownAdapter, ResourceList, iface);
349 if (!NT_SUCCESS(Status))
350 {
351 DPRINT("IMiniportWaveRT_Init failed with %x\n", Status);
352 Miniport->lpVtbl->Release(Miniport);
353 This->bInitialized = FALSE;
354 return Status;
355 }
356
357
358 /* get the miniport device descriptor */
359 Status = Miniport->lpVtbl->GetDescription(Miniport, &This->pDescriptor);
360 if (!NT_SUCCESS(Status))
361 {
362 DPRINT1("failed to get description\n");
363 Miniport->lpVtbl->Release(Miniport);
364 This->bInitialized = FALSE;
365 return Status;
366 }
367
368 /* create the subdevice descriptor */
369 Status = PcCreateSubdeviceDescriptor(&This->SubDeviceDescriptor,
370 3,
371 InterfaceGuids,
372 0,
373 NULL,
374 2,
375 WaveRTPropertySet,
376 0,
377 0,
378 0,
379 NULL,
380 0,
381 NULL,
382 This->pDescriptor);
383
384 if (!NT_SUCCESS(Status))
385 {
386 DPRINT1("PcCreateSubdeviceDescriptor failed with %x\n", Status);
387 Miniport->lpVtbl->Release(Miniport);
388 This->bInitialized = FALSE;
389 return Status;
390 }
391
392 /* check if it supports IPinCount interface */
393 Status = UnknownMiniport->lpVtbl->QueryInterface(UnknownMiniport, &IID_IPinCount, (PVOID*)&PinCount);
394 if (NT_SUCCESS(Status))
395 {
396 /* store IPinCount interface */
397 This->pPinCount = PinCount;
398 }
399
400 /* does the Miniport adapter support IPowerNotify interface*/
401 Status = UnknownMiniport->lpVtbl->QueryInterface(UnknownMiniport, &IID_IPowerNotify, (PVOID*)&PowerNotify);
402 if (NT_SUCCESS(Status))
403 {
404 /* store reference */
405 This->pPowerNotify = PowerNotify;
406 }
407
408 /* increment reference on resource list */
409 ResourceList->lpVtbl->AddRef(ResourceList);
410
411
412 DPRINT("IPortWaveRT successfully initialized\n");
413 return STATUS_SUCCESS;
414 }
415
416
417 NTSTATUS
418 NTAPI
419 IPortWaveRT_fnNewRegistryKey(
420 IN IPortWaveRT * iface,
421 OUT PREGISTRYKEY *OutRegistryKey,
422 IN PUNKNOWN OuterUnknown OPTIONAL,
423 IN ULONG RegistryKeyType,
424 IN ACCESS_MASK DesiredAccess,
425 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
426 IN ULONG CreateOptions OPTIONAL,
427 OUT PULONG Disposition OPTIONAL)
428 {
429 IPortWaveRTImpl * This = (IPortWaveRTImpl*)iface;
430
431 ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
432
433 if (!This->bInitialized)
434 {
435 DPRINT("IPortWaveRT_fnNewRegistryKey called w/o initialized\n");
436 return STATUS_UNSUCCESSFUL;
437 }
438 return PcNewRegistryKey(OutRegistryKey, OuterUnknown, RegistryKeyType, DesiredAccess, This->pDeviceObject, NULL /*FIXME*/, ObjectAttributes, CreateOptions, Disposition);
439 }
440
441 static IPortWaveRTVtbl vt_IPortWaveRTVtbl =
442 {
443 IPortWaveRT_fnQueryInterface,
444 IPortWaveRT_fnAddRef,
445 IPortWaveRT_fnRelease,
446 IPortWaveRT_fnInit,
447 IPortWaveRT_fnGetDeviceProperty,
448 IPortWaveRT_fnNewRegistryKey
449 };
450
451 //---------------------------------------------------------------
452 // ISubdevice interface
453 //
454
455 static
456 NTSTATUS
457 NTAPI
458 ISubDevice_fnQueryInterface(
459 IN ISubdevice *iface,
460 IN REFIID InterfaceId,
461 IN PVOID* Interface)
462 {
463 IPortWaveRTImpl * This = (IPortWaveRTImpl*)CONTAINING_RECORD(iface, IPortWaveRTImpl, lpVtblSubDevice);
464
465 return IPortWaveRT_fnQueryInterface((IPortWaveRT*)This, InterfaceId, Interface);
466 }
467
468 static
469 ULONG
470 NTAPI
471 ISubDevice_fnAddRef(
472 IN ISubdevice *iface)
473 {
474 IPortWaveRTImpl * This = (IPortWaveRTImpl*)CONTAINING_RECORD(iface, IPortWaveRTImpl, lpVtblSubDevice);
475
476 return IPortWaveRT_fnAddRef((IPortWaveRT*)This);
477 }
478
479 static
480 ULONG
481 NTAPI
482 ISubDevice_fnRelease(
483 IN ISubdevice *iface)
484 {
485 IPortWaveRTImpl * This = (IPortWaveRTImpl*)CONTAINING_RECORD(iface, IPortWaveRTImpl, lpVtblSubDevice);
486
487 return IPortWaveRT_fnRelease((IPortWaveRT*)This);
488 }
489
490 static
491 NTSTATUS
492 NTAPI
493 ISubDevice_fnNewIrpTarget(
494 IN ISubdevice *iface,
495 OUT struct IIrpTarget **OutTarget,
496 IN WCHAR * Name,
497 IN PUNKNOWN Unknown,
498 IN POOL_TYPE PoolType,
499 IN PDEVICE_OBJECT DeviceObject,
500 IN PIRP Irp,
501 IN KSOBJECT_CREATE *CreateObject)
502 {
503 NTSTATUS Status;
504 IPortFilterWaveRT * Filter;
505 IPortWaveRTImpl * This = (IPortWaveRTImpl*)CONTAINING_RECORD(iface, IPortWaveRTImpl, lpVtblSubDevice);
506
507 DPRINT("ISubDevice_NewIrpTarget this %p\n", This);
508
509 if (This->Filter)
510 {
511 *OutTarget = (IIrpTarget*)This->Filter;
512 return STATUS_SUCCESS;
513 }
514
515
516 Status = NewPortFilterWaveRT(&Filter);
517 if (!NT_SUCCESS(Status))
518 {
519 return Status;
520 }
521
522 Status = Filter->lpVtbl->Init(Filter, (IPortWaveRT*)This);
523 if (!NT_SUCCESS(Status))
524 {
525 Filter->lpVtbl->Release(Filter);
526 return Status;
527 }
528
529 *OutTarget = (IIrpTarget*)Filter;
530 This->Filter = Filter;
531 return Status;
532 }
533
534 static
535 NTSTATUS
536 NTAPI
537 ISubDevice_fnReleaseChildren(
538 IN ISubdevice *iface)
539 {
540 //IPortWaveRTImpl * This = (IPortWaveRTImpl*)CONTAINING_RECORD(iface, IPortWaveRTImpl, lpVtblSubDevice);
541
542 UNIMPLEMENTED
543 return STATUS_UNSUCCESSFUL;
544 }
545
546 static
547 NTSTATUS
548 NTAPI
549 ISubDevice_fnGetDescriptor(
550 IN ISubdevice *iface,
551 IN SUBDEVICE_DESCRIPTOR ** Descriptor)
552 {
553 IPortWaveRTImpl * This = (IPortWaveRTImpl*)CONTAINING_RECORD(iface, IPortWaveRTImpl, lpVtblSubDevice);
554
555 ASSERT(This->SubDeviceDescriptor != NULL);
556
557 *Descriptor = This->SubDeviceDescriptor;
558
559 DPRINT("ISubDevice_GetDescriptor this %p desc %p\n", This, This->SubDeviceDescriptor);
560 return STATUS_SUCCESS;
561 }
562
563 static
564 NTSTATUS
565 NTAPI
566 ISubDevice_fnDataRangeIntersection(
567 IN ISubdevice *iface,
568 IN ULONG PinId,
569 IN PKSDATARANGE DataRange,
570 IN PKSDATARANGE MatchingDataRange,
571 IN ULONG OutputBufferLength,
572 OUT PVOID ResultantFormat OPTIONAL,
573 OUT PULONG ResultantFormatLength)
574 {
575 IPortWaveRTImpl * This = (IPortWaveRTImpl*)CONTAINING_RECORD(iface, IPortWaveRTImpl, lpVtblSubDevice);
576
577 DPRINT("ISubDevice_DataRangeIntersection this %p\n", This);
578
579 if (This->pMiniport)
580 {
581 return This->pMiniport->lpVtbl->DataRangeIntersection (This->pMiniport, PinId, DataRange, MatchingDataRange, OutputBufferLength, ResultantFormat, ResultantFormatLength);
582 }
583
584 return STATUS_UNSUCCESSFUL;
585 }
586
587 static
588 NTSTATUS
589 NTAPI
590 ISubDevice_fnPowerChangeNotify(
591 IN ISubdevice *iface,
592 IN POWER_STATE PowerState)
593 {
594 IPortWaveRTImpl * This = (IPortWaveRTImpl*)CONTAINING_RECORD(iface, IPortWaveRTImpl, lpVtblSubDevice);
595
596 if (This->pPowerNotify)
597 {
598 This->pPowerNotify->lpVtbl->PowerChangeNotify(This->pPowerNotify, PowerState);
599 }
600
601 return STATUS_SUCCESS;
602 }
603
604 static
605 NTSTATUS
606 NTAPI
607 ISubDevice_fnPinCount(
608 IN ISubdevice *iface,
609 IN ULONG PinId,
610 IN OUT PULONG FilterNecessary,
611 IN OUT PULONG FilterCurrent,
612 IN OUT PULONG FilterPossible,
613 IN OUT PULONG GlobalCurrent,
614 IN OUT PULONG GlobalPossible)
615 {
616 IPortWaveRTImpl * This = (IPortWaveRTImpl*)CONTAINING_RECORD(iface, IPortWaveRTImpl, lpVtblSubDevice);
617
618 if (This->pPinCount)
619 {
620 This->pPinCount->lpVtbl->PinCount(This->pPinCount, PinId, FilterNecessary, FilterCurrent, FilterPossible, GlobalCurrent, GlobalPossible);
621 return STATUS_SUCCESS;
622 }
623
624 /* FIXME
625 * scan filter descriptor
626 */
627 return STATUS_UNSUCCESSFUL;
628 }
629
630 static ISubdeviceVtbl vt_ISubdeviceVtbl =
631 {
632 ISubDevice_fnQueryInterface,
633 ISubDevice_fnAddRef,
634 ISubDevice_fnRelease,
635 ISubDevice_fnNewIrpTarget,
636 ISubDevice_fnReleaseChildren,
637 ISubDevice_fnGetDescriptor,
638 ISubDevice_fnDataRangeIntersection,
639 ISubDevice_fnPowerChangeNotify,
640 ISubDevice_fnPinCount
641 };
642
643
644 ///--------------------------------------------------------------
645 PMINIPORTWAVERT
646 GetWaveRTMiniport(
647 IN IPortWaveRT* iface)
648 {
649 IPortWaveRTImpl * This = (IPortWaveRTImpl *)iface;
650 return This->pMiniport;
651 }
652
653 PDEVICE_OBJECT
654 GetDeviceObjectFromPortWaveRT(
655 PPORTWAVERT iface)
656 {
657 IPortWaveRTImpl * This = (IPortWaveRTImpl *)iface;
658 return This->pDeviceObject;
659 }
660
661 //---------------------------------------------------------------
662 // IPortWaveRT constructor
663 //
664
665 NTSTATUS
666 NewPortWaveRT(
667 OUT PPORT* OutPort)
668 {
669 IPortWaveRTImpl * This;
670
671 This = AllocateItem(NonPagedPool, sizeof(IPortWaveRTImpl), TAG_PORTCLASS);
672 if (!This)
673 return STATUS_INSUFFICIENT_RESOURCES;
674
675 This->lpVtbl = &vt_IPortWaveRTVtbl;
676 This->lpVtblSubDevice = &vt_ISubdeviceVtbl;
677 This->lpVtblPortEvents = &vt_IPortEvents;
678 This->ref = 1;
679 *OutPort = (PPORT)(&This->lpVtbl);
680
681 DPRINT("NewPortWaveRT %p\n", *OutPort);
682
683 return STATUS_SUCCESS;
684 }
685