- Fix a bug which was responsible for most audio-related crashes
[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 UNICODE_STRING Name;
21
22 Name.Length = Name.MaximumLength = (wcslen(ObjectType) + 1) * sizeof(WCHAR) + CreateParametersSize;
23 Name.MaximumLength += sizeof(WCHAR);
24 Name.Buffer = ExAllocatePool(NonPagedPool, Name.MaximumLength);
25
26 if (!Name.Buffer)
27 {
28 return STATUS_INSUFFICIENT_RESOURCES;
29 }
30
31 wcscpy(Name.Buffer, ObjectType);
32 Name.Buffer[wcslen(ObjectType)] = '\\';
33
34 RtlMoveMemory(Name.Buffer + wcslen(ObjectType) +1, CreateParameters, CreateParametersSize);
35
36 Name.Buffer[Name.Length / 2] = L'\0';
37 InitializeObjectAttributes(&ObjectAttributes, &Name, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE | OBJ_OPENIF, ParentHandle, NULL);
38
39
40 Status = IoCreateFile(NodeHandle,
41 DesiredAccess,
42 &ObjectAttributes,
43 &IoStatusBlock,
44 NULL,
45 0,
46 0,
47 FILE_OPEN,
48 FILE_SYNCHRONOUS_IO_NONALERT,
49 NULL,
50 0,
51 CreateFileTypeNone,
52 NULL,
53 IO_NO_PARAMETER_CHECKING | IO_FORCE_ACCESS_CHECK);
54
55 ExFreePool(Name.Buffer);
56 return Status;
57 }
58
59
60 /*
61 @implemented
62 */
63 KSDDKAPI NTSTATUS NTAPI
64 KsCreateTopologyNode(
65 IN HANDLE ParentHandle,
66 IN PKSNODE_CREATE NodeCreate,
67 IN ACCESS_MASK DesiredAccess,
68 OUT PHANDLE NodeHandle)
69 {
70 return KspCreateObjectType(ParentHandle,
71 L"{0621061A-EE75-11D0-B915-00A0C9223196}",
72 (PVOID)NodeCreate,
73 sizeof(KSNODE_CREATE),
74 DesiredAccess,
75 NodeHandle);
76 }
77
78 /*
79 @unimplemented
80 */
81 KSDDKAPI NTSTATUS NTAPI
82 KsValidateTopologyNodeCreateRequest(
83 IN PIRP Irp,
84 IN PKSTOPOLOGY Topology,
85 OUT PKSNODE_CREATE* NodeCreate)
86 {
87 UNIMPLEMENTED;
88 return STATUS_UNSUCCESSFUL;
89 }
90
91 /*
92 @implemented
93 */
94 KSDDKAPI
95 NTSTATUS
96 NTAPI
97 KsTopologyPropertyHandler(
98 IN PIRP Irp,
99 IN PKSPROPERTY Property,
100 IN OUT PVOID Data,
101 IN const KSTOPOLOGY* Topology)
102 {
103 UNICODE_STRING LocalMachine = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\MediaCategories\\");
104 UNICODE_STRING Name = RTL_CONSTANT_STRING(L"Name");
105 UNICODE_STRING GuidString;
106 UNICODE_STRING KeyName;
107 OBJECT_ATTRIBUTES ObjectAttributes;
108 KSMULTIPLE_ITEM * Item;
109 KSP_NODE * Node;
110 PIO_STACK_LOCATION IoStack;
111 ULONG Size;
112 NTSTATUS Status;
113 HANDLE hKey;
114 PKEY_VALUE_PARTIAL_INFORMATION KeyInfo;
115
116 if (Property->Flags != KSPROPERTY_TYPE_GET)
117 {
118 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
119 Irp->IoStatus.Information = 0;
120 return STATUS_NOT_IMPLEMENTED;
121 }
122
123 IoStack = IoGetCurrentIrpStackLocation(Irp);
124
125 switch(Property->Id)
126 {
127 case KSPROPERTY_TOPOLOGY_CATEGORIES:
128 Size = sizeof(KSMULTIPLE_ITEM) + Topology->CategoriesCount * sizeof(GUID);
129 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < Size)
130 {
131 Irp->IoStatus.Information = Size;
132 Status = STATUS_BUFFER_TOO_SMALL;
133 break;
134 }
135
136 Item = (KSMULTIPLE_ITEM*)Irp->UserBuffer;
137 Item->Size = Size;
138 Item->Count = Topology->CategoriesCount;
139
140 RtlMoveMemory((PVOID)(Item + 1), (PVOID)Topology->Categories, Topology->CategoriesCount * sizeof(GUID));
141 Irp->IoStatus.Information = Size;
142 Status = STATUS_SUCCESS;
143 break;
144
145 case KSPROPERTY_TOPOLOGY_NODES:
146 Size = sizeof(KSMULTIPLE_ITEM) + Topology->TopologyNodesCount * sizeof(GUID);
147 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < Size)
148 {
149 Irp->IoStatus.Information = Size;
150 Status = STATUS_BUFFER_TOO_SMALL;
151 break;
152 }
153
154 Item = (KSMULTIPLE_ITEM*)Irp->UserBuffer;
155 Item->Size = Size;
156 Item->Count = Topology->TopologyNodesCount;
157
158 RtlMoveMemory((PVOID)(Item + 1), (PVOID)Topology->TopologyNodes, Topology->TopologyNodesCount * sizeof(GUID));
159 Irp->IoStatus.Information = Size;
160 Status = STATUS_SUCCESS;
161 break;
162
163 case KSPROPERTY_TOPOLOGY_CONNECTIONS:
164 Size = sizeof(KSMULTIPLE_ITEM) + Topology->TopologyConnectionsCount * sizeof(KSTOPOLOGY_CONNECTION);
165 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < Size)
166 {
167 Irp->IoStatus.Information = Size;
168 Status = STATUS_BUFFER_TOO_SMALL;
169 break;
170 }
171
172 Item = (KSMULTIPLE_ITEM*)Irp->UserBuffer;
173 Item->Size = Size;
174 Item->Count = Topology->TopologyConnectionsCount;
175
176 RtlMoveMemory((PVOID)(Item + 1), (PVOID)Topology->TopologyConnections, Topology->TopologyConnectionsCount * sizeof(KSTOPOLOGY_CONNECTION));
177 Irp->IoStatus.Information = Size;
178 Status = STATUS_SUCCESS;
179 break;
180
181 case KSPROPERTY_TOPOLOGY_NAME:
182 Node = (KSP_NODE*)Property;
183
184 Status = RtlStringFromGUID(&Topology->TopologyNodesNames[Node->NodeId], &GuidString);
185 if (!NT_SUCCESS(Status))
186 {
187 Irp->IoStatus.Information = 0;
188 break;
189 }
190
191 KeyName.Length = 0;
192 KeyName.MaximumLength = LocalMachine.Length + GuidString.Length + sizeof(WCHAR);
193 KeyName.Buffer = ExAllocatePool(PagedPool, KeyName.MaximumLength);
194 if (!KeyName.Buffer)
195 {
196 Irp->IoStatus.Information = 0;
197 break;
198 }
199
200 RtlAppendUnicodeStringToString(&KeyName, &LocalMachine);
201 RtlAppendUnicodeStringToString(&KeyName, &GuidString);
202
203
204 InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE, NULL, NULL);
205 Status = ZwOpenKey(&hKey, GENERIC_READ, &ObjectAttributes);
206
207 if (!NT_SUCCESS(Status))
208 {
209 DPRINT1("ZwOpenKey() failed with status 0x%08lx\n", Status);
210 ExFreePool(KeyName.Buffer);
211 Irp->IoStatus.Information = 0;
212 break;
213 }
214 ExFreePool(KeyName.Buffer);
215 Status = ZwQueryValueKey(hKey, &Name, KeyValuePartialInformation, NULL, 0, &Size);
216 if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_TOO_SMALL)
217 {
218 ZwClose(hKey);
219 Irp->IoStatus.Information = 0;
220 break;
221 }
222
223 KeyInfo = (PKEY_VALUE_PARTIAL_INFORMATION) ExAllocatePool(NonPagedPool, Size);
224 if (!KeyInfo)
225 {
226 Status = STATUS_NO_MEMORY;
227 break;
228 }
229
230 Status = ZwQueryValueKey(hKey, &Name, KeyValuePartialInformation, (PVOID)KeyInfo, Size, &Size);
231 if (!NT_SUCCESS(Status))
232 {
233 ExFreePool(KeyInfo);
234 ZwClose(hKey);
235 Irp->IoStatus.Information = 0;
236 break;
237 }
238
239 ZwClose(hKey);
240 if (KeyInfo->DataLength + sizeof(WCHAR) > IoStack->Parameters.DeviceIoControl.OutputBufferLength)
241 {
242 Irp->IoStatus.Information = KeyInfo->DataLength + sizeof(WCHAR);
243 Status = STATUS_BUFFER_TOO_SMALL;
244 ExFreePool(KeyInfo);
245 break;
246 }
247
248 RtlMoveMemory(Irp->UserBuffer, &KeyInfo->Data, KeyInfo->DataLength);
249 ((LPWSTR)Irp->UserBuffer)[KeyInfo->DataLength / sizeof(WCHAR)] = L'\0';
250 Irp->IoStatus.Information = KeyInfo->DataLength + sizeof(WCHAR);
251 ExFreePool(KeyInfo);
252 break;
253 default:
254 Irp->IoStatus.Information = 0;
255 Status = STATUS_NOT_IMPLEMENTED;
256 }
257
258
259 return Status;
260 }