Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygencreate.c
Go to the documentation of this file.
00001 /* 00002 * ReactOS kernel 00003 * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License as published by 00007 * the Free Software Foundation; either version 2 of the License, or 00008 * (at your option) any later version. 00009 * 00010 * This program is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 * GNU General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU General Public License along 00016 * with this program; if not, write to the Free Software Foundation, Inc., 00017 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 00018 */ 00019 /* 00020 * PROJECT: ReactOS kernel 00021 * FILE: drivers/fs/vfat/create.c 00022 * PURPOSE: VFAT Filesystem 00023 * PROGRAMMER: Jason Filby (jasonfilby@yahoo.com) 00024 */ 00025 00026 /* INCLUDES *****************************************************************/ 00027 00028 #define NDEBUG 00029 #include "vfat.h" 00030 00031 /* FUNCTIONS *****************************************************************/ 00032 00033 void 00034 vfat8Dot3ToString (PFAT_DIR_ENTRY pEntry, PUNICODE_STRING NameU) 00035 { 00036 OEM_STRING StringA; 00037 USHORT Length; 00038 CHAR cString[12]; 00039 00040 RtlCopyMemory(cString, pEntry->ShortName, 11); 00041 cString[11] = 0; 00042 if (cString[0] == 0x05) 00043 { 00044 cString[0] = 0xe5; 00045 } 00046 00047 StringA.Buffer = cString; 00048 for (StringA.Length = 0; 00049 StringA.Length < 8 && StringA.Buffer[StringA.Length] != ' '; 00050 StringA.Length++); 00051 StringA.MaximumLength = StringA.Length; 00052 00053 RtlOemStringToUnicodeString(NameU, &StringA, FALSE); 00054 00055 if (pEntry->lCase & VFAT_CASE_LOWER_BASE) 00056 { 00057 RtlDowncaseUnicodeString(NameU, NameU, FALSE); 00058 } 00059 if (cString[8] != ' ') 00060 { 00061 Length = NameU->Length; 00062 NameU->Buffer += Length / sizeof(WCHAR); 00063 if (!FAT_ENTRY_VOLUME(pEntry)) 00064 { 00065 Length += sizeof(WCHAR); 00066 NameU->Buffer[0] = L'.'; 00067 NameU->Buffer++; 00068 } 00069 NameU->Length = 0; 00070 NameU->MaximumLength -= Length; 00071 00072 StringA.Buffer = &cString[8]; 00073 for (StringA.Length = 0; 00074 StringA.Length < 3 && StringA.Buffer[StringA.Length] != ' '; 00075 StringA.Length++); 00076 StringA.MaximumLength = StringA.Length; 00077 RtlOemStringToUnicodeString(NameU, &StringA, FALSE); 00078 if (pEntry->lCase & VFAT_CASE_LOWER_EXT) 00079 { 00080 RtlDowncaseUnicodeString(NameU, NameU, FALSE); 00081 } 00082 NameU->Buffer -= Length / sizeof(WCHAR); 00083 NameU->Length += Length; 00084 NameU->MaximumLength += Length; 00085 } 00086 NameU->Buffer[NameU->Length / sizeof(WCHAR)] = 0; 00087 DPRINT("'%wZ'\n", NameU); 00088 } 00089 00090 NTSTATUS 00091 ReadVolumeLabel (PDEVICE_EXTENSION DeviceExt, PVPB Vpb) 00092 /* 00093 * FUNCTION: Read the volume label 00094 */ 00095 { 00096 PVOID Context = NULL; 00097 ULONG DirIndex = 0; 00098 PDIR_ENTRY Entry; 00099 PVFATFCB pFcb; 00100 LARGE_INTEGER FileOffset; 00101 UNICODE_STRING NameU; 00102 ULONG SizeDirEntry; 00103 ULONG EntriesPerPage; 00104 OEM_STRING StringO; 00105 00106 NameU.Buffer = Vpb->VolumeLabel; 00107 NameU.Length = 0; 00108 NameU.MaximumLength = sizeof(Vpb->VolumeLabel); 00109 *(Vpb->VolumeLabel) = 0; 00110 Vpb->VolumeLabelLength = 0; 00111 00112 if (DeviceExt->Flags & VCB_IS_FATX) 00113 { 00114 SizeDirEntry = sizeof(FATX_DIR_ENTRY); 00115 EntriesPerPage = FATX_ENTRIES_PER_PAGE; 00116 } 00117 else 00118 { 00119 SizeDirEntry = sizeof(FAT_DIR_ENTRY); 00120 EntriesPerPage = FAT_ENTRIES_PER_PAGE; 00121 } 00122 00123 ExAcquireResourceExclusiveLite (&DeviceExt->DirResource, TRUE); 00124 pFcb = vfatOpenRootFCB (DeviceExt); 00125 ExReleaseResourceLite (&DeviceExt->DirResource); 00126 00127 FileOffset.QuadPart = 0; 00128 if (CcMapData(pFcb->FileObject, &FileOffset, SizeDirEntry, TRUE, &Context, (PVOID*)&Entry)) 00129 { 00130 while (TRUE) 00131 { 00132 if (ENTRY_VOLUME(DeviceExt, Entry)) 00133 { 00134 /* copy volume label */ 00135 if (DeviceExt->Flags & VCB_IS_FATX) 00136 { 00137 StringO.Buffer = (PCHAR)Entry->FatX.Filename; 00138 StringO.MaximumLength = StringO.Length = Entry->FatX.FilenameLength; 00139 RtlOemStringToUnicodeString(&NameU, &StringO, FALSE); 00140 } 00141 else 00142 { 00143 vfat8Dot3ToString (&Entry->Fat, &NameU); 00144 } 00145 Vpb->VolumeLabelLength = NameU.Length; 00146 break; 00147 } 00148 if (ENTRY_END(DeviceExt, Entry)) 00149 { 00150 break; 00151 } 00152 DirIndex++; 00153 Entry = (PDIR_ENTRY)((ULONG_PTR)Entry + SizeDirEntry); 00154 if ((DirIndex % EntriesPerPage) == 0) 00155 { 00156 CcUnpinData(Context); 00157 FileOffset.u.LowPart += PAGE_SIZE; 00158 if (!CcMapData(pFcb->FileObject, &FileOffset, SizeDirEntry, TRUE, &Context, (PVOID*)&Entry)) 00159 { 00160 Context = NULL; 00161 break; 00162 } 00163 } 00164 } 00165 if (Context) 00166 { 00167 CcUnpinData(Context); 00168 } 00169 } 00170 ExAcquireResourceExclusiveLite (&DeviceExt->DirResource, TRUE); 00171 vfatReleaseFCB (DeviceExt, pFcb); 00172 ExReleaseResourceLite (&DeviceExt->DirResource); 00173 00174 return STATUS_SUCCESS; 00175 } 00176 00177 NTSTATUS 00178 FindFile ( 00179 PDEVICE_EXTENSION DeviceExt, 00180 PVFATFCB Parent, 00181 PUNICODE_STRING FileToFindU, 00182 PVFAT_DIRENTRY_CONTEXT DirContext, 00183 BOOLEAN First) 00184 /* 00185 * FUNCTION: Find a file 00186 */ 00187 { 00188 PWCHAR PathNameBuffer; 00189 USHORT PathNameBufferLength; 00190 NTSTATUS Status; 00191 PVOID Context = NULL; 00192 PVOID Page; 00193 PVFATFCB rcFcb; 00194 BOOLEAN Found; 00195 UNICODE_STRING PathNameU; 00196 UNICODE_STRING FileToFindUpcase; 00197 BOOLEAN WildCard; 00198 00199 DPRINT ("FindFile(Parent %p, FileToFind '%wZ', DirIndex: %d)\n", 00200 Parent, FileToFindU, DirContext->DirIndex); 00201 DPRINT ("FindFile: Path %wZ\n",&Parent->PathNameU); 00202 00203 PathNameBufferLength = LONGNAME_MAX_LENGTH * sizeof(WCHAR); 00204 PathNameBuffer = ExAllocatePoolWithTag(NonPagedPool, PathNameBufferLength + sizeof(WCHAR), TAG_VFAT); 00205 if (!PathNameBuffer) 00206 { 00207 return STATUS_INSUFFICIENT_RESOURCES; 00208 } 00209 00210 PathNameU.Buffer = PathNameBuffer; 00211 PathNameU.Length = 0; 00212 PathNameU.MaximumLength = PathNameBufferLength; 00213 00214 DirContext->LongNameU.Length = 0; 00215 DirContext->ShortNameU.Length = 0; 00216 00217 WildCard = FsRtlDoesNameContainWildCards(FileToFindU); 00218 00219 if (WildCard == FALSE) 00220 { 00221 /* if there is no '*?' in the search name, than look first for an existing fcb */ 00222 RtlCopyUnicodeString(&PathNameU, &Parent->PathNameU); 00223 if (!vfatFCBIsRoot(Parent)) 00224 { 00225 PathNameU.Buffer[PathNameU.Length / sizeof(WCHAR)] = L'\\'; 00226 PathNameU.Length += sizeof(WCHAR); 00227 } 00228 RtlAppendUnicodeStringToString(&PathNameU, FileToFindU); 00229 PathNameU.Buffer[PathNameU.Length / sizeof(WCHAR)] = 0; 00230 rcFcb = vfatGrabFCBFromTable(DeviceExt, &PathNameU); 00231 if (rcFcb) 00232 { 00233 ULONG startIndex = rcFcb->startIndex; 00234 if ((rcFcb->Flags & FCB_IS_FATX_ENTRY) && !vfatFCBIsRoot(Parent)) 00235 { 00236 startIndex += 2; 00237 } 00238 if(startIndex >= DirContext->DirIndex) 00239 { 00240 RtlCopyUnicodeString(&DirContext->LongNameU, &rcFcb->LongNameU); 00241 RtlCopyUnicodeString(&DirContext->ShortNameU, &rcFcb->ShortNameU); 00242 RtlCopyMemory(&DirContext->DirEntry, &rcFcb->entry, sizeof(DIR_ENTRY)); 00243 DirContext->StartIndex = rcFcb->startIndex; 00244 DirContext->DirIndex = rcFcb->dirIndex; 00245 DPRINT("FindFile: new Name %wZ, DirIndex %d (%d)\n", 00246 &DirContext->LongNameU, DirContext->DirIndex, DirContext->StartIndex); 00247 Status = STATUS_SUCCESS; 00248 } 00249 else 00250 { 00251 DPRINT("FCB not found for %wZ\n", &PathNameU); 00252 Status = STATUS_UNSUCCESSFUL; 00253 } 00254 vfatReleaseFCB(DeviceExt, rcFcb); 00255 ExFreePool(PathNameBuffer); 00256 return Status; 00257 } 00258 } 00259 00260 /* FsRtlIsNameInExpression need the searched string to be upcase, 00261 * even if IgnoreCase is specified */ 00262 Status = RtlUpcaseUnicodeString(&FileToFindUpcase, FileToFindU, TRUE); 00263 if (!NT_SUCCESS(Status)) 00264 { 00265 ExFreePool(PathNameBuffer); 00266 return Status; 00267 } 00268 00269 while(TRUE) 00270 { 00271 Status = DeviceExt->GetNextDirEntry(&Context, &Page, Parent, DirContext, First); 00272 First = FALSE; 00273 if (Status == STATUS_NO_MORE_ENTRIES) 00274 { 00275 break; 00276 } 00277 if (ENTRY_VOLUME(DeviceExt, &DirContext->DirEntry)) 00278 { 00279 DirContext->DirIndex++; 00280 continue; 00281 } 00282 if (WildCard) 00283 { 00284 Found = FsRtlIsNameInExpression(&FileToFindUpcase, &DirContext->LongNameU, TRUE, NULL) || 00285 FsRtlIsNameInExpression(&FileToFindUpcase, &DirContext->ShortNameU, TRUE, NULL); 00286 } 00287 else 00288 { 00289 Found = FsRtlAreNamesEqual(&DirContext->LongNameU, FileToFindU, TRUE, NULL) || 00290 FsRtlAreNamesEqual(&DirContext->ShortNameU, FileToFindU, TRUE, NULL); 00291 } 00292 00293 if (Found) 00294 { 00295 if (WildCard) 00296 { 00297 RtlCopyUnicodeString(&PathNameU, &Parent->PathNameU); 00298 if (!vfatFCBIsRoot(Parent)) 00299 { 00300 PathNameU.Buffer[PathNameU.Length / sizeof(WCHAR)] = L'\\'; 00301 PathNameU.Length += sizeof(WCHAR); 00302 } 00303 RtlAppendUnicodeStringToString(&PathNameU, &DirContext->LongNameU); 00304 PathNameU.Buffer[PathNameU.Length / sizeof(WCHAR)] = 0; 00305 rcFcb = vfatGrabFCBFromTable(DeviceExt, &PathNameU); 00306 if (rcFcb != NULL) 00307 { 00308 RtlCopyMemory(&DirContext->DirEntry, &rcFcb->entry, sizeof(DIR_ENTRY)); 00309 vfatReleaseFCB(DeviceExt, rcFcb); 00310 } 00311 } 00312 DPRINT("%d\n", DirContext->LongNameU.Length); 00313 DPRINT("FindFile: new Name %wZ, DirIndex %d\n", 00314 &DirContext->LongNameU, DirContext->DirIndex); 00315 00316 if (Context) 00317 { 00318 CcUnpinData(Context); 00319 } 00320 RtlFreeUnicodeString(&FileToFindUpcase); 00321 ExFreePool(PathNameBuffer); 00322 return STATUS_SUCCESS; 00323 } 00324 DirContext->DirIndex++; 00325 } 00326 00327 if (Context) 00328 { 00329 CcUnpinData(Context); 00330 } 00331 00332 RtlFreeUnicodeString(&FileToFindUpcase); 00333 ExFreePool(PathNameBuffer); 00334 return Status; 00335 } 00336 00337 static 00338 NTSTATUS 00339 VfatOpenFile ( 00340 PDEVICE_EXTENSION DeviceExt, 00341 PUNICODE_STRING PathNameU, 00342 PFILE_OBJECT FileObject, 00343 PVFATFCB* ParentFcb ) 00344 /* 00345 * FUNCTION: Opens a file 00346 */ 00347 { 00348 PVFATFCB Fcb; 00349 NTSTATUS Status; 00350 00351 DPRINT ("VfatOpenFile(%p, '%wZ', %p, %p)\n", DeviceExt, PathNameU, FileObject, ParentFcb); 00352 00353 if (FileObject->RelatedFileObject) 00354 { 00355 DPRINT ("'%wZ'\n", &FileObject->RelatedFileObject->FileName); 00356 00357 *ParentFcb = FileObject->RelatedFileObject->FsContext; 00358 (*ParentFcb)->RefCount++; 00359 } 00360 else 00361 { 00362 *ParentFcb = NULL; 00363 } 00364 00365 if (!DeviceExt->FatInfo.FixedMedia) 00366 { 00367 Status = VfatBlockDeviceIoControl (DeviceExt->StorageDevice, 00368 IOCTL_DISK_CHECK_VERIFY, 00369 NULL, 00370 0, 00371 NULL, 00372 0, 00373 FALSE); 00374 00375 if (!NT_SUCCESS(Status)) 00376 { 00377 DPRINT ("Status %lx\n", Status); 00378 *ParentFcb = NULL; 00379 return Status; 00380 } 00381 } 00382 00383 if (*ParentFcb) 00384 { 00385 (*ParentFcb)->RefCount++; 00386 } 00387 00388 /* try first to find an existing FCB in memory */ 00389 DPRINT ("Checking for existing FCB in memory\n"); 00390 00391 Status = vfatGetFCBForFile (DeviceExt, ParentFcb, &Fcb, PathNameU); 00392 if (!NT_SUCCESS (Status)) 00393 { 00394 DPRINT ("Could not make a new FCB, status: %x\n", Status); 00395 return Status; 00396 } 00397 if (Fcb->Flags & FCB_DELETE_PENDING) 00398 { 00399 vfatReleaseFCB (DeviceExt, Fcb); 00400 return STATUS_DELETE_PENDING; 00401 } 00402 DPRINT ("Attaching FCB to fileObject\n"); 00403 Status = vfatAttachFCBToFileObject (DeviceExt, Fcb, FileObject); 00404 if (!NT_SUCCESS(Status)) 00405 { 00406 vfatReleaseFCB (DeviceExt, Fcb); 00407 } 00408 return Status; 00409 } 00410 00411 static NTSTATUS 00412 VfatCreateFile ( PDEVICE_OBJECT DeviceObject, PIRP Irp ) 00413 /* 00414 * FUNCTION: Create or open a file 00415 */ 00416 { 00417 PIO_STACK_LOCATION Stack; 00418 PFILE_OBJECT FileObject; 00419 NTSTATUS Status = STATUS_SUCCESS; 00420 PDEVICE_EXTENSION DeviceExt; 00421 ULONG RequestedDisposition, RequestedOptions; 00422 PVFATFCB pFcb = NULL; 00423 PVFATFCB ParentFcb = NULL; 00424 PWCHAR c, last; 00425 BOOLEAN PagingFileCreate = FALSE; 00426 BOOLEAN Dots; 00427 UNICODE_STRING FileNameU; 00428 UNICODE_STRING PathNameU; 00429 00430 /* Unpack the various parameters. */ 00431 Stack = IoGetCurrentIrpStackLocation (Irp); 00432 RequestedDisposition = ((Stack->Parameters.Create.Options >> 24) & 0xff); 00433 RequestedOptions = 00434 Stack->Parameters.Create.Options & FILE_VALID_OPTION_FLAGS; 00435 PagingFileCreate = (Stack->Flags & SL_OPEN_PAGING_FILE) ? TRUE : FALSE; 00436 FileObject = Stack->FileObject; 00437 DeviceExt = DeviceObject->DeviceExtension; 00438 00439 /* Check their validity. */ 00440 if (RequestedOptions & FILE_DIRECTORY_FILE && 00441 RequestedDisposition == FILE_SUPERSEDE) 00442 { 00443 return(STATUS_INVALID_PARAMETER); 00444 } 00445 00446 if (RequestedOptions & FILE_DIRECTORY_FILE && 00447 RequestedOptions & FILE_NON_DIRECTORY_FILE) 00448 { 00449 return(STATUS_INVALID_PARAMETER); 00450 } 00451 00452 /* This a open operation for the volume itself */ 00453 if (FileObject->FileName.Length == 0 && 00454 (FileObject->RelatedFileObject == NULL || FileObject->RelatedFileObject->FsContext2 != NULL)) 00455 { 00456 if (RequestedDisposition != FILE_OPEN && 00457 RequestedDisposition != FILE_OPEN_IF) 00458 { 00459 return(STATUS_ACCESS_DENIED); 00460 } 00461 #if 0 00462 /* In spite of what is shown in WDK, it seems that Windows FAT driver doesn't perform that test */ 00463 if (RequestedOptions & FILE_DIRECTORY_FILE) 00464 { 00465 return(STATUS_NOT_A_DIRECTORY); 00466 } 00467 #endif 00468 00469 pFcb = DeviceExt->VolumeFcb; 00470 vfatAttachFCBToFileObject(DeviceExt, pFcb, FileObject); 00471 pFcb->RefCount++; 00472 00473 Irp->IoStatus.Information = FILE_OPENED; 00474 return(STATUS_SUCCESS); 00475 } 00476 00477 /* 00478 * Check for illegal characters and illegale dot sequences in the file name 00479 */ 00480 PathNameU = FileObject->FileName; 00481 c = PathNameU.Buffer + PathNameU.Length / sizeof(WCHAR); 00482 last = c - 1; 00483 Dots = TRUE; 00484 while (c-- > PathNameU.Buffer) 00485 { 00486 if (*c == L'\\' || c == PathNameU.Buffer) 00487 { 00488 if (Dots && last > c) 00489 { 00490 return(STATUS_OBJECT_NAME_INVALID); 00491 } 00492 last = c - 1; 00493 Dots = TRUE; 00494 } 00495 else if (*c != L'.') 00496 { 00497 Dots = FALSE; 00498 } 00499 00500 if (*c != '\\' && vfatIsLongIllegal(*c)) 00501 { 00502 return(STATUS_OBJECT_NAME_INVALID); 00503 } 00504 } 00505 if (FileObject->RelatedFileObject && PathNameU.Length >= sizeof(WCHAR) && PathNameU.Buffer[0] == L'\\') 00506 { 00507 return(STATUS_OBJECT_NAME_INVALID); 00508 } 00509 if (PathNameU.Length > sizeof(WCHAR) && PathNameU.Buffer[PathNameU.Length/sizeof(WCHAR)-1] == L'\\') 00510 { 00511 PathNameU.Length -= sizeof(WCHAR); 00512 } 00513 00514 /* Try opening the file. */ 00515 Status = VfatOpenFile (DeviceExt, &PathNameU, FileObject, &ParentFcb); 00516 00517 /* 00518 * If the directory containing the file to open doesn't exist then 00519 * fail immediately 00520 */ 00521 if (Status == STATUS_OBJECT_PATH_NOT_FOUND || 00522 Status == STATUS_INVALID_PARAMETER || 00523 Status == STATUS_DELETE_PENDING) 00524 { 00525 if (ParentFcb) 00526 { 00527 vfatReleaseFCB (DeviceExt, ParentFcb); 00528 } 00529 return(Status); 00530 } 00531 if (!NT_SUCCESS(Status) && ParentFcb == NULL) 00532 { 00533 DPRINT1("VfatOpenFile faild for '%wZ', status %x\n", &PathNameU, Status); 00534 return Status; 00535 } 00536 00537 /* 00538 * If the file open failed then create the required file 00539 */ 00540 if (!NT_SUCCESS (Status)) 00541 { 00542 if (RequestedDisposition == FILE_CREATE || 00543 RequestedDisposition == FILE_OPEN_IF || 00544 RequestedDisposition == FILE_OVERWRITE_IF || 00545 RequestedDisposition == FILE_SUPERSEDE) 00546 { 00547 ULONG Attributes; 00548 Attributes = Stack->Parameters.Create.FileAttributes & ~FILE_ATTRIBUTE_NORMAL; 00549 00550 vfatSplitPathName(&PathNameU, NULL, &FileNameU); 00551 Status = VfatAddEntry (DeviceExt, &FileNameU, &pFcb, ParentFcb, RequestedOptions, 00552 (UCHAR)(Attributes & FILE_ATTRIBUTE_VALID_FLAGS)); 00553 vfatReleaseFCB (DeviceExt, ParentFcb); 00554 if (NT_SUCCESS (Status)) 00555 { 00556 Status = vfatAttachFCBToFileObject (DeviceExt, pFcb, FileObject); 00557 if ( !NT_SUCCESS(Status) ) 00558 { 00559 vfatReleaseFCB (DeviceExt, pFcb); 00560 return Status; 00561 } 00562 00563 Irp->IoStatus.Information = FILE_CREATED; 00564 VfatSetAllocationSizeInformation(FileObject, 00565 pFcb, 00566 DeviceExt, 00567 &Irp->Overlay.AllocationSize); 00568 VfatSetExtendedAttributes(FileObject, 00569 Irp->AssociatedIrp.SystemBuffer, 00570 Stack->Parameters.Create.EaLength); 00571 00572 if (PagingFileCreate) 00573 { 00574 pFcb->Flags |= FCB_IS_PAGE_FILE; 00575 } 00576 } 00577 else 00578 { 00579 return(Status); 00580 } 00581 } 00582 else 00583 { 00584 if (ParentFcb) 00585 { 00586 vfatReleaseFCB (DeviceExt, ParentFcb); 00587 } 00588 return(Status); 00589 } 00590 } 00591 else 00592 { 00593 if (ParentFcb) 00594 { 00595 vfatReleaseFCB (DeviceExt, ParentFcb); 00596 } 00597 /* Otherwise fail if the caller wanted to create a new file */ 00598 if (RequestedDisposition == FILE_CREATE) 00599 { 00600 Irp->IoStatus.Information = FILE_EXISTS; 00601 VfatCloseFile (DeviceExt, FileObject); 00602 return(STATUS_OBJECT_NAME_COLLISION); 00603 } 00604 00605 pFcb = FileObject->FsContext; 00606 00607 if (pFcb->OpenHandleCount != 0) 00608 { 00609 Status = IoCheckShareAccess(Stack->Parameters.Create.SecurityContext->DesiredAccess, 00610 Stack->Parameters.Create.ShareAccess, 00611 FileObject, 00612 &pFcb->FCBShareAccess, 00613 FALSE); 00614 if (!NT_SUCCESS(Status)) 00615 { 00616 VfatCloseFile (DeviceExt, FileObject); 00617 return(Status); 00618 } 00619 } 00620 00621 /* 00622 * Check the file has the requested attributes 00623 */ 00624 if (RequestedOptions & FILE_NON_DIRECTORY_FILE && 00625 *pFcb->Attributes & FILE_ATTRIBUTE_DIRECTORY) 00626 { 00627 VfatCloseFile (DeviceExt, FileObject); 00628 return(STATUS_FILE_IS_A_DIRECTORY); 00629 } 00630 if (RequestedOptions & FILE_DIRECTORY_FILE && 00631 !(*pFcb->Attributes & FILE_ATTRIBUTE_DIRECTORY)) 00632 { 00633 VfatCloseFile (DeviceExt, FileObject); 00634 return(STATUS_NOT_A_DIRECTORY); 00635 } 00636 #ifndef USE_ROS_CC_AND_FS 00637 if (!(*pFcb->Attributes & FILE_ATTRIBUTE_DIRECTORY)) 00638 { 00639 if (Stack->Parameters.Create.SecurityContext->DesiredAccess & FILE_WRITE_DATA || 00640 RequestedDisposition == FILE_OVERWRITE || 00641 RequestedDisposition == FILE_OVERWRITE_IF) 00642 { 00643 if (!MmFlushImageSection(&pFcb->SectionObjectPointers, MmFlushForWrite)) 00644 { 00645 DPRINT1("%wZ\n", &pFcb->PathNameU); 00646 DPRINT1("%d %d %d\n", Stack->Parameters.Create.SecurityContext->DesiredAccess & FILE_WRITE_DATA, 00647 RequestedDisposition == FILE_OVERWRITE, RequestedDisposition == FILE_OVERWRITE_IF); 00648 VfatCloseFile (DeviceExt, FileObject); 00649 return STATUS_SHARING_VIOLATION; 00650 } 00651 } 00652 } 00653 #endif 00654 if (PagingFileCreate) 00655 { 00656 /* FIXME: 00657 * Do more checking for page files. It is possible, 00658 * that the file was opened and closed previously 00659 * as a normal cached file. In this case, the cache 00660 * manager has referenced the fileobject and the fcb 00661 * is held in memory. Try to remove the fileobject 00662 * from cache manager and use the fcb. 00663 */ 00664 if (pFcb->RefCount > 1) 00665 { 00666 if(!(pFcb->Flags & FCB_IS_PAGE_FILE)) 00667 { 00668 VfatCloseFile(DeviceExt, FileObject); 00669 return(STATUS_INVALID_PARAMETER); 00670 } 00671 } 00672 else 00673 { 00674 pFcb->Flags |= FCB_IS_PAGE_FILE; 00675 } 00676 } 00677 else 00678 { 00679 if (pFcb->Flags & FCB_IS_PAGE_FILE) 00680 { 00681 VfatCloseFile(DeviceExt, FileObject); 00682 return(STATUS_INVALID_PARAMETER); 00683 } 00684 } 00685 00686 00687 if (RequestedDisposition == FILE_OVERWRITE || 00688 RequestedDisposition == FILE_OVERWRITE_IF || 00689 RequestedDisposition == FILE_SUPERSEDE) 00690 { 00691 ExAcquireResourceExclusiveLite(&(pFcb->MainResource), TRUE); 00692 Status = VfatSetAllocationSizeInformation (FileObject, 00693 pFcb, 00694 DeviceExt, 00695 &Irp->Overlay.AllocationSize); 00696 ExReleaseResourceLite(&(pFcb->MainResource)); 00697 if (!NT_SUCCESS (Status)) 00698 { 00699 VfatCloseFile (DeviceExt, FileObject); 00700 return(Status); 00701 } 00702 } 00703 00704 if (RequestedDisposition == FILE_SUPERSEDE) 00705 { 00706 Irp->IoStatus.Information = FILE_SUPERSEDED; 00707 } 00708 else if (RequestedDisposition == FILE_OVERWRITE || 00709 RequestedDisposition == FILE_OVERWRITE_IF) 00710 { 00711 Irp->IoStatus.Information = FILE_OVERWRITTEN; 00712 } 00713 else 00714 { 00715 Irp->IoStatus.Information = FILE_OPENED; 00716 } 00717 } 00718 00719 if (pFcb->OpenHandleCount == 0) 00720 { 00721 IoSetShareAccess(Stack->Parameters.Create.SecurityContext->DesiredAccess, 00722 Stack->Parameters.Create.ShareAccess, 00723 FileObject, 00724 &pFcb->FCBShareAccess); 00725 } 00726 else 00727 { 00728 IoUpdateShareAccess( 00729 FileObject, 00730 &pFcb->FCBShareAccess 00731 ); 00732 00733 } 00734 00735 pFcb->OpenHandleCount++; 00736 00737 /* FIXME : test write access if requested */ 00738 00739 return(Status); 00740 } 00741 00742 00743 NTSTATUS 00744 VfatCreate (PVFAT_IRP_CONTEXT IrpContext) 00745 /* 00746 * FUNCTION: Create or open a file 00747 */ 00748 { 00749 NTSTATUS Status; 00750 00751 ASSERT(IrpContext); 00752 00753 if (IrpContext->DeviceObject == VfatGlobalData->DeviceObject) 00754 { 00755 /* DeviceObject represents FileSystem instead of logical volume */ 00756 DPRINT ("FsdCreate called with file system\n"); 00757 IrpContext->Irp->IoStatus.Information = FILE_OPENED; 00758 IrpContext->Irp->IoStatus.Status = STATUS_SUCCESS; 00759 IoCompleteRequest (IrpContext->Irp, IO_DISK_INCREMENT); 00760 VfatFreeIrpContext(IrpContext); 00761 return(STATUS_SUCCESS); 00762 } 00763 00764 if (!(IrpContext->Flags & IRPCONTEXT_CANWAIT)) 00765 { 00766 return(VfatQueueRequest (IrpContext)); 00767 } 00768 00769 IrpContext->Irp->IoStatus.Information = 0; 00770 ExAcquireResourceExclusiveLite (&IrpContext->DeviceExt->DirResource, TRUE); 00771 Status = VfatCreateFile (IrpContext->DeviceObject, IrpContext->Irp); 00772 ExReleaseResourceLite (&IrpContext->DeviceExt->DirResource); 00773 00774 IrpContext->Irp->IoStatus.Status = Status; 00775 IoCompleteRequest (IrpContext->Irp, 00776 (CCHAR)(NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT)); 00777 VfatFreeIrpContext(IrpContext); 00778 return(Status); 00779 } 00780 00781 /* EOF */ Generated on Mon May 28 2012 04:16:55 for ReactOS by
1.7.6.1
|