Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygendirwr.c
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: ReactOS kernel 00004 * FILE: drivers/fs/vfat/dirwr.c 00005 * PURPOSE: VFAT Filesystem : write in directory 00006 * 00007 */ 00008 00009 /* INCLUDES *****************************************************************/ 00010 00011 #define NDEBUG 00012 #include "vfat.h" 00013 00014 /* 00015 * update an existing FAT entry 00016 */ 00017 NTSTATUS 00018 VfatUpdateEntry( 00019 IN PVFATFCB pFcb) 00020 { 00021 PVOID Context; 00022 PDIR_ENTRY PinEntry; 00023 LARGE_INTEGER Offset; 00024 ULONG SizeDirEntry; 00025 ULONG dirIndex; 00026 00027 ASSERT(pFcb); 00028 00029 if (pFcb->Flags & FCB_IS_FATX_ENTRY) 00030 { 00031 SizeDirEntry = sizeof(FATX_DIR_ENTRY); 00032 dirIndex = pFcb->startIndex; 00033 } 00034 else 00035 { 00036 SizeDirEntry = sizeof(FAT_DIR_ENTRY); 00037 dirIndex = pFcb->dirIndex; 00038 } 00039 00040 DPRINT("updEntry dirIndex %d, PathName \'%wZ\'\n", dirIndex, &pFcb->PathNameU); 00041 00042 if (vfatFCBIsRoot(pFcb) || (pFcb->Flags & (FCB_IS_FAT|FCB_IS_VOLUME))) 00043 { 00044 return STATUS_SUCCESS; 00045 } 00046 00047 ASSERT(pFcb->parentFcb); 00048 00049 Offset.u.HighPart = 0; 00050 Offset.u.LowPart = dirIndex * SizeDirEntry; 00051 if (CcPinRead(pFcb->parentFcb->FileObject, &Offset, SizeDirEntry, 00052 TRUE, &Context, (PVOID*)&PinEntry)) 00053 { 00054 pFcb->Flags &= ~FCB_IS_DIRTY; 00055 RtlCopyMemory(PinEntry, &pFcb->entry, SizeDirEntry); 00056 CcSetDirtyPinnedData(Context, NULL); 00057 CcUnpinData(Context); 00058 return STATUS_SUCCESS; 00059 } 00060 else 00061 { 00062 DPRINT1("Failed write to \'%wZ\'.\n", &pFcb->parentFcb->PathNameU); 00063 return STATUS_UNSUCCESSFUL; 00064 } 00065 } 00066 00067 /* 00068 * try to find contiguous entries frees in directory, 00069 * extend a directory if is neccesary 00070 */ 00071 BOOLEAN 00072 vfatFindDirSpace( 00073 IN PDEVICE_EXTENSION DeviceExt, 00074 IN PVFATFCB pDirFcb, 00075 IN ULONG nbSlots, 00076 OUT PULONG start) 00077 { 00078 LARGE_INTEGER FileOffset; 00079 ULONG i, count, size, nbFree = 0; 00080 PDIR_ENTRY pFatEntry = NULL; 00081 PVOID Context = NULL; 00082 NTSTATUS Status; 00083 ULONG SizeDirEntry; 00084 FileOffset.QuadPart = 0; 00085 00086 if (DeviceExt->Flags & VCB_IS_FATX) 00087 SizeDirEntry = sizeof(FATX_DIR_ENTRY); 00088 else 00089 SizeDirEntry = sizeof(FAT_DIR_ENTRY); 00090 00091 count = pDirFcb->RFCB.FileSize.u.LowPart / SizeDirEntry; 00092 size = DeviceExt->FatInfo.BytesPerCluster / SizeDirEntry; 00093 for (i = 0; i < count; i++, pFatEntry = (PDIR_ENTRY)((ULONG_PTR)pFatEntry + SizeDirEntry)) 00094 { 00095 if (Context == NULL || (i % size) == 0) 00096 { 00097 if (Context) 00098 { 00099 CcUnpinData(Context); 00100 } 00101 if (!CcPinRead(pDirFcb->FileObject, &FileOffset, DeviceExt->FatInfo.BytesPerCluster, 00102 TRUE, &Context, (PVOID*)&pFatEntry)) 00103 { 00104 return FALSE; 00105 } 00106 FileOffset.u.LowPart += DeviceExt->FatInfo.BytesPerCluster; 00107 } 00108 if (ENTRY_END(DeviceExt, pFatEntry)) 00109 { 00110 break; 00111 } 00112 if (ENTRY_DELETED(DeviceExt, pFatEntry)) 00113 { 00114 nbFree++; 00115 } 00116 else 00117 { 00118 nbFree = 0; 00119 } 00120 if (nbFree == nbSlots) 00121 { 00122 break; 00123 } 00124 } 00125 if (Context) 00126 { 00127 CcUnpinData(Context); 00128 Context = NULL; 00129 } 00130 if (nbFree == nbSlots) 00131 { 00132 /* found enough contiguous free slots */ 00133 *start = i - nbSlots + 1; 00134 } 00135 else 00136 { 00137 *start = i - nbFree; 00138 if (*start + nbSlots > count) 00139 { 00140 LARGE_INTEGER AllocationSize; 00141 /* extend the directory */ 00142 if (vfatFCBIsRoot(pDirFcb) && DeviceExt->FatInfo.FatType != FAT32) 00143 { 00144 /* We can't extend a root directory on a FAT12/FAT16/FATX partition */ 00145 return FALSE; 00146 } 00147 AllocationSize.QuadPart = pDirFcb->RFCB.FileSize.u.LowPart + DeviceExt->FatInfo.BytesPerCluster; 00148 Status = VfatSetAllocationSizeInformation(pDirFcb->FileObject, pDirFcb, 00149 DeviceExt, &AllocationSize); 00150 if (!NT_SUCCESS(Status)) 00151 { 00152 return FALSE; 00153 } 00154 /* clear the new dir cluster */ 00155 FileOffset.u.LowPart = (ULONG)(pDirFcb->RFCB.FileSize.QuadPart - 00156 DeviceExt->FatInfo.BytesPerCluster); 00157 if (!CcPinRead(pDirFcb->FileObject, &FileOffset, DeviceExt->FatInfo.BytesPerCluster, 00158 TRUE, &Context, (PVOID*)&pFatEntry)) 00159 { 00160 return FALSE; 00161 } 00162 if (DeviceExt->Flags & VCB_IS_FATX) 00163 memset(pFatEntry, 0xff, DeviceExt->FatInfo.BytesPerCluster); 00164 else 00165 RtlZeroMemory(pFatEntry, DeviceExt->FatInfo.BytesPerCluster); 00166 } 00167 else if (*start + nbSlots < count) 00168 { 00169 /* clear the entry after the last new entry */ 00170 FileOffset.u.LowPart = (*start + nbSlots) * SizeDirEntry; 00171 if (!CcPinRead(pDirFcb->FileObject, &FileOffset, SizeDirEntry, 00172 TRUE, &Context, (PVOID*)&pFatEntry)) 00173 { 00174 return FALSE; 00175 } 00176 if (DeviceExt->Flags & VCB_IS_FATX) 00177 memset(pFatEntry, 0xff, SizeDirEntry); 00178 else 00179 RtlZeroMemory(pFatEntry, SizeDirEntry); 00180 } 00181 if (Context) 00182 { 00183 CcSetDirtyPinnedData(Context, NULL); 00184 CcUnpinData(Context); 00185 } 00186 } 00187 DPRINT("nbSlots %d nbFree %d, entry number %d\n", nbSlots, nbFree, *start); 00188 return TRUE; 00189 } 00190 00191 /* 00192 create a new FAT entry 00193 */ 00194 static NTSTATUS 00195 FATAddEntry( 00196 IN PDEVICE_EXTENSION DeviceExt, 00197 IN PUNICODE_STRING NameU, 00198 IN PVFATFCB* Fcb, 00199 IN PVFATFCB ParentFcb, 00200 IN ULONG RequestedOptions, 00201 IN UCHAR ReqAttr) 00202 { 00203 PVOID Context = NULL; 00204 PFAT_DIR_ENTRY pFatEntry; 00205 slot *pSlots; 00206 USHORT nbSlots = 0, j, posCar; 00207 PUCHAR Buffer; 00208 BOOLEAN needTilde = FALSE, needLong = FALSE; 00209 BOOLEAN lCaseBase = FALSE, uCaseBase, lCaseExt = FALSE, uCaseExt; 00210 ULONG CurrentCluster; 00211 LARGE_INTEGER SystemTime, FileOffset; 00212 NTSTATUS Status = STATUS_SUCCESS; 00213 ULONG size; 00214 long i; 00215 00216 OEM_STRING NameA; 00217 CHAR aName[13]; 00218 BOOLEAN IsNameLegal; 00219 BOOLEAN SpacesFound; 00220 00221 VFAT_DIRENTRY_CONTEXT DirContext; 00222 WCHAR LongNameBuffer[LONGNAME_MAX_LENGTH + 1]; 00223 WCHAR ShortNameBuffer[13]; 00224 00225 DPRINT("addEntry: Name='%wZ', Dir='%wZ'\n", NameU, &ParentFcb->PathNameU); 00226 00227 DirContext.LongNameU = *NameU; 00228 00229 /* nb of entry needed for long name+normal entry */ 00230 nbSlots = (DirContext.LongNameU.Length / sizeof(WCHAR) + 12) / 13 + 1; 00231 DPRINT("NameLen= %d, nbSlots =%d\n", DirContext.LongNameU.Length / sizeof(WCHAR), nbSlots); 00232 Buffer = ExAllocatePoolWithTag(NonPagedPool, (nbSlots - 1) * sizeof(FAT_DIR_ENTRY), TAG_VFAT); 00233 if (Buffer == NULL) 00234 { 00235 return STATUS_INSUFFICIENT_RESOURCES; 00236 } 00237 RtlZeroMemory(Buffer, (nbSlots - 1) * sizeof(FAT_DIR_ENTRY)); 00238 pSlots = (slot *) Buffer; 00239 00240 NameA.Buffer = aName; 00241 NameA.Length = 0; 00242 NameA.MaximumLength = sizeof(aName); 00243 00244 DirContext.ShortNameU.Buffer = ShortNameBuffer; 00245 DirContext.ShortNameU.Length = 0; 00246 DirContext.ShortNameU.MaximumLength = sizeof(ShortNameBuffer); 00247 00248 RtlZeroMemory(&DirContext.DirEntry.Fat, sizeof(FAT_DIR_ENTRY)); 00249 00250 IsNameLegal = RtlIsNameLegalDOS8Dot3(&DirContext.LongNameU, &NameA, &SpacesFound); 00251 00252 if (!IsNameLegal || SpacesFound) 00253 { 00254 GENERATE_NAME_CONTEXT NameContext; 00255 VFAT_DIRENTRY_CONTEXT SearchContext; 00256 WCHAR ShortSearchName[13]; 00257 needTilde = TRUE; 00258 needLong = TRUE; 00259 RtlZeroMemory(&NameContext, sizeof(GENERATE_NAME_CONTEXT)); 00260 SearchContext.LongNameU.Buffer = LongNameBuffer; 00261 SearchContext.LongNameU.MaximumLength = sizeof(LongNameBuffer); 00262 SearchContext.ShortNameU.Buffer = ShortSearchName; 00263 SearchContext.ShortNameU.MaximumLength = sizeof(ShortSearchName); 00264 00265 for (i = 0; i < 100; i++) 00266 { 00267 RtlGenerate8dot3Name(&DirContext.LongNameU, FALSE, &NameContext, &DirContext.ShortNameU); 00268 DirContext.ShortNameU.Buffer[DirContext.ShortNameU.Length / sizeof(WCHAR)] = 0; 00269 SearchContext.DirIndex = 0; 00270 Status = FindFile(DeviceExt, ParentFcb, &DirContext.ShortNameU, &SearchContext, TRUE); 00271 if (!NT_SUCCESS(Status)) 00272 { 00273 break; 00274 } 00275 } 00276 if (i == 100) /* FIXME : what to do after this ? */ 00277 { 00278 ExFreePoolWithTag(Buffer, TAG_VFAT); 00279 return STATUS_UNSUCCESSFUL; 00280 } 00281 IsNameLegal = RtlIsNameLegalDOS8Dot3(&DirContext.ShortNameU, &NameA, &SpacesFound); 00282 aName[NameA.Length]=0; 00283 } 00284 else 00285 { 00286 aName[NameA.Length] = 0; 00287 for (posCar = 0; posCar < DirContext.LongNameU.Length / sizeof(WCHAR); posCar++) 00288 { 00289 if (DirContext.LongNameU.Buffer[posCar] == L'.') 00290 { 00291 break; 00292 } 00293 } 00294 /* check if the name and the extension contains upper case characters */ 00295 RtlDowncaseUnicodeString(&DirContext.ShortNameU, &DirContext.LongNameU, FALSE); 00296 DirContext.ShortNameU.Buffer[DirContext.ShortNameU.Length / sizeof(WCHAR)] = 0; 00297 uCaseBase = wcsncmp(DirContext.LongNameU.Buffer, 00298 DirContext.ShortNameU.Buffer, posCar) ? TRUE : FALSE; 00299 if (posCar < DirContext.LongNameU.Length/sizeof(WCHAR)) 00300 { 00301 i = DirContext.LongNameU.Length / sizeof(WCHAR) - posCar; 00302 uCaseExt = wcsncmp(DirContext.LongNameU.Buffer + posCar, 00303 DirContext.ShortNameU.Buffer + posCar, i) ? TRUE : FALSE; 00304 } 00305 else 00306 { 00307 uCaseExt = FALSE; 00308 } 00309 /* check if the name and the extension contains lower case characters */ 00310 RtlUpcaseUnicodeString(&DirContext.ShortNameU, &DirContext.LongNameU, FALSE); 00311 DirContext.ShortNameU.Buffer[DirContext.ShortNameU.Length / sizeof(WCHAR)] = 0; 00312 lCaseBase = wcsncmp(DirContext.LongNameU.Buffer, 00313 DirContext.ShortNameU.Buffer, posCar) ? TRUE : FALSE; 00314 if (posCar < DirContext.LongNameU.Length / sizeof(WCHAR)) 00315 { 00316 i = DirContext.LongNameU.Length / sizeof(WCHAR) - posCar; 00317 lCaseExt = wcsncmp(DirContext.LongNameU.Buffer + posCar, 00318 DirContext.ShortNameU.Buffer + posCar, i) ? TRUE : FALSE; 00319 } 00320 else 00321 { 00322 lCaseExt = FALSE; 00323 } 00324 if ((lCaseBase && uCaseBase) || (lCaseExt && uCaseExt)) 00325 { 00326 needLong = TRUE; 00327 } 00328 } 00329 DPRINT("'%s', '%wZ', needTilde=%d, needLong=%d\n", 00330 aName, &DirContext.LongNameU, needTilde, needLong); 00331 memset(DirContext.DirEntry.Fat.ShortName, ' ', 11); 00332 for (i = 0; i < 8 && aName[i] && aName[i] != '.'; i++) 00333 { 00334 DirContext.DirEntry.Fat.Filename[i] = aName[i]; 00335 } 00336 if (aName[i] == '.') 00337 { 00338 i++; 00339 for (j = 0; j < 3 && aName[i]; j++, i++) 00340 { 00341 DirContext.DirEntry.Fat.Ext[j] = aName[i]; 00342 } 00343 } 00344 if (DirContext.DirEntry.Fat.Filename[0] == 0xe5) 00345 { 00346 DirContext.DirEntry.Fat.Filename[0] = 0x05; 00347 } 00348 00349 if (needLong) 00350 { 00351 RtlCopyMemory(LongNameBuffer, DirContext.LongNameU.Buffer, DirContext.LongNameU.Length); 00352 DirContext.LongNameU.Buffer = LongNameBuffer; 00353 DirContext.LongNameU.MaximumLength = sizeof(LongNameBuffer); 00354 DirContext.LongNameU.Buffer[DirContext.LongNameU.Length / sizeof(WCHAR)] = 0; 00355 memset(DirContext.LongNameU.Buffer + DirContext.LongNameU.Length / sizeof(WCHAR) + 1, 0xff, 00356 DirContext.LongNameU.MaximumLength - DirContext.LongNameU.Length - sizeof(WCHAR)); 00357 } 00358 else 00359 { 00360 nbSlots = 1; 00361 if (lCaseBase) 00362 { 00363 DirContext.DirEntry.Fat.lCase |= VFAT_CASE_LOWER_BASE; 00364 } 00365 if (lCaseExt) 00366 { 00367 DirContext.DirEntry.Fat.lCase |= VFAT_CASE_LOWER_EXT; 00368 } 00369 } 00370 00371 DPRINT ("dos name=%11.11s\n", DirContext.DirEntry.Fat.Filename); 00372 00373 /* set attributes */ 00374 DirContext.DirEntry.Fat.Attrib = ReqAttr; 00375 if (RequestedOptions & FILE_DIRECTORY_FILE) 00376 { 00377 DirContext.DirEntry.Fat.Attrib |= FILE_ATTRIBUTE_DIRECTORY; 00378 } 00379 /* set dates and times */ 00380 KeQuerySystemTime(&SystemTime); 00381 FsdSystemTimeToDosDateTime(DeviceExt, &SystemTime, &DirContext.DirEntry.Fat.CreationDate, 00382 &DirContext.DirEntry.Fat.CreationTime); 00383 DirContext.DirEntry.Fat.UpdateDate = DirContext.DirEntry.Fat.CreationDate; 00384 DirContext.DirEntry.Fat.UpdateTime = DirContext.DirEntry.Fat.CreationTime; 00385 DirContext.DirEntry.Fat.AccessDate = DirContext.DirEntry.Fat.CreationDate; 00386 00387 if (needLong) 00388 { 00389 /* calculate checksum for 8.3 name */ 00390 for (pSlots[0].alias_checksum = 0, i = 0; i < 11; i++) 00391 { 00392 pSlots[0].alias_checksum = (((pSlots[0].alias_checksum & 1) << 7 00393 | ((pSlots[0].alias_checksum & 0xfe) >> 1)) 00394 + DirContext.DirEntry.Fat.ShortName[i]); 00395 } 00396 /* construct slots and entry */ 00397 for (i = nbSlots - 2; i >= 0; i--) 00398 { 00399 DPRINT("construct slot %d\n", i); 00400 pSlots[i].attr = 0xf; 00401 if (i) 00402 { 00403 pSlots[i].id = (unsigned char)(nbSlots - i - 1); 00404 } 00405 else 00406 { 00407 pSlots[i].id = (unsigned char)(nbSlots - i - 1 + 0x40); 00408 } 00409 pSlots[i].alias_checksum = pSlots[0].alias_checksum; 00410 RtlCopyMemory(pSlots[i].name0_4, DirContext.LongNameU.Buffer + (nbSlots - i - 2) * 13, 10); 00411 RtlCopyMemory(pSlots[i].name5_10, DirContext.LongNameU.Buffer + (nbSlots - i - 2) * 13 + 5, 12); 00412 RtlCopyMemory(pSlots[i].name11_12, DirContext.LongNameU.Buffer + (nbSlots - i - 2) * 13 + 11, 4); 00413 } 00414 } 00415 /* try to find nbSlots contiguous entries frees in directory */ 00416 if (!vfatFindDirSpace(DeviceExt, ParentFcb, nbSlots, &DirContext.StartIndex)) 00417 { 00418 ExFreePoolWithTag(Buffer, TAG_VFAT); 00419 return STATUS_DISK_FULL; 00420 } 00421 DirContext.DirIndex = DirContext.StartIndex + nbSlots - 1; 00422 if (RequestedOptions & FILE_DIRECTORY_FILE) 00423 { 00424 CurrentCluster = 0; 00425 Status = NextCluster(DeviceExt, 0, &CurrentCluster, TRUE); 00426 if (CurrentCluster == 0xffffffff || !NT_SUCCESS(Status)) 00427 { 00428 ExFreePoolWithTag(Buffer, TAG_VFAT); 00429 if (!NT_SUCCESS(Status)) 00430 { 00431 return Status; 00432 } 00433 return STATUS_DISK_FULL; 00434 } 00435 if (DeviceExt->FatInfo.FatType == FAT32) 00436 { 00437 DirContext.DirEntry.Fat.FirstClusterHigh = (unsigned short)(CurrentCluster >> 16); 00438 } 00439 DirContext.DirEntry.Fat.FirstCluster = (unsigned short)CurrentCluster; 00440 } 00441 00442 i = DeviceExt->FatInfo.BytesPerCluster / sizeof(FAT_DIR_ENTRY); 00443 FileOffset.u.HighPart = 0; 00444 FileOffset.u.LowPart = DirContext.StartIndex * sizeof(FAT_DIR_ENTRY); 00445 if (DirContext.StartIndex / i == DirContext.DirIndex / i) 00446 { 00447 /* one cluster */ 00448 if (!CcPinRead(ParentFcb->FileObject, &FileOffset, nbSlots * sizeof(FAT_DIR_ENTRY), 00449 TRUE, &Context, (PVOID*)&pFatEntry)) 00450 { 00451 ExFreePoolWithTag(Buffer, TAG_VFAT); 00452 return STATUS_UNSUCCESSFUL; 00453 } 00454 if (nbSlots > 1) 00455 { 00456 RtlCopyMemory(pFatEntry, Buffer, (nbSlots - 1) * sizeof(FAT_DIR_ENTRY)); 00457 } 00458 RtlCopyMemory(pFatEntry + (nbSlots - 1), &DirContext.DirEntry.Fat, sizeof(FAT_DIR_ENTRY)); 00459 } 00460 else 00461 { 00462 /* two clusters */ 00463 size = DeviceExt->FatInfo.BytesPerCluster - 00464 (DirContext.StartIndex * sizeof(FAT_DIR_ENTRY)) % DeviceExt->FatInfo.BytesPerCluster; 00465 i = size / sizeof(FAT_DIR_ENTRY); 00466 if (!CcPinRead(ParentFcb->FileObject, &FileOffset, size, TRUE, 00467 &Context, (PVOID*)&pFatEntry)) 00468 { 00469 ExFreePoolWithTag(Buffer, TAG_VFAT); 00470 return STATUS_UNSUCCESSFUL; 00471 } 00472 RtlCopyMemory(pFatEntry, Buffer, size); 00473 CcSetDirtyPinnedData(Context, NULL); 00474 CcUnpinData(Context); 00475 FileOffset.u.LowPart += size; 00476 if (!CcPinRead(ParentFcb->FileObject, &FileOffset, 00477 nbSlots * sizeof(FAT_DIR_ENTRY) - size, 00478 TRUE, &Context, (PVOID*)&pFatEntry)) 00479 { 00480 ExFreePoolWithTag(Buffer, TAG_VFAT); 00481 return STATUS_UNSUCCESSFUL; 00482 } 00483 if (nbSlots - 1 > i) 00484 { 00485 RtlCopyMemory(pFatEntry, (PVOID)(Buffer + size), (nbSlots - 1 - i) * sizeof(FAT_DIR_ENTRY)); 00486 } 00487 RtlCopyMemory(pFatEntry + nbSlots - 1 - i, &DirContext.DirEntry.Fat, sizeof(FAT_DIR_ENTRY)); 00488 } 00489 CcSetDirtyPinnedData(Context, NULL); 00490 CcUnpinData(Context); 00491 00492 Status = vfatMakeFCBFromDirEntry(DeviceExt, ParentFcb, &DirContext, Fcb); 00493 if (!NT_SUCCESS(Status)) 00494 { 00495 ExFreePoolWithTag(Buffer, TAG_VFAT); 00496 return Status; 00497 } 00498 00499 DPRINT("new : entry=%11.11s\n", (*Fcb)->entry.Fat.Filename); 00500 DPRINT("new : entry=%11.11s\n", DirContext.DirEntry.Fat.Filename); 00501 00502 if (RequestedOptions & FILE_DIRECTORY_FILE) 00503 { 00504 FileOffset.QuadPart = 0; 00505 if (!CcPinRead((*Fcb)->FileObject, &FileOffset, DeviceExt->FatInfo.BytesPerCluster, TRUE, 00506 &Context, (PVOID*)&pFatEntry)) 00507 { 00508 ExFreePoolWithTag(Buffer, TAG_VFAT); 00509 return STATUS_UNSUCCESSFUL; 00510 } 00511 /* clear the new directory cluster */ 00512 RtlZeroMemory(pFatEntry, DeviceExt->FatInfo.BytesPerCluster); 00513 /* create '.' and '..' */ 00514 RtlCopyMemory(&pFatEntry[0].Attrib, &DirContext.DirEntry.Fat.Attrib, sizeof(FAT_DIR_ENTRY) - 11); 00515 RtlCopyMemory(pFatEntry[0].ShortName, ". ", 11); 00516 RtlCopyMemory(&pFatEntry[1].Attrib, &DirContext.DirEntry.Fat.Attrib, sizeof(FAT_DIR_ENTRY) - 11); 00517 RtlCopyMemory(pFatEntry[1].ShortName, ".. ", 11); 00518 pFatEntry[1].FirstCluster = ParentFcb->entry.Fat.FirstCluster; 00519 pFatEntry[1].FirstClusterHigh = ParentFcb->entry.Fat.FirstClusterHigh; 00520 if (vfatFCBIsRoot(ParentFcb)) 00521 { 00522 pFatEntry[1].FirstCluster = 0; 00523 pFatEntry[1].FirstClusterHigh = 0; 00524 } 00525 CcSetDirtyPinnedData(Context, NULL); 00526 CcUnpinData(Context); 00527 } 00528 ExFreePoolWithTag(Buffer, TAG_VFAT); 00529 DPRINT("addentry ok\n"); 00530 return STATUS_SUCCESS; 00531 } 00532 00533 /* 00534 create a new FAT entry 00535 */ 00536 static NTSTATUS 00537 FATXAddEntry( 00538 IN PDEVICE_EXTENSION DeviceExt, 00539 IN PUNICODE_STRING NameU, 00540 IN PVFATFCB* Fcb, 00541 IN PVFATFCB ParentFcb, 00542 IN ULONG RequestedOptions, 00543 IN UCHAR ReqAttr) 00544 { 00545 PVOID Context = NULL; 00546 LARGE_INTEGER SystemTime, FileOffset; 00547 OEM_STRING NameA; 00548 VFAT_DIRENTRY_CONTEXT DirContext; 00549 PFATX_DIR_ENTRY pFatXDirEntry; 00550 ULONG Index; 00551 00552 DPRINT("addEntry: Name='%wZ', Dir='%wZ'\n", NameU, &ParentFcb->PathNameU); 00553 00554 DirContext.LongNameU = *NameU; 00555 00556 if (DirContext.LongNameU.Length / sizeof(WCHAR) > 42) 00557 { 00558 /* name too long */ 00559 return STATUS_NAME_TOO_LONG; 00560 } 00561 00562 /* try to find 1 entry free in directory */ 00563 if (!vfatFindDirSpace(DeviceExt, ParentFcb, 1, &DirContext.StartIndex)) 00564 { 00565 return STATUS_DISK_FULL; 00566 } 00567 Index = DirContext.DirIndex = DirContext.StartIndex; 00568 if (!vfatFCBIsRoot(ParentFcb)) 00569 { 00570 DirContext.DirIndex += 2; 00571 DirContext.StartIndex += 2; 00572 } 00573 00574 DirContext.ShortNameU.Buffer = 0; 00575 DirContext.ShortNameU.Length = 0; 00576 DirContext.ShortNameU.MaximumLength = 0; 00577 RtlZeroMemory(&DirContext.DirEntry.FatX, sizeof(FATX_DIR_ENTRY)); 00578 memset(DirContext.DirEntry.FatX.Filename, 0xff, 42); 00579 DirContext.DirEntry.FatX.FirstCluster = 0; 00580 DirContext.DirEntry.FatX.FileSize = 0; 00581 00582 /* set file name */ 00583 NameA.Buffer = (PCHAR)DirContext.DirEntry.FatX.Filename; 00584 NameA.Length = 0; 00585 NameA.MaximumLength = 42; 00586 RtlUnicodeStringToOemString(&NameA, &DirContext.LongNameU, FALSE); 00587 DirContext.DirEntry.FatX.FilenameLength = (unsigned char)NameA.Length; 00588 00589 /* set attributes */ 00590 DirContext.DirEntry.FatX.Attrib = ReqAttr; 00591 if (RequestedOptions & FILE_DIRECTORY_FILE) 00592 { 00593 DirContext.DirEntry.FatX.Attrib |= FILE_ATTRIBUTE_DIRECTORY; 00594 } 00595 00596 /* set dates and times */ 00597 KeQuerySystemTime(&SystemTime); 00598 FsdSystemTimeToDosDateTime(DeviceExt, &SystemTime, &DirContext.DirEntry.FatX.CreationDate, 00599 &DirContext.DirEntry.FatX.CreationTime); 00600 DirContext.DirEntry.FatX.UpdateDate = DirContext.DirEntry.FatX.CreationDate; 00601 DirContext.DirEntry.FatX.UpdateTime = DirContext.DirEntry.FatX.CreationTime; 00602 DirContext.DirEntry.FatX.AccessDate = DirContext.DirEntry.FatX.CreationDate; 00603 DirContext.DirEntry.FatX.AccessTime = DirContext.DirEntry.FatX.CreationTime; 00604 00605 /* add entry into parent directory */ 00606 FileOffset.u.HighPart = 0; 00607 FileOffset.u.LowPart = Index * sizeof(FATX_DIR_ENTRY); 00608 if (!CcPinRead(ParentFcb->FileObject, &FileOffset, sizeof(FATX_DIR_ENTRY), 00609 TRUE, &Context, (PVOID*)&pFatXDirEntry)) 00610 { 00611 return STATUS_UNSUCCESSFUL; 00612 } 00613 RtlCopyMemory(pFatXDirEntry, &DirContext.DirEntry.FatX, sizeof(FATX_DIR_ENTRY)); 00614 CcSetDirtyPinnedData(Context, NULL); 00615 CcUnpinData(Context); 00616 00617 /* FIXME: check status */ 00618 vfatMakeFCBFromDirEntry(DeviceExt, ParentFcb, &DirContext, Fcb); 00619 00620 DPRINT("addentry ok\n"); 00621 return STATUS_SUCCESS; 00622 } 00623 00624 NTSTATUS 00625 VfatAddEntry( 00626 IN PDEVICE_EXTENSION DeviceExt, 00627 IN PUNICODE_STRING NameU, 00628 IN PVFATFCB *Fcb, 00629 IN PVFATFCB ParentFcb, 00630 IN ULONG RequestedOptions, 00631 IN UCHAR ReqAttr) 00632 { 00633 if (DeviceExt->Flags & VCB_IS_FATX) 00634 return FATXAddEntry(DeviceExt, NameU, Fcb, ParentFcb, RequestedOptions, ReqAttr); 00635 else 00636 return FATAddEntry(DeviceExt, NameU, Fcb, ParentFcb, RequestedOptions, ReqAttr); 00637 } 00638 00639 /* 00640 * deleting an existing FAT entry 00641 */ 00642 static NTSTATUS 00643 FATDelEntry( 00644 IN PDEVICE_EXTENSION DeviceExt, 00645 IN PVFATFCB pFcb) 00646 { 00647 ULONG CurrentCluster = 0, NextCluster, i; 00648 PVOID Context = NULL; 00649 LARGE_INTEGER Offset; 00650 PFAT_DIR_ENTRY pDirEntry = NULL; 00651 00652 ASSERT(pFcb); 00653 ASSERT(pFcb->parentFcb); 00654 00655 DPRINT("delEntry PathName \'%wZ\'\n", &pFcb->PathNameU); 00656 DPRINT("delete entry: %d to %d\n", pFcb->startIndex, pFcb->dirIndex); 00657 Offset.u.HighPart = 0; 00658 for (i = pFcb->startIndex; i <= pFcb->dirIndex; i++) 00659 { 00660 if (Context == NULL || ((i * sizeof(FAT_DIR_ENTRY)) % PAGE_SIZE) == 0) 00661 { 00662 if (Context) 00663 { 00664 CcSetDirtyPinnedData(Context, NULL); 00665 CcUnpinData(Context); 00666 } 00667 Offset.u.LowPart = (i * sizeof(FAT_DIR_ENTRY) / PAGE_SIZE) * PAGE_SIZE; 00668 if (!CcPinRead(pFcb->parentFcb->FileObject, &Offset, sizeof(FAT_DIR_ENTRY), TRUE, 00669 &Context, (PVOID*)&pDirEntry)) 00670 { 00671 return STATUS_UNSUCCESSFUL; 00672 } 00673 } 00674 pDirEntry[i % (PAGE_SIZE / sizeof(FAT_DIR_ENTRY))].Filename[0] = 0xe5; 00675 if (i == pFcb->dirIndex) 00676 { 00677 CurrentCluster = 00678 vfatDirEntryGetFirstCluster(DeviceExt, 00679 (PDIR_ENTRY)&pDirEntry[i % (PAGE_SIZE / sizeof(FAT_DIR_ENTRY))]); 00680 } 00681 } 00682 if (Context) 00683 { 00684 CcSetDirtyPinnedData(Context, NULL); 00685 CcUnpinData(Context); 00686 } 00687 00688 while (CurrentCluster && CurrentCluster != 0xffffffff) 00689 { 00690 GetNextCluster(DeviceExt, CurrentCluster, &NextCluster); 00691 /* FIXME: check status */ 00692 WriteCluster(DeviceExt, CurrentCluster, 0); 00693 CurrentCluster = NextCluster; 00694 } 00695 return STATUS_SUCCESS; 00696 } 00697 00698 /* 00699 * deleting an existing FAT entry 00700 */ 00701 static NTSTATUS 00702 FATXDelEntry( 00703 IN PDEVICE_EXTENSION DeviceExt, 00704 IN PVFATFCB pFcb) 00705 { 00706 ULONG CurrentCluster = 0, NextCluster; 00707 PVOID Context = NULL; 00708 LARGE_INTEGER Offset; 00709 PFATX_DIR_ENTRY pDirEntry; 00710 ULONG StartIndex; 00711 00712 ASSERT(pFcb); 00713 ASSERT(pFcb->parentFcb); 00714 ASSERT(pFcb->Flags & FCB_IS_FATX_ENTRY); 00715 00716 StartIndex = pFcb->startIndex; 00717 00718 DPRINT("delEntry PathName \'%wZ\'\n", &pFcb->PathNameU); 00719 DPRINT("delete entry: %d\n", StartIndex); 00720 Offset.u.HighPart = 0; 00721 Offset.u.LowPart = (StartIndex * sizeof(FATX_DIR_ENTRY) / PAGE_SIZE) * PAGE_SIZE; 00722 if (!CcPinRead(pFcb->parentFcb->FileObject, &Offset, sizeof(FATX_DIR_ENTRY), TRUE, 00723 &Context, (PVOID*)&pDirEntry)) 00724 { 00725 DPRINT1("CcPinRead(Offset %x:%x, Length %d) failed\n", Offset.u.HighPart, Offset.u.LowPart, PAGE_SIZE); 00726 return STATUS_UNSUCCESSFUL; 00727 } 00728 pDirEntry = &pDirEntry[StartIndex % (PAGE_SIZE / sizeof(FATX_DIR_ENTRY))]; 00729 pDirEntry->FilenameLength = 0xe5; 00730 CurrentCluster = vfatDirEntryGetFirstCluster(DeviceExt, 00731 (PDIR_ENTRY)pDirEntry); 00732 CcSetDirtyPinnedData(Context, NULL); 00733 CcUnpinData(Context); 00734 00735 while (CurrentCluster && CurrentCluster != 0xffffffff) 00736 { 00737 GetNextCluster(DeviceExt, CurrentCluster, &NextCluster); 00738 /* FIXME: check status */ 00739 WriteCluster(DeviceExt, CurrentCluster, 0); 00740 CurrentCluster = NextCluster; 00741 } 00742 return STATUS_SUCCESS; 00743 } 00744 00745 NTSTATUS 00746 VfatDelEntry( 00747 IN PDEVICE_EXTENSION DeviceExt, 00748 IN PVFATFCB pFcb) 00749 { 00750 if (DeviceExt->Flags & VCB_IS_FATX) 00751 return FATXDelEntry(DeviceExt, pFcb); 00752 else 00753 return FATDelEntry(DeviceExt, pFcb); 00754 } 00755 00756 /* EOF */ Generated on Fri May 25 2012 04:25:59 for ReactOS by
1.7.6.1
|