Create a branch for cmake bringup.
[reactos.git] / 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 = AllocateItem(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 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 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 KSP_NODE * Node;
156 PIO_STACK_LOCATION IoStack;
157 ULONG Size;
158 NTSTATUS Status;
159 HANDLE hKey;
160 PKEY_VALUE_PARTIAL_INFORMATION KeyInfo;
161
162 IoStack = IoGetCurrentIrpStackLocation(Irp);
163
164 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);
165
166 if (Property->Flags != KSPROPERTY_TYPE_GET)
167 {
168 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
169 Irp->IoStatus.Information = 0;
170 return STATUS_NOT_IMPLEMENTED;
171 }
172
173 switch(Property->Id)
174 {
175 case KSPROPERTY_TOPOLOGY_CATEGORIES:
176 return KsHandleSizedListQuery(Irp, Topology->CategoriesCount, sizeof(GUID), Topology->Categories);
177
178 case KSPROPERTY_TOPOLOGY_NODES:
179 return KsHandleSizedListQuery(Irp, Topology->TopologyNodesCount, sizeof(GUID), Topology->TopologyNodes);
180
181 case KSPROPERTY_TOPOLOGY_CONNECTIONS:
182 return KsHandleSizedListQuery(Irp, Topology->TopologyConnectionsCount, sizeof(KSTOPOLOGY_CONNECTION), Topology->TopologyConnections);
183
184 case KSPROPERTY_TOPOLOGY_NAME:
185 Node = (KSP_NODE*)Property;
186
187 if (Node->NodeId >= Topology->TopologyNodesCount)
188 {
189 Irp->IoStatus.Information = 0;
190 Status = STATUS_INVALID_PARAMETER;
191 break;
192 }
193
194 Status = RtlStringFromGUID(&Topology->TopologyNodesNames[Node->NodeId], &GuidString);
195 if (!NT_SUCCESS(Status))
196 {
197 Irp->IoStatus.Information = 0;
198 break;
199 }
200
201 KeyName.Length = 0;
202 KeyName.MaximumLength = LocalMachine.Length + GuidString.Length + sizeof(WCHAR);
203 KeyName.Buffer = AllocateItem(PagedPool, KeyName.MaximumLength);
204 if (!KeyName.Buffer)
205 {
206 Irp->IoStatus.Information = 0;
207 Status = STATUS_INSUFFICIENT_RESOURCES;
208 RtlFreeUnicodeString(&GuidString);
209 break;
210 }
211
212 RtlAppendUnicodeStringToString(&KeyName, &LocalMachine);
213 RtlAppendUnicodeStringToString(&KeyName, &GuidString);
214
215 RtlFreeUnicodeString(&GuidString);
216
217 InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE, NULL, NULL);
218 Status = ZwOpenKey(&hKey, GENERIC_READ, &ObjectAttributes);
219
220 FreeItem(KeyName.Buffer);
221
222 if (!NT_SUCCESS(Status))
223 {
224 DPRINT1("ZwOpenKey() failed with status 0x%08lx\n", Status);
225 Irp->IoStatus.Information = 0;
226 break;
227 }
228
229 Status = ZwQueryValueKey(hKey, &Name, KeyValuePartialInformation, NULL, 0, &Size);
230 if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_TOO_SMALL)
231 {
232 ZwClose(hKey);
233 Irp->IoStatus.Information = 0;
234 break;
235 }
236
237 ASSERT(Size);
238 KeyInfo = (PKEY_VALUE_PARTIAL_INFORMATION) AllocateItem(NonPagedPool, Size);
239 if (!KeyInfo)
240 {
241 Status = STATUS_NO_MEMORY;
242 break;
243 }
244
245 Status = ZwQueryValueKey(hKey, &Name, KeyValuePartialInformation, (PVOID)KeyInfo, Size, &Size);
246 if (!NT_SUCCESS(Status))
247 {
248 FreeItem(KeyInfo);
249 ZwClose(hKey);
250 Irp->IoStatus.Information = 0;
251 break;
252 }
253
254 ZwClose(hKey);
255 if (KeyInfo->DataLength + sizeof(WCHAR) > IoStack->Parameters.DeviceIoControl.OutputBufferLength)
256 {
257 Irp->IoStatus.Information = KeyInfo->DataLength + sizeof(WCHAR);
258 Status = STATUS_MORE_ENTRIES;
259 FreeItem(KeyInfo);
260 break;
261 }
262
263 RtlMoveMemory(Irp->UserBuffer, &KeyInfo->Data, KeyInfo->DataLength);
264 ((LPWSTR)Irp->UserBuffer)[KeyInfo->DataLength / sizeof(WCHAR)] = L'\0';
265 Irp->IoStatus.Information = KeyInfo->DataLength + sizeof(WCHAR);
266 FreeItem(KeyInfo);
267 break;
268 default:
269 Irp->IoStatus.Information = 0;
270 Status = STATUS_NOT_IMPLEMENTED;
271 }
272
273
274 return Status;
275 }
276