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;
CPortWaveRTStreamInit(IUnknown * OuterUnknown)20 CPortWaveRTStreamInit(IUnknown *OuterUnknown) {}
~CPortWaveRTStreamInit()21 virtual ~CPortWaveRTStreamInit() {}
22
23 };
24
25 NTSTATUS
26 NTAPI
QueryInterface(IN REFIID refiid,OUT PVOID * Output)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
AllocatePagesForMdl(IN PHYSICAL_ADDRESS HighAddress,IN SIZE_T TotalBytes)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
AllocateContiguousPagesForMdl(IN PHYSICAL_ADDRESS LowAddress,IN PHYSICAL_ADDRESS HighAddress,IN SIZE_T TotalBytes)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
MapAllocatedPages(IN PMDL MemoryDescriptorList,IN MEMORY_CACHING_TYPE CacheType)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
UnmapAllocatedPages(IN PVOID BaseAddress,IN PMDL MemoryDescriptorList)105 CPortWaveRTStreamInit::UnmapAllocatedPages(
106 IN PVOID BaseAddress,
107 IN PMDL MemoryDescriptorList)
108 {
109 MmUnmapLockedPages(BaseAddress, MemoryDescriptorList);
110 }
111
112 VOID
113 NTAPI
FreePagesFromMdl(IN PMDL MemoryDescriptorList)114 CPortWaveRTStreamInit::FreePagesFromMdl(
115 IN PMDL MemoryDescriptorList)
116 {
117 MmFreePagesFromMdl(MemoryDescriptorList);
118 ExFreePool(MemoryDescriptorList);
119 }
120
121 ULONG
122 NTAPI
GetPhysicalPagesCount(IN PMDL MemoryDescriptorList)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
GetPhysicalPageAddress(IN PPHYSICAL_ADDRESS Address,IN PMDL MemoryDescriptorList,IN ULONG Index)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
NewPortWaveRTStream(PPORTWAVERTSTREAM * OutStream)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