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