[FLTMGR] Implement FltGetVolumeName()
[reactos.git] / drivers / filters / fltmgr / Volume.c
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 FltGetVolumeName(
196 _In_ PFLT_VOLUME Volume,
197 _Inout_opt_ PUNICODE_STRING VolumeName,
198 _Out_opt_ PULONG BufferSizeNeeded)
199 {
200 NTSTATUS Status;
201
202 /* Check if caller just probes for size */
203 if (VolumeName == NULL)
204 {
205 /* Totally broken call */
206 if (BufferSizeNeeded == NULL)
207 {
208 return STATUS_INVALID_PARAMETER;
209 }
210
211 /* Return the appropriate size and quit */
212 *BufferSizeNeeded = Volume->DeviceName.Length;
213 return STATUS_BUFFER_TOO_SMALL;
214 }
215
216 /* We have an output buffer! Assume it's too small */
217 Status = STATUS_BUFFER_TOO_SMALL;
218
219 /* If we have output size, fill it */
220 if (BufferSizeNeeded != NULL)
221 {
222 *BufferSizeNeeded = Volume->DeviceName.Length;
223 }
224
225 /* Init that we didn't return a thing */
226 VolumeName->Length = 0;
227
228 /* If we have enough room, copy and return success */
229 if (VolumeName->MaximumLength >= Volume->DeviceName.Length)
230 {
231 RtlCopyUnicodeString(VolumeName, &Volume->DeviceName);
232 Status = STATUS_SUCCESS;
233 }
234
235 return Status;
236 }
237
238
239 /* INTERNAL FUNCTIONS ******************************************************/