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