:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[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_CLEANUP:
55          return VfatCleanup(IrpContext);
56       default:
57          DPRINT1 ("Unexpected major function %x\n", IrpContext->MajorFunction);
58          IrpContext->Irp->IoStatus.Status = STATUS_DRIVER_INTERNAL_ERROR;
59          IoCompleteRequest(IrpContext->Irp, IO_NO_INCREMENT);
60          VfatFreeIrpContext(IrpContext);
61          return STATUS_DRIVER_INTERNAL_ERROR;
62    }
63 }
64
65
66 NTSTATUS STDCALL VfatBuildRequest (
67         IN PDEVICE_OBJECT DeviceObject,
68         IN PIRP Irp)
69 {
70    NTSTATUS Status;
71    PVFAT_IRP_CONTEXT IrpContext;
72
73    DPRINT ("VfatBuildRequest (DeviceObject %x, Irp %x)\n", DeviceObject, Irp);
74
75    assert (DeviceObject);
76    assert (Irp);
77
78    FsRtlEnterFileSystem();
79    IrpContext = VfatAllocateIrpContext(DeviceObject, Irp);
80    if (IrpContext == NULL)
81    {
82       Status = STATUS_INSUFFICIENT_RESOURCES;
83       Irp->IoStatus.Status = Status;
84       IoCompleteRequest (Irp, IO_NO_INCREMENT);
85    }
86    else
87    {
88       Status = VfatDispatchRequest (IrpContext);
89    }
90    FsRtlExitFileSystem();
91    return Status;
92 }
93
94 VOID VfatFreeIrpContext (PVFAT_IRP_CONTEXT IrpContext)
95 {
96    assert (IrpContext);
97    ExFreePool(IrpContext);
98 }
99
100 PVFAT_IRP_CONTEXT VfatAllocateIrpContext(PDEVICE_OBJECT DeviceObject, PIRP Irp)
101 {
102    PVFAT_IRP_CONTEXT IrpContext;
103    PIO_STACK_LOCATION Stack;
104    UCHAR MajorFunction;
105    DPRINT ("VfatAllocateIrpContext(DeviceObject %x, Irp %x)\n", DeviceObject, Irp);
106
107    assert (DeviceObject);
108    assert (Irp);
109
110    IrpContext = ExAllocatePool (NonPagedPool, sizeof(VFAT_IRP_CONTEXT));
111    if (IrpContext)
112    {
113       RtlZeroMemory(IrpContext, sizeof(IrpContext));
114       IrpContext->Irp = Irp;
115       IrpContext->DeviceObject = DeviceObject;
116       IrpContext->DeviceExt = DeviceObject->DeviceExtension;
117       IrpContext->Stack = IoGetCurrentIrpStackLocation(Irp);
118       assert (IrpContext->Stack);
119       MajorFunction = IrpContext->MajorFunction = IrpContext->Stack->MajorFunction;
120       IrpContext->MinorFunction = IrpContext->Stack->MinorFunction;
121       IrpContext->FileObject = IrpContext->Stack->FileObject;
122       if (MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL ||
123           MajorFunction == IRP_MJ_DEVICE_CONTROL ||
124           MajorFunction == IRP_MJ_SHUTDOWN)
125       {
126          IrpContext->Flags |= IRPCONTEXT_CANWAIT;
127       }
128       else if (MajorFunction != IRP_MJ_CLEANUP &&
129                MajorFunction != IRP_MJ_CLOSE &&
130                IoIsOperationSynchronous(Irp))
131       {
132          IrpContext->Flags |= IRPCONTEXT_CANWAIT;
133       }
134    }
135    return IrpContext;
136 }
137
138 VOID STDCALL VfatDoRequest (PVOID IrpContext)
139 {
140    ULONG Count = InterlockedDecrement(&QueueCount);
141    DPRINT ("VfatDoRequest (IrpContext %x), MajorFunction %x, %d\n", IrpContext, ((PVFAT_IRP_CONTEXT)IrpContext)->MajorFunction, Count);
142    VfatDispatchRequest((PVFAT_IRP_CONTEXT)IrpContext);
143
144 }
145
146 NTSTATUS VfatQueueRequest(PVFAT_IRP_CONTEXT IrpContext)
147 {
148    ULONG Count = InterlockedIncrement(&QueueCount);
149    DPRINT ("VfatQueueRequest (IrpContext %x), %d\n", IrpContext, Count);
150
151    assert (IrpContext != NULL);
152    assert (IrpContext->Irp != NULL);
153
154    IrpContext->Flags |= IRPCONTEXT_CANWAIT;
155    IoMarkIrpPending (IrpContext->Irp);
156    ExInitializeWorkItem (&IrpContext->WorkQueueItem, VfatDoRequest, IrpContext);
157    ExQueueWorkItem(&IrpContext->WorkQueueItem, CriticalWorkQueue);
158    return STATUS_PENDING;
159 }
160
161 PVOID VfatGetUserBuffer(IN PIRP Irp)
162 {
163    assert(Irp);
164
165    if (Irp->MdlAddress)
166    {
167       return MmGetSystemAddressForMdl(Irp->MdlAddress);
168    }
169    else
170    {
171       return Irp->UserBuffer;
172    }
173 }
174
175 NTSTATUS VfatLockUserBuffer(IN PIRP Irp, IN ULONG Length, IN LOCK_OPERATION Operation)
176 {
177    assert(Irp);
178
179    if (Irp->MdlAddress)
180    {
181       return STATUS_SUCCESS;
182    }
183
184    IoAllocateMdl(Irp->UserBuffer, Length, FALSE, FALSE, Irp);
185
186    if (!Irp->MdlAddress)
187    {
188       return STATUS_INSUFFICIENT_RESOURCES;
189    }
190
191    MmProbeAndLockPages(Irp->MdlAddress, Irp->RequestorMode, Operation);
192
193    return STATUS_SUCCESS;
194 }
195
196