[REACTOS]
[reactos.git] / reactos / drivers / filesystems / fastfat / misc.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: drivers/fs/vfat/misc.c
5 * PURPOSE: VFAT Filesystem
6 * PROGRAMMER:
7 *
8 */
9
10 /* INCLUDES *****************************************************************/
11
12 #define NDEBUG
13 #include "vfat.h"
14
15 /* GLOBALS ******************************************************************/
16
17 const char* MajorFunctionNames[] =
18 {
19 "IRP_MJ_CREATE",
20 "IRP_MJ_CREATE_NAMED_PIPE",
21 "IRP_MJ_CLOSE",
22 "IRP_MJ_READ",
23 "IRP_MJ_WRITE",
24 "IRP_MJ_QUERY_INFORMATION",
25 "IRP_MJ_SET_INFORMATION",
26 "IRP_MJ_QUERY_EA",
27 "IRP_MJ_SET_EA",
28 "IRP_MJ_FLUSH_BUFFERS",
29 "IRP_MJ_QUERY_VOLUME_INFORMATION",
30 "IRP_MJ_SET_VOLUME_INFORMATION",
31 "IRP_MJ_DIRECTORY_CONTROL",
32 "IRP_MJ_FILE_SYSTEM_CONTROL",
33 "IRP_MJ_DEVICE_CONTROL",
34 "IRP_MJ_INTERNAL_DEVICE_CONTROL",
35 "IRP_MJ_SHUTDOWN",
36 "IRP_MJ_LOCK_CONTROL",
37 "IRP_MJ_CLEANUP",
38 "IRP_MJ_CREATE_MAILSLOT",
39 "IRP_MJ_QUERY_SECURITY",
40 "IRP_MJ_SET_SECURITY",
41 "IRP_MJ_POWER",
42 "IRP_MJ_SYSTEM_CONTROL",
43 "IRP_MJ_DEVICE_CHANGE",
44 "IRP_MJ_QUERY_QUOTA",
45 "IRP_MJ_SET_QUOTA",
46 "IRP_MJ_PNP",
47 "IRP_MJ_MAXIMUM_FUNCTION"
48 };
49
50 /* FUNCTIONS ****************************************************************/
51
52 static LONG QueueCount = 0;
53
54 static NTSTATUS VfatLockControl(
55 IN PVFAT_IRP_CONTEXT IrpContext
56 )
57 {
58 PVFATFCB Fcb;
59 NTSTATUS Status;
60
61 DPRINT("VfatLockControl(IrpContext %p)\n", IrpContext);
62
63 ASSERT(IrpContext);
64
65 Fcb = (PVFATFCB)IrpContext->FileObject->FsContext;
66
67 if (IrpContext->DeviceObject == VfatGlobalData->DeviceObject)
68 {
69 Status = STATUS_INVALID_DEVICE_REQUEST;
70 goto Fail;
71 }
72
73 if (*Fcb->Attributes & FILE_ATTRIBUTE_DIRECTORY)
74 {
75 Status = STATUS_INVALID_PARAMETER;
76 goto Fail;
77 }
78
79 Status = FsRtlProcessFileLock(&Fcb->FileLock,
80 IrpContext->Irp,
81 NULL
82 );
83
84 VfatFreeIrpContext(IrpContext);
85 return Status;
86
87 Fail:;
88 IrpContext->Irp->IoStatus.Status = Status;
89 IoCompleteRequest(IrpContext->Irp, (CCHAR)(NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT));
90 VfatFreeIrpContext(IrpContext);
91 return Status;
92 }
93
94 static NTSTATUS
95 VfatDispatchRequest (IN PVFAT_IRP_CONTEXT IrpContext)
96 {
97 DPRINT ("VfatDispatchRequest (IrpContext %p), is called for %s\n", IrpContext,
98 IrpContext->MajorFunction >= IRP_MJ_MAXIMUM_FUNCTION ? "????" : MajorFunctionNames[IrpContext->MajorFunction]);
99
100 ASSERT(IrpContext);
101
102 switch (IrpContext->MajorFunction)
103 {
104 case IRP_MJ_CLOSE:
105 return VfatClose (IrpContext);
106 case IRP_MJ_CREATE:
107 return VfatCreate (IrpContext);
108 case IRP_MJ_READ:
109 return VfatRead (IrpContext);
110 case IRP_MJ_WRITE:
111 return VfatWrite (IrpContext);
112 case IRP_MJ_FILE_SYSTEM_CONTROL:
113 return VfatFileSystemControl(IrpContext);
114 case IRP_MJ_QUERY_INFORMATION:
115 return VfatQueryInformation (IrpContext);
116 case IRP_MJ_SET_INFORMATION:
117 return VfatSetInformation (IrpContext);
118 case IRP_MJ_DIRECTORY_CONTROL:
119 return VfatDirectoryControl(IrpContext);
120 case IRP_MJ_QUERY_VOLUME_INFORMATION:
121 return VfatQueryVolumeInformation(IrpContext);
122 case IRP_MJ_SET_VOLUME_INFORMATION:
123 return VfatSetVolumeInformation(IrpContext);
124 case IRP_MJ_LOCK_CONTROL:
125 return VfatLockControl(IrpContext);
126 case IRP_MJ_CLEANUP:
127 return VfatCleanup(IrpContext);
128 case IRP_MJ_FLUSH_BUFFERS:
129 return VfatFlush(IrpContext);
130 case IRP_MJ_PNP:
131 return VfatPnp(IrpContext);
132 default:
133 DPRINT1 ("Unexpected major function %x\n", IrpContext->MajorFunction);
134 IrpContext->Irp->IoStatus.Status = STATUS_DRIVER_INTERNAL_ERROR;
135 IoCompleteRequest(IrpContext->Irp, IO_NO_INCREMENT);
136 VfatFreeIrpContext(IrpContext);
137 return STATUS_DRIVER_INTERNAL_ERROR;
138 }
139 }
140
141 NTSTATUS NTAPI VfatBuildRequest (
142 IN PDEVICE_OBJECT DeviceObject,
143 IN PIRP Irp)
144 {
145 NTSTATUS Status;
146 PVFAT_IRP_CONTEXT IrpContext;
147
148 DPRINT ("VfatBuildRequest (DeviceObject %p, Irp %p)\n", DeviceObject, Irp);
149
150 ASSERT(DeviceObject);
151 ASSERT(Irp);
152 IrpContext = VfatAllocateIrpContext(DeviceObject, Irp);
153 if (IrpContext == NULL)
154 {
155 Status = STATUS_INSUFFICIENT_RESOURCES;
156 Irp->IoStatus.Status = Status;
157 IoCompleteRequest (Irp, IO_NO_INCREMENT);
158 }
159 else
160 {
161 FsRtlEnterFileSystem();
162 Status = VfatDispatchRequest (IrpContext);
163 FsRtlExitFileSystem();
164 }
165 return Status;
166 }
167
168 VOID VfatFreeIrpContext (PVFAT_IRP_CONTEXT IrpContext)
169 {
170 ASSERT(IrpContext);
171 ExFreeToNPagedLookasideList(&VfatGlobalData->IrpContextLookasideList, IrpContext);
172 }
173
174 PVFAT_IRP_CONTEXT VfatAllocateIrpContext(PDEVICE_OBJECT DeviceObject, PIRP Irp)
175 {
176 PVFAT_IRP_CONTEXT IrpContext;
177 /*PIO_STACK_LOCATION Stack;*/
178 UCHAR MajorFunction;
179 DPRINT ("VfatAllocateIrpContext(DeviceObject %p, Irp %p)\n", DeviceObject, Irp);
180
181 ASSERT(DeviceObject);
182 ASSERT(Irp);
183
184 IrpContext = ExAllocateFromNPagedLookasideList(&VfatGlobalData->IrpContextLookasideList);
185 if (IrpContext)
186 {
187 RtlZeroMemory(IrpContext, sizeof(VFAT_IRP_CONTEXT));
188 IrpContext->Irp = Irp;
189 IrpContext->DeviceObject = DeviceObject;
190 IrpContext->DeviceExt = DeviceObject->DeviceExtension;
191 IrpContext->Stack = IoGetCurrentIrpStackLocation(Irp);
192 ASSERT(IrpContext->Stack);
193 MajorFunction = IrpContext->MajorFunction = IrpContext->Stack->MajorFunction;
194 IrpContext->MinorFunction = IrpContext->Stack->MinorFunction;
195 IrpContext->FileObject = IrpContext->Stack->FileObject;
196 IrpContext->Flags = 0;
197 if (MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL ||
198 MajorFunction == IRP_MJ_DEVICE_CONTROL ||
199 MajorFunction == IRP_MJ_SHUTDOWN)
200 {
201 IrpContext->Flags |= IRPCONTEXT_CANWAIT;
202 }
203 else if (MajorFunction != IRP_MJ_CLEANUP &&
204 MajorFunction != IRP_MJ_CLOSE &&
205 IoIsOperationSynchronous(Irp))
206 {
207 IrpContext->Flags |= IRPCONTEXT_CANWAIT;
208 }
209 KeInitializeEvent(&IrpContext->Event, NotificationEvent, FALSE);
210 IrpContext->RefCount = 0;
211 }
212 return IrpContext;
213 }
214
215 static VOID NTAPI VfatDoRequest (PVOID IrpContext)
216 {
217 InterlockedDecrement(&QueueCount);
218 DPRINT ("VfatDoRequest (IrpContext %p), MajorFunction %x, %d\n", IrpContext, ((PVFAT_IRP_CONTEXT)IrpContext)->MajorFunction, QueueCount);
219 FsRtlEnterFileSystem();
220 VfatDispatchRequest((PVFAT_IRP_CONTEXT)IrpContext);
221 FsRtlExitFileSystem();
222
223 }
224
225 NTSTATUS VfatQueueRequest(PVFAT_IRP_CONTEXT IrpContext)
226 {
227 InterlockedIncrement(&QueueCount);
228 DPRINT ("VfatQueueRequest (IrpContext %p), %d\n", IrpContext, QueueCount);
229
230 ASSERT(IrpContext != NULL);
231 ASSERT(IrpContext->Irp != NULL);
232
233 IrpContext->Flags |= IRPCONTEXT_CANWAIT;
234 IoMarkIrpPending (IrpContext->Irp);
235 ExInitializeWorkItem (&IrpContext->WorkQueueItem, VfatDoRequest, IrpContext);
236 ExQueueWorkItem(&IrpContext->WorkQueueItem, CriticalWorkQueue);
237 return STATUS_PENDING;
238 }
239
240 PVOID VfatGetUserBuffer(IN PIRP Irp)
241 {
242 ASSERT(Irp);
243
244 if (Irp->MdlAddress)
245 {
246 /* This call may be in the paging path, so use maximum priority */
247 /* FIXME: call with normal priority in the non-paging path */
248 return MmGetSystemAddressForMdlSafe(Irp->MdlAddress, HighPagePriority);
249 }
250 else
251 {
252 return Irp->UserBuffer;
253 }
254 }
255
256 NTSTATUS VfatLockUserBuffer(IN PIRP Irp, IN ULONG Length, IN LOCK_OPERATION Operation)
257 {
258 ASSERT(Irp);
259
260 if (Irp->MdlAddress)
261 {
262 return STATUS_SUCCESS;
263 }
264
265 IoAllocateMdl(Irp->UserBuffer, Length, FALSE, FALSE, Irp);
266
267 if (!Irp->MdlAddress)
268 {
269 return STATUS_INSUFFICIENT_RESOURCES;
270 }
271
272 MmProbeAndLockPages(Irp->MdlAddress, Irp->RequestorMode, Operation);
273
274 return STATUS_SUCCESS;
275 }
276
277