090e5eea7e8acbc5f9837df075c83cf47fb9b953
[reactos.git] / reactos / drivers / filesystems / fastfat_new / create.c
1 /*
2 * PROJECT: ReactOS FAT file system driver
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: drivers/filesystems/fastfat/create.c
5 * PURPOSE: Create routines
6 * PROGRAMMERS: Aleksey Bragin (aleksey@reactos.org)
7 */
8
9 /* INCLUDES *****************************************************************/
10
11 #define NDEBUG
12 #include "fastfat.h"
13
14 /* FUNCTIONS *****************************************************************/
15
16 IO_STATUS_BLOCK
17 NTAPI
18 FatiOpenRootDcb(IN PFAT_IRP_CONTEXT IrpContext,
19 IN PFILE_OBJECT FileObject,
20 IN PVCB Vcb,
21 IN PACCESS_MASK DesiredAccess,
22 IN USHORT ShareAccess,
23 IN ULONG CreateDisposition)
24 {
25 IO_STATUS_BLOCK Iosb;
26
27 DPRINT1("Opening root directory\n");
28
29 Iosb.Status = STATUS_NOT_IMPLEMENTED;
30
31 return Iosb;
32 }
33
34 NTSTATUS
35 NTAPI
36 FatiCreate(IN PFAT_IRP_CONTEXT IrpContext,
37 IN PIRP Irp)
38 {
39 /* Boolean options */
40 BOOLEAN CreateDirectory;
41 BOOLEAN SequentialOnly;
42 BOOLEAN NoIntermediateBuffering;
43 BOOLEAN OpenDirectory;
44 BOOLEAN IsPagingFile;
45 BOOLEAN OpenTargetDirectory;
46 BOOLEAN DirectoryFile;
47 BOOLEAN NonDirectoryFile;
48 BOOLEAN NoEaKnowledge;
49 BOOLEAN DeleteOnClose;
50 BOOLEAN TemporaryFile;
51 ULONG CreateDisposition;
52
53 /* Control blocks */
54 PVCB Vcb, DecodedVcb;
55 PFCB Fcb;
56 PCCB Ccb;
57 PFCB ParentDcb;
58
59 /* IRP data */
60 PFILE_OBJECT FileObject;
61 PFILE_OBJECT RelatedFO;
62 UNICODE_STRING FileName;
63 ULONG AllocationSize;
64 PFILE_FULL_EA_INFORMATION EaBuffer;
65 PACCESS_MASK DesiredAccess;
66 ULONG Options;
67 UCHAR FileAttributes;
68 USHORT ShareAccess;
69 ULONG EaLength;
70
71 /* Misc */
72 NTSTATUS Status;
73 IO_STATUS_BLOCK Iosb;
74 PIO_STACK_LOCATION IrpSp;
75
76 /* Get current IRP stack location */
77 IrpSp = IoGetCurrentIrpStackLocation(Irp);
78
79 DPRINT1("FatCommonCreate\n", 0 );
80 DPRINT1("Irp = %08lx\n", Irp );
81 DPRINT1("\t->Flags = %08lx\n", Irp->Flags );
82 DPRINT1("\t->FileObject = %08lx\n", IrpSp->FileObject );
83 DPRINT1("\t->RelatedFileObject = %08lx\n", IrpSp->FileObject->RelatedFileObject );
84 DPRINT1("\t->FileName = %wZ\n", &IrpSp->FileObject->FileName );
85 DPRINT1("\t->AllocationSize.LowPart = %08lx\n", Irp->Overlay.AllocationSize.LowPart );
86 DPRINT1("\t->AllocationSize.HighPart = %08lx\n", Irp->Overlay.AllocationSize.HighPart );
87 DPRINT1("\t->SystemBuffer = %08lx\n", Irp->AssociatedIrp.SystemBuffer );
88 DPRINT1("\t->DesiredAccess = %08lx\n", IrpSp->Parameters.Create.SecurityContext->DesiredAccess );
89 DPRINT1("\t->Options = %08lx\n", IrpSp->Parameters.Create.Options );
90 DPRINT1("\t->FileAttributes = %04x\n", IrpSp->Parameters.Create.FileAttributes );
91 DPRINT1("\t->ShareAccess = %04x\n", IrpSp->Parameters.Create.ShareAccess );
92 DPRINT1("\t->EaLength = %08lx\n", IrpSp->Parameters.Create.EaLength );
93
94 /* Apply a special hack for Win32, idea taken from FASTFAT reference driver from WDK */
95 if ((IrpSp->FileObject->FileName.Length > sizeof(WCHAR)) &&
96 (IrpSp->FileObject->FileName.Buffer[1] == L'\\') &&
97 (IrpSp->FileObject->FileName.Buffer[0] == L'\\'))
98 {
99 /* Remove a leading slash */
100 IrpSp->FileObject->FileName.Length -= sizeof(WCHAR);
101 RtlMoveMemory(&IrpSp->FileObject->FileName.Buffer[0],
102 &IrpSp->FileObject->FileName.Buffer[1],
103 IrpSp->FileObject->FileName.Length );
104
105 /* Check again: if there are still two leading slashes,
106 exit with an error */
107 if ((IrpSp->FileObject->FileName.Length > sizeof(WCHAR)) &&
108 (IrpSp->FileObject->FileName.Buffer[1] == L'\\') &&
109 (IrpSp->FileObject->FileName.Buffer[0] == L'\\'))
110 {
111 FatCompleteRequest( IrpContext, Irp, STATUS_OBJECT_NAME_INVALID );
112
113 DPRINT1("FatiCreate: STATUS_OBJECT_NAME_INVALID\n");
114 return STATUS_OBJECT_NAME_INVALID;
115 }
116 }
117
118 /* Make sure we have SecurityContext */
119 ASSERT(IrpSp->Parameters.Create.SecurityContext != NULL);
120
121 /* Get necessary data out of IRP */
122 FileObject = IrpSp->FileObject;
123 FileName = FileObject->FileName;
124 RelatedFO = FileObject->RelatedFileObject;
125 AllocationSize = Irp->Overlay.AllocationSize.LowPart;
126 EaBuffer = Irp->AssociatedIrp.SystemBuffer;
127 DesiredAccess = &IrpSp->Parameters.Create.SecurityContext->DesiredAccess;
128 Options = IrpSp->Parameters.Create.Options;
129 FileAttributes = (UCHAR)(IrpSp->Parameters.Create.FileAttributes & ~FILE_ATTRIBUTE_NORMAL);
130 ShareAccess = IrpSp->Parameters.Create.ShareAccess;
131 EaLength = IrpSp->Parameters.Create.EaLength;
132
133 /* Set VPB to related object's VPB if it exists */
134 if (RelatedFO)
135 FileObject->Vpb = RelatedFO->Vpb;
136
137 /* Prepare file attributes mask */
138 FileAttributes &= (FILE_ATTRIBUTE_READONLY |
139 FILE_ATTRIBUTE_HIDDEN |
140 FILE_ATTRIBUTE_SYSTEM |
141 FILE_ATTRIBUTE_ARCHIVE);
142
143 /* Get the volume control object */
144 Vcb = &((PVOLUME_DEVICE_OBJECT)IrpSp->DeviceObject)->Vcb;
145
146 /* Get options */
147 DirectoryFile = BooleanFlagOn(Options, FILE_DIRECTORY_FILE);
148 NonDirectoryFile = BooleanFlagOn(Options, FILE_NON_DIRECTORY_FILE);
149 SequentialOnly = BooleanFlagOn(Options, FILE_SEQUENTIAL_ONLY);
150 NoIntermediateBuffering = BooleanFlagOn(Options, FILE_NO_INTERMEDIATE_BUFFERING);
151 NoEaKnowledge = BooleanFlagOn(Options, FILE_NO_EA_KNOWLEDGE);
152 DeleteOnClose = BooleanFlagOn(Options, FILE_DELETE_ON_CLOSE);
153 TemporaryFile = BooleanFlagOn(IrpSp->Parameters.Create.FileAttributes,
154 FILE_ATTRIBUTE_TEMPORARY );
155 IsPagingFile = BooleanFlagOn(IrpSp->Flags, SL_OPEN_PAGING_FILE);
156 OpenTargetDirectory = BooleanFlagOn(IrpSp->Flags, SL_OPEN_TARGET_DIRECTORY);
157
158 /* Calculate create disposition */
159 CreateDisposition = (Options >> 24) & 0x000000ff;
160
161 /* Get Create/Open directory flags based on it */
162 CreateDirectory = (BOOLEAN)(DirectoryFile &&
163 ((CreateDisposition == FILE_CREATE) ||
164 (CreateDisposition == FILE_OPEN_IF)));
165
166 OpenDirectory = (BOOLEAN)(DirectoryFile &&
167 ((CreateDisposition == FILE_OPEN) ||
168 (CreateDisposition == FILE_OPEN_IF)));
169
170 /* Validate parameters: directory/nondirectory mismatch and
171 AllocationSize being more than 4GB */
172 if ((DirectoryFile && NonDirectoryFile) ||
173 Irp->Overlay.AllocationSize.HighPart != 0)
174 {
175 FatCompleteRequest(IrpContext, Irp, STATUS_INVALID_PARAMETER);
176
177 DPRINT1("FatiCreate: STATUS_INVALID_PARAMETER\n", 0);
178 return STATUS_INVALID_PARAMETER;
179 }
180
181 /* Acquire the VCB lock exclusively */
182 if (!FatAcquireExclusiveVcb(IrpContext, Vcb))
183 {
184 // TODO: Postpone the IRP for later processing
185 ASSERT(FALSE);
186 return STATUS_NOT_IMPLEMENTED;
187 }
188
189 // TODO: Verify the VCB
190
191 /* If VCB is locked, then no file openings are possible */
192 if (Vcb->State & VCB_STATE_FLAG_LOCKED)
193 {
194 DPRINT1("This volume is locked\n");
195 Status = STATUS_ACCESS_DENIED;
196
197 /* Cleanup and return */
198 FatReleaseVcb(IrpContext, Vcb);
199 return Status;
200 }
201
202 // TODO: Check if the volume is write protected and disallow DELETE_ON_CLOSE
203
204 // TODO: Make sure EAs aren't supported on FAT32
205
206 /* Check if it's a volume open request */
207 if (FileName.Length == 0)
208 {
209 /* Test related FO to be sure */
210 if (!RelatedFO ||
211 FatDecodeFileObject(RelatedFO, &DecodedVcb, &Fcb, &Ccb) == UserVolumeOpen)
212 {
213 /* It is indeed a volume open request */
214 DPRINT1("Volume open request, not implemented now!\n");
215 UNIMPLEMENTED;
216 }
217 }
218
219 /* Check if this is a relative open */
220 if (RelatedFO)
221 {
222 // RelatedFO will be a parent directory
223 UNIMPLEMENTED;
224 }
225 else
226 {
227 /* Absolute open */
228 if ((FileName.Length == sizeof(WCHAR)) &&
229 (FileName.Buffer[0] == L'\\'))
230 {
231 /* Check if it's ok to open it */
232 if (NonDirectoryFile)
233 {
234 DPRINT1("Trying to open root dir as a file\n");
235
236 /* Cleanup and return */
237 FatReleaseVcb(IrpContext, Vcb);
238 return STATUS_FILE_IS_A_DIRECTORY;
239 }
240
241 /* Check delete on close on a root dir */
242 if (DeleteOnClose)
243 {
244 /* Cleanup and return */
245 FatReleaseVcb(IrpContext, Vcb);
246 return STATUS_CANNOT_DELETE;
247 }
248
249 /* Call root directory open routine */
250 Iosb = FatiOpenRootDcb(IrpContext,
251 FileObject,
252 Vcb,
253 DesiredAccess,
254 ShareAccess,
255 CreateDisposition);
256
257 Irp->IoStatus.Information = Iosb.Information;
258
259 /* Cleanup and return */
260 FatReleaseVcb(IrpContext, Vcb);
261 return Iosb.Status;
262 }
263 else
264 {
265 /* Not a root dir */
266 ParentDcb = Vcb->RootDcb;
267 DPRINT1("ParentDcb %p\n", ParentDcb);
268 }
269 }
270
271 //return Iosb.Status;
272 return STATUS_SUCCESS;
273 }
274
275 NTSTATUS
276 NTAPI
277 FatCreate(PDEVICE_OBJECT DeviceObject, PIRP Irp)
278 {
279 PFAT_IRP_CONTEXT IrpContext;
280 NTSTATUS Status;
281 //PVOLUME_DEVICE_OBJECT VolumeDO = (PVOLUME_DEVICE_OBJECT)DeviceObject;
282
283 DPRINT1("FatCreate()\n");
284
285 /* If it's called with our Disk FS device object - it's always open */
286 // TODO: Add check for CDROM FS device object
287 if (DeviceObject == FatGlobalData.DiskDeviceObject)
288 {
289 /* Complete the request and return success */
290 Irp->IoStatus.Status = STATUS_SUCCESS;
291 Irp->IoStatus.Information = FILE_OPENED;
292
293 IoCompleteRequest(Irp, IO_DISK_INCREMENT);
294
295 return STATUS_SUCCESS;
296 }
297
298 /* Enter FsRtl critical region */
299 FsRtlEnterFileSystem();
300
301 /* Build an irp context */
302 IrpContext = FatBuildIrpContext(Irp, TRUE);
303
304 /* Call internal function */
305 Status = FatiCreate(IrpContext, Irp);
306
307 /* Leave FsRtl critical region */
308 FsRtlExitFileSystem();
309
310 return Status;
311 }
312
313 /* EOF */