1 /*++ 2 3 Copyright (C) Microsoft Corporation. All rights reserved. 4 5 Module Name: 6 7 mmc.h 8 9 Abstract: 10 11 Functions/macros for using the scratch buffer and scratch request/SRB 12 in the serial I/O queue context 13 14 Author: 15 16 Environment: 17 18 kernel mode only 19 20 Notes: 21 22 23 Revision History: 24 25 --*/ 26 27 #ifndef __SCRATCH_H__ 28 #define __SCRATCH_H__ 29 30 31 _IRQL_requires_max_(APC_LEVEL) 32 VOID 33 ScratchBuffer_Deallocate( 34 _Inout_ PCDROM_DEVICE_EXTENSION DeviceExtension 35 ); 36 37 _IRQL_requires_max_(APC_LEVEL) 38 BOOLEAN 39 ScratchBuffer_Allocate( 40 _Inout_ PCDROM_DEVICE_EXTENSION DeviceExtension 41 ); 42 43 VOID 44 ScratchBuffer_ResetItems( 45 _Inout_ PCDROM_DEVICE_EXTENSION DeviceExtension, 46 _In_ BOOLEAN ResetRequestHistory 47 ); 48 49 _IRQL_requires_max_(APC_LEVEL) 50 VOID 51 ScratchBuffer_SetupSrb( 52 _Inout_ PCDROM_DEVICE_EXTENSION DeviceExtension, 53 _In_opt_ WDFREQUEST OriginalRequest, 54 _In_ ULONG MaximumTransferLength, 55 _In_ BOOLEAN GetDataFromDevice 56 ); 57 58 VOID 59 ScratchBuffer_SetupReadWriteSrb( 60 _Inout_ PCDROM_DEVICE_EXTENSION DeviceExtension, 61 _In_ WDFREQUEST OriginalRequest, 62 _In_ LARGE_INTEGER StartingOffset, 63 _In_ ULONG RequiredLength, 64 _Inout_updates_bytes_(RequiredLength) UCHAR* DataBuffer, 65 _In_ BOOLEAN IsReadRequest, 66 _In_ BOOLEAN UsePartialMdl 67 ); 68 69 NTSTATUS 70 ScratchBuffer_SendSrb( 71 _Inout_ PCDROM_DEVICE_EXTENSION DeviceExtension, 72 _In_ BOOLEAN SynchronousSrb, 73 _When_(SynchronousSrb, _Pre_null_) 74 _When_(!SynchronousSrb, _In_opt_) 75 PSRB_HISTORY_ITEM *SrbHistoryItem 76 ); 77 78 NTSTATUS 79 ScratchBuffer_PerformNextReadWrite( 80 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension, 81 _In_ BOOLEAN FirstTry 82 ); 83 84 #if DBG 85 #define ScratchBuffer_BeginUse(context) ScratchBuffer_BeginUseX((context), __FILE__, __LINE__) 86 #else 87 #define ScratchBuffer_BeginUse(context) ScratchBuffer_BeginUseX((context), NULL, (ULONG)-1) 88 #endif 89 90 FORCEINLINE VOID ScratchBuffer_BeginUseX(_Inout_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_opt_ LPCSTR File, ULONG Line) 91 { 92 // NOTE: these are not "real" locks. They are simply to help 93 // avoid multiple uses of the scratch buffer. Thus, it 94 // is not critical to have atomic operations here. 95 PVOID tmp = InterlockedCompareExchangePointer((PVOID)&(DeviceExtension->ScratchContext.ScratchInUse), (PVOID)-1, NULL); 96 NT_ASSERT(tmp == NULL); 97 UNREFERENCED_PARAMETER(tmp); //defensive coding, avoid PREFAST warning. 98 DeviceExtension->ScratchContext.ScratchInUseFileName = File; 99 DeviceExtension->ScratchContext.ScratchInUseLineNumber = Line; 100 ScratchBuffer_ResetItems(DeviceExtension, TRUE); 101 RequestClearSendTime(DeviceExtension->ScratchContext.ScratchRequest); 102 return; 103 } 104 FORCEINLINE VOID ScratchBuffer_EndUse(_Inout_ PCDROM_DEVICE_EXTENSION DeviceExtension) 105 { 106 // NOTE: these are not "real" locks. They are simply to help 107 // avoid multiple uses of the scratch buffer. Thus, it 108 // is not critical to have atomic operations here. 109 110 // On lock release, we erase ScratchInUseFileName and ScratchInUseLineNumber _before_ releasing ScratchInUse, 111 // because otherwise we may erase these after the lock has been acquired again by another thread. We store the 112 // old values of ScratchInUseFileName and ScratchInUseLineNumber in local variables to facilitate debugging, 113 // if the ASSERT at the end of the function is hit. 114 PCSTR scratchInUseFileName; 115 ULONG scratchInUseLineNumber; 116 PVOID tmp; 117 118 scratchInUseFileName = DeviceExtension->ScratchContext.ScratchInUseFileName; 119 scratchInUseLineNumber = DeviceExtension->ScratchContext.ScratchInUseLineNumber; 120 UNREFERENCED_PARAMETER(scratchInUseFileName); 121 UNREFERENCED_PARAMETER(scratchInUseLineNumber); 122 DeviceExtension->ScratchContext.ScratchInUseFileName = NULL; 123 DeviceExtension->ScratchContext.ScratchInUseLineNumber = 0; 124 125 // 126 // If we have used the PartialMdl in the scratch context we should notify MM that we will be reusing it 127 // otherwise it may leak System VA if some one below us has mapped the same. 128 // 129 130 if (DeviceExtension->ScratchContext.PartialMdlIsBuilt != FALSE) 131 { 132 MmPrepareMdlForReuse(DeviceExtension->ScratchContext.PartialMdl); 133 DeviceExtension->ScratchContext.PartialMdlIsBuilt = FALSE; 134 } 135 136 tmp = InterlockedCompareExchangePointer((PVOID)&(DeviceExtension->ScratchContext.ScratchInUse), NULL, (PVOID)-1); 137 NT_ASSERT(tmp == ((PVOID)-1)); 138 UNREFERENCED_PARAMETER(tmp); //defensive coding, avoid PREFAST warning. 139 return; 140 } 141 142 VOID 143 CompressSrbHistoryData( 144 _Inout_ PSRB_HISTORY RequestHistory 145 ); 146 147 VOID 148 ValidateSrbHistoryDataPresumptions( 149 _In_ SRB_HISTORY const* RequestHistory 150 ); 151 152 _IRQL_requires_max_(APC_LEVEL) 153 NTSTATUS 154 ScratchBuffer_ExecuteCdbEx( 155 _Inout_ PCDROM_DEVICE_EXTENSION DeviceExtension, 156 _In_opt_ WDFREQUEST OriginalRequest, 157 _In_ ULONG TransferSize, 158 _In_ BOOLEAN GetDataFromDevice, 159 _In_ PCDB Cdb, 160 _In_ UCHAR OprationLength, 161 _In_ ULONG TimeoutValue 162 ); 163 164 _IRQL_requires_max_(APC_LEVEL) 165 FORCEINLINE // __REACTOS__ 166 NTSTATUS 167 ScratchBuffer_ExecuteCdb( 168 _Inout_ PCDROM_DEVICE_EXTENSION DeviceExtension, 169 _In_opt_ WDFREQUEST OriginalRequest, 170 _In_ ULONG TransferSize, 171 _In_ BOOLEAN GetDataFromDevice, 172 _In_ PCDB Cdb, 173 _In_ UCHAR OprationLength 174 ) 175 { 176 return ScratchBuffer_ExecuteCdbEx(DeviceExtension, 177 OriginalRequest, 178 TransferSize, 179 GetDataFromDevice, 180 Cdb, 181 OprationLength, 182 0); 183 } 184 185 KDEFERRED_ROUTINE ScratchBuffer_ReadWriteTimerRoutine; 186 187 #endif //__SCRATCH_H__ 188