Sync up to trunk head.
[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 = 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 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 = ExAllocatePool(PagedPool, KeyName.MaximumLength);
204 if (!KeyName.Buffer)
205 {
206 Irp->IoStatus.Information = 0;
207 Status = STATUS_INSUFFICIENT_RESOURCES;
208 break;
209 }
210
211 RtlAppendUnicodeStringToString(&KeyName, &LocalMachine);
212 RtlAppendUnicodeStringToString(&KeyName, &GuidString);
213
214
215 InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE, NULL, NULL);
216 Status = ZwOpenKey(&hKey, GENERIC_READ, &ObjectAttributes);
217
218 if (!NT_SUCCESS(Status))
219 {
220 DPRINT1("ZwOpenKey() failed with status 0x%08lx\n", Status);
221 ExFreePool(KeyName.Buffer);
222 Irp->IoStatus.Information = 0;
223 break;
224 }
225 ExFreePool(KeyName.Buffer);
226 Status = ZwQueryValueKey(hKey, &Name, KeyValuePartialInformation, NULL, 0, &Size);
227 if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_TOO_SMALL)
228 {
229 ZwClose(hKey);
230 Irp->IoStatus.Information = 0;
231 break;
232 }
233
234 KeyInfo = (PKEY_VALUE_PARTIAL_INFORMATION) ExAllocatePool(NonPagedPool, Size);
235 if (!KeyInfo)
236 {
237 Status = STATUS_NO_MEMORY;
238 break;
239 }
240
241 Status = ZwQueryValueKey(hKey, &Name, KeyValuePartialInformation, (PVOID)KeyInfo, Size, &Size);
242 if (!NT_SUCCESS(Status))
243 {
244 ExFreePool(KeyInfo);
245 ZwClose(hKey);
246 Irp->IoStatus.Information = 0;
247 break;
248 }
249
250 ZwClose(hKey);
251 if (KeyInfo->DataLength + sizeof(WCHAR) > IoStack->Parameters.DeviceIoControl.OutputBufferLength)
252 {
253 Irp->IoStatus.Information = KeyInfo->DataLength + sizeof(WCHAR);
254 Status = STATUS_MORE_ENTRIES;
255 ExFreePool(KeyInfo);
256 break;
257 }
258
259 RtlMoveMemory(Irp->UserBuffer, &KeyInfo->Data, KeyInfo->DataLength);
260 ((LPWSTR)Irp->UserBuffer)[KeyInfo->DataLength / sizeof(WCHAR)] = L'\0';
261 Irp->IoStatus.Information = KeyInfo->DataLength + sizeof(WCHAR);
262 ExFreePool(KeyInfo);
263 break;
264 default:
265 Irp->IoStatus.Information = 0;
266 Status = STATUS_NOT_IMPLEMENTED;
267 }
268
269
270 return Status;
271 }
272