Synchronize with trunk's revision r57629.
[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 + 1 * 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, ObjectType);
46 RtlAppendUnicodeToString(&Name, L"\\");
47 /* append create parameters */
48 RtlMoveMemory(Name.Buffer + (Name.Length / sizeof(WCHAR)), CreateParameters, CreateParametersSize);
49 Name.Length += CreateParametersSize;
50 Name.Buffer[Name.Length / 2] = L'\0';
51
52 InitializeObjectAttributes(&ObjectAttributes, &Name, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE | OBJ_OPENIF, ParentHandle, NULL);
53 /* create the instance */
54 Status = IoCreateFile(NodeHandle,
55 DesiredAccess,
56 &ObjectAttributes,
57 &IoStatusBlock,
58 NULL,
59 0,
60 0,
61 FILE_OPEN,
62 0,
63 NULL,
64 0,
65 CreateFileTypeNone,
66 NULL,
67 IO_NO_PARAMETER_CHECKING | IO_FORCE_ACCESS_CHECK);
68
69 /* free request buffer */
70 FreeItem(Name.Buffer);
71 return Status;
72 }
73
74
75 /*
76 @implemented
77 */
78 KSDDKAPI NTSTATUS NTAPI
79 KsCreateTopologyNode(
80 IN HANDLE ParentHandle,
81 IN PKSNODE_CREATE NodeCreate,
82 IN ACCESS_MASK DesiredAccess,
83 OUT PHANDLE NodeHandle)
84 {
85 return KspCreateObjectType(ParentHandle,
86 KSSTRING_TopologyNode,
87 (PVOID)NodeCreate,
88 sizeof(KSNODE_CREATE),
89 DesiredAccess,
90 NodeHandle);
91 }
92
93 /*
94 @implemented
95 */
96 KSDDKAPI
97 NTSTATUS
98 NTAPI
99 KsValidateTopologyNodeCreateRequest(
100 IN PIRP Irp,
101 IN PKSTOPOLOGY Topology,
102 OUT PKSNODE_CREATE* OutNodeCreate)
103 {
104 PKSNODE_CREATE NodeCreate;
105 ULONG Size;
106 NTSTATUS Status;
107
108 /* did the caller miss the topology */
109 if (!Topology)
110 return STATUS_INVALID_PARAMETER;
111
112 /* set create param size */
113 Size = sizeof(KSNODE_CREATE);
114
115 /* fetch create parameters */
116 Status = KspCopyCreateRequest(Irp,
117 KSSTRING_TopologyNode,
118 &Size,
119 (PVOID*)&NodeCreate);
120
121 if (!NT_SUCCESS(Status))
122 return Status;
123
124 if (NodeCreate->CreateFlags != 0 || (NodeCreate->Node >= Topology->TopologyNodesCount && NodeCreate->Node != MAXULONG))
125 {
126 /* invalid node create */
127 FreeItem(NodeCreate);
128 return STATUS_UNSUCCESSFUL;
129 }
130
131 /* store result */
132 *OutNodeCreate = NodeCreate;
133
134 return Status;
135 }
136
137 /*
138 @implemented
139 */
140 KSDDKAPI
141 NTSTATUS
142 NTAPI
143 KsTopologyPropertyHandler(
144 IN PIRP Irp,
145 IN PKSPROPERTY Property,
146 IN OUT PVOID Data,
147 IN const KSTOPOLOGY* Topology)
148 {
149 KSP_NODE * Node;
150 PIO_STACK_LOCATION IoStack;
151 NTSTATUS Status;
152 PKEY_VALUE_PARTIAL_INFORMATION KeyInfo;
153 LPGUID Guid;
154
155 IoStack = IoGetCurrentIrpStackLocation(Irp);
156
157 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);
158
159 if (Property->Flags != KSPROPERTY_TYPE_GET)
160 {
161 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
162 Irp->IoStatus.Information = 0;
163 return STATUS_NOT_IMPLEMENTED;
164 }
165
166 switch(Property->Id)
167 {
168 case KSPROPERTY_TOPOLOGY_CATEGORIES:
169 return KsHandleSizedListQuery(Irp, Topology->CategoriesCount, sizeof(GUID), Topology->Categories);
170
171 case KSPROPERTY_TOPOLOGY_NODES:
172 return KsHandleSizedListQuery(Irp, Topology->TopologyNodesCount, sizeof(GUID), Topology->TopologyNodes);
173
174 case KSPROPERTY_TOPOLOGY_CONNECTIONS:
175 return KsHandleSizedListQuery(Irp, Topology->TopologyConnectionsCount, sizeof(KSTOPOLOGY_CONNECTION), Topology->TopologyConnections);
176
177 case KSPROPERTY_TOPOLOGY_NAME:
178 Node = (KSP_NODE*)Property;
179
180 /* check for invalid node id */
181 if (Node->NodeId >= Topology->TopologyNodesCount)
182 {
183 /* invalid node id */
184 Irp->IoStatus.Information = 0;
185 Status = STATUS_INVALID_PARAMETER;
186 break;
187 }
188
189 /* check if there is a name supplied */
190 if (!IsEqualGUIDAligned(&Topology->TopologyNodesNames[Node->NodeId], &GUID_NULL))
191 {
192 /* node name has been supplied */
193 Guid = (LPGUID)&Topology->TopologyNodesNames[Node->NodeId];
194 }
195 else
196 {
197 /* fallback to topology node type */
198 Guid = (LPGUID)&Topology->TopologyNodes[Node->NodeId];
199 }
200
201 /* read topology node name */
202 Status = KspReadMediaCategory(Guid, &KeyInfo);
203 if (!NT_SUCCESS(Status))
204 {
205 Irp->IoStatus.Information = 0;
206 break;
207 }
208
209 /* store result size */
210 Irp->IoStatus.Information = KeyInfo->DataLength + sizeof(WCHAR);
211
212 /* check for buffer overflow */
213 if (KeyInfo->DataLength + sizeof(WCHAR) > IoStack->Parameters.DeviceIoControl.OutputBufferLength)
214 {
215 /* buffer too small */
216 Status = STATUS_BUFFER_OVERFLOW;
217 FreeItem(KeyInfo);
218 break;
219 }
220
221 /* copy result buffer */
222 RtlMoveMemory(Irp->UserBuffer, &KeyInfo->Data, KeyInfo->DataLength);
223
224 /* zero terminate it */
225 ((LPWSTR)Irp->UserBuffer)[KeyInfo->DataLength / sizeof(WCHAR)] = L'\0';
226
227 /* free key info */
228 FreeItem(KeyInfo);
229
230 break;
231 default:
232 Irp->IoStatus.Information = 0;
233 Status = STATUS_NOT_FOUND;
234 }
235
236
237 return Status;
238 }
239