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