2 * COPYRIGHT: See COPYING in the top level directory
4 * FILE: drivers/wdm/audio/backpln/portcls/resource.cpp
5 * PURPOSE: Port Class driver / ResourceList implementation
6 * PROGRAMMER: Andrew Greenwood
12 #include "private.hpp"
14 class CResourceList
: public IResourceList
17 STDMETHODIMP
QueryInterface( REFIID InterfaceId
, PVOID
* Interface
);
19 STDMETHODIMP_(ULONG
) AddRef()
21 InterlockedIncrement(&m_Ref
);
24 STDMETHODIMP_(ULONG
) Release()
26 InterlockedDecrement(&m_Ref
);
37 CResourceList(IUnknown
* OuterUnknown
) {}
38 virtual ~CResourceList() {}
41 PUNKNOWN m_OuterUnknown
;
43 PCM_RESOURCE_LIST m_TranslatedResourceList
;
44 PCM_RESOURCE_LIST m_UntranslatedResourceList
;
45 ULONG m_NumberOfEntries
;
53 CResourceList::QueryInterface(
57 UNICODE_STRING GuidString
;
59 if (IsEqualGUIDAligned(refiid
, IID_IResourceList
) ||
60 IsEqualGUIDAligned(refiid
, IID_IUnknown
))
62 *Output
= PVOID(PRESOURCELIST(this));
63 PUNKNOWN(*Output
)->AddRef();
64 return STATUS_SUCCESS
;
67 if (RtlStringFromGUID(refiid
, &GuidString
) == STATUS_SUCCESS
)
69 DPRINT1("IResourceList_QueryInterface no interface!!! iface %S\n", GuidString
.Buffer
);
70 RtlFreeUnicodeString(&GuidString
);
73 return STATUS_UNSUCCESSFUL
;
78 CResourceList::NumberOfEntries()
80 // ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
82 return m_NumberOfEntries
;
87 CResourceList::NumberOfEntriesOfType(
88 IN CM_RESOURCE_TYPE Type
)
90 ULONG Index
, Count
= 0;
91 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
93 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL
);
95 if (!m_TranslatedResourceList
)
101 // I guess the translated and untranslated lists will be same length?
102 for (Index
= 0; Index
< m_TranslatedResourceList
->List
[0].PartialResourceList
.Count
; Index
++ )
104 PartialDescriptor
= &m_TranslatedResourceList
->List
[0].PartialResourceList
.PartialDescriptors
[Index
];
105 DPRINT("Descriptor Type %u\n", PartialDescriptor
->Type
);
106 if (PartialDescriptor
->Type
== Type
)
108 // Yay! Finally found one that matches!
113 DPRINT("Found %d type %d\n", Count
, Type
);
117 PCM_PARTIAL_RESOURCE_DESCRIPTOR
119 CResourceList::FindTranslatedEntry(
120 IN CM_RESOURCE_TYPE Type
,
123 ULONG DescIndex
, Count
= 0;
124 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
126 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL
);
128 if (!m_TranslatedResourceList
)
134 for (DescIndex
= 0; DescIndex
< m_TranslatedResourceList
->List
[0].PartialResourceList
.Count
; DescIndex
++ )
136 PartialDescriptor
= &m_TranslatedResourceList
->List
[0].PartialResourceList
.PartialDescriptors
[DescIndex
];
138 if (PartialDescriptor
->Type
== Type
)
140 // Yay! Finally found one that matches!
143 return PartialDescriptor
;
152 PCM_PARTIAL_RESOURCE_DESCRIPTOR
154 CResourceList::FindUntranslatedEntry(
155 IN CM_RESOURCE_TYPE Type
,
158 ULONG DescIndex
, Count
= 0;
159 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
161 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL
);
163 if (!m_UntranslatedResourceList
)
169 for (DescIndex
= 0; DescIndex
< m_UntranslatedResourceList
->List
[0].PartialResourceList
.Count
; DescIndex
++ )
171 PartialDescriptor
= &m_UntranslatedResourceList
->List
[0].PartialResourceList
.PartialDescriptors
[DescIndex
];
173 if (PartialDescriptor
->Type
== Type
)
175 // Yay! Finally found one that matches!
178 return PartialDescriptor
;
188 CResourceList::AddEntry(
189 IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Translated
,
190 IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Untranslated
)
192 PCM_RESOURCE_LIST NewUntranslatedResources
, NewTranslatedResources
;
193 ULONG NewTranslatedSize
, NewUntranslatedSize
, TranslatedSize
, UntranslatedSize
, ResourceCount
;
195 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL
);
197 // calculate translated resource list size
198 ResourceCount
= m_TranslatedResourceList
->List
[0].PartialResourceList
.Count
;
200 NewTranslatedSize
= FIELD_OFFSET(CM_RESOURCE_LIST
, List
[0].PartialResourceList
.PartialDescriptors
[ResourceCount
+1]);
201 TranslatedSize
= FIELD_OFFSET(CM_RESOURCE_LIST
, List
[0].PartialResourceList
.PartialDescriptors
[ResourceCount
]);
203 NewTranslatedSize
= sizeof(CM_RESOURCE_LIST
) + (ResourceCount
> 0 ? (ResourceCount
+1) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
) : 0);
204 TranslatedSize
= sizeof(CM_RESOURCE_LIST
) + (ResourceCount
> 0 ? (ResourceCount
) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
) : 0);
207 NewTranslatedResources
= (PCM_RESOURCE_LIST
)AllocateItem(m_PoolType
, NewTranslatedSize
, TAG_PORTCLASS
);
208 if (!NewTranslatedResources
)
209 return STATUS_INSUFFICIENT_RESOURCES
;
212 // calculate untranslated resouce list size
213 ResourceCount
= m_UntranslatedResourceList
->List
[0].PartialResourceList
.Count
;
216 NewUntranslatedSize
= FIELD_OFFSET(CM_RESOURCE_LIST
, List
[0].PartialResourceList
.PartialDescriptors
[ResourceCount
+1]);
217 UntranslatedSize
= FIELD_OFFSET(CM_RESOURCE_LIST
, List
[0].PartialResourceList
.PartialDescriptors
[ResourceCount
]);
219 NewUntranslatedSize
= sizeof(CM_RESOURCE_LIST
) + (ResourceCount
> 0 ? (ResourceCount
+1) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
) : 0);
220 UntranslatedSize
= sizeof(CM_RESOURCE_LIST
) + (ResourceCount
> 0 ? (ResourceCount
) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
) : 0);
225 // allocate untranslated resource list size
226 NewUntranslatedResources
= (PCM_RESOURCE_LIST
)AllocateItem(m_PoolType
, NewUntranslatedSize
, TAG_PORTCLASS
);
227 if (!NewUntranslatedResources
)
229 FreeItem(NewTranslatedResources
, TAG_PORTCLASS
);
230 return STATUS_INSUFFICIENT_RESOURCES
;
233 // now copy translated resource list
234 RtlMoveMemory(NewTranslatedResources
, m_TranslatedResourceList
, TranslatedSize
);
235 RtlMoveMemory((PUCHAR
)NewTranslatedResources
+ TranslatedSize
, Translated
, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
));
237 // now copy untranslated resource list
238 RtlMoveMemory(NewUntranslatedResources
, m_UntranslatedResourceList
, UntranslatedSize
);
239 RtlMoveMemory((PUCHAR
)NewUntranslatedResources
+ UntranslatedSize
, Untranslated
, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
));
242 FreeItem(m_TranslatedResourceList
, TAG_PORTCLASS
);
243 FreeItem(m_UntranslatedResourceList
, TAG_PORTCLASS
);
246 m_UntranslatedResourceList
= NewUntranslatedResources
;
247 m_TranslatedResourceList
= NewTranslatedResources
;
249 // increment descriptor count
250 NewUntranslatedResources
->List
[0].PartialResourceList
.Count
++;
251 NewTranslatedResources
->List
[0].PartialResourceList
.Count
++;
256 return STATUS_SUCCESS
;
261 CResourceList::AddEntryFromParent(
262 IN IResourceList
* Parent
,
263 IN CM_RESOURCE_TYPE Type
,
266 PCM_PARTIAL_RESOURCE_DESCRIPTOR Translated
, Untranslated
;
268 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL
);
270 Translated
= Parent
->FindTranslatedEntry(Type
, Index
);
271 Untranslated
= Parent
->FindUntranslatedEntry(Type
, Index
);
273 if (Translated
&& Untranslated
)
275 // add entry from parent
276 return AddEntry(Translated
, Untranslated
);
280 return STATUS_INVALID_PARAMETER
;
285 CResourceList::TranslatedList()
287 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL
);
289 return m_TranslatedResourceList
;
294 CResourceList::UntranslatedList()
296 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL
);
298 return m_UntranslatedResourceList
;
306 OUT PRESOURCELIST
* OutResourceList
,
307 IN PUNKNOWN OuterUnknown OPTIONAL
,
308 IN POOL_TYPE PoolType
,
309 IN PCM_RESOURCE_LIST TranslatedResourceList
,
310 IN PCM_RESOURCE_LIST UntranslatedResourceList
)
312 PCM_RESOURCE_LIST NewUntranslatedResources
, NewTranslatedResources
;
313 ULONG NewTranslatedSize
, NewUntranslatedSize
, ResourceCount
;
314 CResourceList
* NewList
;
317 if (!TranslatedResourceList
)
320 // if the untranslated resource list is also not provided, it becomes an empty resource list
322 if (UntranslatedResourceList
)
324 // invalid parameter mix
325 return STATUS_INVALID_PARAMETER
;
331 // if the translated resource list is also not provided, it becomes an empty resource list
333 if (!UntranslatedResourceList
)
335 // invalid parameter mix
336 return STATUS_INVALID_PARAMETER
;
340 NewList
= new(PoolType
, TAG_PORTCLASS
)CResourceList(OuterUnknown
);
342 return STATUS_INSUFFICIENT_RESOURCES
;
344 Status
= NewList
->QueryInterface(IID_IResourceList
, (PVOID
*)OutResourceList
);
346 if (!NT_SUCCESS(Status
))
351 // calculate translated resource list size
352 ResourceCount
= TranslatedResourceList
->List
[0].PartialResourceList
.Count
;
354 NewTranslatedSize
= FIELD_OFFSET(CM_RESOURCE_LIST
, List
[0].PartialResourceList
.PartialDescriptors
[ResourceCount
]);
356 NewTranslatedSize
= sizeof(CM_RESOURCE_LIST
) + (ResourceCount
> 0 ? (ResourceCount
-1) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
) : 0);
359 // store resource count
360 NewList
->m_NumberOfEntries
= ResourceCount
;
362 // calculate untranslated resouce list size
363 ResourceCount
= UntranslatedResourceList
->List
[0].PartialResourceList
.Count
;
365 NewUntranslatedSize
= FIELD_OFFSET(CM_RESOURCE_LIST
, List
[0].PartialResourceList
.PartialDescriptors
[ResourceCount
]);
367 NewUntranslatedSize
= sizeof(CM_RESOURCE_LIST
) + (ResourceCount
> 0 ? (ResourceCount
-1) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
) : 0);
370 // allocate translated resource list
371 NewTranslatedResources
= (PCM_RESOURCE_LIST
)AllocateItem(PoolType
, NewTranslatedSize
, TAG_PORTCLASS
);
372 if (!NewTranslatedResources
)
374 FreeItem(NewList
, TAG_PORTCLASS
);
375 return STATUS_INSUFFICIENT_RESOURCES
;
378 // allocate untranslated resource list
379 NewUntranslatedResources
= (PCM_RESOURCE_LIST
)AllocateItem(PoolType
, NewUntranslatedSize
, TAG_PORTCLASS
);
380 if (!NewUntranslatedResources
)
382 FreeItem(NewList
, TAG_PORTCLASS
);
383 FreeItem(NewTranslatedResources
, TAG_PORTCLASS
);
384 return STATUS_INSUFFICIENT_RESOURCES
;
387 // copy resource lists
388 RtlCopyMemory(NewTranslatedResources
, TranslatedResourceList
, NewTranslatedSize
);
389 RtlCopyMemory(NewUntranslatedResources
, UntranslatedResourceList
, NewUntranslatedSize
);
391 // store resource lists
392 NewList
->m_TranslatedResourceList
= NewTranslatedResources
;
393 NewList
->m_UntranslatedResourceList
= NewUntranslatedResources
;
395 return STATUS_SUCCESS
;
401 PcNewResourceSublist(
402 OUT PRESOURCELIST
* OutResourceList
,
403 IN PUNKNOWN OuterUnknown OPTIONAL
,
404 IN POOL_TYPE PoolType
,
405 IN PRESOURCELIST ParentList
,
406 IN ULONG MaximumEntries
)
408 CResourceList
* NewList
, *Parent
;
410 if (!OutResourceList
|| !ParentList
|| !MaximumEntries
)
411 return STATUS_INVALID_PARAMETER
;
413 Parent
= (CResourceList
*)ParentList
;
415 if (!Parent
->m_TranslatedResourceList
->List
->PartialResourceList
.Count
||
416 !Parent
->m_UntranslatedResourceList
->List
->PartialResourceList
.Count
)
418 // parent list can't be empty
419 return STATUS_INVALID_PARAMETER
;
422 NewList
= new(PoolType
, TAG_PORTCLASS
) CResourceList(OuterUnknown
);
424 return STATUS_INSUFFICIENT_RESOURCES
;
426 NewList
->m_TranslatedResourceList
= (PCM_RESOURCE_LIST
)AllocateItem(PoolType
, sizeof(CM_RESOURCE_LIST
), TAG_PORTCLASS
);
427 if (!NewList
->m_TranslatedResourceList
)
430 return STATUS_INSUFFICIENT_RESOURCES
;
433 NewList
->m_UntranslatedResourceList
= (PCM_RESOURCE_LIST
)AllocateItem(PoolType
, sizeof(CM_RESOURCE_LIST
), TAG_PORTCLASS
);
434 if (!NewList
->m_UntranslatedResourceList
)
437 return STATUS_INSUFFICIENT_RESOURCES
;
440 RtlCopyMemory(NewList
->m_TranslatedResourceList
, Parent
->m_TranslatedResourceList
, sizeof(CM_RESOURCE_LIST
));
441 RtlCopyMemory(NewList
->m_UntranslatedResourceList
, Parent
->m_UntranslatedResourceList
, sizeof(CM_RESOURCE_LIST
));
443 // mark list as empty
444 NewList
->m_TranslatedResourceList
->List
->PartialResourceList
.Count
= 0;
445 NewList
->m_UntranslatedResourceList
->List
->PartialResourceList
.Count
= 0;
447 NewList
->m_OuterUnknown
= OuterUnknown
;
448 NewList
->m_PoolType
= PoolType
;
451 *OutResourceList
= (IResourceList
*)NewList
;
453 DPRINT("PcNewResourceSublist OutResourceList %p OuterUnknown %p ParentList %p\n", *OutResourceList
, OuterUnknown
, ParentList
);
454 return STATUS_SUCCESS
;