allocators.c
[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 PFILE_OBJECT FileObject;
27 UNICODE_STRING Name;
28 PKSIOBJECT_HEADER ObjectHeader;
29
30 /* acquire parent file object */
31 Status = ObReferenceObjectByHandle(ParentHandle,
32 GENERIC_READ | GENERIC_WRITE,
33 IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
34
35 if (!NT_SUCCESS(Status))
36 {
37 DPRINT("Failed to reference parent %x\n", Status);
38 return Status;
39 }
40
41 /* get parent object header */
42 ObjectHeader = (PKSIOBJECT_HEADER)FileObject->FsContext;
43 /* sanity check */
44 ASSERT(ObjectHeader);
45
46 /* calculate request length */
47 Name.Length = 0;
48 Name.MaximumLength = wcslen(ObjectType) * sizeof(WCHAR) + CreateParametersSize + ObjectHeader->ObjectClass.MaximumLength + 2 * sizeof(WCHAR);
49 Name.MaximumLength += sizeof(WCHAR);
50 /* acquire request buffer */
51 Name.Buffer = ExAllocatePool(NonPagedPool, Name.MaximumLength);
52 /* check for success */
53 if (!Name.Buffer)
54 {
55 /* insufficient resources */
56 ObDereferenceObject(FileObject);
57 return STATUS_INSUFFICIENT_RESOURCES;
58 }
59
60 /* build a request which looks like \Parent\{ObjectGuid}\CreateParameters
61 * For pins the parent is the reference string used in registration
62 * For clocks it is full path for pin\{ClockGuid}\ClockCreateParams
63 */
64
65 RtlAppendUnicodeStringToString(&Name, &ObjectHeader->ObjectClass);
66 RtlAppendUnicodeToString(&Name, L"\\");
67 RtlAppendUnicodeToString(&Name, ObjectType);
68 RtlAppendUnicodeToString(&Name, L"\\");
69 /* append create parameters */
70 RtlMoveMemory(Name.Buffer + (Name.Length / sizeof(WCHAR)), CreateParameters, CreateParametersSize);
71 Name.Length += CreateParametersSize;
72 Name.Buffer[Name.Length / 2] = L'\0';
73
74 InitializeObjectAttributes(&ObjectAttributes, &Name, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE | OBJ_OPENIF, ParentHandle, NULL);
75 /* create the instance */
76 Status = IoCreateFile(NodeHandle,
77 DesiredAccess,
78 &ObjectAttributes,
79 &IoStatusBlock,
80 NULL,
81 0,
82 0,
83 FILE_OPEN,
84 FILE_SYNCHRONOUS_IO_NONALERT,
85 NULL,
86 0,
87 CreateFileTypeNone,
88 NULL,
89 IO_NO_PARAMETER_CHECKING | IO_FORCE_ACCESS_CHECK);
90
91 /* free request buffer */
92 ExFreePool(Name.Buffer);
93 /* release parent handle */
94 ObDereferenceObject(FileObject);
95 return Status;
96 }
97
98
99 /*
100 @implemented
101 */
102 KSDDKAPI NTSTATUS NTAPI
103 KsCreateTopologyNode(
104 IN HANDLE ParentHandle,
105 IN PKSNODE_CREATE NodeCreate,
106 IN ACCESS_MASK DesiredAccess,
107 OUT PHANDLE NodeHandle)
108 {
109 return KspCreateObjectType(ParentHandle,
110 L"{0621061A-EE75-11D0-B915-00A0C9223196}",
111 (PVOID)NodeCreate,
112 sizeof(KSNODE_CREATE),
113 DesiredAccess,
114 NodeHandle);
115 }
116
117 /*
118 @unimplemented
119 */
120 KSDDKAPI NTSTATUS NTAPI
121 KsValidateTopologyNodeCreateRequest(
122 IN PIRP Irp,
123 IN PKSTOPOLOGY Topology,
124 OUT PKSNODE_CREATE* NodeCreate)
125 {
126 UNIMPLEMENTED;
127 return STATUS_UNSUCCESSFUL;
128 }
129
130 /*
131 @implemented
132 */
133 KSDDKAPI
134 NTSTATUS
135 NTAPI
136 KsTopologyPropertyHandler(
137 IN PIRP Irp,
138 IN PKSPROPERTY Property,
139 IN OUT PVOID Data,
140 IN const KSTOPOLOGY* Topology)
141 {
142 UNICODE_STRING LocalMachine = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\MediaCategories\\");
143 UNICODE_STRING Name = RTL_CONSTANT_STRING(L"Name");
144 UNICODE_STRING GuidString;
145 UNICODE_STRING KeyName;
146 OBJECT_ATTRIBUTES ObjectAttributes;
147 KSMULTIPLE_ITEM * Item;
148 KSP_NODE * Node;
149 PIO_STACK_LOCATION IoStack;
150 ULONG Size;
151 NTSTATUS Status;
152 HANDLE hKey;
153 PKEY_VALUE_PARTIAL_INFORMATION KeyInfo;
154
155 if (Property->Flags != KSPROPERTY_TYPE_GET)
156 {
157 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
158 Irp->IoStatus.Information = 0;
159 return STATUS_NOT_IMPLEMENTED;
160 }
161
162 IoStack = IoGetCurrentIrpStackLocation(Irp);
163
164 switch(Property->Id)
165 {
166 case KSPROPERTY_TOPOLOGY_CATEGORIES:
167 Size = sizeof(KSMULTIPLE_ITEM) + Topology->CategoriesCount * sizeof(GUID);
168 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < Size)
169 {
170 Irp->IoStatus.Information = Size;
171 Status = STATUS_BUFFER_TOO_SMALL;
172 break;
173 }
174
175 Item = (KSMULTIPLE_ITEM*)Irp->UserBuffer;
176 Item->Size = Size;
177 Item->Count = Topology->CategoriesCount;
178
179 RtlMoveMemory((PVOID)(Item + 1), (PVOID)Topology->Categories, Topology->CategoriesCount * sizeof(GUID));
180 Irp->IoStatus.Information = Size;
181 Status = STATUS_SUCCESS;
182 break;
183
184 case KSPROPERTY_TOPOLOGY_NODES:
185 Size = sizeof(KSMULTIPLE_ITEM) + Topology->TopologyNodesCount * sizeof(GUID);
186 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < Size)
187 {
188 Irp->IoStatus.Information = Size;
189 Status = STATUS_BUFFER_TOO_SMALL;
190 break;
191 }
192
193 Item = (KSMULTIPLE_ITEM*)Irp->UserBuffer;
194 Item->Size = Size;
195 Item->Count = Topology->TopologyNodesCount;
196
197 RtlMoveMemory((PVOID)(Item + 1), (PVOID)Topology->TopologyNodes, Topology->TopologyNodesCount * sizeof(GUID));
198 Irp->IoStatus.Information = Size;
199 Status = STATUS_SUCCESS;
200 break;
201
202 case KSPROPERTY_TOPOLOGY_CONNECTIONS:
203 Size = sizeof(KSMULTIPLE_ITEM) + Topology->TopologyConnectionsCount * sizeof(KSTOPOLOGY_CONNECTION);
204 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < Size)
205 {
206 Irp->IoStatus.Information = Size;
207 Status = STATUS_BUFFER_TOO_SMALL;
208 break;
209 }
210
211 Item = (KSMULTIPLE_ITEM*)Irp->UserBuffer;
212 Item->Size = Size;
213 Item->Count = Topology->TopologyConnectionsCount;
214
215 RtlMoveMemory((PVOID)(Item + 1), (PVOID)Topology->TopologyConnections, Topology->TopologyConnectionsCount * sizeof(KSTOPOLOGY_CONNECTION));
216 Irp->IoStatus.Information = Size;
217 Status = STATUS_SUCCESS;
218 break;
219
220 case KSPROPERTY_TOPOLOGY_NAME:
221 Node = (KSP_NODE*)Property;
222
223 Status = RtlStringFromGUID(&Topology->TopologyNodesNames[Node->NodeId], &GuidString);
224 if (!NT_SUCCESS(Status))
225 {
226 Irp->IoStatus.Information = 0;
227 break;
228 }
229
230 KeyName.Length = 0;
231 KeyName.MaximumLength = LocalMachine.Length + GuidString.Length + sizeof(WCHAR);
232 KeyName.Buffer = ExAllocatePool(PagedPool, KeyName.MaximumLength);
233 if (!KeyName.Buffer)
234 {
235 Irp->IoStatus.Information = 0;
236 break;
237 }
238
239 RtlAppendUnicodeStringToString(&KeyName, &LocalMachine);
240 RtlAppendUnicodeStringToString(&KeyName, &GuidString);
241
242
243 InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE, NULL, NULL);
244 Status = ZwOpenKey(&hKey, GENERIC_READ, &ObjectAttributes);
245
246 if (!NT_SUCCESS(Status))
247 {
248 DPRINT1("ZwOpenKey() failed with status 0x%08lx\n", Status);
249 ExFreePool(KeyName.Buffer);
250 Irp->IoStatus.Information = 0;
251 break;
252 }
253 ExFreePool(KeyName.Buffer);
254 Status = ZwQueryValueKey(hKey, &Name, KeyValuePartialInformation, NULL, 0, &Size);
255 if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_TOO_SMALL)
256 {
257 ZwClose(hKey);
258 Irp->IoStatus.Information = 0;
259 break;
260 }
261
262 KeyInfo = (PKEY_VALUE_PARTIAL_INFORMATION) ExAllocatePool(NonPagedPool, Size);
263 if (!KeyInfo)
264 {
265 Status = STATUS_NO_MEMORY;
266 break;
267 }
268
269 Status = ZwQueryValueKey(hKey, &Name, KeyValuePartialInformation, (PVOID)KeyInfo, Size, &Size);
270 if (!NT_SUCCESS(Status))
271 {
272 ExFreePool(KeyInfo);
273 ZwClose(hKey);
274 Irp->IoStatus.Information = 0;
275 break;
276 }
277
278 ZwClose(hKey);
279 if (KeyInfo->DataLength + sizeof(WCHAR) > IoStack->Parameters.DeviceIoControl.OutputBufferLength)
280 {
281 Irp->IoStatus.Information = KeyInfo->DataLength + sizeof(WCHAR);
282 Status = STATUS_BUFFER_TOO_SMALL;
283 ExFreePool(KeyInfo);
284 break;
285 }
286
287 RtlMoveMemory(Irp->UserBuffer, &KeyInfo->Data, KeyInfo->DataLength);
288 ((LPWSTR)Irp->UserBuffer)[KeyInfo->DataLength / sizeof(WCHAR)] = L'\0';
289 Irp->IoStatus.Information = KeyInfo->DataLength + sizeof(WCHAR);
290 ExFreePool(KeyInfo);
291 break;
292 default:
293 Irp->IoStatus.Information = 0;
294 Status = STATUS_NOT_IMPLEMENTED;
295 }
296
297
298 return Status;
299 }
300
301 NTSTATUS
302 NTAPI
303 KspTopologyPropertyHandler(
304 IN PIRP Irp,
305 IN PKSIDENTIFIER Request,
306 IN OUT PVOID Data)
307 {
308
309 return STATUS_NOT_IMPLEMENTED;
310 }