1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel Streaming
4 * FILE: drivers/ksfilter/ks/filter.c
5 * PURPOSE: KS IKsFilter interface functions
6 * PROGRAMMER: Johannes Anderwald
7 */
8
9 #include "precomp.h"
10
11 #define NDEBUG
12 #include <debug.h>
13
14 typedef struct
15 {
16 KSBASIC_HEADER Header;
17 KSFILTER Filter;
18
19 IKsControlVtbl *lpVtblKsControl;
20 IKsFilterFactory * FilterFactory;
21 IKsProcessingObjectVtbl * lpVtblKsProcessingObject;
22 LONG ref;
23
24 PKSIOBJECT_HEADER ObjectHeader;
25 KSTOPOLOGY Topology;
26 PKSFILTERFACTORY Factory;
27 PFILE_OBJECT FileObject;
28 KMUTEX ControlMutex;
29 KMUTEX ProcessingMutex;
30
31 PKSWORKER Worker;
32 WORK_QUEUE_ITEM WorkItem;
33 KSGATE Gate;
34
35 PFNKSFILTERPOWER Sleep;
36 PFNKSFILTERPOWER Wake;
37
38 ULONG *PinInstanceCount;
39 PKSPIN * FirstPin;
40 PKSPROCESSPIN_INDEXENTRY ProcessPinIndex;
41
42 }IKsFilterImpl;
43
44 const GUID IID_IKsControl = {0x28F54685L, 0x06FD, 0x11D2, {0xB2, 0x7A, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
45 const GUID IID_IKsFilter = {0x3ef6ee44L, 0x0D41, 0x11d2, {0xbe, 0xDA, 0x00, 0xc0, 0x4f, 0x8e, 0xF4, 0x57}};
46 const GUID KSPROPSETID_Topology = {0x720D4AC0L, 0x7533, 0x11D0, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
47 const GUID KSPROPSETID_Pin = {0x8C134960L, 0x51AD, 0x11CF, {0x87, 0x8A, 0x94, 0xF8, 0x01, 0xC1, 0x00, 0x00}};
48 const GUID KSPROPSETID_General = {0x1464EDA5L, 0x6A8F, 0x11D1, {0x9A, 0xA7, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
49
50 VOID
51 IKsFilter_RemoveFilterFromFilterFactory(
52 IKsFilterImpl * This,
53 PKSFILTERFACTORY FilterFactory);
54
55 NTSTATUS NTAPI FilterTopologyPropertyHandler(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
56 NTSTATUS NTAPI FilterPinPropertyHandler(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
57 NTSTATUS NTAPI FilterGeneralComponentIdHandler(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
58
59 DEFINE_KSPROPERTY_TOPOLOGYSET(IKsFilterTopologySet, FilterTopologyPropertyHandler);
60 DEFINE_KSPROPERTY_PINPROPOSEDATAFORMAT(IKsFilterPinSet, FilterPinPropertyHandler, FilterPinPropertyHandler, FilterPinPropertyHandler);
61 DEFINE_KSPROPERTY_GENEREAL_COMPONENTID(IKsFilterGeneralSet, FilterGeneralComponentIdHandler);
62
63 KSPROPERTY_SET FilterPropertySet[] =
64 {
65 {
66 &KSPROPSETID_Topology,
67 sizeof(IKsFilterTopologySet) / sizeof(KSPROPERTY_ITEM),
68 (const KSPROPERTY_ITEM*)&IKsFilterTopologySet,
69 0,
70 NULL
71 },
72 {
73 &KSPROPSETID_Pin,
74 sizeof(IKsFilterPinSet) / sizeof(KSPROPERTY_ITEM),
75 (const KSPROPERTY_ITEM*)&IKsFilterPinSet,
76 0,
77 NULL
78 },
79 {
80 &KSPROPSETID_General,
81 sizeof(IKsFilterGeneralSet) / sizeof(KSPROPERTY_ITEM),
82 (const KSPROPERTY_ITEM*)&IKsFilterGeneralSet,
83 0,
84 NULL
85 }
86 };
87
88 NTSTATUS
89 NTAPI
IKsProcessingObject_fnQueryInterface(IKsProcessingObject * iface,IN REFIID refiid,OUT PVOID * Output)90 IKsProcessingObject_fnQueryInterface(
91 IKsProcessingObject * iface,
92 IN REFIID refiid,
93 OUT PVOID* Output)
94 {
95 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsProcessingObject);
96
97 if (IsEqualGUIDAligned(refiid, &IID_IUnknown))
98 {
99 *Output = &This->Header.OuterUnknown;
100 _InterlockedIncrement(&This->ref);
101 return STATUS_SUCCESS;
102 }
103 return STATUS_UNSUCCESSFUL;
104 }
105
106 ULONG
107 NTAPI
IKsProcessingObject_fnAddRef(IKsProcessingObject * iface)108 IKsProcessingObject_fnAddRef(
109 IKsProcessingObject * iface)
110 {
111 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsProcessingObject);
112
113 return InterlockedIncrement(&This->ref);
114 }
115
116 ULONG
117 NTAPI
IKsProcessingObject_fnRelease(IKsProcessingObject * iface)118 IKsProcessingObject_fnRelease(
119 IKsProcessingObject * iface)
120 {
121 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsProcessingObject);
122
123 InterlockedDecrement(&This->ref);
124
125 /* Return new reference count */
126 return This->ref;
127 }
128
129 VOID
130 NTAPI
IKsProcessingObject_fnProcessingObjectWork(IKsProcessingObject * iface)131 IKsProcessingObject_fnProcessingObjectWork(
132 IKsProcessingObject * iface)
133 {
134 NTSTATUS Status;
135 LARGE_INTEGER TimeOut;
136 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsProcessingObject);
137
138 DPRINT1("processing object\n");
139 /* first check if running at passive level */
140 if (KeGetCurrentIrql() == PASSIVE_LEVEL)
141 {
142 /* acquire processing mutex */
143 KeWaitForSingleObject(&This->ControlMutex, Executive, KernelMode, FALSE, NULL);
144 }
145 else
146 {
147 /* dispatch level processing */
148 if (KeReadStateMutex(&This->ControlMutex) == 0)
149 {
150 /* some thread was faster */
151 DPRINT1("processing object too slow\n");
152 return;
153 }
154
155 /* acquire processing mutex */
156 TimeOut.QuadPart = 0LL;
157 Status = KeWaitForSingleObject(&This->ControlMutex, Executive, KernelMode, FALSE, &TimeOut);
158
159 if (Status == STATUS_TIMEOUT)
160 {
161 /* some thread was faster */
162 DPRINT1("processing object too slow\n");
163 return;
164 }
165 }
166
167 do
168 {
169
170 /* check if the and-gate has been enabled again */
171 if (This->Gate.Count != 0)
172 {
173 /* gate is open */
174 DPRINT1("processing object gate open\n");
175 break;
176 }
177
178 DPRINT1("IKsProcessingObject_fnProcessingObjectWork not implemented\n");
179 ASSERT(0);
180
181 }while(TRUE);
182
183 /* release process mutex */
184 KeReleaseMutex(&This->ProcessingMutex, FALSE);
185 }
186
187 PKSGATE
188 NTAPI
IKsProcessingObject_fnGetAndGate(IKsProcessingObject * iface)189 IKsProcessingObject_fnGetAndGate(
190 IKsProcessingObject * iface)
191 {
192 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsProcessingObject);
193
194 /* return and gate */
195 return &This->Gate;
196 }
197
198 VOID
199 NTAPI
IKsProcessingObject_fnProcess(IKsProcessingObject * iface,IN BOOLEAN Asynchronous)200 IKsProcessingObject_fnProcess(
201 IKsProcessingObject * iface,
202 IN BOOLEAN Asynchronous)
203 {
204 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsProcessingObject);
205
206 /* should the action be asynchronous */
207 if (Asynchronous)
208 {
209 /* queue work item */
210 KsQueueWorkItem(This->Worker, &This->WorkItem);
211 DPRINT1("queueing\n");
212 /* done */
213 return;
214 }
215
216 /* does the filter require explicit deferred processing */
217 if ((This->Filter.Descriptor->Flags & (KSFILTER_FLAG_DISPATCH_LEVEL_PROCESSING | KSFILTER_FLAG_CRITICAL_PROCESSING | KSFILTER_FLAG_HYPERCRITICAL_PROCESSING)) &&
218 KeGetCurrentIrql() > PASSIVE_LEVEL)
219 {
220 /* queue work item */
221 KsQueueWorkItem(This->Worker, &This->WorkItem);
222 DPRINT1("queueing\n");
223 /* done */
224 return;
225 }
226 DPRINT1("invoke\n");
227 /* call worker routine directly */
228 iface->lpVtbl->ProcessingObjectWork(iface);
229 }
230
231 VOID
232 NTAPI
IKsProcessingObject_fnReset(IKsProcessingObject * iface)233 IKsProcessingObject_fnReset(
234 IKsProcessingObject * iface)
235 {
236 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsProcessingObject);
237
238 /* acquire processing mutex */
239 KeWaitForSingleObject(&This->ProcessingMutex, Executive, KernelMode, FALSE, NULL);
240
241 /* check if the filter supports dispatch routines */
242 if (This->Filter.Descriptor->Dispatch)
243 {
244 /* has the filter a reset routine */
245 if (This->Filter.Descriptor->Dispatch->Reset)
246 {
247 /* reset filter */
248 This->Filter.Descriptor->Dispatch->Reset(&This->Filter);
249 }
250 }
251
252 /* release process mutex */
253 KeReleaseMutex(&This->ProcessingMutex, FALSE);
254 }
255
256 VOID
257 NTAPI
IKsProcessingObject_fnTriggerNotification(IKsProcessingObject * iface)258 IKsProcessingObject_fnTriggerNotification(
259 IKsProcessingObject * iface)
260 {
261
262 }
263
264 static IKsProcessingObjectVtbl vt_IKsProcessingObject =
265 {
266 IKsProcessingObject_fnQueryInterface,
267 IKsProcessingObject_fnAddRef,
268 IKsProcessingObject_fnRelease,
269 IKsProcessingObject_fnProcessingObjectWork,
270 IKsProcessingObject_fnGetAndGate,
271 IKsProcessingObject_fnProcess,
272 IKsProcessingObject_fnReset,
273 IKsProcessingObject_fnTriggerNotification
274 };
275
276
277 //---------------------------------------------------------------------------------------------------------
278 NTSTATUS
279 NTAPI
IKsControl_fnQueryInterface(IKsControl * iface,IN REFIID refiid,OUT PVOID * Output)280 IKsControl_fnQueryInterface(
281 IKsControl * iface,
282 IN REFIID refiid,
283 OUT PVOID* Output)
284 {
285 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsControl);
286
287 if (IsEqualGUIDAligned(refiid, &IID_IUnknown))
288 {
289 *Output = &This->Header.OuterUnknown;
290 _InterlockedIncrement(&This->ref);
291 return STATUS_SUCCESS;
292 }
293 return STATUS_UNSUCCESSFUL;
294 }
295
296 ULONG
297 NTAPI
IKsControl_fnAddRef(IKsControl * iface)298 IKsControl_fnAddRef(
299 IKsControl * iface)
300 {
301 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsControl);
302
303 return InterlockedIncrement(&This->ref);
304 }
305
306 ULONG
307 NTAPI
IKsControl_fnRelease(IKsControl * iface)308 IKsControl_fnRelease(
309 IKsControl * iface)
310 {
311 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsControl);
312
313 InterlockedDecrement(&This->ref);
314
315 /* Return new reference count */
316 return This->ref;
317 }
318
319 NTSTATUS
320 NTAPI
IKsControl_fnKsProperty(IKsControl * iface,IN PKSPROPERTY Property,IN ULONG PropertyLength,IN OUT PVOID PropertyData,IN ULONG DataLength,OUT ULONG * BytesReturned)321 IKsControl_fnKsProperty(
322 IKsControl * iface,
323 IN PKSPROPERTY Property,
324 IN ULONG PropertyLength,
325 IN OUT PVOID PropertyData,
326 IN ULONG DataLength,
327 OUT ULONG* BytesReturned)
328 {
329 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsControl);
330
331 return KsSynchronousIoControlDevice(This->FileObject, KernelMode, IOCTL_KS_PROPERTY, Property, PropertyLength, PropertyData, DataLength, BytesReturned);
332 }
333
334
335 NTSTATUS
336 NTAPI
IKsControl_fnKsMethod(IKsControl * iface,IN PKSMETHOD Method,IN ULONG MethodLength,IN OUT PVOID MethodData,IN ULONG DataLength,OUT ULONG * BytesReturned)337 IKsControl_fnKsMethod(
338 IKsControl * iface,
339 IN PKSMETHOD Method,
340 IN ULONG MethodLength,
341 IN OUT PVOID MethodData,
342 IN ULONG DataLength,
343 OUT ULONG* BytesReturned)
344 {
345 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsControl);
346
347 return KsSynchronousIoControlDevice(This->FileObject, KernelMode, IOCTL_KS_METHOD, Method, MethodLength, MethodData, DataLength, BytesReturned);
348 }
349
350
351 NTSTATUS
352 NTAPI
IKsControl_fnKsEvent(IKsControl * iface,IN PKSEVENT Event OPTIONAL,IN ULONG EventLength,IN OUT PVOID EventData,IN ULONG DataLength,OUT ULONG * BytesReturned)353 IKsControl_fnKsEvent(
354 IKsControl * iface,
355 IN PKSEVENT Event OPTIONAL,
356 IN ULONG EventLength,
357 IN OUT PVOID EventData,
358 IN ULONG DataLength,
359 OUT ULONG* BytesReturned)
360 {
361 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsControl);
362
363 if (Event)
364 {
365 return KsSynchronousIoControlDevice(This->FileObject, KernelMode, IOCTL_KS_ENABLE_EVENT, Event, EventLength, EventData, DataLength, BytesReturned);
366 }
367 else
368 {
369 return KsSynchronousIoControlDevice(This->FileObject, KernelMode, IOCTL_KS_DISABLE_EVENT, EventData, DataLength, NULL, 0, BytesReturned);
370 }
371
372 }
373
374 static IKsControlVtbl vt_IKsControl =
375 {
376 IKsControl_fnQueryInterface,
377 IKsControl_fnAddRef,
378 IKsControl_fnRelease,
379 IKsControl_fnKsProperty,
380 IKsControl_fnKsMethod,
381 IKsControl_fnKsEvent
382 };
383
384
385 NTSTATUS
386 NTAPI
IKsFilter_fnQueryInterface(IKsFilter * iface,IN REFIID refiid,OUT PVOID * Output)387 IKsFilter_fnQueryInterface(
388 IKsFilter * iface,
389 IN REFIID refiid,
390 OUT PVOID* Output)
391 {
392 NTSTATUS Status;
393 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, Header.OuterUnknown);
394
395 if (IsEqualGUIDAligned(refiid, &IID_IUnknown) ||
396 IsEqualGUIDAligned(refiid, &IID_IKsFilter))
397 {
398 *Output = &This->Header.OuterUnknown;
399 _InterlockedIncrement(&This->ref);
400 return STATUS_SUCCESS;
401 }
402 else if (IsEqualGUIDAligned(refiid, &IID_IKsControl))
403 {
404 *Output = &This->lpVtblKsControl;
405 _InterlockedIncrement(&This->ref);
406 return STATUS_SUCCESS;
407 }
408
409 if (This->Header.ClientAggregate)
410 {
411 /* using client aggregate */
412 Status = This->Header.ClientAggregate->lpVtbl->QueryInterface(This->Header.ClientAggregate, refiid, Output);
413
414 if (NT_SUCCESS(Status))
415 {
416 /* client aggregate supports interface */
417 return Status;
418 }
419 }
420
421 DPRINT("IKsFilter_fnQueryInterface no interface\n");
422 return STATUS_NOT_SUPPORTED;
423 }
424
425 ULONG
426 NTAPI
IKsFilter_fnAddRef(IKsFilter * iface)427 IKsFilter_fnAddRef(
428 IKsFilter * iface)
429 {
430 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, Header.OuterUnknown);
431
432 return InterlockedIncrement(&This->ref);
433 }
434
435 ULONG
436 NTAPI
IKsFilter_fnRelease(IKsFilter * iface)437 IKsFilter_fnRelease(
438 IKsFilter * iface)
439 {
440 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, Header.OuterUnknown);
441
442 InterlockedDecrement(&This->ref);
443
444 if (This->ref == 0)
445 {
446 FreeItem(This);
447 return 0;
448 }
449 /* Return new reference count */
450 return This->ref;
451
452 }
453
454 PKSFILTER
455 NTAPI
IKsFilter_fnGetStruct(IKsFilter * iface)456 IKsFilter_fnGetStruct(
457 IKsFilter * iface)
458 {
459 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, Header.OuterUnknown);
460
461 return &This->Filter;
462 }
463
464 BOOL
465 NTAPI
IKsFilter_fnDoAllNecessaryPinsExist(IKsFilter * iface)466 IKsFilter_fnDoAllNecessaryPinsExist(
467 IKsFilter * iface)
468 {
469 UNIMPLEMENTED;
470 return FALSE;
471 }
472
473 NTSTATUS
474 NTAPI
IKsFilter_fnCreateNode(IKsFilter * iface,IN PIRP Irp,IN IKsPin * Pin,IN PLIST_ENTRY ListEntry)475 IKsFilter_fnCreateNode(
476 IKsFilter * iface,
477 IN PIRP Irp,
478 IN IKsPin * Pin,
479 IN PLIST_ENTRY ListEntry)
480 {
481 UNIMPLEMENTED;
482 return STATUS_NOT_IMPLEMENTED;
483 }
484
485 NTSTATUS
486 NTAPI
IKsFilter_fnBindProcessPinsToPipeSection(IKsFilter * iface,IN struct KSPROCESSPIPESECTION * Section,IN PVOID Create,IN PKSPIN KsPin,OUT IKsPin ** Pin,OUT PKSGATE * OutGate)487 IKsFilter_fnBindProcessPinsToPipeSection(
488 IKsFilter * iface,
489 IN struct KSPROCESSPIPESECTION *Section,
490 IN PVOID Create,
491 IN PKSPIN KsPin,
492 OUT IKsPin **Pin,
493 OUT PKSGATE *OutGate)
494 {
495 UNIMPLEMENTED;
496 return STATUS_NOT_IMPLEMENTED;
497 }
498
499 NTSTATUS
500 NTAPI
IKsFilter_fnUnbindProcessPinsFromPipeSection(IKsFilter * iface,IN struct KSPROCESSPIPESECTION * Section)501 IKsFilter_fnUnbindProcessPinsFromPipeSection(
502 IKsFilter * iface,
503 IN struct KSPROCESSPIPESECTION *Section)
504 {
505 UNIMPLEMENTED;
506 return STATUS_NOT_IMPLEMENTED;
507 }
508
509 NTSTATUS
510 NTAPI
IKsFilter_fnAddProcessPin(IKsFilter * iface,IN PKSPROCESSPIN ProcessPin)511 IKsFilter_fnAddProcessPin(
512 IKsFilter * iface,
513 IN PKSPROCESSPIN ProcessPin)
514 {
515 NTSTATUS Status;
516 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, Header.OuterUnknown);
517
518 /* first acquire processing mutex */
519 KeWaitForSingleObject(&This->ProcessingMutex, Executive, KernelMode, FALSE, NULL);
520
521 /* sanity check */
522 ASSERT(This->Filter.Descriptor->PinDescriptorsCount > ProcessPin->Pin->Id);
523
524 /* allocate new process pin array */
525 Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->ProcessPinIndex[ProcessPin->Pin->Id].Pins,
526 (This->Filter.Descriptor->PinDescriptorsCount + 1) * sizeof(PVOID),
527 This->Filter.Descriptor->PinDescriptorsCount * sizeof(PVOID),
528 0);
529
530 if (NT_SUCCESS(Status))
531 {
532 /* store process pin */
533 This->ProcessPinIndex[ProcessPin->Pin->Id].Pins[This->ProcessPinIndex[ProcessPin->Pin->Id].Count] = ProcessPin;
534 This->ProcessPinIndex[ProcessPin->Pin->Id].Count++;
535 }
536
537 /* release process mutex */
538 KeReleaseMutex(&This->ProcessingMutex, FALSE);
539
540 return Status;
541 }
542
543 NTSTATUS
544 NTAPI
IKsFilter_fnRemoveProcessPin(IKsFilter * iface,IN PKSPROCESSPIN ProcessPin)545 IKsFilter_fnRemoveProcessPin(
546 IKsFilter * iface,
547 IN PKSPROCESSPIN ProcessPin)
548 {
549 ULONG Index;
550 ULONG Count;
551 PKSPROCESSPIN * Pins;
552
553 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, Header.OuterUnknown);
554
555 /* first acquire processing mutex */
556 KeWaitForSingleObject(&This->ProcessingMutex, Executive, KernelMode, FALSE, NULL);
557
558 /* sanity check */
559 ASSERT(ProcessPin->Pin);
560 ASSERT(ProcessPin->Pin->Id);
561
562 Count = This->ProcessPinIndex[ProcessPin->Pin->Id].Count;
563 Pins = This->ProcessPinIndex[ProcessPin->Pin->Id].Pins;
564
565 /* search for current process pin */
566 for(Index = 0; Index < Count; Index++)
567 {
568 if (Pins[Index] == ProcessPin)
569 {
570 RtlMoveMemory(&Pins[Index], &Pins[Index + 1], (Count - (Index + 1)) * sizeof(PVOID));
571 break;
572 }
573
574 }
575
576 /* decrement pin count */
577 This->ProcessPinIndex[ProcessPin->Pin->Id].Count--;
578
579 if (!This->ProcessPinIndex[ProcessPin->Pin->Id].Count)
580 {
581 /* clear entry object bag will delete it */
582 This->ProcessPinIndex[ProcessPin->Pin->Id].Pins = NULL;
583 }
584
585 /* release process mutex */
586 KeReleaseMutex(&This->ProcessingMutex, FALSE);
587
588 /* done */
589 return STATUS_SUCCESS;
590 }
591
592 BOOL
593 NTAPI
IKsFilter_fnReprepareProcessPipeSection(IKsFilter * iface,IN struct KSPROCESSPIPESECTION * PipeSection,IN PULONG Data)594 IKsFilter_fnReprepareProcessPipeSection(
595 IKsFilter * iface,
596 IN struct KSPROCESSPIPESECTION *PipeSection,
597 IN PULONG Data)
598 {
599 UNIMPLEMENTED;
600 return FALSE;
601 }
602
603 VOID
604 NTAPI
IKsFilter_fnDeliverResetState(IKsFilter * iface,IN struct KSPROCESSPIPESECTION * PipeSection,IN KSRESET ResetState)605 IKsFilter_fnDeliverResetState(
606 IKsFilter * iface,
607 IN struct KSPROCESSPIPESECTION *PipeSection,
608 IN KSRESET ResetState)
609 {
610 UNIMPLEMENTED;
611 }
612
613 BOOL
614 NTAPI
IKsFilter_fnIsFrameHolding(IKsFilter * iface)615 IKsFilter_fnIsFrameHolding(
616 IKsFilter * iface)
617 {
618 UNIMPLEMENTED;
619 return FALSE;
620 }
621
622 VOID
623 NTAPI
IKsFilter_fnRegisterForCopyCallbacks(IKsFilter * iface,IKsQueue * Queue,BOOL Register)624 IKsFilter_fnRegisterForCopyCallbacks(
625 IKsFilter * iface,
626 IKsQueue *Queue,
627 BOOL Register)
628 {
629 UNIMPLEMENTED;
630 }
631
632 PKSPROCESSPIN_INDEXENTRY
633 NTAPI
IKsFilter_fnGetProcessDispatch(IKsFilter * iface)634 IKsFilter_fnGetProcessDispatch(
635 IKsFilter * iface)
636 {
637 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, Header.OuterUnknown);
638
639 return This->ProcessPinIndex;
640 }
641
642 static IKsFilterVtbl vt_IKsFilter =
643 {
644 IKsFilter_fnQueryInterface,
645 IKsFilter_fnAddRef,
646 IKsFilter_fnRelease,
647 IKsFilter_fnGetStruct,
648 IKsFilter_fnDoAllNecessaryPinsExist,
649 IKsFilter_fnCreateNode,
650 IKsFilter_fnBindProcessPinsToPipeSection,
651 IKsFilter_fnUnbindProcessPinsFromPipeSection,
652 IKsFilter_fnAddProcessPin,
653 IKsFilter_fnRemoveProcessPin,
654 IKsFilter_fnReprepareProcessPipeSection,
655 IKsFilter_fnDeliverResetState,
656 IKsFilter_fnIsFrameHolding,
657 IKsFilter_fnRegisterForCopyCallbacks,
658 IKsFilter_fnGetProcessDispatch
659 };
660
661 NTSTATUS
IKsFilter_GetFilterFromIrp(IN PIRP Irp,OUT IKsFilter ** Filter)662 IKsFilter_GetFilterFromIrp(
663 IN PIRP Irp,
664 OUT IKsFilter **Filter)
665 {
666 PIO_STACK_LOCATION IoStack;
667 PKSIOBJECT_HEADER ObjectHeader;
668 NTSTATUS Status;
669
670 /* get current irp stack */
671 IoStack = IoGetCurrentIrpStackLocation(Irp);
672
673 /* sanity check */
674 ASSERT(IoStack->FileObject != NULL);
675
676 ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->FsContext2;
677
678 /* sanity is important */
679 ASSERT(ObjectHeader != NULL);
680 ASSERT(ObjectHeader->Type == KsObjectTypeFilter);
681 ASSERT(ObjectHeader->Unknown != NULL);
682
683 /* get our private interface */
684 Status = ObjectHeader->Unknown->lpVtbl->QueryInterface(ObjectHeader->Unknown, &IID_IKsFilter, (PVOID*)Filter);
685
686 if (!NT_SUCCESS(Status))
687 {
688 /* something is wrong here */
689 DPRINT1("KS: Misbehaving filter %p\n", ObjectHeader->Unknown);
690 Irp->IoStatus.Status = Status;
691
692 /* complete and forget irp */
693 CompleteRequest(Irp, IO_NO_INCREMENT);
694 return Status;
695 }
696 return Status;
697 }
698
699
700 NTSTATUS
701 NTAPI
IKsFilter_DispatchClose(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)702 IKsFilter_DispatchClose(
703 IN PDEVICE_OBJECT DeviceObject,
704 IN PIRP Irp)
705 {
706 IKsFilter * Filter;
707 IKsFilterImpl * This;
708 NTSTATUS Status;
709
710 /* obtain filter from object header */
711 Status = IKsFilter_GetFilterFromIrp(Irp, &Filter);
712 if (!NT_SUCCESS(Status))
713 return Status;
714
715 /* get our real implementation */
716 This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Header.OuterUnknown);
717
718 /* does the driver support notifications */
719 if (This->Filter.Descriptor && This->Filter.Descriptor->Dispatch && This->Filter.Descriptor->Dispatch->Close)
720 {
721 /* call driver's filter close function */
722 Status = This->Filter.Descriptor->Dispatch->Close(&This->Filter, Irp);
723 }
724
725 if (NT_SUCCESS(Status) && Status != STATUS_PENDING)
726 {
727 /* save the result */
728 Irp->IoStatus.Status = Status;
729 /* complete irp */
730 CompleteRequest(Irp, IO_NO_INCREMENT);
731
732 /* remove our instance from the filter factory */
733 IKsFilter_RemoveFilterFromFilterFactory(This, This->Factory);
734
735 /* free object header */
736 KsFreeObjectHeader(This->ObjectHeader);
737 }
738 else
739 {
740 /* complete and forget */
741 Irp->IoStatus.Status = Status;
742 /* complete irp */
743 CompleteRequest(Irp, IO_NO_INCREMENT);
744 }
745
746 /* done */
747 return Status;
748 }
749
750 NTSTATUS
KspHandlePropertyInstances(IN PIO_STATUS_BLOCK IoStatus,IN PKSIDENTIFIER Request,IN OUT PVOID Data,IN IKsFilterImpl * This,IN BOOL Global)751 KspHandlePropertyInstances(
752 IN PIO_STATUS_BLOCK IoStatus,
753 IN PKSIDENTIFIER Request,
754 IN OUT PVOID Data,
755 IN IKsFilterImpl * This,
756 IN BOOL Global)
757 {
758 KSPIN_CINSTANCES * Instances;
759 KSP_PIN * Pin = (KSP_PIN*)Request;
760
761 if (!This->Filter.Descriptor || !This->Filter.Descriptor->PinDescriptorsCount)
762 {
763 /* no filter / pin descriptor */
764 IoStatus->Status = STATUS_NOT_IMPLEMENTED;
765 return STATUS_NOT_IMPLEMENTED;
766 }
767
768 /* ignore custom structs for now */
769 ASSERT(This->Filter.Descriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX));
770 ASSERT(This->Filter.Descriptor->PinDescriptorsCount > Pin->PinId);
771
772 Instances = (KSPIN_CINSTANCES*)Data;
773 /* max instance count */
774 Instances->PossibleCount = This->Filter.Descriptor->PinDescriptors[Pin->PinId].InstancesPossible;
775 /* current instance count */
776 Instances->CurrentCount = This->PinInstanceCount[Pin->PinId];
777
778 IoStatus->Information = sizeof(KSPIN_CINSTANCES);
779 IoStatus->Status = STATUS_SUCCESS;
780 return STATUS_SUCCESS;
781 }
782
783 NTSTATUS
KspHandleNecessaryPropertyInstances(IN PIO_STATUS_BLOCK IoStatus,IN PKSIDENTIFIER Request,IN OUT PVOID Data,IN IKsFilterImpl * This)784 KspHandleNecessaryPropertyInstances(
785 IN PIO_STATUS_BLOCK IoStatus,
786 IN PKSIDENTIFIER Request,
787 IN OUT PVOID Data,
788 IN IKsFilterImpl * This)
789 {
790 PULONG Result;
791 KSP_PIN * Pin = (KSP_PIN*)Request;
792
793 if (!This->Filter.Descriptor || !This->Filter.Descriptor->PinDescriptorsCount)
794 {
795 /* no filter / pin descriptor */
796 IoStatus->Status = STATUS_NOT_IMPLEMENTED;
797 return STATUS_NOT_IMPLEMENTED;
798 }
799
800 /* ignore custom structs for now */
801 ASSERT(This->Filter.Descriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX));
802 ASSERT(This->Filter.Descriptor->PinDescriptorsCount > Pin->PinId);
803
804 Result = (PULONG)Data;
805 *Result = This->Filter.Descriptor->PinDescriptors[Pin->PinId].InstancesNecessary;
806
807 IoStatus->Information = sizeof(ULONG);
808 IoStatus->Status = STATUS_SUCCESS;
809 return STATUS_SUCCESS;
810 }
811
812 NTSTATUS
KspHandleDataIntersection(IN PIRP Irp,IN PIO_STATUS_BLOCK IoStatus,IN PKSIDENTIFIER Request,IN OUT PVOID Data,IN ULONG DataLength,IN IKsFilterImpl * This)813 KspHandleDataIntersection(
814 IN PIRP Irp,
815 IN PIO_STATUS_BLOCK IoStatus,
816 IN PKSIDENTIFIER Request,
817 IN OUT PVOID Data,
818 IN ULONG DataLength,
819 IN IKsFilterImpl * This)
820 {
821 PKSMULTIPLE_ITEM MultipleItem;
822 PKSDATARANGE DataRange;
823 NTSTATUS Status = STATUS_NO_MATCH;
824 ULONG Index, Length;
825 PIO_STACK_LOCATION IoStack;
826 KSP_PIN * Pin = (KSP_PIN*)Request;
827
828 /* get stack location */
829 IoStack = IoGetCurrentIrpStackLocation(Irp);
830
831 /* sanity check */
832 ASSERT(DataLength == IoStack->Parameters.DeviceIoControl.OutputBufferLength);
833
834 /* Access parameters */
835 MultipleItem = (PKSMULTIPLE_ITEM)(Pin + 1);
836 DataRange = (PKSDATARANGE)(MultipleItem + 1);
837
838 /* FIXME make sure its 64 bit aligned */
839 ASSERT(((ULONG_PTR)DataRange & 0x7) == 0);
840
841 if (!This->Filter.Descriptor || !This->Filter.Descriptor->PinDescriptorsCount)
842 {
843 /* no filter / pin descriptor */
844 IoStatus->Status = STATUS_NOT_IMPLEMENTED;
845 return STATUS_NOT_IMPLEMENTED;
846 }
847
848 /* ignore custom structs for now */
849 ASSERT(This->Filter.Descriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX));
850 ASSERT(This->Filter.Descriptor->PinDescriptorsCount > Pin->PinId);
851
852 if (This->Filter.Descriptor->PinDescriptors[Pin->PinId].IntersectHandler == NULL ||
853 This->Filter.Descriptor->PinDescriptors[Pin->PinId].PinDescriptor.DataRanges == NULL ||
854 This->Filter.Descriptor->PinDescriptors[Pin->PinId].PinDescriptor.DataRangesCount == 0)
855 {
856 /* no driver supported intersect handler / no provided data ranges */
857 IoStatus->Status = STATUS_NOT_IMPLEMENTED;
858 return STATUS_NOT_IMPLEMENTED;
859 }
860
861 for(Index = 0; Index < MultipleItem->Count; Index++)
862 {
863 UNICODE_STRING MajorFormat, SubFormat, Specifier;
864 /* convert the guid to string */
865 RtlStringFromGUID(&DataRange->MajorFormat, &MajorFormat);
866 RtlStringFromGUID(&DataRange->SubFormat, &SubFormat);
867 RtlStringFromGUID(&DataRange->Specifier, &Specifier);
868
869 DPRINT("KspHandleDataIntersection Index %lu PinId %lu MajorFormat %S SubFormat %S Specifier %S FormatSize %lu SampleSize %lu Align %lu Flags %lx Reserved %lx DataLength %lu\n", Index, Pin->PinId, MajorFormat.Buffer, SubFormat.Buffer, Specifier.Buffer,
870 DataRange->FormatSize, DataRange->SampleSize, DataRange->Alignment, DataRange->Flags, DataRange->Reserved, DataLength);
871
872 /* FIXME implement KsPinDataIntersectionEx */
873 /* Call miniport's proprietary handler */
874 Status = This->Filter.Descriptor->PinDescriptors[Pin->PinId].IntersectHandler(&This->Filter,
875 Irp,
876 Pin,
877 DataRange,
878 This->Filter.Descriptor->PinDescriptors[Pin->PinId].PinDescriptor.DataRanges[0], /* HACK */
879 DataLength,
880 Data,
881 &Length);
882 DPRINT("KspHandleDataIntersection Status %lx\n", Status);
883
884 if (Status == STATUS_SUCCESS || Status == STATUS_BUFFER_OVERFLOW || Status == STATUS_BUFFER_TOO_SMALL)
885 {
886 ASSERT(Length);
887 IoStatus->Information = Length;
888 break;
889 }
890
891 DataRange = (PKSDATARANGE)((PUCHAR)DataRange + DataRange->FormatSize);
892 /* FIXME make sure its 64 bit aligned */
893 ASSERT(((ULONG_PTR)DataRange & 0x7) == 0);
894 }
895 IoStatus->Status = Status;
896 return Status;
897 }
898
899 NTSTATUS
900 NTAPI
FilterTopologyPropertyHandler(IN PIRP Irp,IN PKSIDENTIFIER Request,IN OUT PVOID Data)901 FilterTopologyPropertyHandler(
902 IN PIRP Irp,
903 IN PKSIDENTIFIER Request,
904 IN OUT PVOID Data)
905 {
906 IKsFilterImpl * This;
907
908 /* get filter implementation */
909 This = (IKsFilterImpl*)KSPROPERTY_ITEM_IRP_STORAGE(Irp);
910
911 /* sanity check */
912 ASSERT(This);
913
914 return KsTopologyPropertyHandler(Irp, Request, Data, &This->Topology);
915
916 }
917
918 NTSTATUS
919 NTAPI
FilterGeneralComponentIdHandler(IN PIRP Irp,IN PKSIDENTIFIER Request,IN OUT PVOID Data)920 FilterGeneralComponentIdHandler(
921 IN PIRP Irp,
922 IN PKSIDENTIFIER Request,
923 IN OUT PVOID Data)
924 {
925 PIO_STACK_LOCATION IoStack;
926 IKsFilterImpl * This;
927
928 /* get filter implementation */
929 This = (IKsFilterImpl*)KSPROPERTY_ITEM_IRP_STORAGE(Irp);
930
931 /* sanity check */
932 ASSERT(This);
933
934 /* get current stack location */
935 IoStack = IoGetCurrentIrpStackLocation(Irp);
936 ASSERT(IoStack->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(KSCOMPONENTID));
937
938 if (This->Filter.Descriptor->ComponentId != NULL)
939 {
940 RtlMoveMemory(Data, This->Filter.Descriptor->ComponentId, sizeof(KSCOMPONENTID));
941 Irp->IoStatus.Information = sizeof(KSCOMPONENTID);
942 return STATUS_SUCCESS;
943 }
944 else
945 {
946 /* not valid */
947 return STATUS_NOT_FOUND;
948 }
949
950 }
951
952 NTSTATUS
953 NTAPI
FilterPinPropertyHandler(IN PIRP Irp,IN PKSIDENTIFIER Request,IN OUT PVOID Data)954 FilterPinPropertyHandler(
955 IN PIRP Irp,
956 IN PKSIDENTIFIER Request,
957 IN OUT PVOID Data)
958 {
959 PIO_STACK_LOCATION IoStack;
960 IKsFilterImpl * This;
961 NTSTATUS Status = STATUS_UNSUCCESSFUL;
962
963 /* get filter implementation */
964 This = (IKsFilterImpl*)KSPROPERTY_ITEM_IRP_STORAGE(Irp);
965
966 /* sanity check */
967 ASSERT(This);
968
969 /* get current stack location */
970 IoStack = IoGetCurrentIrpStackLocation(Irp);
971
972 switch(Request->Id)
973 {
974 case KSPROPERTY_PIN_CTYPES:
975 case KSPROPERTY_PIN_DATAFLOW:
976 case KSPROPERTY_PIN_DATARANGES:
977 case KSPROPERTY_PIN_INTERFACES:
978 case KSPROPERTY_PIN_MEDIUMS:
979 case KSPROPERTY_PIN_COMMUNICATION:
980 case KSPROPERTY_PIN_CATEGORY:
981 case KSPROPERTY_PIN_NAME:
982 case KSPROPERTY_PIN_CONSTRAINEDDATARANGES:
983 Status = KspPinPropertyHandler(Irp, Request, Data, This->Filter.Descriptor->PinDescriptorsCount, (const KSPIN_DESCRIPTOR*)This->Filter.Descriptor->PinDescriptors, This->Filter.Descriptor->PinDescriptorSize);
984 break;
985 case KSPROPERTY_PIN_GLOBALCINSTANCES:
986 Status = KspHandlePropertyInstances(&Irp->IoStatus, Request, Data, This, TRUE);
987 break;
988 case KSPROPERTY_PIN_CINSTANCES:
989 Status = KspHandlePropertyInstances(&Irp->IoStatus, Request, Data, This, FALSE);
990 break;
991 case KSPROPERTY_PIN_NECESSARYINSTANCES:
992 Status = KspHandleNecessaryPropertyInstances(&Irp->IoStatus, Request, Data, This);
993 break;
994
995 case KSPROPERTY_PIN_DATAINTERSECTION:
996 Status = KspHandleDataIntersection(Irp, &Irp->IoStatus, Request, Data, IoStack->Parameters.DeviceIoControl.OutputBufferLength, This);
997 break;
998 default:
999 UNIMPLEMENTED;
1000 Status = STATUS_NOT_FOUND;
1001 }
1002 DPRINT("KspPinPropertyHandler Pins %lu Request->Id %lu Status %lx\n", This->Filter.Descriptor->PinDescriptorsCount, Request->Id, Status);
1003
1004
1005 return Status;
1006 }
1007
1008 NTSTATUS
1009 NTAPI
IKsFilter_DispatchDeviceIoControl(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)1010 IKsFilter_DispatchDeviceIoControl(
1011 IN PDEVICE_OBJECT DeviceObject,
1012 IN PIRP Irp)
1013 {
1014 PIO_STACK_LOCATION IoStack;
1015 IKsFilter * Filter;
1016 IKsFilterImpl * This;
1017 NTSTATUS Status;
1018 PKSFILTER FilterInstance;
1019 UNICODE_STRING GuidString;
1020 PKSPROPERTY Property;
1021 ULONG SetCount = 0;
1022 PKSP_NODE NodeProperty;
1023 PKSNODE_DESCRIPTOR NodeDescriptor;
1024
1025 /* obtain filter from object header */
1026 Status = IKsFilter_GetFilterFromIrp(Irp, &Filter);
1027 if (!NT_SUCCESS(Status))
1028 return Status;
1029
1030 /* get our real implementation */
1031 This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Header.OuterUnknown);
1032
1033 /* current irp stack */
1034 IoStack = IoGetCurrentIrpStackLocation(Irp);
1035
1036 /* get property from input buffer */
1037 Property = (PKSPROPERTY)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
1038
1039 /* get filter instance */
1040 FilterInstance = Filter->lpVtbl->GetStruct(Filter);
1041
1042 /* sanity check */
1043 ASSERT(IoStack->Parameters.DeviceIoControl.InputBufferLength >= sizeof(KSIDENTIFIER));
1044 ASSERT(FilterInstance);
1045 ASSERT(FilterInstance->Descriptor);
1046 ASSERT(FilterInstance->Descriptor->AutomationTable);
1047
1048 /* acquire control mutex */
1049 KeWaitForSingleObject(This->Header.ControlMutex, Executive, KernelMode, FALSE, NULL);
1050
1051 if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_METHOD)
1052 {
1053 const KSMETHOD_SET *MethodSet = NULL;
1054 ULONG MethodItemSize = 0;
1055
1056 /* check if the driver supports method sets */
1057 if (FilterInstance->Descriptor->AutomationTable->MethodSetsCount)
1058 {
1059 SetCount = FilterInstance->Descriptor->AutomationTable->MethodSetsCount;
1060 MethodSet = FilterInstance->Descriptor->AutomationTable->MethodSets;
1061 MethodItemSize = FilterInstance->Descriptor->AutomationTable->MethodItemSize;
1062 }
1063
1064 /* call method set handler */
1065 Status = KspMethodHandlerWithAllocator(Irp, SetCount, MethodSet, NULL, MethodItemSize);
1066 }
1067 else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_PROPERTY)
1068 {
1069 const KSPROPERTY_SET *PropertySet = NULL;
1070 ULONG PropertyItemSize = 0;
1071
1072 /* check if the driver supports method sets */
1073 if (Property->Flags & KSPROPERTY_TYPE_TOPOLOGY)
1074 {
1075 ASSERT(IoStack->Parameters.DeviceIoControl.InputBufferLength >= sizeof(KSP_NODE));
1076 NodeProperty = (PKSP_NODE)Property;
1077 NodeDescriptor = (PKSNODE_DESCRIPTOR)((ULONG_PTR)FilterInstance->Descriptor->NodeDescriptors + FilterInstance->Descriptor->NodeDescriptorSize * NodeProperty->NodeId);
1078 if (NodeDescriptor->AutomationTable != NULL)
1079 {
1080 SetCount = NodeDescriptor->AutomationTable->PropertySetsCount;
1081 PropertySet = NodeDescriptor->AutomationTable->PropertySets;
1082 PropertyItemSize = 0;
1083 }
1084 }
1085 else if (FilterInstance->Descriptor->AutomationTable->PropertySetsCount)
1086 {
1087 SetCount = FilterInstance->Descriptor->AutomationTable->PropertySetsCount;
1088 PropertySet = FilterInstance->Descriptor->AutomationTable->PropertySets;
1089 PropertyItemSize = FilterInstance->Descriptor->AutomationTable->PropertyItemSize;
1090 // FIXME: handle variable sized property items
1091 ASSERT(PropertyItemSize == sizeof(KSPROPERTY_ITEM));
1092 PropertyItemSize = 0;
1093 }
1094
1095 /* needed for our property handlers */
1096 KSPROPERTY_ITEM_IRP_STORAGE(Irp) = (KSPROPERTY_ITEM*)This;
1097
1098 /* call property handler */
1099 Status = KspPropertyHandler(Irp, SetCount, PropertySet, NULL, PropertyItemSize);
1100 }
1101 else
1102 {
1103 /* sanity check */
1104 ASSERT(IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_ENABLE_EVENT ||
1105 IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_DISABLE_EVENT);
1106
1107 if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_ENABLE_EVENT)
1108 {
1109 /* call enable event handlers */
1110 Status = KspEnableEvent(Irp,
1111 FilterInstance->Descriptor->AutomationTable->EventSetsCount,
1112 (PKSEVENT_SET)FilterInstance->Descriptor->AutomationTable->EventSets,
1113 &This->Header.EventList,
1114 KSEVENTS_SPINLOCK,
1115 (PVOID)&This->Header.EventListLock,
1116 NULL,
1117 FilterInstance->Descriptor->AutomationTable->EventItemSize);
1118 }
1119 else
1120 {
1121 /* disable event handler */
1122 Status = KsDisableEvent(Irp, &This->Header.EventList, KSEVENTS_SPINLOCK, &This->Header.EventListLock);
1123 }
1124 }
1125
1126 RtlStringFromGUID(&Property->Set, &GuidString);
1127 DPRINT("IKsFilter_DispatchDeviceIoControl property PinCount %x\n", FilterInstance->Descriptor->PinDescriptorsCount);
1128 DPRINT("IKsFilter_DispatchDeviceIoControl property Set |%S| Id %u Flags %x Status %lx ResultLength %lu\n", GuidString.Buffer, Property->Id, Property->Flags, Status, Irp->IoStatus.Information);
1129 RtlFreeUnicodeString(&GuidString);
1130
1131 /* release filter */
1132 Filter->lpVtbl->Release(Filter);
1133
1134 /* release control mutex */
1135 KeReleaseMutex(This->Header.ControlMutex, FALSE);
1136
1137 if (Status != STATUS_PENDING)
1138 {
1139 Irp->IoStatus.Status = Status;
1140 CompleteRequest(Irp, IO_NO_INCREMENT);
1141 }
1142
1143 /* done */
1144 return Status;
1145 }
1146
1147 static KSDISPATCH_TABLE DispatchTable =
1148 {
1149 IKsFilter_DispatchDeviceIoControl,
1150 KsDispatchInvalidDeviceRequest,
1151 KsDispatchInvalidDeviceRequest,
1152 KsDispatchInvalidDeviceRequest,
1153 IKsFilter_DispatchClose,
1154 KsDispatchQuerySecurity,
1155 KsDispatchSetSecurity,
1156 KsDispatchFastIoDeviceControlFailure,
1157 KsDispatchFastReadFailure,
1158 KsDispatchFastReadFailure,
1159 };
1160
1161
1162 NTSTATUS
IKsFilter_CreateDescriptors(IKsFilterImpl * This,KSFILTER_DESCRIPTOR * FilterDescriptor)1163 IKsFilter_CreateDescriptors(
1164 IKsFilterImpl * This,
1165 KSFILTER_DESCRIPTOR* FilterDescriptor)
1166 {
1167 ULONG Index = 0;
1168 NTSTATUS Status;
1169 PKSNODE_DESCRIPTOR NodeDescriptor;
1170
1171 /* initialize pin descriptors */
1172 This->FirstPin = NULL;
1173 This->PinInstanceCount = NULL;
1174 This->ProcessPinIndex = NULL;
1175
1176 /* initialize topology descriptor */
1177 This->Topology.CategoriesCount = FilterDescriptor->CategoriesCount;
1178 This->Topology.Categories = FilterDescriptor->Categories;
1179 This->Topology.TopologyNodesCount = FilterDescriptor->NodeDescriptorsCount;
1180 This->Topology.TopologyConnectionsCount = FilterDescriptor->ConnectionsCount;
1181 This->Topology.TopologyConnections = FilterDescriptor->Connections;
1182
1183 /* are there any templates */
1184 if (FilterDescriptor->PinDescriptorsCount)
1185 {
1186 /* sanity check */
1187 ASSERT(FilterDescriptor->PinDescriptors);
1188
1189 /* FIXME handle variable sized pin descriptors */
1190 ASSERT(FilterDescriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX));
1191
1192 /* store pin descriptors ex */
1193 Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->Filter.Descriptor->PinDescriptors, FilterDescriptor->PinDescriptorSize * FilterDescriptor->PinDescriptorsCount,
1194 FilterDescriptor->PinDescriptorSize * FilterDescriptor->PinDescriptorsCount, 0);
1195
1196 if (!NT_SUCCESS(Status))
1197 {
1198 DPRINT("IKsFilter_CreateDescriptors _KsEdit failed %lx\n", Status);
1199 return Status;
1200 }
1201
1202 /* store pin instance count */
1203 Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->PinInstanceCount, sizeof(ULONG) * FilterDescriptor->PinDescriptorsCount,
1204 sizeof(ULONG) * FilterDescriptor->PinDescriptorsCount, 0);
1205
1206 if (!NT_SUCCESS(Status))
1207 {
1208 DPRINT("IKsFilter_CreateDescriptors _KsEdit failed %lx\n", Status);
1209 return Status;
1210 }
1211
1212 /* store instantiated pin arrays */
1213 Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->FirstPin, sizeof(PVOID) * FilterDescriptor->PinDescriptorsCount,
1214 sizeof(PVOID) * FilterDescriptor->PinDescriptorsCount, 0);
1215
1216 if (!NT_SUCCESS(Status))
1217 {
1218 DPRINT("IKsFilter_CreateDescriptors _KsEdit failed %lx\n", Status);
1219 return Status;
1220 }
1221
1222 /* add new pin factory */
1223 RtlMoveMemory((PVOID)This->Filter.Descriptor->PinDescriptors, FilterDescriptor->PinDescriptors, FilterDescriptor->PinDescriptorSize * FilterDescriptor->PinDescriptorsCount);
1224
1225 /* allocate process pin index */
1226 Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->ProcessPinIndex, sizeof(KSPROCESSPIN_INDEXENTRY) * FilterDescriptor->PinDescriptorsCount,
1227 sizeof(KSPROCESSPIN_INDEXENTRY) * FilterDescriptor->PinDescriptorsCount, 0);
1228
1229 if (!NT_SUCCESS(Status))
1230 {
1231 DPRINT("IKsFilter_CreateDescriptors _KsEdit failed %lx\n", Status);
1232 return Status;
1233 }
1234
1235 }
1236
1237
1238 if (FilterDescriptor->ConnectionsCount)
1239 {
1240 /* modify connections array */
1241 Status = _KsEdit(This->Filter.Bag,
1242 (PVOID*)&This->Filter.Descriptor->Connections,
1243 FilterDescriptor->ConnectionsCount * sizeof(KSTOPOLOGY_CONNECTION),
1244 FilterDescriptor->ConnectionsCount * sizeof(KSTOPOLOGY_CONNECTION),
1245 0);
1246
1247 This->Topology.TopologyConnections = This->Filter.Descriptor->Connections;
1248 This->Topology.TopologyConnectionsCount = ((PKSFILTER_DESCRIPTOR)This->Filter.Descriptor)->ConnectionsCount = FilterDescriptor->ConnectionsCount;
1249 }
1250
1251 if (FilterDescriptor->NodeDescriptorsCount)
1252 {
1253 /* sanity check */
1254 ASSERT(FilterDescriptor->NodeDescriptors);
1255
1256 /* sanity check */
1257 ASSERT(FilterDescriptor->NodeDescriptorSize >= sizeof(KSNODE_DESCRIPTOR));
1258
1259 This->Topology.TopologyNodes = AllocateItem(NonPagedPool, sizeof(GUID) * FilterDescriptor->NodeDescriptorsCount);
1260 /* allocate topology node types array */
1261 if (!This->Topology.TopologyNodes)
1262 {
1263 DPRINT("IKsFilter_CreateDescriptors OutOfMemory TopologyNodesCount %lu\n", FilterDescriptor->NodeDescriptorsCount);
1264 return STATUS_INSUFFICIENT_RESOURCES;
1265 }
1266
1267 This->Topology.TopologyNodesNames = AllocateItem(NonPagedPool, sizeof(GUID) * FilterDescriptor->NodeDescriptorsCount);
1268 /* allocate topology names array */
1269 if (!This->Topology.TopologyNodesNames)
1270 {
1271 FreeItem((PVOID)This->Topology.TopologyNodes);
1272 DPRINT("IKsFilter_CreateDescriptors OutOfMemory TopologyNodesCount %lu\n", FilterDescriptor->NodeDescriptorsCount);
1273 return STATUS_INSUFFICIENT_RESOURCES;
1274 }
1275
1276 DPRINT("NodeDescriptorCount %lu\n", FilterDescriptor->NodeDescriptorsCount);
1277 NodeDescriptor = (PKSNODE_DESCRIPTOR)FilterDescriptor->NodeDescriptors;
1278 for(Index = 0; Index < FilterDescriptor->NodeDescriptorsCount; Index++)
1279 {
1280 DPRINT("Index %lu Type %p Name %p\n", Index, NodeDescriptor->Type, NodeDescriptor->Name);
1281
1282 /* copy topology type */
1283 if (NodeDescriptor->Type)
1284 RtlMoveMemory((PVOID)&This->Topology.TopologyNodes[Index], NodeDescriptor->Type, sizeof(GUID));
1285
1286 /* copy topology name */
1287 if (NodeDescriptor->Name)
1288 RtlMoveMemory((PVOID)&This->Topology.TopologyNodesNames[Index], NodeDescriptor->Name, sizeof(GUID));
1289
1290 // next node descriptor
1291 NodeDescriptor = (PKSNODE_DESCRIPTOR)((ULONG_PTR)NodeDescriptor + FilterDescriptor->NodeDescriptorSize);
1292 }
1293 }
1294 /* done! */
1295 return STATUS_SUCCESS;
1296 }
1297
1298 NTSTATUS
IKsFilter_CopyFilterDescriptor(IKsFilterImpl * This,const KSFILTER_DESCRIPTOR * FilterDescriptor)1299 IKsFilter_CopyFilterDescriptor(
1300 IKsFilterImpl * This,
1301 const KSFILTER_DESCRIPTOR* FilterDescriptor)
1302 {
1303 NTSTATUS Status;
1304 KSAUTOMATION_TABLE AutomationTable;
1305
1306 This->Filter.Descriptor = AllocateItem(NonPagedPool, sizeof(KSFILTER_DESCRIPTOR));
1307 if (!This->Filter.Descriptor)
1308 return STATUS_INSUFFICIENT_RESOURCES;
1309
1310 Status = KsAddItemToObjectBag(This->Filter.Bag, (PVOID)This->Filter.Descriptor, NULL);
1311 if (!NT_SUCCESS(Status))
1312 {
1313 FreeItem((PVOID)This->Filter.Descriptor);
1314 This->Filter.Descriptor = NULL;
1315 return STATUS_INSUFFICIENT_RESOURCES;
1316 }
1317
1318 /* copy filter descriptor fields */
1319 RtlMoveMemory((PVOID)This->Filter.Descriptor, FilterDescriptor, sizeof(KSFILTER_DESCRIPTOR));
1320
1321 /* zero automation table */
1322 RtlZeroMemory(&AutomationTable, sizeof(KSAUTOMATION_TABLE));
1323
1324 /* setup filter property sets */
1325 AutomationTable.PropertyItemSize = sizeof(KSPROPERTY_ITEM);
1326 AutomationTable.PropertySetsCount = 3;
1327 AutomationTable.PropertySets = FilterPropertySet;
1328
1329 /* merge filter automation table */
1330 Status = KsMergeAutomationTables((PKSAUTOMATION_TABLE*)&This->Filter.Descriptor->AutomationTable, (PKSAUTOMATION_TABLE)FilterDescriptor->AutomationTable, &AutomationTable, This->Filter.Bag);
1331
1332 return Status;
1333 }
1334
1335
1336 VOID
IKsFilter_AddPin(PKSFILTER Filter,PKSPIN Pin)1337 IKsFilter_AddPin(
1338 PKSFILTER Filter,
1339 PKSPIN Pin)
1340 {
1341 PKSPIN NextPin, CurPin;
1342 PKSBASIC_HEADER BasicHeader;
1343 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
1344
1345 /* sanity check */
1346 ASSERT(Pin->Id < This->Filter.Descriptor->PinDescriptorsCount);
1347
1348 if (This->FirstPin[Pin->Id] == NULL)
1349 {
1350 /* welcome first pin */
1351 This->FirstPin[Pin->Id] = Pin;
1352 This->PinInstanceCount[Pin->Id]++;
1353 return;
1354 }
1355
1356 /* get first pin */
1357 CurPin = This->FirstPin[Pin->Id];
1358
1359 do
1360 {
1361 /* get next instantiated pin */
1362 NextPin = KsPinGetNextSiblingPin(CurPin);
1363 if (!NextPin)
1364 break;
1365
1366 NextPin = CurPin;
1367
1368 }while(NextPin != NULL);
1369
1370 /* get basic header */
1371 BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)CurPin - sizeof(KSBASIC_HEADER));
1372
1373 /* store pin */
1374 BasicHeader->Next.Pin = Pin;
1375 }
1376
1377 VOID
IKsFilter_RemovePin(PKSFILTER Filter,PKSPIN Pin)1378 IKsFilter_RemovePin(
1379 PKSFILTER Filter,
1380 PKSPIN Pin)
1381 {
1382 PKSPIN NextPin, CurPin, LastPin;
1383 PKSBASIC_HEADER BasicHeader;
1384 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
1385
1386 /* sanity check */
1387 ASSERT(Pin->Id < This->Filter.Descriptor->PinDescriptorsCount);
1388
1389 /* get first pin */
1390 CurPin = This->FirstPin[Pin->Id];
1391
1392 LastPin = NULL;
1393 do
1394 {
1395 /* get next instantiated pin */
1396 NextPin = KsPinGetNextSiblingPin(CurPin);
1397
1398 if (CurPin == Pin)
1399 {
1400 if (LastPin)
1401 {
1402 /* get basic header of last pin */
1403 BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)LastPin - sizeof(KSBASIC_HEADER));
1404
1405 BasicHeader->Next.Pin = NextPin;
1406 }
1407 else
1408 {
1409 /* erase last pin */
1410 This->FirstPin[Pin->Id] = NextPin;
1411 }
1412 /* decrement pin instance count */
1413 This->PinInstanceCount[Pin->Id]--;
1414 return;
1415 }
1416
1417 if (!NextPin)
1418 break;
1419
1420 LastPin = CurPin;
1421 NextPin = CurPin;
1422
1423 }while(NextPin != NULL);
1424
1425 /* pin not found */
1426 ASSERT(0);
1427 }
1428
1429
1430 NTSTATUS
1431 NTAPI
IKsFilter_DispatchCreatePin(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)1432 IKsFilter_DispatchCreatePin(
1433 IN PDEVICE_OBJECT DeviceObject,
1434 IN PIRP Irp)
1435 {
1436 IKsFilterImpl * This;
1437 PKSOBJECT_CREATE_ITEM CreateItem;
1438 PKSPIN_CONNECT Connect;
1439 NTSTATUS Status;
1440
1441 DPRINT("IKsFilter_DispatchCreatePin\n");
1442
1443 /* get the create item */
1444 CreateItem = KSCREATE_ITEM_IRP_STORAGE(Irp);
1445
1446 /* get the filter object */
1447 This = (IKsFilterImpl*)CreateItem->Context;
1448
1449 /* sanity check */
1450 ASSERT(This->Header.Type == KsObjectTypeFilter);
1451
1452 /* acquire control mutex */
1453 KeWaitForSingleObject(This->Header.ControlMutex, Executive, KernelMode, FALSE, NULL);
1454
1455 /* now validate the connect request */
1456 Status = KspValidateConnectRequest(Irp, This->Filter.Descriptor->PinDescriptorsCount, (PVOID)This->Filter.Descriptor->PinDescriptors, This->Filter.Descriptor->PinDescriptorSize, &Connect);
1457
1458 DPRINT("IKsFilter_DispatchCreatePin KsValidateConnectRequest %lx\n", Status);
1459
1460 if (NT_SUCCESS(Status))
1461 {
1462 /* sanity check */
1463 ASSERT(Connect->PinId < This->Filter.Descriptor->PinDescriptorsCount);
1464
1465 DPRINT("IKsFilter_DispatchCreatePin KsValidateConnectRequest PinId %lu CurrentInstanceCount %lu MaxPossible %lu\n", Connect->PinId,
1466 This->PinInstanceCount[Connect->PinId],
1467 This->Filter.Descriptor->PinDescriptors[Connect->PinId].InstancesPossible);
1468
1469 if (This->PinInstanceCount[Connect->PinId] < This->Filter.Descriptor->PinDescriptors[Connect->PinId].InstancesPossible)
1470 {
1471 /* create the pin */
1472 Status = KspCreatePin(DeviceObject, Irp, This->Header.KsDevice, This->FilterFactory, (IKsFilter*)&This->Header.OuterUnknown, Connect, (KSPIN_DESCRIPTOR_EX*)&This->Filter.Descriptor->PinDescriptors[Connect->PinId]);
1473
1474 DPRINT("IKsFilter_DispatchCreatePin KspCreatePin %lx\n", Status);
1475 }
1476 else
1477 {
1478 /* maximum instance count reached, bye-bye */
1479 Status = STATUS_UNSUCCESSFUL;
1480 DPRINT("IKsFilter_DispatchCreatePin MaxInstance %lu CurInstance %lu %lx\n", This->Filter.Descriptor->PinDescriptors[Connect->PinId].InstancesPossible, This->PinInstanceCount[Connect->PinId]);
1481 }
1482 }
1483
1484 /* release control mutex */
1485 KeReleaseMutex(This->Header.ControlMutex, FALSE);
1486
1487 if (Status != STATUS_PENDING)
1488 {
1489 /* complete request */
1490 Irp->IoStatus.Status = Status;
1491 CompleteRequest(Irp, IO_NO_INCREMENT);
1492 }
1493
1494 /* done */
1495 DPRINT("IKsFilter_DispatchCreatePin Result %lx\n", Status);
1496 return Status;
1497 }
1498
1499 NTSTATUS
1500 NTAPI
IKsFilter_DispatchCreateNode(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)1501 IKsFilter_DispatchCreateNode(
1502 IN PDEVICE_OBJECT DeviceObject,
1503 IN PIRP Irp)
1504 {
1505 UNIMPLEMENTED;
1506 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
1507 CompleteRequest(Irp, IO_NO_INCREMENT);
1508 return STATUS_UNSUCCESSFUL;
1509 }
1510
1511
1512 VOID
IKsFilter_AttachFilterToFilterFactory(IKsFilterImpl * This,PKSFILTERFACTORY FilterFactory)1513 IKsFilter_AttachFilterToFilterFactory(
1514 IKsFilterImpl * This,
1515 PKSFILTERFACTORY FilterFactory)
1516 {
1517 PKSBASIC_HEADER BasicHeader;
1518 PKSFILTER Filter;
1519
1520
1521 /* get filter factory basic header */
1522 BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)FilterFactory - sizeof(KSBASIC_HEADER));
1523
1524 /* sanity check */
1525 ASSERT(BasicHeader->Type == KsObjectTypeFilterFactory);
1526
1527 if (BasicHeader->FirstChild.FilterFactory == NULL)
1528 {
1529 /* welcome first instantiated filter */
1530 BasicHeader->FirstChild.Filter = &This->Filter;
1531 return;
1532 }
1533
1534 /* set to first entry */
1535 Filter = BasicHeader->FirstChild.Filter;
1536
1537 do
1538 {
1539 /* get basic header */
1540 BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)Filter - sizeof(KSBASIC_HEADER));
1541 /* sanity check */
1542 ASSERT(BasicHeader->Type == KsObjectTypeFilter);
1543
1544 if (BasicHeader->Next.Filter)
1545 {
1546 /* iterate to next filter factory */
1547 Filter = BasicHeader->Next.Filter;
1548 }
1549 else
1550 {
1551 /* found last entry */
1552 break;
1553 }
1554 }while(TRUE);
1555
1556 /* attach filter factory */
1557 BasicHeader->Next.Filter = &This->Filter;
1558 }
1559
1560 VOID
IKsFilter_RemoveFilterFromFilterFactory(IKsFilterImpl * This,PKSFILTERFACTORY FilterFactory)1561 IKsFilter_RemoveFilterFromFilterFactory(
1562 IKsFilterImpl * This,
1563 PKSFILTERFACTORY FilterFactory)
1564 {
1565 PKSBASIC_HEADER BasicHeader;
1566 PKSFILTER Filter, LastFilter;
1567
1568 /* get filter factory basic header */
1569 BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)FilterFactory - sizeof(KSBASIC_HEADER));
1570
1571 /* sanity check */
1572 ASSERT(BasicHeader->Type == KsObjectTypeFilterFactory);
1573 ASSERT(BasicHeader->FirstChild.Filter != NULL);
1574
1575
1576 /* set to first entry */
1577 Filter = BasicHeader->FirstChild.Filter;
1578 LastFilter = NULL;
1579
1580 do
1581 {
1582 if (Filter == &This->Filter)
1583 {
1584 if (LastFilter)
1585 {
1586 /* get basic header */
1587 BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)LastFilter - sizeof(KSBASIC_HEADER));
1588 /* remove filter instance */
1589 BasicHeader->Next.Filter = This->Header.Next.Filter;
1590 break;
1591 }
1592 else
1593 {
1594 /* remove filter instance */
1595 BasicHeader->FirstChild.Filter = This->Header.Next.Filter;
1596 break;
1597 }
1598 }
1599
1600 /* get basic header */
1601 BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)Filter - sizeof(KSBASIC_HEADER));
1602 /* sanity check */
1603 ASSERT(BasicHeader->Type == KsObjectTypeFilter);
1604
1605 LastFilter = Filter;
1606 if (BasicHeader->Next.Filter)
1607 {
1608 /* iterate to next filter factory */
1609 Filter = BasicHeader->Next.Filter;
1610 }
1611 else
1612 {
1613 /* filter is not in list */
1614 ASSERT(0);
1615 break;
1616 }
1617 }while(TRUE);
1618 }
1619
1620 VOID
1621 NTAPI
IKsFilter_FilterCentricWorker(IN PVOID Ctx)1622 IKsFilter_FilterCentricWorker(
1623 IN PVOID Ctx)
1624 {
1625 IKsProcessingObject * Object = (IKsProcessingObject*)Ctx;
1626
1627 /* sanity check */
1628 ASSERT(Object);
1629
1630 /* perform work */
1631 Object->lpVtbl->ProcessingObjectWork(Object);
1632 }
1633
1634 NTSTATUS
1635 NTAPI
KspCreateFilter(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp,IN IKsFilterFactory * iface)1636 KspCreateFilter(
1637 IN PDEVICE_OBJECT DeviceObject,
1638 IN PIRP Irp,
1639 IN IKsFilterFactory *iface)
1640 {
1641 IKsFilterImpl * This;
1642 IKsDevice *KsDevice;
1643 PKSFILTERFACTORY Factory;
1644 PIO_STACK_LOCATION IoStack;
1645 PDEVICE_EXTENSION DeviceExtension;
1646 NTSTATUS Status;
1647 PKSOBJECT_CREATE_ITEM CreateItem;
1648
1649 /* get device extension */
1650 DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
1651
1652 /* get the filter factory */
1653 Factory = iface->lpVtbl->GetStruct(iface);
1654
1655 if (!Factory || !Factory->FilterDescriptor)
1656 {
1657 /* Sorry it just will not work */
1658 return STATUS_UNSUCCESSFUL;
1659 }
1660
1661 if (Factory->FilterDescriptor->Flags & KSFILTER_FLAG_DENY_USERMODE_ACCESS)
1662 {
1663 if (Irp->RequestorMode == UserMode)
1664 {
1665 /* filter not accessible from user mode */
1666 DPRINT1("Access denied\n");
1667 return STATUS_UNSUCCESSFUL;
1668 }
1669 }
1670
1671 /* allocate filter instance */
1672 This = AllocateItem(NonPagedPool, sizeof(IKsFilterImpl));
1673 if (!This)
1674 {
1675 DPRINT1("KspCreateFilter OutOfMemory\n");
1676 return STATUS_INSUFFICIENT_RESOURCES;
1677 }
1678
1679 /* initialize object bag */
1680 This->Filter.Bag = AllocateItem(NonPagedPool, sizeof(KSIOBJECT_BAG));
1681 if (!This->Filter.Bag)
1682 {
1683 /* no memory */
1684 FreeItem(This);
1685 DPRINT1("KspCreateFilter OutOfMemory\n");
1686 return STATUS_INSUFFICIENT_RESOURCES;
1687 }
1688 KsDevice = (IKsDevice*)&DeviceExtension->DeviceHeader->BasicHeader.OuterUnknown;
1689 KsDevice->lpVtbl->InitializeObjectBag(KsDevice, (PKSIOBJECT_BAG)This->Filter.Bag, NULL);
1690
1691 /* copy filter descriptor */
1692 Status = IKsFilter_CopyFilterDescriptor(This, Factory->FilterDescriptor);
1693 if (!NT_SUCCESS(Status))
1694 {
1695 /* not enough memory */
1696 FreeItem(This->Filter.Bag);
1697 FreeItem(This);
1698 DPRINT("KspCreateFilter IKsFilter_CopyFilterDescriptor failed %lx\n", Status);
1699 return STATUS_INSUFFICIENT_RESOURCES;
1700 }
1701
1702 /* get current irp stack */
1703 IoStack = IoGetCurrentIrpStackLocation(Irp);
1704
1705 /* allocate create items */
1706 CreateItem = AllocateItem(NonPagedPool, sizeof(KSOBJECT_CREATE_ITEM) * 2);
1707 if (!CreateItem)
1708 {
1709 /* no memory */
1710 FreeItem(This->Filter.Bag);
1711 FreeItem(This);
1712 DPRINT1("KspCreateFilter OutOfMemory\n");
1713 return STATUS_INSUFFICIENT_RESOURCES;
1714 }
1715
1716 /* initialize pin create item */
1717 CreateItem[0].Create = IKsFilter_DispatchCreatePin;
1718 CreateItem[0].Context = (PVOID)This;
1719 CreateItem[0].Flags = KSCREATE_ITEM_FREEONSTOP;
1720 RtlInitUnicodeString(&CreateItem[0].ObjectClass, KSSTRING_Pin);
1721 /* initialize node create item */
1722 CreateItem[1].Create = IKsFilter_DispatchCreateNode;
1723 CreateItem[1].Context = (PVOID)This;
1724 CreateItem[1].Flags = KSCREATE_ITEM_FREEONSTOP;
1725 RtlInitUnicodeString(&CreateItem[1].ObjectClass, KSSTRING_TopologyNode);
1726
1727
1728 /* initialize filter instance */
1729 This->ref = 1;
1730 This->Header.OuterUnknown = (PUNKNOWN)&vt_IKsFilter;
1731 This->lpVtblKsControl = &vt_IKsControl;
1732 This->lpVtblKsProcessingObject = &vt_IKsProcessingObject;
1733
1734 This->Factory = Factory;
1735 This->FilterFactory = iface;
1736 This->FileObject = IoStack->FileObject;
1737 KeInitializeMutex(&This->ProcessingMutex, 0);
1738
1739 /* initialize basic header */
1740 This->Header.KsDevice = &DeviceExtension->DeviceHeader->KsDevice;
1741 This->Header.Parent.KsFilterFactory = iface->lpVtbl->GetStruct(iface);
1742 This->Header.Type = KsObjectTypeFilter;
1743 This->Header.ControlMutex = &This->ControlMutex;
1744 KeInitializeMutex(This->Header.ControlMutex, 0);
1745 InitializeListHead(&This->Header.EventList);
1746 KeInitializeSpinLock(&This->Header.EventListLock);
1747
1748 /* initialize and gate */
1749 KsGateInitializeAnd(&This->Gate, NULL);
1750
1751 /* FIXME initialize and gate based on pin flags */
1752
1753 /* initialize work item */
1754 ExInitializeWorkItem(&This->WorkItem, IKsFilter_FilterCentricWorker, (PVOID)This->lpVtblKsProcessingObject);
1755
1756 /* allocate counted work item */
1757 Status = KsRegisterCountedWorker(HyperCriticalWorkQueue, &This->WorkItem, &This->Worker);
1758 if (!NT_SUCCESS(Status))
1759 {
1760 /* what can go wrong, goes wrong */
1761 DPRINT1("KsRegisterCountedWorker failed with %lx\n", Status);
1762 FreeItem(This);
1763 FreeItem(CreateItem);
1764 return Status;
1765 }
1766
1767 /* allocate the stream descriptors */
1768 Status = IKsFilter_CreateDescriptors(This, (PKSFILTER_DESCRIPTOR)Factory->FilterDescriptor);
1769 if (!NT_SUCCESS(Status))
1770 {
1771 /* what can go wrong, goes wrong */
1772 DPRINT1("IKsFilter_CreateDescriptors failed with %lx\n", Status);
1773 KsUnregisterWorker(This->Worker);
1774 FreeItem(This);
1775 FreeItem(CreateItem);
1776 return Status;
1777 }
1778
1779
1780
1781 /* does the filter have a filter dispatch */
1782 if (Factory->FilterDescriptor->Dispatch)
1783 {
1784 /* does it have a create routine */
1785 if (Factory->FilterDescriptor->Dispatch->Create)
1786 {
1787 /* now let driver initialize the filter instance */
1788
1789 ASSERT(This->Header.KsDevice);
1790 ASSERT(This->Header.KsDevice->Started);
1791 Status = Factory->FilterDescriptor->Dispatch->Create(&This->Filter, Irp);
1792
1793 if (!NT_SUCCESS(Status) && Status != STATUS_PENDING)
1794 {
1795 /* driver failed to initialize */
1796 DPRINT1("Driver: Status %x\n", Status);
1797
1798 /* free filter instance */
1799 KsUnregisterWorker(This->Worker);
1800 FreeItem(This);
1801 FreeItem(CreateItem);
1802 return Status;
1803 }
1804 }
1805 }
1806
1807 /* now allocate the object header */
1808 Status = KsAllocateObjectHeader((PVOID*)&This->ObjectHeader, 2, CreateItem, Irp, &DispatchTable);
1809 if (!NT_SUCCESS(Status))
1810 {
1811 /* failed to allocate object header */
1812 DPRINT1("Failed to allocate object header %x\n", Status);
1813
1814 return Status;
1815 }
1816
1817 /* initialize object header extra fields */
1818 This->ObjectHeader->Type = KsObjectTypeFilter;
1819 This->ObjectHeader->Unknown = (PUNKNOWN)&This->Header.OuterUnknown;
1820 This->ObjectHeader->ObjectType = (PVOID)&This->Filter;
1821
1822 /* attach filter to filter factory */
1823 IKsFilter_AttachFilterToFilterFactory(This, This->Header.Parent.KsFilterFactory);
1824
1825 /* completed initialization */
1826 DPRINT1("KspCreateFilter done %lx KsDevice %p\n", Status, This->Header.KsDevice);
1827 return Status;
1828 }
1829
1830 /*
1831 @implemented
1832 */
1833 KSDDKAPI
1834 VOID
1835 NTAPI
KsFilterAcquireProcessingMutex(IN PKSFILTER Filter)1836 KsFilterAcquireProcessingMutex(
1837 IN PKSFILTER Filter)
1838 {
1839 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
1840
1841 KeWaitForSingleObject(&This->ProcessingMutex, Executive, KernelMode, FALSE, NULL);
1842 }
1843
1844 /*
1845 @implemented
1846 */
1847 KSDDKAPI
1848 VOID
1849 NTAPI
KsFilterReleaseProcessingMutex(IN PKSFILTER Filter)1850 KsFilterReleaseProcessingMutex(
1851 IN PKSFILTER Filter)
1852 {
1853 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
1854
1855 KeReleaseMutex(&This->ProcessingMutex, FALSE);
1856 }
1857
1858
1859 /*
1860 @implemented
1861 */
1862 KSDDKAPI
1863 NTSTATUS
1864 NTAPI
KsFilterAddTopologyConnections(IN PKSFILTER Filter,IN ULONG NewConnectionsCount,IN const KSTOPOLOGY_CONNECTION * const NewTopologyConnections)1865 KsFilterAddTopologyConnections (
1866 IN PKSFILTER Filter,
1867 IN ULONG NewConnectionsCount,
1868 IN const KSTOPOLOGY_CONNECTION *const NewTopologyConnections)
1869 {
1870 ULONG Count;
1871 NTSTATUS Status;
1872 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
1873
1874 DPRINT("KsFilterAddTopologyConnections\n");
1875
1876 ASSERT(This->Filter.Descriptor);
1877 Count = This->Filter.Descriptor->ConnectionsCount + NewConnectionsCount;
1878
1879
1880 /* modify connections array */
1881 Status = _KsEdit(This->Filter.Bag,
1882 (PVOID*)&This->Filter.Descriptor->Connections,
1883 Count * sizeof(KSTOPOLOGY_CONNECTION),
1884 This->Filter.Descriptor->ConnectionsCount * sizeof(KSTOPOLOGY_CONNECTION),
1885 0);
1886
1887 if (!NT_SUCCESS(Status))
1888 {
1889 /* failed */
1890 DPRINT("KsFilterAddTopologyConnections KsEdit failed with %lx\n", Status);
1891 return Status;
1892 }
1893
1894 /* FIXME verify connections */
1895
1896 /* copy new connections */
1897 RtlMoveMemory((PVOID)&This->Filter.Descriptor->Connections[This->Filter.Descriptor->ConnectionsCount],
1898 NewTopologyConnections,
1899 NewConnectionsCount * sizeof(KSTOPOLOGY_CONNECTION));
1900
1901 /* update topology */
1902 This->Topology.TopologyConnectionsCount += NewConnectionsCount;
1903 ((PKSFILTER_DESCRIPTOR)This->Filter.Descriptor)->ConnectionsCount += NewConnectionsCount;
1904 This->Topology.TopologyConnections = This->Filter.Descriptor->Connections;
1905
1906 return Status;
1907 }
1908
1909 /*
1910 @implemented
1911 */
1912 KSDDKAPI
1913 VOID
1914 NTAPI
KsFilterAttemptProcessing(IN PKSFILTER Filter,IN BOOLEAN Asynchronous)1915 KsFilterAttemptProcessing(
1916 IN PKSFILTER Filter,
1917 IN BOOLEAN Asynchronous)
1918 {
1919 PKSGATE Gate;
1920 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
1921
1922 /* get gate */
1923 Gate = This->lpVtblKsProcessingObject->GetAndGate((IKsProcessingObject*)This->lpVtblKsProcessingObject);
1924
1925 if (!KsGateCaptureThreshold(Gate))
1926 {
1927 /* filter control gate is closed */
1928 return;
1929 }
1930 DPRINT1("processing\n");
1931 /* try initiate processing */
1932 This->lpVtblKsProcessingObject->Process((IKsProcessingObject*)This->lpVtblKsProcessingObject, Asynchronous);
1933 }
1934
1935 /*
1936 @unimplemented
1937 */
1938 KSDDKAPI
1939 NTSTATUS
1940 NTAPI
KsFilterCreateNode(IN PKSFILTER Filter,IN const KSNODE_DESCRIPTOR * const NodeDescriptor,OUT PULONG NodeID)1941 KsFilterCreateNode (
1942 IN PKSFILTER Filter,
1943 IN const KSNODE_DESCRIPTOR *const NodeDescriptor,
1944 OUT PULONG NodeID)
1945 {
1946 UNIMPLEMENTED;
1947 return STATUS_NOT_IMPLEMENTED;
1948 }
1949
1950 /*
1951 @implemented
1952 */
1953 KSDDKAPI
1954 NTSTATUS
1955 NTAPI
KsFilterCreatePinFactory(IN PKSFILTER Filter,IN const KSPIN_DESCRIPTOR_EX * const InPinDescriptor,OUT PULONG PinID)1956 KsFilterCreatePinFactory (
1957 IN PKSFILTER Filter,
1958 IN const KSPIN_DESCRIPTOR_EX *const InPinDescriptor,
1959 OUT PULONG PinID)
1960 {
1961 ULONG Count;
1962 NTSTATUS Status;
1963 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
1964
1965 DPRINT("KsFilterCreatePinFactory\n");
1966
1967 /* calculate new count */
1968 Count = This->Filter.Descriptor->PinDescriptorsCount + 1;
1969
1970 /* sanity check */
1971 ASSERT(This->Filter.Descriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX));
1972
1973 /* modify pin descriptors ex array */
1974 Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->Filter.Descriptor->PinDescriptors, Count * This->Filter.Descriptor->PinDescriptorSize, This->Filter.Descriptor->PinDescriptorsCount * This->Filter.Descriptor->PinDescriptorSize, 0);
1975 if (!NT_SUCCESS(Status))
1976 {
1977 /* failed */
1978 DPRINT("KsFilterCreatePinFactory _KsEdit failed with %lx\n", Status);
1979 return Status;
1980 }
1981
1982 /* modify pin instance count array */
1983 Status = _KsEdit(This->Filter.Bag,(PVOID*)&This->PinInstanceCount, sizeof(ULONG) * Count, sizeof(ULONG) * This->Filter.Descriptor->PinDescriptorsCount, 0);
1984 if (!NT_SUCCESS(Status))
1985 {
1986 /* failed */
1987 DPRINT("KsFilterCreatePinFactory _KsEdit failed with %lx\n", Status);
1988 return Status;
1989 }
1990
1991 /* modify first pin array */
1992 Status = _KsEdit(This->Filter.Bag,(PVOID*)&This->FirstPin, sizeof(PVOID) * Count, sizeof(PVOID) * This->Filter.Descriptor->PinDescriptorsCount, 0);
1993 if (!NT_SUCCESS(Status))
1994 {
1995 /* failed */
1996 DPRINT("KsFilterCreatePinFactory _KsEdit failed with %lx\n", Status);
1997 return Status;
1998 }
1999
2000 /* add new pin factory */
2001 RtlMoveMemory((PVOID)&This->Filter.Descriptor->PinDescriptors[This->Filter.Descriptor->PinDescriptorsCount], InPinDescriptor, sizeof(KSPIN_DESCRIPTOR_EX));
2002
2003 /* allocate process pin index */
2004 Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->ProcessPinIndex, sizeof(KSPROCESSPIN_INDEXENTRY) * Count,
2005 sizeof(KSPROCESSPIN_INDEXENTRY) * This->Filter.Descriptor->PinDescriptorsCount, 0);
2006
2007 if (!NT_SUCCESS(Status))
2008 {
2009 DPRINT("KsFilterCreatePinFactory _KsEdit failed %lx\n", Status);
2010 return Status;
2011 }
2012
2013 /* store new pin id */
2014 *PinID = This->Filter.Descriptor->PinDescriptorsCount;
2015
2016 /* increment pin descriptor count */
2017 ((PKSFILTER_DESCRIPTOR)This->Filter.Descriptor)->PinDescriptorsCount++;
2018
2019
2020 DPRINT("KsFilterCreatePinFactory done\n");
2021 return STATUS_SUCCESS;
2022
2023 }
2024
2025 /*
2026 @unimplemented
2027 */
2028 KSDDKAPI
2029 PKSGATE
2030 NTAPI
KsFilterGetAndGate(IN PKSFILTER Filter)2031 KsFilterGetAndGate(
2032 IN PKSFILTER Filter)
2033 {
2034 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
2035
2036 /* return and-gate */
2037 return &This->Gate;
2038 }
2039
2040 /*
2041 @implemented
2042 */
2043 KSDDKAPI
2044 ULONG
2045 NTAPI
KsFilterGetChildPinCount(IN PKSFILTER Filter,IN ULONG PinId)2046 KsFilterGetChildPinCount(
2047 IN PKSFILTER Filter,
2048 IN ULONG PinId)
2049 {
2050 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
2051
2052 if (PinId >= This->Filter.Descriptor->PinDescriptorsCount)
2053 {
2054 /* index is out of bounds */
2055 return 0;
2056 }
2057 /* return pin instance count */
2058 return This->PinInstanceCount[PinId];
2059 }
2060
2061 /*
2062 @implemented
2063 */
2064 KSDDKAPI
2065 PKSPIN
2066 NTAPI
KsFilterGetFirstChildPin(IN PKSFILTER Filter,IN ULONG PinId)2067 KsFilterGetFirstChildPin(
2068 IN PKSFILTER Filter,
2069 IN ULONG PinId)
2070 {
2071 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
2072
2073 if (PinId >= This->Filter.Descriptor->PinDescriptorsCount)
2074 {
2075 /* index is out of bounds */
2076 return NULL;
2077 }
2078
2079 /* return first pin index */
2080 return This->FirstPin[PinId];
2081 }
2082
2083 /*
2084 @implemented
2085 */
2086 KSDDKAPI
2087 VOID
2088 NTAPI
KsFilterRegisterPowerCallbacks(IN PKSFILTER Filter,IN PFNKSFILTERPOWER Sleep OPTIONAL,IN PFNKSFILTERPOWER Wake OPTIONAL)2089 KsFilterRegisterPowerCallbacks(
2090 IN PKSFILTER Filter,
2091 IN PFNKSFILTERPOWER Sleep OPTIONAL,
2092 IN PFNKSFILTERPOWER Wake OPTIONAL)
2093 {
2094 IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
2095
2096 This->Sleep = Sleep;
2097 This->Wake = Wake;
2098 }
2099
2100 /*
2101 @implemented
2102 */
2103 KSDDKAPI
2104 PKSFILTER
2105 NTAPI
KsGetFilterFromIrp(IN PIRP Irp)2106 KsGetFilterFromIrp(
2107 IN PIRP Irp)
2108 {
2109 PIO_STACK_LOCATION IoStack;
2110 PKSIOBJECT_HEADER ObjectHeader;
2111
2112 DPRINT("KsGetFilterFromIrp\n");
2113
2114 /* get current irp stack location */
2115 IoStack = IoGetCurrentIrpStackLocation(Irp);
2116
2117 /* sanity check */
2118 ASSERT(IoStack->FileObject);
2119
2120 /* get object header */
2121 ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->FsContext2;
2122
2123 if (ObjectHeader->Type == KsObjectTypeFilter)
2124 {
2125 /* irp is targeted at the filter */
2126 return (PKSFILTER)ObjectHeader->ObjectType;
2127 }
2128 else if (ObjectHeader->Type == KsObjectTypePin)
2129 {
2130 /* irp is for a pin */
2131 return KsPinGetParentFilter((PKSPIN)ObjectHeader->ObjectType);
2132 }
2133 else
2134 {
2135 /* irp is unappropiate to retrieve a filter */
2136 return NULL;
2137 }
2138 }
2139