KS Pins
The minidriver supplies a KSPIN_DESCRIPTOR structure for each type of pin to be instantiated. A pin descriptor structure is known as a pin factory. Each pin factory can instantiate one or more pin instances of a particular type. A pin factory contains several arrays that describe the type of pin that this descriptor instantiates.
The minidriver specifies one or more KS categories to which pins created by this descriptor belong in the Categories member of KSPIN_DESCRIPTOR. KS uses categories to connect pin instances when it builds a filter graph. The KSPROPERTY_TOPOLOGY_CATEGORIES property queries for the array of functional categories that a driver supports.
A minidriver provides an INF file that registers one or more pin device names. At installation, the operating system loads the names and corresponding categories into the system registry. Clients can then make create-file calls with these device names to instantiate pins.
User-mode clients call the Win32 function CreateFile with the name of the device. For example, "\\.\filters\audio\default renderer" could be a link to the audio device that has been configured for default output. Kernel-mode clients call ZwCreateFile from kernel mode. After the create-file routine returns a file handle, KS clients communicate with pin instances through KS Properties.
In the pin descriptor structures, the minidriver lays out arrays of KSPIN_INTERFACE structures and KSPIN_MEDIUM structures that specify the interfaces and mediums supported by that pin factory. KSPIN_DESCRIPTOR is also where the minidriver specifies the valid data ranges for pins created by that factory. It does this by providing a pointer to an array of KSDATARANGE structures. The minidriver also specifies the directions of data and communication flow for new pins created by this pin factory.
A minidriver enables run-time discovery of pin factories by supporting the KSPROPSETID_Pin property set.
To create a pin connection, call the KsCreatePin routine. In this call, the minidriver passes a pointer to a structure of type KSPIN_CONNECT that describes the requested connection. When a pin is created, the filter sees the new pin as a file object subordinate to the file object for that filter.
The minidriver calls KsValidateConnectRequest with the descriptor structures provided in the resulting IRP_MJ_CREATE. This routine validates these structures and returns a pointer to the connection structure and the root file object.
Minidrivers use the DataFlow and Communication members of KSPIN_DESCRIPTOR structures to define the following pin specifics:
IRP source pin versus IRP sink pin
An IRP source pin issues IRPs; an IRP sink pin receives them. A user-mode client sends I/O requests directly to an IRP sink pin through the relevant file handle. Clients use KSPROPERTY_PIN_COMMUNICATION to check whether data flows in or out of a pin type.
Data source pin versus data sink pin
A data source pin is an output pin on a filter; a data sink pin is an input pin. The property of being a data source or sink is independent of being an IRP source or sink. For example, the client can connect a data source, IRP sink pin to a data sink, IRP source pin. Clients use KSPROPERTY_PIN_DATAFLOW to check whether data flows in or out of a pin type.
When terminating a connection, the handle of the source pin must be closed before the underlying file object is destroyed. If the source pin relies on resources provided by the sink pin, it is the responsibility of the sink pin to notify the source when the connection is terminated.
A client interacts with a kernel streaming pin by calling the DeviceIoControl routine (described in the Microsoft Windows SDK documentation) with IRP_MJ_DEVICE_CONTROL. The caller identifies its request by the I/O control code that it places at Parameters.DeviceIoControl.IoControlCode in the I/O stack location structure.
To support requests, the minidriver supplies a pointer to a KSDISPATCH_TABLE structure in a call to KsAllocateObjectHeader.
Write requests contain a pointer to an array of KSSTREAM_HEADER structures that in turn contain pointers to stream data. Read requests contain a pointer to an array of empty header structures where the read data should be returned.