- Changed the file names to unicode strings.
[reactos.git] / reactos / drivers / fs / vfat / create.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 /* $Id: create.c,v 1.64 2003/10/11 17:51:56 hbirr Exp $
20 *
21 * PROJECT: ReactOS kernel
22 * FILE: drivers/fs/vfat/create.c
23 * PURPOSE: VFAT Filesystem
24 * PROGRAMMER: Jason Filby (jasonfilby@yahoo.com)
25 * Hartmut Birr
26 */
27
28 /* INCLUDES *****************************************************************/
29
30 #include <ddk/ntddk.h>
31 #include <wchar.h>
32 #include <limits.h>
33
34 #define NDEBUG
35 #include <debug.h>
36
37 #include "vfat.h"
38
39 /* GLOBALS *******************************************************************/
40
41 #define ENTRIES_PER_PAGE (PAGE_SIZE / sizeof (FATDirEntry))
42
43 /* FUNCTIONS *****************************************************************/
44
45 void vfat8Dot3ToString (PFAT_DIR_ENTRY pEntry, PUNICODE_STRING NameU)
46 {
47 OEM_STRING StringA;
48 ULONG Length;
49 CHAR cString[12];
50
51 memcpy(cString, pEntry->Filename, 11);
52 cString[11] = 0;
53 if (cString[0] == 0x05)
54 {
55 cString[0] = 0xe5;
56 }
57
58 StringA.Buffer = cString;
59 for (StringA.Length = 0;
60 StringA.Length < 8 && StringA.Buffer[StringA.Length] != ' ';
61 StringA.Length++);
62 StringA.MaximumLength = StringA.Length;
63
64 RtlOemStringToUnicodeString(NameU, &StringA, FALSE);
65
66 if (pEntry->lCase & VFAT_CASE_LOWER_BASE)
67 {
68 RtlDowncaseUnicodeString(NameU, NameU, FALSE);
69 }
70 if (cString[8] != ' ')
71 {
72 Length = NameU->Length;
73 NameU->Buffer += Length / sizeof(WCHAR);
74 if (!ENTRY_VOLUME(pEntry))
75 {
76 Length += sizeof(WCHAR);
77 NameU->Buffer[0] = L'.';
78 NameU->Buffer++;
79 }
80 NameU->Length = 0;
81 NameU->MaximumLength -= Length;
82
83 StringA.Buffer = &cString[8];
84 for (StringA.Length = 0;
85 StringA.Length < 3 && StringA.Buffer[StringA.Length] != ' ';
86 StringA.Length++);
87 StringA.MaximumLength = StringA.Length;
88 RtlOemStringToUnicodeString(NameU, &StringA, FALSE);
89 if (pEntry->lCase & VFAT_CASE_LOWER_EXT)
90 {
91 RtlDowncaseUnicodeString(NameU, NameU, FALSE);
92 }
93 NameU->Buffer -= Length / sizeof(WCHAR);
94 NameU->Length += Length;
95 NameU->MaximumLength += Length;
96 }
97 NameU->Buffer[NameU->Length / sizeof(WCHAR)] = 0;
98 DPRINT("'%wZ'\n", NameU);
99 }
100
101 NTSTATUS
102 ReadVolumeLabel (PDEVICE_EXTENSION DeviceExt, PVPB Vpb)
103 /*
104 * FUNCTION: Read the volume label
105 */
106 {
107 PVOID Context = NULL;
108 ULONG DirIndex = 0;
109 FATDirEntry* Entry;
110 PVFATFCB pFcb;
111 LARGE_INTEGER FileOffset;
112 UNICODE_STRING NameU;
113
114 NameU.Buffer = Vpb->VolumeLabel;
115 NameU.Length = 0;
116 NameU.MaximumLength = sizeof(Vpb->VolumeLabel);
117 *(Vpb->VolumeLabel) = 0;
118 Vpb->VolumeLabelLength = 0;
119
120 ExAcquireResourceExclusiveLite (&DeviceExt->DirResource, TRUE);
121 pFcb = vfatOpenRootFCB (DeviceExt);
122 ExReleaseResourceLite (&DeviceExt->DirResource);
123
124 FileOffset.QuadPart = 0;
125 if (CcMapData(pFcb->FileObject, &FileOffset, PAGE_SIZE, TRUE, &Context, (PVOID*)&Entry))
126 {
127 while (TRUE)
128 {
129 if (ENTRY_VOLUME(Entry))
130 {
131 /* copy volume label */
132 vfat8Dot3ToString (Entry, &NameU);
133 Vpb->VolumeLabelLength = NameU.Length;
134 break;
135 }
136 if (ENTRY_END(Entry))
137 {
138 break;
139 }
140 DirIndex++;
141 Entry++;
142 if ((DirIndex % ENTRIES_PER_PAGE) == 0)
143 {
144 CcUnpinData(Context);
145 FileOffset.u.LowPart += PAGE_SIZE;
146 if (!CcMapData(pFcb->FileObject, &FileOffset, PAGE_SIZE, TRUE, &Context, (PVOID*)&Entry))
147 {
148 Context = NULL;
149 break;
150 }
151 }
152 }
153 if (Context)
154 {
155 CcUnpinData(Context);
156 }
157 }
158 ExAcquireResourceExclusiveLite (&DeviceExt->DirResource, TRUE);
159 vfatReleaseFCB (DeviceExt, pFcb);
160 ExReleaseResourceLite (&DeviceExt->DirResource);
161
162 return STATUS_SUCCESS;
163 }
164
165 NTSTATUS
166 FindFile (PDEVICE_EXTENSION DeviceExt,
167 PVFATFCB Parent,
168 PUNICODE_STRING FileToFindU,
169 PVFAT_DIRENTRY_CONTEXT DirContext,
170 BOOLEAN First)
171 /*
172 * FUNCTION: Find a file
173 */
174 {
175 WCHAR PathNameBuffer[MAX_PATH];
176 NTSTATUS Status;
177 PVOID Context = NULL;
178 PVOID Page;
179 PVFATFCB rcFcb;
180 BOOLEAN FoundLong;
181 BOOLEAN FoundShort;
182 UNICODE_STRING PathNameU;
183 BOOLEAN WildCard;
184 PWCHAR curr, last;
185
186 DPRINT ("FindFile(Parent %x, FileToFind '%wZ', DirIndex: %d)\n",
187 Parent, FileToFindU, DirContext->DirIndex);
188 DPRINT ("FindFile: Path %wZ)\n",&Parent->PathNameU);
189
190 PathNameU.Buffer = PathNameBuffer;
191 PathNameU.Length = 0;
192 PathNameU.MaximumLength = sizeof(PathNameBuffer);
193
194 DirContext->LongNameU.Length = 0;
195 DirContext->ShortNameU.Length = 0;
196
197 /* FIXME: Use FsRtlDoesNameContainWildCards */
198 WildCard = FALSE;
199 curr = FileToFindU->Buffer;
200 last = FileToFindU->Buffer + FileToFindU->Length / sizeof(WCHAR);
201 while (curr < last)
202 {
203 if (*curr == L'?' || *curr == L'*')
204 {
205 WildCard = TRUE;
206 break;
207 }
208 curr++;
209 }
210
211 if (WildCard == FALSE)
212 {
213 /* if there is no '*?' in the search name, than look first for an existing fcb */
214 RtlCopyUnicodeString(&PathNameU, &Parent->PathNameU);
215 if (!vfatFCBIsRoot(Parent))
216 {
217 PathNameU.Buffer[PathNameU.Length / sizeof(WCHAR)] = L'\\';
218 PathNameU.Length += sizeof(WCHAR);
219 }
220 RtlAppendUnicodeStringToString(&PathNameU, FileToFindU);
221 PathNameU.Buffer[PathNameU.Length / sizeof(WCHAR)] = 0;
222 rcFcb = vfatGrabFCBFromTable(DeviceExt, &PathNameU);
223 if (rcFcb)
224 {
225 if(rcFcb->startIndex >= DirContext->DirIndex)
226 {
227 RtlCopyUnicodeString(&DirContext->LongNameU, &rcFcb->LongNameU);
228 RtlCopyUnicodeString(&DirContext->ShortNameU, &rcFcb->ShortNameU);
229 memcpy(&DirContext->FatDirEntry, &rcFcb->entry, sizeof(FATDirEntry));
230 DirContext->StartIndex = rcFcb->startIndex;
231 DirContext->DirIndex = rcFcb->dirIndex;
232 DPRINT("FindFile: new Name %wZ, DirIndex %d (%d)\n",
233 &DirContext->LongNameU, DirContext->DirIndex, DirContext->StartIndex);
234 Status = STATUS_SUCCESS;
235 }
236 else
237 {
238 CHECKPOINT1;
239 Status = STATUS_UNSUCCESSFUL;
240 }
241 vfatReleaseFCB(DeviceExt, rcFcb);
242 return Status;
243 }
244 }
245
246 while(TRUE)
247 {
248 Status = vfatGetNextDirEntry(&Context, &Page, Parent, DirContext, First);
249 First = FALSE;
250 if (Status == STATUS_NO_MORE_ENTRIES)
251 {
252 break;
253 }
254 if (ENTRY_VOLUME(&DirContext->FatDirEntry))
255 {
256 DirContext->DirIndex++;
257 continue;
258 }
259 DirContext->LongNameU.Buffer[DirContext->LongNameU.Length / sizeof(WCHAR)] = 0;
260 DirContext->ShortNameU.Buffer[DirContext->ShortNameU.Length / sizeof(WCHAR)] = 0;
261 if (WildCard)
262 {
263 /* FIXME: Use FsRtlIsNameInExpression */
264 if (DirContext->LongNameU.Length > 0 &&
265 wstrcmpjoki (DirContext->LongNameU.Buffer, FileToFindU->Buffer))
266 {
267 FoundLong = TRUE;
268 }
269 else
270 {
271 FoundLong = FALSE;
272 }
273 if (FoundLong == FALSE)
274 {
275 /* FIXME: Use FsRtlIsNameInExpression */
276 FoundShort = wstrcmpjoki (DirContext->ShortNameU.Buffer, FileToFindU->Buffer);
277 }
278 else
279 {
280 FoundShort = FALSE;
281 }
282 }
283 else
284 {
285 FoundLong = RtlEqualUnicodeString(&DirContext->LongNameU, FileToFindU, TRUE);
286 if (FoundLong == FALSE)
287 {
288 FoundShort = RtlEqualUnicodeString(&DirContext->ShortNameU, FileToFindU, TRUE);
289 }
290 }
291
292 if (FoundLong || FoundShort)
293 {
294 if (WildCard)
295 {
296 RtlCopyUnicodeString(&PathNameU, &Parent->PathNameU);
297 if (!vfatFCBIsRoot(Parent))
298 {
299 PathNameU.Buffer[PathNameU.Length / sizeof(WCHAR)] = L'\\';
300 PathNameU.Length += sizeof(WCHAR);
301 }
302 RtlAppendUnicodeStringToString(&PathNameU, &DirContext->LongNameU);
303 PathNameU.Buffer[PathNameU.Length / sizeof(WCHAR)] = 0;
304 rcFcb = vfatGrabFCBFromTable(DeviceExt, &PathNameU);
305 if (rcFcb != NULL)
306 {
307 memcpy(&DirContext->FatDirEntry, &rcFcb->entry, sizeof(FATDirEntry));
308 vfatReleaseFCB(DeviceExt, rcFcb);
309 }
310 }
311 DPRINT("%d\n", DirContext->LongNameU.Length);
312 DPRINT("FindFile: new Name %wZ, DirIndex %d\n",
313 &DirContext->LongNameU, DirContext->DirIndex);
314
315 if (Context)
316 {
317 CcUnpinData(Context);
318 }
319 return STATUS_SUCCESS;
320 }
321 DirContext->DirIndex++;
322 }
323
324 if (Context)
325 {
326 CcUnpinData(Context);
327 }
328
329 return Status;
330 }
331
332 NTSTATUS
333 VfatOpenFile (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject,
334 PUNICODE_STRING FileNameU)
335 /*
336 * FUNCTION: Opens a file
337 */
338 {
339 PVFATFCB ParentFcb;
340 PVFATFCB Fcb;
341 NTSTATUS Status;
342 UNICODE_STRING NameU;
343 WCHAR Name[MAX_PATH];
344
345 DPRINT ("VfatOpenFile(%08lx, %08lx, '%wZ')\n", DeviceExt, FileObject, FileNameU);
346
347 if (FileObject->RelatedFileObject)
348 {
349 DPRINT ("Converting relative filename to absolute filename\n");
350
351 NameU.Buffer = Name;
352 NameU.Length = 0;
353 NameU.MaximumLength = sizeof(Name);
354
355 Fcb = FileObject->RelatedFileObject->FsContext;
356 RtlCopyUnicodeString(&NameU, &Fcb->PathNameU);
357 if (!vfatFCBIsRoot(Fcb))
358 {
359 NameU.Buffer[NameU.Length / sizeof(WCHAR)] = L'\\';
360 NameU.Length += sizeof(WCHAR);
361 }
362 RtlAppendUnicodeStringToString(&NameU, FileNameU);
363 NameU.Buffer[NameU.Length / sizeof(WCHAR)] = 0;
364 FileNameU = &NameU;
365 }
366
367 DPRINT ("PathName to open: '%wZ'\n", FileNameU);
368
369 /* try first to find an existing FCB in memory */
370 DPRINT ("Checking for existing FCB in memory\n");
371 Fcb = vfatGrabFCBFromTable (DeviceExt, FileNameU);
372 if (Fcb == NULL)
373 {
374 DPRINT ("No existing FCB found, making a new one if file exists.\n");
375 Status = vfatGetFCBForFile (DeviceExt, &ParentFcb, &Fcb, FileNameU);
376 if (ParentFcb != NULL)
377 {
378 vfatReleaseFCB (DeviceExt, ParentFcb);
379 }
380 if (!NT_SUCCESS (Status))
381 {
382 DPRINT ("Could not make a new FCB, status: %x\n", Status);
383 return Status;
384 }
385 }
386 if (Fcb->Flags & FCB_DELETE_PENDING)
387 {
388 vfatReleaseFCB (DeviceExt, Fcb);
389 return STATUS_DELETE_PENDING;
390 }
391 DPRINT ("Attaching FCB to fileObject\n");
392 Status = vfatAttachFCBToFileObject (DeviceExt, Fcb, FileObject);
393
394 return Status;
395 }
396
397 VOID STATIC
398 VfatSupersedeFile(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject,
399 PVFATFCB Fcb)
400 {
401 ULONG Cluster, NextCluster;
402 NTSTATUS Status;
403
404 Fcb->entry.FileSize = 0;
405 if (DeviceExt->FatInfo.FatType == FAT32)
406 {
407 Cluster = Fcb->entry.FirstCluster + Fcb->entry.FirstClusterHigh * 65536;
408 }
409 else
410 {
411 Cluster = Fcb->entry.FirstCluster;
412 }
413 Fcb->entry.FirstCluster = 0;
414 Fcb->entry.FirstClusterHigh = 0;
415 VfatUpdateEntry (Fcb);
416 if (Fcb->RFCB.FileSize.QuadPart > 0)
417 {
418 Fcb->RFCB.AllocationSize.QuadPart = 0;
419 Fcb->RFCB.FileSize.QuadPart = 0;
420 Fcb->RFCB.ValidDataLength.QuadPart = 0;
421 /* Notify cache manager about the change in file size if caching is
422 initialized on the file stream */
423 if (FileObject->SectionObjectPointer->SharedCacheMap != NULL)
424 {
425 CcSetFileSizes(FileObject, (PCC_FILE_SIZES)&Fcb->RFCB.AllocationSize);
426 }
427 }
428 while (Cluster != 0xffffffff && Cluster > 1)
429 {
430 Status = GetNextCluster (DeviceExt, Cluster, &NextCluster, FALSE);
431 WriteCluster (DeviceExt, Cluster, 0);
432 Cluster = NextCluster;
433 }
434 }
435
436 NTSTATUS
437 VfatCreateFile (PDEVICE_OBJECT DeviceObject, PIRP Irp)
438 /*
439 * FUNCTION: Create or open a file
440 */
441 {
442 PIO_STACK_LOCATION Stack;
443 PFILE_OBJECT FileObject;
444 NTSTATUS Status = STATUS_SUCCESS;
445 PDEVICE_EXTENSION DeviceExt;
446 ULONG RequestedDisposition, RequestedOptions;
447 PVFATCCB pCcb;
448 PVFATFCB pFcb;
449 PWCHAR c;
450 BOOLEAN PagingFileCreate = FALSE;
451 LARGE_INTEGER AllocationSize;
452
453 /* Unpack the various parameters. */
454 Stack = IoGetCurrentIrpStackLocation (Irp);
455 RequestedDisposition = ((Stack->Parameters.Create.Options >> 24) & 0xff);
456 RequestedOptions =
457 Stack->Parameters.Create.Options & FILE_VALID_OPTION_FLAGS;
458 PagingFileCreate = (Stack->Flags & SL_OPEN_PAGING_FILE) ? TRUE : FALSE;
459 FileObject = Stack->FileObject;
460 DeviceExt = DeviceObject->DeviceExtension;
461
462 /* Check their validity. */
463 if (RequestedOptions & FILE_DIRECTORY_FILE &&
464 RequestedDisposition == FILE_SUPERSEDE)
465 {
466 return(STATUS_INVALID_PARAMETER);
467 }
468
469 /* This a open operation for the volume itself */
470 if (FileObject->FileName.Length == 0 &&
471 FileObject->RelatedFileObject == NULL)
472 {
473 if (RequestedDisposition == FILE_CREATE ||
474 RequestedDisposition == FILE_OVERWRITE_IF ||
475 RequestedDisposition == FILE_SUPERSEDE)
476 {
477 return(STATUS_ACCESS_DENIED);
478 }
479 if (RequestedOptions & FILE_DIRECTORY_FILE)
480 {
481 return(STATUS_NOT_A_DIRECTORY);
482 }
483 pFcb = DeviceExt->VolumeFcb;
484 pCcb = ExAllocateFromNPagedLookasideList(&VfatGlobalData->CcbLookasideList);
485 if (pCcb == NULL)
486 {
487 return (STATUS_INSUFFICIENT_RESOURCES);
488 }
489 memset(pCcb, 0, sizeof(VFATCCB));
490 FileObject->Flags |= FO_FCB_IS_VALID;
491 FileObject->SectionObjectPointer = &pFcb->SectionObjectPointers;
492 FileObject->FsContext = pFcb;
493 FileObject->FsContext2 = pCcb;
494 pFcb->RefCount++;
495
496 Irp->IoStatus.Information = FILE_OPENED;
497 return(STATUS_SUCCESS);
498 }
499
500 /*
501 * Check for illegal characters in the file name
502 */
503 c = FileObject->FileName.Buffer + FileObject->FileName.Length / sizeof(WCHAR);
504 while (c-- > FileObject->FileName.Buffer)
505 {
506 if (*c != '\\' && vfatIsLongIllegal(*c))
507 {
508 return(STATUS_OBJECT_NAME_INVALID);
509 }
510 }
511
512 /* Try opening the file. */
513 Status = VfatOpenFile (DeviceExt, FileObject, &FileObject->FileName);
514
515 /*
516 * If the directory containing the file to open doesn't exist then
517 * fail immediately
518 */
519 if (Status == STATUS_OBJECT_PATH_NOT_FOUND ||
520 Status == STATUS_INVALID_PARAMETER ||
521 Status == STATUS_DELETE_PENDING)
522 {
523 return(Status);
524 }
525
526 /*
527 * If the file open failed then create the required file
528 */
529 if (!NT_SUCCESS (Status))
530 {
531 if (RequestedDisposition == FILE_CREATE ||
532 RequestedDisposition == FILE_OPEN_IF ||
533 RequestedDisposition == FILE_OVERWRITE_IF ||
534 RequestedDisposition == FILE_SUPERSEDE)
535 {
536 ULONG Attributes;
537 Attributes = Stack->Parameters.Create.FileAttributes;
538 Status = VfatAddEntry (DeviceExt, &FileObject->FileName, FileObject, RequestedOptions,
539 (UCHAR)(Attributes & FILE_ATTRIBUTE_VALID_FLAGS));
540 if (NT_SUCCESS (Status))
541 {
542 pFcb = FileObject->FsContext;
543 Irp->IoStatus.Information = FILE_CREATED;
544 VfatSetAllocationSizeInformation(FileObject,
545 pFcb,
546 DeviceExt,
547 &Irp->Overlay.AllocationSize);
548 VfatSetExtendedAttributes(FileObject,
549 Irp->AssociatedIrp.SystemBuffer,
550 Stack->Parameters.Create.EaLength);
551 IoSetShareAccess(0 /*DesiredAccess*/,
552 Stack->Parameters.Create.ShareAccess,
553 FileObject,
554 &pFcb->FCBShareAccess);
555
556 if (PagingFileCreate)
557 {
558 pFcb->Flags |= FCB_IS_PAGE_FILE;
559 }
560 }
561 else
562 {
563 return(Status);
564 }
565 }
566 else
567 {
568 return(Status);
569 }
570 }
571 else
572 {
573 /* Otherwise fail if the caller wanted to create a new file */
574 if (RequestedDisposition == FILE_CREATE)
575 {
576 Irp->IoStatus.Information = FILE_EXISTS;
577 VfatCloseFile (DeviceExt, FileObject);
578 return(STATUS_OBJECT_NAME_COLLISION);
579 }
580
581 pFcb = FileObject->FsContext;
582
583 /*
584 * Check the file has the requested attributes
585 */
586 if (RequestedOptions & FILE_NON_DIRECTORY_FILE &&
587 pFcb->entry.Attrib & FILE_ATTRIBUTE_DIRECTORY)
588 {
589 VfatCloseFile (DeviceExt, FileObject);
590 return(STATUS_FILE_IS_A_DIRECTORY);
591 }
592 if (RequestedOptions & FILE_DIRECTORY_FILE &&
593 !(pFcb->entry.Attrib & FILE_ATTRIBUTE_DIRECTORY))
594 {
595 VfatCloseFile (DeviceExt, FileObject);
596 return(STATUS_NOT_A_DIRECTORY);
597 }
598
599 if (PagingFileCreate)
600 {
601 /* FIXME:
602 * Do more checking for page files. It is possible,
603 * that the file was opened and closed previously
604 * as a normal cached file. In this case, the cache
605 * manager has referenced the fileobject and the fcb
606 * is held in memory. Try to remove the fileobject
607 * from cache manager and use the fcb.
608 */
609 if (pFcb->RefCount > 1)
610 {
611 if(!(pFcb->Flags & FCB_IS_PAGE_FILE))
612 {
613 VfatCloseFile(DeviceExt, FileObject);
614 return(STATUS_INVALID_PARAMETER);
615 }
616 }
617 else
618 {
619 pFcb->Flags |= FCB_IS_PAGE_FILE;
620 }
621 }
622 else
623 {
624 if (pFcb->Flags & FCB_IS_PAGE_FILE)
625 {
626 VfatCloseFile(DeviceExt, FileObject);
627 return(STATUS_INVALID_PARAMETER);
628 }
629 }
630
631
632 if (RequestedDisposition == FILE_OVERWRITE ||
633 RequestedDisposition == FILE_OVERWRITE_IF)
634 {
635 AllocationSize.QuadPart = 0;
636 Status = VfatSetAllocationSizeInformation (FileObject,
637 pFcb,
638 DeviceExt,
639 &AllocationSize);
640 if (!NT_SUCCESS (Status))
641 {
642 VfatCloseFile (DeviceExt, FileObject);
643 return(Status);
644 }
645 }
646
647
648 /* Supersede the file */
649 if (RequestedDisposition == FILE_SUPERSEDE)
650 {
651 VfatSupersedeFile(DeviceExt, FileObject, pFcb);
652 Irp->IoStatus.Information = FILE_SUPERSEDED;
653 }
654 else
655 {
656 Irp->IoStatus.Information = FILE_OPENED;
657 }
658 }
659
660 /* FIXME : test share access */
661 /* FIXME : test write access if requested */
662
663 return(Status);
664 }
665
666
667 NTSTATUS VfatCreate (PVFAT_IRP_CONTEXT IrpContext)
668 /*
669 * FUNCTION: Create or open a file
670 */
671 {
672 NTSTATUS Status;
673
674 assert (IrpContext);
675
676 if (IrpContext->DeviceObject == VfatGlobalData->DeviceObject)
677 {
678 /* DeviceObject represents FileSystem instead of logical volume */
679 DPRINT ("FsdCreate called with file system\n");
680 IrpContext->Irp->IoStatus.Information = FILE_OPENED;
681 IrpContext->Irp->IoStatus.Status = STATUS_SUCCESS;
682 IoCompleteRequest (IrpContext->Irp, IO_DISK_INCREMENT);
683 VfatFreeIrpContext(IrpContext);
684 return(STATUS_SUCCESS);
685 }
686
687 if (!(IrpContext->Flags & IRPCONTEXT_CANWAIT))
688 {
689 return(VfatQueueRequest (IrpContext));
690 }
691
692 IrpContext->Irp->IoStatus.Information = 0;
693 ExAcquireResourceExclusiveLite (&IrpContext->DeviceExt->DirResource, TRUE);
694 Status = VfatCreateFile (IrpContext->DeviceObject, IrpContext->Irp);
695 ExReleaseResourceLite (&IrpContext->DeviceExt->DirResource);
696
697 IrpContext->Irp->IoStatus.Status = Status;
698 IoCompleteRequest (IrpContext->Irp,
699 (CCHAR)(NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT));
700 VfatFreeIrpContext(IrpContext);
701 return(Status);
702 }
703
704 /* EOF */