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