xref: /reactos/drivers/filters/fltmgr/Volume.c (revision cdf90707)
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