xref: /reactos/drivers/ksfilter/ks/topology.c (revision c2c66aff)
1 /*
2  * COPYRIGHT:       See COPYING in the top level directory
3  * PROJECT:         ReactOS Kernel Streaming
4  * FILE:            drivers/ksfilter/ks/topoology.c
5  * PURPOSE:         KS Allocator functions
6  * PROGRAMMER:      Johannes Anderwald
7  */
8 
9 #include "precomp.h"
10 
11 #define NDEBUG
12 #include <debug.h>
13 
14 NTSTATUS
15 NTAPI
KspCreateObjectType(IN HANDLE ParentHandle,IN LPWSTR ObjectType,PVOID CreateParameters,UINT CreateParametersSize,IN ACCESS_MASK DesiredAccess,OUT PHANDLE NodeHandle)16 KspCreateObjectType(
17     IN HANDLE ParentHandle,
18     IN LPWSTR ObjectType,
19     PVOID CreateParameters,
20     UINT CreateParametersSize,
21     IN  ACCESS_MASK DesiredAccess,
22     OUT PHANDLE NodeHandle)
23 {
24     NTSTATUS Status;
25     IO_STATUS_BLOCK IoStatusBlock;
26     OBJECT_ATTRIBUTES ObjectAttributes;
27     UNICODE_STRING Name;
28 
29     /* calculate request length */
30     Name.Length = 0;
31     Name.MaximumLength = (USHORT)(wcslen(ObjectType) * sizeof(WCHAR) + CreateParametersSize +  1 * sizeof(WCHAR));
32     Name.MaximumLength += sizeof(WCHAR);
33     /* acquire request buffer */
34     Name.Buffer = AllocateItem(NonPagedPool, Name.MaximumLength);
35     /* check for success */
36     if (!Name.Buffer)
37     {
38         /* insufficient resources */
39         return STATUS_INSUFFICIENT_RESOURCES;
40     }
41 
42     /* build a request which looks like {ObjectClass}\CreateParameters
43      * For pins the parent is the reference string used in registration
44      * For clocks it is full path for pin\{ClockGuid}\ClockCreateParams
45      */
46     RtlAppendUnicodeToString(&Name, ObjectType);
47     RtlAppendUnicodeToString(&Name, L"\\");
48     /* append create parameters */
49     RtlMoveMemory(Name.Buffer + (Name.Length / sizeof(WCHAR)), CreateParameters, CreateParametersSize);
50     Name.Length += CreateParametersSize;
51     Name.Buffer[Name.Length / 2] = L'\0';
52 
53     InitializeObjectAttributes(&ObjectAttributes, &Name, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE | OBJ_OPENIF, ParentHandle, NULL);
54     /* create the instance */
55     Status = IoCreateFile(NodeHandle,
56                           DesiredAccess,
57                           &ObjectAttributes,
58                           &IoStatusBlock,
59                           NULL,
60                           0,
61                           0,
62                           FILE_OPEN,
63                           0,
64                           NULL,
65                           0,
66                           CreateFileTypeNone,
67                           NULL,
68                           IO_NO_PARAMETER_CHECKING | IO_FORCE_ACCESS_CHECK);
69 
70     /* free request buffer */
71     FreeItem(Name.Buffer);
72     return Status;
73 }
74 
75 
76 /*
77     @implemented
78 */
79 KSDDKAPI NTSTATUS NTAPI
KsCreateTopologyNode(IN HANDLE ParentHandle,IN PKSNODE_CREATE NodeCreate,IN ACCESS_MASK DesiredAccess,OUT PHANDLE NodeHandle)80 KsCreateTopologyNode(
81     IN  HANDLE ParentHandle,
82     IN  PKSNODE_CREATE NodeCreate,
83     IN  ACCESS_MASK DesiredAccess,
84     OUT PHANDLE NodeHandle)
85 {
86     return KspCreateObjectType(ParentHandle,
87                                KSSTRING_TopologyNode,
88                                (PVOID)NodeCreate,
89                                sizeof(KSNODE_CREATE),
90                                DesiredAccess,
91                                NodeHandle);
92 }
93 
94 /*
95     @implemented
96 */
97 KSDDKAPI
98 NTSTATUS
99 NTAPI
KsValidateTopologyNodeCreateRequest(IN PIRP Irp,IN PKSTOPOLOGY Topology,OUT PKSNODE_CREATE * OutNodeCreate)100 KsValidateTopologyNodeCreateRequest(
101     IN  PIRP Irp,
102     IN  PKSTOPOLOGY Topology,
103     OUT PKSNODE_CREATE* OutNodeCreate)
104 {
105     PKSNODE_CREATE NodeCreate;
106     ULONG Size;
107     NTSTATUS Status;
108 
109     /* did the caller miss the topology */
110     if (!Topology)
111         return STATUS_INVALID_PARAMETER;
112 
113     /* set create param  size */
114     Size = sizeof(KSNODE_CREATE);
115 
116     /* fetch create parameters */
117     Status = KspCopyCreateRequest(Irp,
118                                   KSSTRING_TopologyNode,
119                                   &Size,
120                                   (PVOID*)&NodeCreate);
121 
122     if (!NT_SUCCESS(Status))
123         return Status;
124 
125     if (NodeCreate->CreateFlags != 0 || (NodeCreate->Node >= Topology->TopologyNodesCount && NodeCreate->Node != MAXULONG))
126     {
127         /* invalid node create */
128         FreeItem(NodeCreate);
129         return STATUS_UNSUCCESSFUL;
130     }
131 
132     /* store result */
133     *OutNodeCreate = NodeCreate;
134 
135     return Status;
136 }
137 
138 /*
139     @implemented
140 */
141 KSDDKAPI
142 NTSTATUS
143 NTAPI
KsTopologyPropertyHandler(IN PIRP Irp,IN PKSPROPERTY Property,IN OUT PVOID Data,IN const KSTOPOLOGY * Topology)144 KsTopologyPropertyHandler(
145     IN  PIRP Irp,
146     IN  PKSPROPERTY Property,
147     IN  OUT PVOID Data,
148     IN  const KSTOPOLOGY* Topology)
149 {
150     KSP_NODE * Node;
151     PIO_STACK_LOCATION IoStack;
152     NTSTATUS Status;
153     PKEY_VALUE_PARTIAL_INFORMATION KeyInfo;
154     LPGUID Guid;
155 
156     IoStack = IoGetCurrentIrpStackLocation(Irp);
157 
158     DPRINT("KsTopologyPropertyHandler Irp %p Property %p Data %p Topology %p OutputLength %lu PropertyId %lu\n", Irp, Property, Data, Topology, IoStack->Parameters.DeviceIoControl.OutputBufferLength, Property->Id);
159 
160     if (Property->Flags != KSPROPERTY_TYPE_GET)
161     {
162         Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
163         Irp->IoStatus.Information = 0;
164         return STATUS_NOT_IMPLEMENTED;
165     }
166 
167     switch(Property->Id)
168     {
169         case KSPROPERTY_TOPOLOGY_CATEGORIES:
170             return KsHandleSizedListQuery(Irp, Topology->CategoriesCount, sizeof(GUID), Topology->Categories);
171 
172         case KSPROPERTY_TOPOLOGY_NODES:
173             return KsHandleSizedListQuery(Irp, Topology->TopologyNodesCount, sizeof(GUID), Topology->TopologyNodes);
174 
175         case KSPROPERTY_TOPOLOGY_CONNECTIONS:
176             return KsHandleSizedListQuery(Irp, Topology->TopologyConnectionsCount, sizeof(KSTOPOLOGY_CONNECTION), Topology->TopologyConnections);
177 
178         case KSPROPERTY_TOPOLOGY_NAME:
179             Node = (KSP_NODE*)Property;
180 
181             /* check for invalid node id */
182             if (Node->NodeId >= Topology->TopologyNodesCount)
183             {
184                 /* invalid node id */
185                 Irp->IoStatus.Information = 0;
186                 Status = STATUS_INVALID_PARAMETER;
187                 break;
188             }
189 
190             /* check if there is a name supplied */
191             if (!IsEqualGUIDAligned(&Topology->TopologyNodesNames[Node->NodeId], &GUID_NULL))
192             {
193                 /* node name has been supplied */
194                 Guid = (LPGUID)&Topology->TopologyNodesNames[Node->NodeId];
195             }
196             else
197             {
198                 /* fallback to topology node type */
199                 Guid = (LPGUID)&Topology->TopologyNodes[Node->NodeId];
200             }
201 
202             /* read topology node name */
203             Status = KspReadMediaCategory(Guid, &KeyInfo);
204             if (!NT_SUCCESS(Status))
205             {
206                 Irp->IoStatus.Information = 0;
207                 break;
208             }
209 
210             /* store result size */
211             Irp->IoStatus.Information = KeyInfo->DataLength + sizeof(WCHAR);
212 
213             /* check for buffer overflow */
214             if (KeyInfo->DataLength + sizeof(WCHAR) > IoStack->Parameters.DeviceIoControl.OutputBufferLength)
215             {
216                 /* buffer too small */
217                 Status = STATUS_BUFFER_OVERFLOW;
218                 FreeItem(KeyInfo);
219                 break;
220             }
221 
222             /* copy result buffer */
223             RtlMoveMemory(Irp->AssociatedIrp.SystemBuffer, &KeyInfo->Data, KeyInfo->DataLength);
224 
225             /* zero terminate it */
226             ((LPWSTR)Irp->AssociatedIrp.SystemBuffer)[KeyInfo->DataLength / sizeof(WCHAR)] = L'\0';
227 
228             /* free key info */
229             FreeItem(KeyInfo);
230 
231             break;
232         default:
233              Irp->IoStatus.Information = 0;
234            Status = STATUS_NOT_FOUND;
235     }
236 
237     Irp->IoStatus.Status = Status;
238     return Status;
239 }
240 
241