[KS]
[reactos.git] / reactos / drivers / ksfilter / ks / topology.c
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
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
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
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
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