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 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 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 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 86 CResourceList::NumberOfEntries() 87 { 88 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL); 89 90 return m_NumberOfEntries; 91 } 92 93 ULONG 94 NTAPI 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 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 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 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 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 276 CResourceList::TranslatedList() 277 { 278 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL); 279 280 return m_TranslatedResourceList; 281 } 282 283 PCM_RESOURCE_LIST 284 NTAPI 285 CResourceList::UntranslatedList() 286 { 287 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL); 288 289 return m_UntranslatedResourceList; 290 } 291 292 PORTCLASSAPI 293 NTSTATUS 294 NTAPI 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 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