1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS Kernel Streaming 4 * FILE: drivers/wdm/audio/backpln/portcls/port_wavertstream.cpp 5 * PURPOSE: WaveRTStream helper object 6 * PROGRAMMER: Johannes Anderwald 7 */ 8 9 #include "private.hpp" 10 11 #define NDEBUG 12 #include <debug.h> 13 14 class CPortWaveRTStreamInit : public CUnknownImpl<IPortWaveRTStreamInit> 15 { 16 public: 17 STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface); 18 19 IMP_IPortWaveRTStreamInit; 20 CPortWaveRTStreamInit(IUnknown *OuterUnknown) {} 21 virtual ~CPortWaveRTStreamInit() {} 22 23 }; 24 25 NTSTATUS 26 NTAPI 27 CPortWaveRTStreamInit::QueryInterface( 28 IN REFIID refiid, 29 OUT PVOID* Output) 30 { 31 32 DPRINT("IPortWaveRTStream_fnQueryInterface entered\n"); 33 34 if (IsEqualGUIDAligned(refiid, IID_IPortWaveRTStream) || 35 IsEqualGUIDAligned(refiid, IID_IUnknown)) 36 { 37 *Output = PVOID(PPORTWAVERTSTREAM(this)); 38 PUNKNOWN(*Output)->AddRef(); 39 return STATUS_SUCCESS; 40 } 41 return STATUS_UNSUCCESSFUL; 42 } 43 44 PMDL 45 NTAPI 46 CPortWaveRTStreamInit::AllocatePagesForMdl( 47 IN PHYSICAL_ADDRESS HighAddress, 48 IN SIZE_T TotalBytes) 49 { 50 return MmAllocatePagesForMdl(RtlConvertUlongToLargeInteger(0), HighAddress, RtlConvertUlongToLargeInteger(0), TotalBytes); 51 } 52 53 PMDL 54 NTAPI 55 CPortWaveRTStreamInit::AllocateContiguousPagesForMdl( 56 IN PHYSICAL_ADDRESS LowAddress, 57 IN PHYSICAL_ADDRESS HighAddress, 58 IN SIZE_T TotalBytes) 59 { 60 PMDL Mdl; 61 PVOID Buffer; 62 PHYSICAL_ADDRESS Address; 63 64 Buffer = MmAllocateContiguousMemorySpecifyCache(TotalBytes, LowAddress, HighAddress, RtlConvertUlongToLargeInteger(0), MmNonCached); 65 if (!Buffer) 66 { 67 DPRINT("MmAllocateContiguousMemorySpecifyCache failed\n"); 68 return NULL; 69 } 70 71 Address = MmGetPhysicalAddress(Buffer); 72 73 MmFreeContiguousMemorySpecifyCache(Buffer, TotalBytes, MmNonCached); 74 75 Mdl = MmAllocatePagesForMdl(Address, HighAddress, RtlConvertUlongToLargeInteger(0), TotalBytes); 76 if (!Mdl) 77 { 78 DPRINT("MmAllocatePagesForMdl failed\n"); 79 return NULL; 80 } 81 82 if (MmGetMdlByteCount(Mdl) < TotalBytes) 83 { 84 DPRINT("ByteCount %u Required %u\n", MmGetMdlByteCount(Mdl), TotalBytes); 85 MmFreePagesFromMdl(Mdl); 86 ExFreePool(Mdl); 87 return NULL; 88 } 89 90 DPRINT("Result %p\n", Mdl); 91 return Mdl; 92 } 93 94 PVOID 95 NTAPI 96 CPortWaveRTStreamInit::MapAllocatedPages( 97 IN PMDL MemoryDescriptorList, 98 IN MEMORY_CACHING_TYPE CacheType) 99 { 100 return MmMapLockedPagesSpecifyCache(MemoryDescriptorList, KernelMode, CacheType, NULL, 0, NormalPagePriority); 101 } 102 103 VOID 104 NTAPI 105 CPortWaveRTStreamInit::UnmapAllocatedPages( 106 IN PVOID BaseAddress, 107 IN PMDL MemoryDescriptorList) 108 { 109 MmUnmapLockedPages(BaseAddress, MemoryDescriptorList); 110 } 111 112 VOID 113 NTAPI 114 CPortWaveRTStreamInit::FreePagesFromMdl( 115 IN PMDL MemoryDescriptorList) 116 { 117 MmFreePagesFromMdl(MemoryDescriptorList); 118 ExFreePool(MemoryDescriptorList); 119 } 120 121 ULONG 122 NTAPI 123 CPortWaveRTStreamInit::GetPhysicalPagesCount( 124 IN PMDL MemoryDescriptorList) 125 { 126 return ADDRESS_AND_SIZE_TO_SPAN_PAGES(0, MmGetMdlByteCount(MemoryDescriptorList)); 127 } 128 129 PHYSICAL_ADDRESS 130 NTAPI 131 CPortWaveRTStreamInit::GetPhysicalPageAddress( 132 IN PPHYSICAL_ADDRESS Address, 133 IN PMDL MemoryDescriptorList, 134 IN ULONG Index) 135 { 136 PVOID Buffer; 137 ULONG Pages; 138 PHYSICAL_ADDRESS Result, Addr; 139 140 Pages = ADDRESS_AND_SIZE_TO_SPAN_PAGES(0, MmGetMdlByteCount(MemoryDescriptorList)); 141 if (Pages <= Index) 142 { 143 DPRINT("OutOfBounds: Pages %u Index %u\n", Pages, Index); 144 return RtlConvertUlongToLargeInteger(0); 145 } 146 147 Buffer = (PUCHAR)MmGetSystemAddressForMdlSafe(MemoryDescriptorList, LowPagePriority) + (Index * PAGE_SIZE); 148 149 Addr = MmGetPhysicalAddress(Buffer); 150 Address->QuadPart = Addr.QuadPart; 151 Result.QuadPart = (ULONG_PTR)Address; 152 153 return Result; 154 } 155 156 NTSTATUS 157 NewPortWaveRTStream( 158 PPORTWAVERTSTREAM *OutStream) 159 { 160 NTSTATUS Status; 161 CPortWaveRTStreamInit* This = new(NonPagedPool, TAG_PORTCLASS) CPortWaveRTStreamInit(NULL); 162 if (!This) 163 return STATUS_INSUFFICIENT_RESOURCES; 164 165 Status = This->QueryInterface(IID_IPortWaveRTStream, (PVOID*)OutStream); 166 167 if (!NT_SUCCESS(Status)) 168 { 169 delete This; 170 return Status; 171 } 172 173 *OutStream = (PPORTWAVERTSTREAM)This; 174 return Status; 175 } 176