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