1 /* 2 * PROJECT: Filesystem Filter Manager 3 * LICENSE: GPL - See COPYING in the top level directory 4 * FILE: drivers/filters/fltmgr/Context.c 5 * PURPOSE: Contains routines for the volume 6 * PROGRAMMERS: Ged Murphy (gedmurphy@reactos.org) 7 */ 8 9 /* INCLUDES ******************************************************************/ 10 11 #include "fltmgr.h" 12 #include "fltmgrint.h" 13 14 #define NDEBUG 15 #include <debug.h> 16 17 18 /* DATA *********************************************************************/ 19 20 21 22 /* EXPORTED FUNCTIONS ******************************************************/ 23 24 NTSTATUS 25 FLTAPI 26 FltGetVolumeProperties( 27 _In_ PFLT_VOLUME Volume, 28 _Out_writes_bytes_to_opt_(VolumePropertiesLength, *LengthReturned) PFLT_VOLUME_PROPERTIES VolumeProperties, 29 _In_ ULONG VolumePropertiesLength, 30 _Out_ PULONG LengthReturned 31 ) 32 { 33 ULONG BufferRequired; 34 ULONG BytesWritten; 35 PCHAR Ptr; 36 NTSTATUS Status; 37 38 /* Calculate the required buffer size */ 39 BufferRequired = sizeof(FLT_VOLUME_PROPERTIES) + 40 Volume->CDODriverName.Length + 41 Volume->DeviceName.Length + 42 Volume->CDODeviceName.Length; 43 44 /* If we don't have enough buffer to fill in the fixed struct, return with the required size */ 45 if (VolumePropertiesLength < sizeof(FLT_VOLUME_PROPERTIES)) 46 { 47 *LengthReturned = BufferRequired; 48 return STATUS_BUFFER_TOO_SMALL; 49 } 50 51 /* Clear out the buffer */ 52 RtlZeroMemory(VolumeProperties, sizeof(FLT_VOLUME_PROPERTIES)); 53 54 /* Fill in the fixed data */ 55 VolumeProperties->DeviceType = Volume->DeviceObject->DeviceType; 56 VolumeProperties->DeviceObjectFlags = Volume->DeviceObject->Flags; 57 VolumeProperties->AlignmentRequirement = Volume->DeviceObject->AlignmentRequirement; 58 VolumeProperties->SectorSize = Volume->DeviceObject->SectorSize; 59 if (Volume->DiskDeviceObject) 60 { 61 VolumeProperties->DeviceCharacteristics = Volume->DiskDeviceObject->Characteristics; 62 } 63 else 64 { 65 VolumeProperties->DeviceCharacteristics = Volume->DeviceObject->Characteristics; 66 } 67 68 /* So far we've written the fixed struct data */ 69 BytesWritten = sizeof(FLT_VOLUME_PROPERTIES); 70 Ptr = (PCHAR)(VolumeProperties + 1); 71 72 /* Make sure we have enough room to add the dynamic data */ 73 if (VolumePropertiesLength >= BufferRequired) 74 { 75 /* Add the FS device name */ 76 VolumeProperties->FileSystemDeviceName.Length = 0; 77 VolumeProperties->FileSystemDeviceName.MaximumLength = Volume->CDODeviceName.Length; 78 VolumeProperties->FileSystemDeviceName.Buffer = (PWCH)Ptr; 79 RtlCopyUnicodeString(&VolumeProperties->FileSystemDeviceName, &Volume->CDODeviceName); 80 Ptr += VolumeProperties->FileSystemDeviceName.Length; 81 82 /* Add the driver name */ 83 VolumeProperties->FileSystemDriverName.Length = 0; 84 VolumeProperties->FileSystemDriverName.MaximumLength = Volume->CDODriverName.Length; 85 VolumeProperties->FileSystemDriverName.Buffer = (PWCH)Ptr; 86 RtlCopyUnicodeString(&VolumeProperties->FileSystemDriverName, &Volume->CDODriverName); 87 Ptr += VolumeProperties->FileSystemDriverName.Length; 88 89 /* Add the volume name */ 90 VolumeProperties->RealDeviceName.Length = 0; 91 VolumeProperties->RealDeviceName.MaximumLength = Volume->DeviceName.Length; 92 VolumeProperties->RealDeviceName.Buffer = (PWCH)Ptr; 93 RtlCopyUnicodeString(&VolumeProperties->RealDeviceName, &Volume->DeviceName); 94 95 BytesWritten = BufferRequired; 96 97 Status = STATUS_SUCCESS; 98 } 99 else 100 { 101 Status = STATUS_BUFFER_OVERFLOW; 102 } 103 104 /* Set the number of bytes we wrote and return */ 105 *LengthReturned = BytesWritten; 106 return Status; 107 } 108 109 110 NTSTATUS 111 FLTAPI 112 FltEnumerateVolumes( 113 _In_ PFLT_FILTER Filter, 114 _Out_writes_to_opt_(VolumeListSize,*NumberVolumesReturned) PFLT_VOLUME *VolumeList, 115 _In_ ULONG VolumeListSize, 116 _Out_ PULONG NumberVolumesReturned) 117 { 118 ULONG i; 119 PFLTP_FRAME Frame; 120 PFLT_VOLUME Volume; 121 PLIST_ENTRY ListEntry; 122 ULONG NumberOfVolumes = 0; 123 NTSTATUS Status = STATUS_SUCCESS; 124 125 PAGED_CODE(); 126 127 Frame = Filter->Frame; 128 129 /* Lock the attached volumes list */ 130 KeEnterCriticalRegion(); 131 ExAcquireResourceSharedLite(&Frame->AttachedVolumes.rLock, TRUE); 132 133 /* If it's not empty */ 134 if (!IsListEmpty(&Frame->AttachedVolumes.rList)) 135 { 136 /* Browse every entry */ 137 for (ListEntry = Frame->AttachedVolumes.rList.Flink; 138 ListEntry != &Frame->AttachedVolumes.rList; 139 ListEntry = ListEntry->Flink) 140 { 141 /* Get the volume */ 142 Volume = CONTAINING_RECORD(ListEntry, FLT_VOLUME, Base.PrimaryLink); 143 144 /* If there's still room in the output buffer */ 145 if (NumberOfVolumes < VolumeListSize) 146 { 147 /* Reference the volume and return it */ 148 FltObjectReference(Volume); 149 VolumeList[NumberOfVolumes] = Volume; 150 } 151 152 /* We returned one more volume */ 153 ++NumberOfVolumes; 154 } 155 } 156 157 /* Release the list */ 158 ExReleaseResourceLite(&Frame->AttachedVolumes.rLock); 159 KeLeaveCriticalRegion(); 160 161 /* If we want to return more volumes than we can */ 162 if (NumberOfVolumes > VolumeListSize) 163 { 164 /* We will clear output */ 165 for (i = 0; i < VolumeListSize; ++i) 166 { 167 FltObjectDereference(VolumeList[i]); 168 VolumeList[i] = NULL; 169 } 170 171 /* And set failure status */ 172 Status = STATUS_BUFFER_TOO_SMALL; 173 } 174 175 /* Always return the max amount of volumes we want to return */ 176 *NumberVolumesReturned = NumberOfVolumes; 177 178 /* Done */ 179 return Status; 180 } 181 182 NTSTATUS 183 FLTAPI 184 FltDetachVolume( 185 _Inout_ PFLT_FILTER Filter, 186 _Inout_ PFLT_VOLUME Volume, 187 _In_opt_ PCUNICODE_STRING InstanceName) 188 { 189 UNIMPLEMENTED; 190 return STATUS_NOT_IMPLEMENTED; 191 } 192 193 NTSTATUS 194 FLTAPI 195 FltAttachVolume( 196 _Inout_ PFLT_FILTER Filter, 197 _Inout_ PFLT_VOLUME Volume, 198 _In_opt_ PCUNICODE_STRING InstanceName, 199 _Outptr_opt_result_maybenull_ PFLT_INSTANCE *RetInstance) 200 { 201 UNIMPLEMENTED; 202 return STATUS_NOT_IMPLEMENTED; 203 } 204 205 NTSTATUS 206 FLTAPI 207 FltGetVolumeName( 208 _In_ PFLT_VOLUME Volume, 209 _Inout_opt_ PUNICODE_STRING VolumeName, 210 _Out_opt_ PULONG BufferSizeNeeded) 211 { 212 NTSTATUS Status; 213 214 /* Check if caller just probes for size */ 215 if (VolumeName == NULL) 216 { 217 /* Totally broken call */ 218 if (BufferSizeNeeded == NULL) 219 { 220 return STATUS_INVALID_PARAMETER; 221 } 222 223 /* Return the appropriate size and quit */ 224 *BufferSizeNeeded = Volume->DeviceName.Length; 225 return STATUS_BUFFER_TOO_SMALL; 226 } 227 228 /* We have an output buffer! Assume it's too small */ 229 Status = STATUS_BUFFER_TOO_SMALL; 230 231 /* If we have output size, fill it */ 232 if (BufferSizeNeeded != NULL) 233 { 234 *BufferSizeNeeded = Volume->DeviceName.Length; 235 } 236 237 /* Init that we didn't return a thing */ 238 VolumeName->Length = 0; 239 240 /* If we have enough room, copy and return success */ 241 if (VolumeName->MaximumLength >= Volume->DeviceName.Length) 242 { 243 RtlCopyUnicodeString(VolumeName, &Volume->DeviceName); 244 Status = STATUS_SUCCESS; 245 } 246 247 return Status; 248 } 249 250 251 /* INTERNAL FUNCTIONS ******************************************************/ 252