update for HEAD-2003021201
[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 VfatDispatchRequest (
26         IN PVFAT_IRP_CONTEXT IrpContext)
27 {
28    DPRINT ("VfatDispatchRequest (IrpContext %x), MajorFunction %x\n", IrpContext, IrpContext->MajorFunction);
29
30    assert (IrpContext);
31
32    switch (IrpContext->MajorFunction)
33    {
34       case IRP_MJ_CLOSE:
35          return VfatClose (IrpContext);
36       case IRP_MJ_CREATE:
37          return VfatCreate (IrpContext);
38       case IRP_MJ_READ:
39          return VfatRead (IrpContext);
40       case IRP_MJ_WRITE:
41          return VfatWrite (IrpContext);
42       case IRP_MJ_FILE_SYSTEM_CONTROL:
43          return VfatFileSystemControl(IrpContext);
44       case IRP_MJ_QUERY_INFORMATION:
45          return VfatQueryInformation (IrpContext);
46       case IRP_MJ_SET_INFORMATION:
47          return VfatSetInformation (IrpContext);
48       case IRP_MJ_DIRECTORY_CONTROL:
49          return VfatDirectoryControl(IrpContext);
50       case IRP_MJ_QUERY_VOLUME_INFORMATION:
51          return VfatQueryVolumeInformation(IrpContext);
52       case IRP_MJ_SET_VOLUME_INFORMATION:
53          return VfatSetVolumeInformation(IrpContext);
54       case IRP_MJ_LOCK_CONTROL:
55          return VfatLockControl(IrpContext);
56       case IRP_MJ_CLEANUP:
57          return VfatCleanup(IrpContext);
58       case IRP_MJ_FLUSH_BUFFERS:
59          return VfatFlush(IrpContext);
60       default:
61          DPRINT1 ("Unexpected major function %x\n", IrpContext->MajorFunction);
62          IrpContext->Irp->IoStatus.Status = STATUS_DRIVER_INTERNAL_ERROR;
63          IoCompleteRequest(IrpContext->Irp, IO_NO_INCREMENT);
64          VfatFreeIrpContext(IrpContext);
65          return STATUS_DRIVER_INTERNAL_ERROR;
66    }
67 }
68
69 NTSTATUS VfatLockControl(
70    IN PVFAT_IRP_CONTEXT IrpContext
71    )
72 {
73    PVFATFCB Fcb;
74    PVFATCCB Ccb;
75    NTSTATUS Status;
76
77    DPRINT("VfatLockControl(IrpContext %x)\n", IrpContext);
78  
79    assert(IrpContext);
80
81    Ccb = (PVFATCCB)IrpContext->FileObject->FsContext2;
82    Fcb = Ccb->pFcb;
83
84    if (IrpContext->DeviceObject == VfatGlobalData->DeviceObject)
85    {
86       Status = STATUS_INVALID_DEVICE_REQUEST;
87       goto Fail;
88    }
89
90    if (Fcb->entry.Attrib & FILE_ATTRIBUTE_DIRECTORY)
91    {
92       Status = STATUS_INVALID_PARAMETER;
93       goto Fail;
94    }
95
96    Status = FsRtlProcessFileLock(&Fcb->FileLock,
97                                  IrpContext->Irp,
98                                  NULL
99                                  );
100
101    VfatFreeIrpContext(IrpContext);
102    return Status;
103
104 Fail:;
105    IrpContext->Irp->IoStatus.Status = Status;
106    IofCompleteRequest(IrpContext->Irp, NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT);
107    VfatFreeIrpContext(IrpContext);
108    return Status;
109 }
110
111 NTSTATUS STDCALL VfatBuildRequest (
112         IN PDEVICE_OBJECT DeviceObject,
113         IN PIRP Irp)
114 {
115    NTSTATUS Status;
116    PVFAT_IRP_CONTEXT IrpContext;
117
118    DPRINT ("VfatBuildRequest (DeviceObject %x, Irp %x)\n", DeviceObject, Irp);
119
120    assert (DeviceObject);
121    assert (Irp);
122
123    FsRtlEnterFileSystem();
124    IrpContext = VfatAllocateIrpContext(DeviceObject, Irp);
125    if (IrpContext == NULL)
126    {
127       Status = STATUS_INSUFFICIENT_RESOURCES;
128       Irp->IoStatus.Status = Status;
129       IoCompleteRequest (Irp, IO_NO_INCREMENT);
130    }
131    else
132    {
133       Status = VfatDispatchRequest (IrpContext);
134    }
135    FsRtlExitFileSystem();
136    return Status;
137 }
138
139 VOID VfatFreeIrpContext (PVFAT_IRP_CONTEXT IrpContext)
140 {
141    assert (IrpContext);
142    ExFreeToNPagedLookasideList(&VfatGlobalData->IrpContextLookasideList, IrpContext);
143 }
144
145 PVFAT_IRP_CONTEXT VfatAllocateIrpContext(PDEVICE_OBJECT DeviceObject, PIRP Irp)
146 {
147    PVFAT_IRP_CONTEXT IrpContext;
148    PIO_STACK_LOCATION Stack;
149    UCHAR MajorFunction;
150    DPRINT ("VfatAllocateIrpContext(DeviceObject %x, Irp %x)\n", DeviceObject, Irp);
151
152    assert (DeviceObject);
153    assert (Irp);
154
155    IrpContext = ExAllocateFromNPagedLookasideList(&VfatGlobalData->IrpContextLookasideList);
156    if (IrpContext)
157    {
158       RtlZeroMemory(IrpContext, sizeof(IrpContext));
159       IrpContext->Irp = Irp;
160       IrpContext->DeviceObject = DeviceObject;
161       IrpContext->DeviceExt = DeviceObject->DeviceExtension;
162       IrpContext->Stack = IoGetCurrentIrpStackLocation(Irp);
163       assert (IrpContext->Stack);
164       MajorFunction = IrpContext->MajorFunction = IrpContext->Stack->MajorFunction;
165       IrpContext->MinorFunction = IrpContext->Stack->MinorFunction;
166       IrpContext->FileObject = IrpContext->Stack->FileObject;
167       if (MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL ||
168           MajorFunction == IRP_MJ_DEVICE_CONTROL ||
169           MajorFunction == IRP_MJ_SHUTDOWN)
170       {
171          IrpContext->Flags |= IRPCONTEXT_CANWAIT;
172       }
173       else if (MajorFunction != IRP_MJ_CLEANUP &&
174                MajorFunction != IRP_MJ_CLOSE &&
175                IoIsOperationSynchronous(Irp))
176       {
177          IrpContext->Flags |= IRPCONTEXT_CANWAIT;
178       }
179    }
180    return IrpContext;
181 }
182
183 VOID STDCALL VfatDoRequest (PVOID IrpContext)
184 {
185    ULONG Count = InterlockedDecrement(&QueueCount);
186    DPRINT ("VfatDoRequest (IrpContext %x), MajorFunction %x, %d\n", IrpContext, ((PVFAT_IRP_CONTEXT)IrpContext)->MajorFunction, Count);
187    VfatDispatchRequest((PVFAT_IRP_CONTEXT)IrpContext);
188
189 }
190
191 NTSTATUS VfatQueueRequest(PVFAT_IRP_CONTEXT IrpContext)
192 {
193    ULONG Count = InterlockedIncrement(&QueueCount);
194    DPRINT ("VfatQueueRequest (IrpContext %x), %d\n", IrpContext, Count);
195
196    assert (IrpContext != NULL);
197    assert (IrpContext->Irp != NULL);
198
199    IrpContext->Flags |= IRPCONTEXT_CANWAIT;
200    IoMarkIrpPending (IrpContext->Irp);
201    ExInitializeWorkItem (&IrpContext->WorkQueueItem, VfatDoRequest, IrpContext);
202    ExQueueWorkItem(&IrpContext->WorkQueueItem, CriticalWorkQueue);
203    return STATUS_PENDING;
204 }
205
206 PVOID VfatGetUserBuffer(IN PIRP Irp)
207 {
208    assert(Irp);
209
210    if (Irp->MdlAddress)
211    {
212       return MmGetSystemAddressForMdl(Irp->MdlAddress);
213    }
214    else
215    {
216       return Irp->UserBuffer;
217    }
218 }
219
220 NTSTATUS VfatLockUserBuffer(IN PIRP Irp, IN ULONG Length, IN LOCK_OPERATION Operation)
221 {
222    assert(Irp);
223
224    if (Irp->MdlAddress)
225    {
226       return STATUS_SUCCESS;
227    }
228
229    IoAllocateMdl(Irp->UserBuffer, Length, FALSE, FALSE, Irp);
230
231    if (!Irp->MdlAddress)
232    {
233       return STATUS_INSUFFICIENT_RESOURCES;
234    }
235
236    MmProbeAndLockPages(Irp->MdlAddress, Irp->RequestorMode, Operation);
237
238    return STATUS_SUCCESS;
239 }
240
241