1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS
4 * FILE: drivers/wdm/audio/backpln/portcls/resource.cpp
5 * PURPOSE: Port Class driver / ResourceList implementation
6 * PROGRAMMER: Andrew Greenwood
7 * Johannes Anderwald
8 * HISTORY:
9 * 27 Jan 07 Created
10 */
11
12 #include "private.hpp"
13
14 #define NDEBUG
15 #include <debug.h>
16
17 class CResourceList : public CUnknownImpl<IResourceList>
18 {
19 public:
20 STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
21
22 IMP_IResourceList;
23
CResourceList(IUnknown * OuterUnknown)24 CResourceList(IUnknown * OuterUnknown) :
25 m_OuterUnknown(OuterUnknown),
26 m_PoolType(NonPagedPool),
27 m_TranslatedResourceList(0),
28 m_UntranslatedResourceList(0),
29 m_NumberOfEntries(0),
30 m_MaxEntries(0)
31 {
32 }
33 virtual ~CResourceList();
34
35 public:
36 PUNKNOWN m_OuterUnknown;
37 POOL_TYPE m_PoolType;
38 PCM_RESOURCE_LIST m_TranslatedResourceList;
39 PCM_RESOURCE_LIST m_UntranslatedResourceList;
40 ULONG m_NumberOfEntries;
41 ULONG m_MaxEntries;
42 };
43
~CResourceList()44 CResourceList::~CResourceList()
45 {
46 if (m_TranslatedResourceList)
47 {
48 /* Free resource list */
49 FreeItem(m_TranslatedResourceList, TAG_PORTCLASS);
50 }
51
52 if (m_UntranslatedResourceList)
53 {
54 /* Free resource list */
55 FreeItem(m_UntranslatedResourceList, TAG_PORTCLASS);
56 }
57 }
58
59 NTSTATUS
60 NTAPI
QueryInterface(IN REFIID refiid,OUT PVOID * Output)61 CResourceList::QueryInterface(
62 IN REFIID refiid,
63 OUT PVOID* Output)
64 {
65 UNICODE_STRING GuidString;
66
67 if (IsEqualGUIDAligned(refiid, IID_IResourceList) ||
68 IsEqualGUIDAligned(refiid, IID_IUnknown))
69 {
70 *Output = PVOID(PRESOURCELIST(this));
71 PUNKNOWN(*Output)->AddRef();
72 return STATUS_SUCCESS;
73 }
74
75 if (RtlStringFromGUID(refiid, &GuidString) == STATUS_SUCCESS)
76 {
77 DPRINT1("IResourceList_QueryInterface no interface!!! iface %S\n", GuidString.Buffer);
78 RtlFreeUnicodeString(&GuidString);
79 }
80
81 return STATUS_UNSUCCESSFUL;
82 }
83
84 ULONG
85 NTAPI
NumberOfEntries()86 CResourceList::NumberOfEntries()
87 {
88 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
89
90 return m_NumberOfEntries;
91 }
92
93 ULONG
94 NTAPI
NumberOfEntriesOfType(IN CM_RESOURCE_TYPE Type)95 CResourceList::NumberOfEntriesOfType(
96 IN CM_RESOURCE_TYPE Type)
97 {
98 ULONG Index, Count = 0;
99 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
100
101 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
102
103 /* Is there a resource list? */
104 if (!m_UntranslatedResourceList)
105 {
106 /* No resource list provided */
107 return 0;
108 }
109
110 for (Index = 0; Index < m_NumberOfEntries; Index ++ )
111 {
112
113 /* Get descriptor */
114 PartialDescriptor = &m_UntranslatedResourceList->List[0].PartialResourceList.PartialDescriptors[Index];
115 if (PartialDescriptor->Type == Type)
116 {
117 /* Yay! Finally found one that matches! */
118 Count++;
119 }
120 }
121
122 DPRINT("Found %d type %d\n", Count, Type);
123 return Count;
124 }
125
126 PCM_PARTIAL_RESOURCE_DESCRIPTOR
127 NTAPI
FindTranslatedEntry(IN CM_RESOURCE_TYPE Type,IN ULONG Index)128 CResourceList::FindTranslatedEntry(
129 IN CM_RESOURCE_TYPE Type,
130 IN ULONG Index)
131 {
132 ULONG DescIndex, Count = 0;
133 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
134
135 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
136
137 /* Is there a resource list? */
138 if (!m_TranslatedResourceList)
139 {
140 /* No resource list */
141 return NULL;
142 }
143
144 for (DescIndex = 0; DescIndex < m_NumberOfEntries; DescIndex ++ )
145 {
146 /* Get descriptor */
147 PartialDescriptor = &m_TranslatedResourceList->List[0].PartialResourceList.PartialDescriptors[DescIndex];
148
149 if (PartialDescriptor->Type == Type)
150 {
151 /* Found type, is it the requested index? */
152 if (Index == Count)
153 {
154 /* Found */
155 return PartialDescriptor;
156 }
157
158 /* Need to continue search */
159 Count++;
160 }
161 }
162
163 /* No such descriptor */
164 return NULL;
165 }
166
167 PCM_PARTIAL_RESOURCE_DESCRIPTOR
168 NTAPI
FindUntranslatedEntry(IN CM_RESOURCE_TYPE Type,IN ULONG Index)169 CResourceList::FindUntranslatedEntry(
170 IN CM_RESOURCE_TYPE Type,
171 IN ULONG Index)
172 {
173 ULONG DescIndex, Count = 0;
174 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
175
176 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
177
178 /* Is there a resource list? */
179 if (!m_UntranslatedResourceList)
180 {
181 /* Empty resource list */
182 return NULL;
183 }
184
185 /* Search descriptors */
186 for (DescIndex = 0; DescIndex < m_NumberOfEntries; DescIndex ++ )
187 {
188 /* Get descriptor */
189 PartialDescriptor = &m_UntranslatedResourceList->List[0].PartialResourceList.PartialDescriptors[DescIndex];
190
191 if (PartialDescriptor->Type == Type)
192 {
193 /* Found type, is it the requested index? */
194 if (Index == Count)
195 {
196 /* Found */
197 return PartialDescriptor;
198 }
199
200 /* Need to continue search */
201 Count++;
202 }
203 }
204
205 /* No such descriptor */
206 return NULL;
207 }
208
209 NTSTATUS
210 NTAPI
AddEntry(IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Translated,IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Untranslated)211 CResourceList::AddEntry(
212 IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Translated,
213 IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Untranslated)
214 {
215 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
216
217 /* Sanity check */
218 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
219
220 /* Is there still room for another entry */
221 if (m_NumberOfEntries >= m_MaxEntries)
222 {
223 /* No more space */
224 return STATUS_INSUFFICIENT_RESOURCES;
225 }
226
227 /* Get free descriptor */
228 PartialDescriptor = &m_UntranslatedResourceList->List[0].PartialResourceList.PartialDescriptors[m_NumberOfEntries];
229
230 /* Copy descriptor */
231 RtlCopyMemory(PartialDescriptor, Untranslated, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
232
233 /* Get free descriptor */
234 PartialDescriptor = &m_TranslatedResourceList->List[0].PartialResourceList.PartialDescriptors[m_NumberOfEntries];
235
236 /* Copy descriptor */
237 RtlCopyMemory(PartialDescriptor, Translated, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
238
239 /* Add entry count */
240 m_NumberOfEntries++;
241 m_UntranslatedResourceList->List[0].PartialResourceList.Count++;
242 m_TranslatedResourceList->List[0].PartialResourceList.Count++;
243
244 /* Done */
245 return STATUS_SUCCESS;
246 }
247
248 NTSTATUS
249 NTAPI
AddEntryFromParent(IN IResourceList * Parent,IN CM_RESOURCE_TYPE Type,IN ULONG Index)250 CResourceList::AddEntryFromParent(
251 IN IResourceList* Parent,
252 IN CM_RESOURCE_TYPE Type,
253 IN ULONG Index)
254 {
255 PCM_PARTIAL_RESOURCE_DESCRIPTOR Translated, Untranslated;
256
257 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
258
259 /* Get entries from parent */
260 Translated = Parent->FindTranslatedEntry(Type, Index);
261 Untranslated = Parent->FindUntranslatedEntry(Type, Index);
262
263 /* Are both found? */
264 if (Translated && Untranslated)
265 {
266 /* Add entry from parent */
267 return AddEntry(Translated, Untranslated);
268 }
269
270 /* Entry not found */
271 return STATUS_INVALID_PARAMETER;
272 }
273
274 PCM_RESOURCE_LIST
275 NTAPI
TranslatedList()276 CResourceList::TranslatedList()
277 {
278 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
279
280 return m_TranslatedResourceList;
281 }
282
283 PCM_RESOURCE_LIST
284 NTAPI
UntranslatedList()285 CResourceList::UntranslatedList()
286 {
287 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
288
289 return m_UntranslatedResourceList;
290 }
291
292 PORTCLASSAPI
293 NTSTATUS
294 NTAPI
PcNewResourceList(OUT PRESOURCELIST * OutResourceList,IN PUNKNOWN OuterUnknown OPTIONAL,IN POOL_TYPE PoolType,IN PCM_RESOURCE_LIST TranslatedResourceList,IN PCM_RESOURCE_LIST UntranslatedResourceList)295 PcNewResourceList(
296 OUT PRESOURCELIST* OutResourceList,
297 IN PUNKNOWN OuterUnknown OPTIONAL,
298 IN POOL_TYPE PoolType,
299 IN PCM_RESOURCE_LIST TranslatedResourceList,
300 IN PCM_RESOURCE_LIST UntranslatedResourceList)
301 {
302 PCM_RESOURCE_LIST NewUntranslatedResources, NewTranslatedResources;
303 ULONG ResourceSize, ResourceCount;
304 CResourceList* NewList;
305 NTSTATUS Status;
306
307 if (!TranslatedResourceList)
308 {
309 /* If the untranslated resource list is also not provided, it becomes an empty resource list */
310 if (UntranslatedResourceList)
311 {
312 /* Invalid parameter mix */
313 return STATUS_INVALID_PARAMETER;
314 }
315 }
316 else
317 {
318 /* If the translated resource list is also not provided, it becomes an empty resource list */
319 if (!UntranslatedResourceList)
320 {
321 /* Invalid parameter mix */
322 return STATUS_INVALID_PARAMETER;
323 }
324 }
325
326 /* Allocate resource list */
327 NewList = new(PoolType, TAG_PORTCLASS)CResourceList(OuterUnknown);
328 if (!NewList)
329 return STATUS_INSUFFICIENT_RESOURCES;
330
331 /* Query resource list */
332 Status = NewList->QueryInterface(IID_IResourceList, (PVOID*)OutResourceList);
333 if (!NT_SUCCESS(Status))
334 {
335 /* Ouch, FIX ME */
336 delete NewList;
337 return STATUS_INVALID_PARAMETER;
338 }
339
340 /* Is there a resource list */
341 if (!TranslatedResourceList)
342 {
343 /* Empty resource list */
344 return STATUS_SUCCESS;
345 }
346
347 /* Sanity check */
348 ASSERT(UntranslatedResourceList->List[0].PartialResourceList.Count == TranslatedResourceList->List[0].PartialResourceList.Count);
349
350 /* Get resource count */
351 ResourceCount = UntranslatedResourceList->List[0].PartialResourceList.Count;
352 #ifdef _MSC_VER
353 ResourceSize = FIELD_OFFSET(CM_RESOURCE_LIST, List[0].PartialResourceList.PartialDescriptors[ResourceCount]);
354 #else
355 ResourceSize = sizeof(CM_RESOURCE_LIST) - sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) + (ResourceCount) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
356 #endif
357
358 /* Allocate translated resource list */
359 NewTranslatedResources = (PCM_RESOURCE_LIST)AllocateItem(PoolType, ResourceSize, TAG_PORTCLASS);
360 if (!NewTranslatedResources)
361 {
362 /* No memory */
363 delete NewList;
364 return STATUS_INSUFFICIENT_RESOURCES;
365 }
366
367 /* Allocate untranslated resource list */
368 NewUntranslatedResources = (PCM_RESOURCE_LIST)AllocateItem(PoolType, ResourceSize, TAG_PORTCLASS);
369 if (!NewUntranslatedResources)
370 {
371 /* No memory */
372 delete NewList;
373 FreeItem(NewTranslatedResources, TAG_PORTCLASS);
374 return STATUS_INSUFFICIENT_RESOURCES;
375 }
376
377 /* Copy resource lists */
378 RtlCopyMemory(NewTranslatedResources, TranslatedResourceList, ResourceSize);
379 RtlCopyMemory(NewUntranslatedResources, UntranslatedResourceList, ResourceSize);
380
381 /* Init resource list */
382 NewList->m_TranslatedResourceList= NewTranslatedResources;
383 NewList->m_UntranslatedResourceList = NewUntranslatedResources;
384 NewList->m_NumberOfEntries = ResourceCount;
385 NewList->m_MaxEntries = ResourceCount;
386 NewList->m_PoolType = PoolType;
387
388 /* Done */
389 return STATUS_SUCCESS;
390 }
391
392 PORTCLASSAPI
393 NTSTATUS
394 NTAPI
PcNewResourceSublist(OUT PRESOURCELIST * OutResourceList,IN PUNKNOWN OuterUnknown OPTIONAL,IN POOL_TYPE PoolType,IN PRESOURCELIST ParentList,IN ULONG MaximumEntries)395 PcNewResourceSublist(
396 OUT PRESOURCELIST* OutResourceList,
397 IN PUNKNOWN OuterUnknown OPTIONAL,
398 IN POOL_TYPE PoolType,
399 IN PRESOURCELIST ParentList,
400 IN ULONG MaximumEntries)
401 {
402 CResourceList* NewList;
403 ULONG ResourceSize;
404
405 if (!OutResourceList || !ParentList || !MaximumEntries)
406 return STATUS_INVALID_PARAMETER;
407
408 /* Allocate new list */
409 NewList = new(PoolType, TAG_PORTCLASS) CResourceList(OuterUnknown);
410 if (!NewList)
411 return STATUS_INSUFFICIENT_RESOURCES;
412
413 /* Get resource size */
414 #ifdef _MSC_VER
415 ResourceSize = FIELD_OFFSET(CM_RESOURCE_LIST, List[0].PartialResourceList.PartialDescriptors[MaximumEntries]);
416 #else
417 ResourceSize = sizeof(CM_RESOURCE_LIST) - sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) + (MaximumEntries) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
418 #endif
419
420 /* Allocate resource list */
421 NewList->m_TranslatedResourceList = (PCM_RESOURCE_LIST)AllocateItem(PoolType, ResourceSize, TAG_PORTCLASS);
422 if (!NewList->m_TranslatedResourceList)
423 {
424 /* No memory */
425 delete NewList;
426 return STATUS_INSUFFICIENT_RESOURCES;
427 }
428
429 /* Allocate resource list */
430 NewList->m_UntranslatedResourceList = (PCM_RESOURCE_LIST)AllocateItem(PoolType, ResourceSize, TAG_PORTCLASS);
431 if (!NewList->m_UntranslatedResourceList)
432 {
433 /* No memory */
434 delete NewList;
435 return STATUS_INSUFFICIENT_RESOURCES;
436 }
437
438 /* Copy resource lists */
439 RtlCopyMemory(NewList->m_TranslatedResourceList, ParentList->TranslatedList(), sizeof(CM_RESOURCE_LIST));
440 RtlCopyMemory(NewList->m_UntranslatedResourceList, ParentList->UntranslatedList(), sizeof(CM_RESOURCE_LIST));
441
442 /* Resource list is empty */
443 NewList->m_UntranslatedResourceList->List[0].PartialResourceList.Count = 0;
444 NewList->m_TranslatedResourceList->List[0].PartialResourceList.Count = 0;
445
446 /* Store members */
447 NewList->m_OuterUnknown = OuterUnknown;
448 NewList->m_PoolType = PoolType;
449 NewList->AddRef();
450 NewList->m_NumberOfEntries = 0;
451 NewList->m_MaxEntries = MaximumEntries;
452
453 /* Store result */
454 *OutResourceList = (IResourceList*)NewList;
455
456 /* Done */
457 return STATUS_SUCCESS;
458 }
459