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