- Store KSPROPERTY_SET in Irp when using KsPropertyHandler
[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
10 #include "priv.h"
11
12
13 NTSTATUS
14 NTAPI
15 KspCreateObjectType(
16 IN HANDLE ParentHandle,
17 IN LPWSTR ObjectType,
18 PVOID CreateParameters,
19 UINT CreateParametersSize,
20 IN ACCESS_MASK DesiredAccess,
21 OUT PHANDLE NodeHandle)
22 {
23 NTSTATUS Status;
24 IO_STATUS_BLOCK IoStatusBlock;
25 OBJECT_ATTRIBUTES ObjectAttributes;
26 UNICODE_STRING Name;
27
28 /* calculate request length */
29 Name.Length = 0;
30 Name.MaximumLength = wcslen(ObjectType) * sizeof(WCHAR) + CreateParametersSize + 2 * sizeof(WCHAR);
31 Name.MaximumLength += sizeof(WCHAR);
32 /* acquire request buffer */
33 Name.Buffer = ExAllocatePool(NonPagedPool, Name.MaximumLength);
34 /* check for success */
35 if (!Name.Buffer)
36 {
37 /* insufficient resources */
38 return STATUS_INSUFFICIENT_RESOURCES;
39 }
40
41 /* build a request which looks like \{ObjectClass}\CreateParameters
42 * For pins the parent is the reference string used in registration
43 * For clocks it is full path for pin\{ClockGuid}\ClockCreateParams
44 */
45 RtlAppendUnicodeToString(&Name, L"\\");
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 ExFreePool(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 UNICODE_STRING LocalMachine = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\MediaCategories\\");
151 UNICODE_STRING Name = RTL_CONSTANT_STRING(L"Name");
152 UNICODE_STRING GuidString;
153 UNICODE_STRING KeyName;
154 OBJECT_ATTRIBUTES ObjectAttributes;
155 KSMULTIPLE_ITEM * Item;
156 KSP_NODE * Node;
157 PIO_STACK_LOCATION IoStack;
158 ULONG Size;
159 NTSTATUS Status;
160 HANDLE hKey;
161 PKEY_VALUE_PARTIAL_INFORMATION KeyInfo;
162
163 DPRINT("KsTopologyPropertyHandler Irp %p Property %p Data %p Topology %p\n", Irp, Property, Data, Topology);
164
165 if (Property->Flags != KSPROPERTY_TYPE_GET)
166 {
167 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
168 Irp->IoStatus.Information = 0;
169 return STATUS_NOT_IMPLEMENTED;
170 }
171
172 IoStack = IoGetCurrentIrpStackLocation(Irp);
173
174 switch(Property->Id)
175 {
176 case KSPROPERTY_TOPOLOGY_CATEGORIES:
177 Size = sizeof(KSMULTIPLE_ITEM) + Topology->CategoriesCount * sizeof(GUID);
178 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < Size)
179 {
180 Irp->IoStatus.Information = Size;
181 Status = STATUS_MORE_ENTRIES;
182 break;
183 }
184
185 Item = (KSMULTIPLE_ITEM*)Irp->UserBuffer;
186 Item->Size = Size;
187 Item->Count = Topology->CategoriesCount;
188
189 if (Topology->CategoriesCount)
190 {
191 RtlMoveMemory((PVOID)(Item + 1), (PVOID)Topology->Categories, Topology->CategoriesCount * sizeof(GUID));
192 }
193 Irp->IoStatus.Information = Size;
194 Status = STATUS_SUCCESS;
195 break;
196
197 case KSPROPERTY_TOPOLOGY_NODES:
198 Size = sizeof(KSMULTIPLE_ITEM) + Topology->TopologyNodesCount * sizeof(GUID);
199 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < Size)
200 {
201 Irp->IoStatus.Information = Size;
202 Status = STATUS_MORE_ENTRIES;
203 break;
204 }
205
206 Item = (KSMULTIPLE_ITEM*)Irp->UserBuffer;
207 Item->Size = Size;
208 Item->Count = Topology->TopologyNodesCount;
209
210 RtlMoveMemory((PVOID)(Item + 1), (PVOID)Topology->TopologyNodes, Topology->TopologyNodesCount * sizeof(GUID));
211 if (Topology->TopologyNodesCount)
212 {
213 RtlMoveMemory((PVOID)(Item + 1), (PVOID)Topology->TopologyNodes, Topology->TopologyNodesCount * sizeof(GUID));
214 }
215 Irp->IoStatus.Information = Size;
216 Status = STATUS_SUCCESS;
217 break;
218
219 case KSPROPERTY_TOPOLOGY_CONNECTIONS:
220 Size = sizeof(KSMULTIPLE_ITEM) + Topology->TopologyConnectionsCount * sizeof(KSTOPOLOGY_CONNECTION);
221 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < Size)
222 {
223 Irp->IoStatus.Information = Size;
224 Status = STATUS_MORE_ENTRIES;
225 break;
226 }
227
228 Item = (KSMULTIPLE_ITEM*)Irp->UserBuffer;
229 Item->Size = Size;
230 Item->Count = Topology->TopologyConnectionsCount;
231
232 if (Topology->TopologyConnections)
233 {
234 RtlMoveMemory((PVOID)(Item + 1), (PVOID)Topology->TopologyConnections, Topology->TopologyConnectionsCount * sizeof(KSTOPOLOGY_CONNECTION));
235 }
236
237 Irp->IoStatus.Information = Size;
238 Status = STATUS_SUCCESS;
239 break;
240
241 case KSPROPERTY_TOPOLOGY_NAME:
242 Node = (KSP_NODE*)Property;
243
244 if (Node->NodeId >= Topology->TopologyNodesCount)
245 {
246 Irp->IoStatus.Information = 0;
247 Status = STATUS_INVALID_PARAMETER;
248 break;
249 }
250
251 Status = RtlStringFromGUID(&Topology->TopologyNodesNames[Node->NodeId], &GuidString);
252 if (!NT_SUCCESS(Status))
253 {
254 Irp->IoStatus.Information = 0;
255 break;
256 }
257
258 KeyName.Length = 0;
259 KeyName.MaximumLength = LocalMachine.Length + GuidString.Length + sizeof(WCHAR);
260 KeyName.Buffer = ExAllocatePool(PagedPool, KeyName.MaximumLength);
261 if (!KeyName.Buffer)
262 {
263 Irp->IoStatus.Information = 0;
264 Status = STATUS_INSUFFICIENT_RESOURCES;
265 break;
266 }
267
268 RtlAppendUnicodeStringToString(&KeyName, &LocalMachine);
269 RtlAppendUnicodeStringToString(&KeyName, &GuidString);
270
271
272 InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE, NULL, NULL);
273 Status = ZwOpenKey(&hKey, GENERIC_READ, &ObjectAttributes);
274
275 if (!NT_SUCCESS(Status))
276 {
277 DPRINT1("ZwOpenKey() failed with status 0x%08lx\n", Status);
278 ExFreePool(KeyName.Buffer);
279 Irp->IoStatus.Information = 0;
280 break;
281 }
282 ExFreePool(KeyName.Buffer);
283 Status = ZwQueryValueKey(hKey, &Name, KeyValuePartialInformation, NULL, 0, &Size);
284 if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_TOO_SMALL)
285 {
286 ZwClose(hKey);
287 Irp->IoStatus.Information = 0;
288 break;
289 }
290
291 KeyInfo = (PKEY_VALUE_PARTIAL_INFORMATION) ExAllocatePool(NonPagedPool, Size);
292 if (!KeyInfo)
293 {
294 Status = STATUS_NO_MEMORY;
295 break;
296 }
297
298 Status = ZwQueryValueKey(hKey, &Name, KeyValuePartialInformation, (PVOID)KeyInfo, Size, &Size);
299 if (!NT_SUCCESS(Status))
300 {
301 ExFreePool(KeyInfo);
302 ZwClose(hKey);
303 Irp->IoStatus.Information = 0;
304 break;
305 }
306
307 ZwClose(hKey);
308 if (KeyInfo->DataLength + sizeof(WCHAR) > IoStack->Parameters.DeviceIoControl.OutputBufferLength)
309 {
310 Irp->IoStatus.Information = KeyInfo->DataLength + sizeof(WCHAR);
311 Status = STATUS_BUFFER_TOO_SMALL;
312 ExFreePool(KeyInfo);
313 break;
314 }
315
316 RtlMoveMemory(Irp->UserBuffer, &KeyInfo->Data, KeyInfo->DataLength);
317 ((LPWSTR)Irp->UserBuffer)[KeyInfo->DataLength / sizeof(WCHAR)] = L'\0';
318 Irp->IoStatus.Information = KeyInfo->DataLength + sizeof(WCHAR);
319 ExFreePool(KeyInfo);
320 break;
321 default:
322 Irp->IoStatus.Information = 0;
323 Status = STATUS_NOT_IMPLEMENTED;
324 }
325
326
327 return Status;
328 }
329
330 NTSTATUS
331 NTAPI
332 KspTopologyPropertyHandler(
333 IN PIRP Irp,
334 IN PKSIDENTIFIER Request,
335 IN OUT PVOID Data)
336 {
337
338 return STATUS_NOT_IMPLEMENTED;
339 }