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