reactos操作系统实现(127)

前端之家收集整理的这篇文章主要介绍了reactos操作系统实现(127)前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

从上面的代码里可以看到调用函数VfatAddEntry添加文件或目录的入口,其实现的代码如下:

#001 NTSTATUS

#002 VfatAddEntry(

#003 IN PDEVICE_EXTENSION DeviceExt,

#004 IN PUNICODE_STRING NameU,

#005 IN PVFATFCB *Fcb,

#006 IN PVFATFCB ParentFcb,

#007 IN ULONG RequestedOptions,

#008 IN UCHAR ReqAttr)

#009 {

这里判断是使用扩展的FAT16或者FAT32

#010 if (DeviceExt->Flags & VCB_IS_FATX)

#011 return FATXAddEntry(DeviceExt,NameU,Fcb,ParentFcb,RequestedOptions,ReqAttr);

#012 else

这里使用原来的FAT16或者FAT32

#013 return FATAddEntry(DeviceExt,ReqAttr);

#014 }

接着来分析创建一个FAT入口函数FATAddEntry

#001 static NTSTATUS

#002 FATAddEntry(

#003 IN PDEVICE_EXTENSION DeviceExt,

#005 IN PVFATFCB* Fcb,

#008 IN UCHAR ReqAttr)

#009 {

#010 PVOID Context = NULL;

#011 PFAT_DIR_ENTRY pFatEntry;

#012 slot *pSlots;

#013 USHORT nbSlots = 0,j,posCar;

#014 PUCHAR Buffer;

#015 BOOLEAN needTilde = FALSE,needLong = FALSE;

#016 BOOLEAN lCaseBase = FALSE,uCaseBase,lCaseExt = FALSE,uCaseExt;

#017 ULONG CurrentCluster;

#018 LARGE_INTEGER SystemTime,FileOffset;

#019 NTSTATUS Status = STATUS_SUCCESS;

#020 ULONG size;

#021 long i;

#022

#023 OEM_STRING NameA;

#024 CHAR aName[13];

#025 BOOLEAN IsNameLegal;

#026 BOOLEAN SpacesFound;

#027

#028 VFAT_DIRENTRY_CONTEXT DirContext;

#029 WCHAR LongNameBuffer[LONGNAME_MAX_LENGTH + 1];

#030 WCHAR ShortNameBuffer[13];

#031

#032 DPRINT("addEntry: Name='%wZ',Dir='%wZ'/n",&ParentFcb->PathNameU);

#033

#034 DirContext.LongNameU = *NameU;

#035

#036 /* nb of entry needed for long name+normal entry */

计算一个FAT入口的占用内存大小。

#037 nbSlots = (DirContext.LongNameU.Length / sizeof(WCHAR) + 12) / 13 + 1;

#038 DPRINT("NameLen= %d,nbSlots =%d/n",DirContext.LongNameU.Length / sizeof(WCHAR),nbSlots);

分配FAT的入口内存。

#039 Buffer = ExAllocatePoolWithTag(NonPagedPool,(nbSlots - 1) * sizeof(FAT_DIR_ENTRY),TAG_VFAT);

#040 if (Buffer == NULL)

#041 {

#042 return STATUS_INSUFFICIENT_RESOURCES;

#043 }

#044 RtlZeroMemory(Buffer,(nbSlots - 1) * sizeof(FAT_DIR_ENTRY));

#045 pSlots = (slot *) Buffer;

#046

#047 NameA.Buffer = aName;

#048 NameA.Length = 0;

#049 NameA.MaximumLength = sizeof(aName);

#050

#051 DirContext.ShortNameU.Buffer = ShortNameBuffer;

#052 DirContext.ShortNameU.Length = 0;

#053 DirContext.ShortNameU.MaximumLength = sizeof(ShortNameBuffer);

#054

#055 RtlZeroMemory(&DirContext.DirEntry.Fat,sizeof(FAT_DIR_ENTRY));

#056

判断文件名称是否符合DOS里的8.3文件命名格式。

#057 IsNameLegal = RtlIsNameLegalDOS8Dot3(&DirContext.LongNameU,&NameA,&SpacesFound);

#058

#059 if (!IsNameLegal || SpacesFound)

#060 {

如果是非法的文件名称,或者包括有空格,就进入下面的处理。

#061 GENERATE_NAME_CONTEXT NameContext;

#062 VFAT_DIRENTRY_CONTEXT SearchContext;

#063 WCHAR ShortSearchName[13];

#064 needTilde = TRUE;

#065 needLong = TRUE;

#066 RtlZeroMemory(&NameContext,sizeof(GENERATE_NAME_CONTEXT));

#067 SearchContext.LongNameU.Buffer = LongNameBuffer;

#068 SearchContext.LongNameU.MaximumLength = sizeof(LongNameBuffer);

#069 SearchContext.ShortNameU.Buffer = ShortSearchName;

#070 SearchContext.ShortNameU.MaximumLength = sizeof(ShortSearchName);

#071

尝试100次来分配新的文件名称,并找新分配的文件名是否已经存。

#072 for (i = 0; i < 100; i++)

#073 {

#074 RtlGenerate8dot3Name(&DirContext.LongNameU,FALSE,&NameContext,&DirContext.ShortNameU);

#075 DirContext.ShortNameU.Buffer[DirContext.ShortNameU.Length / sizeof(WCHAR)] = 0;

#076 SearchContext.DirIndex = 0;

查找新分配的文件是否存在。

#077 Status = FindFile(DeviceExt,&DirContext.ShortNameU,&SearchContext,TRUE);

#078 if (!NT_SUCCESS(Status))

#079 {

#080 break;

#081 }

#082 }

尝试100次分配新的文件名称都失败,就直接返回创建文件失败。

#083 if (i == 100) /* FIXME : what to do after this ? */

#084 {

#085 ExFreePoolWithTag(Buffer,TAG_VFAT);

#086 return STATUS_UNSUCCESSFUL;

#087 }

这里就已经重新分配文件成功了,保存起来在后面使用。

#088 IsNameLegal = RtlIsNameLegalDOS8Dot3(&DirContext.ShortNameU,&SpacesFound);

#089 aName[NameA.Length]=0;

#090 }

#091 else

#092 {

#093 aName[NameA.Length] = 0;

检查文件名称是否包括点分隔符。

#094 for (posCar = 0; posCar < DirContext.LongNameU.Length / sizeof(WCHAR); posCar++)

#095 {

#096 if (DirContext.LongNameU.Buffer[posCar] == L'.')

#097 {

#098 break;

#099 }

#100 }

#101 /* check if the name and the extension contains upper case characters */

检查文件名称和扩展名称是否同为小写。

#102 RtlDowncaseUnicodeString(&DirContext.ShortNameU,&DirContext.LongNameU,FALSE);

#103 DirContext.ShortNameU.Buffer[DirContext.ShortNameU.Length / sizeof(WCHAR)] = 0;

#104 uCaseBase = wcsncmp(DirContext.LongNameU.Buffer,

#105 DirContext.ShortNameU.Buffer,posCar) ? TRUE : FALSE;

#106 if (posCar < DirContext.LongNameU.Length/sizeof(WCHAR))

#107 {

#108 i = DirContext.LongNameU.Length / sizeof(WCHAR) - posCar;

#109 uCaseExt = wcsncmp(DirContext.LongNameU.Buffer + posCar,

#110 DirContext.ShortNameU.Buffer + posCar,i) ? TRUE : FALSE;

#111 }

#112 else

#113 {

#114 uCaseExt = FALSE;

#115 }

#116 /* check if the name and the extension contains lower case characters */

检查文件名称和扩展名称是否同为大写。

#117 RtlUpcaseUnicodeString(&DirContext.ShortNameU,FALSE);

#118 DirContext.ShortNameU.Buffer[DirContext.ShortNameU.Length / sizeof(WCHAR)] = 0;

#119 lCaseBase = wcsncmp(DirContext.LongNameU.Buffer,

#120 DirContext.ShortNameU.Buffer,posCar) ? TRUE : FALSE;

#121 if (posCar < DirContext.LongNameU.Length / sizeof(WCHAR))

#122 {

#123 i = DirContext.LongNameU.Length / sizeof(WCHAR) - posCar;

#124 lCaseExt = wcsncmp(DirContext.LongNameU.Buffer + posCar,

#125 DirContext.ShortNameU.Buffer + posCar,i) ? TRUE : FALSE;

#126 }

#127 else

#128 {

#129 lCaseExt = FALSE;

#130 }

#131 if ((lCaseBase && uCaseBase) || (lCaseExt && uCaseExt))

#132 {

#133 needLong = TRUE;

#134 }

#135 }

#136 DPRINT("'%s','%wZ',needTilde=%d,needLong=%d/n",

#137 aName,needTilde,needLong);

设置FAT入口的文件名称

#138 memset(DirContext.DirEntry.Fat.ShortName,' ',11);

#139 for (i = 0; i < 8 && aName[i] && aName[i] != '.'; i++)

#140 {

#141 DirContext.DirEntry.Fat.Filename[i] = aName[i];

#142 }

#143 if (aName[i] == '.')

#144 {

#145 i++;

#146 for (j = 0; j < 3 && aName[i]; j++,i++)

#147 {

#148 DirContext.DirEntry.Fat.Ext[j] = aName[i];

#149 }

#150 }

#151 if (DirContext.DirEntry.Fat.Filename[0] == 0xe5)

#152 {

#153 DirContext.DirEntry.Fat.Filename[0] = 0x05;

#154 }

#155

如果需要长文件名称

#156 if (needLong)

#157 {

#158 RtlCopyMemory(LongNameBuffer,DirContext.LongNameU.Buffer,DirContext.LongNameU.Length);

#159 DirContext.LongNameU.Buffer = LongNameBuffer;

#160 DirContext.LongNameU.MaximumLength = sizeof(LongNameBuffer);

#161 DirContext.LongNameU.Buffer[DirContext.LongNameU.Length / sizeof(WCHAR)] = 0;

#162 memset(DirContext.LongNameU.Buffer + DirContext.LongNameU.Length / sizeof(WCHAR) + 1,0xff,

#163 DirContext.LongNameU.MaximumLength - DirContext.LongNameU.Length - sizeof(WCHAR));

#164 }

#165 else

#166 {

这里是使用短文件名称

#167 nbSlots = 1;

#168 if (lCaseBase)

#169 {

#170 DirContext.DirEntry.Fat.lCase |= VFAT_CASE_LOWER_BASE;

#171 }

#172 if (lCaseExt)

#173 {

#174 DirContext.DirEntry.Fat.lCase |= VFAT_CASE_LOWER_EXT;

#175 }

#176 }

#177

#178 DPRINT ("dos name=%11.11s/n",DirContext.DirEntry.Fat.Filename);

#179

#180 /* set attributes */

设置FAT属性

#181 DirContext.DirEntry.Fat.Attrib = ReqAttr;

#182 if (RequestedOptions & FILE_DIRECTORY_FILE)

#183 {

#184 DirContext.DirEntry.Fat.Attrib |= FILE_ATTRIBUTE_DIRECTORY;

#185 }

#186 /* set dates and times */

设置FAT创建的系统日期和时间。

#187 KeQuerySystemTime(&SystemTime);

#188 FsdSystemTimeToDosDateTime(DeviceExt,&SystemTime,&DirContext.DirEntry.Fat.CreationDate,

#189 &DirContext.DirEntry.Fat.CreationTime);

#190 DirContext.DirEntry.Fat.UpdateDate = DirContext.DirEntry.Fat.CreationDate;

#191 DirContext.DirEntry.Fat.UpdateTime = DirContext.DirEntry.Fat.CreationTime;

#192 DirContext.DirEntry.Fat.AccessDate = DirContext.DirEntry.Fat.CreationDate;

#193

#194 if (needLong)

#195 {

#196 /* calculate checksum for 8.3 name */

#197 for (pSlots[0].alias_checksum = 0,i = 0; i < 11; i++)

#198 {

#199 pSlots[0].alias_checksum = (((pSlots[0].alias_checksum & 1) << 7

#200 | ((pSlots[0].alias_checksum & 0xfe) >> 1))

#201 + DirContext.DirEntry.Fat.ShortName[i]);

#202 }

#203 /* construct slots and entry */

构造所有入口。

#204 for (i = nbSlots - 2; i >= 0; i--)

#205 {

#206 DPRINT("construct slot %d/n",i);

#207 pSlots[i].attr = 0xf;

#208 if (i)

#209 {

#210 pSlots[i].id = (unsigned char)(nbSlots - i - 1);

#211 }

#212 else

#213 {

#214 pSlots[i].id = (unsigned char)(nbSlots - i - 1 + 0x40);

#215 }

#216 pSlots[i].alias_checksum = pSlots[0].alias_checksum;

#217 RtlCopyMemory(pSlots[i].name0_4,DirContext.LongNameU.Buffer + (nbSlots - i - 2) * 13,10);

#218 RtlCopyMemory(pSlots[i].name5_10,DirContext.LongNameU.Buffer + (nbSlots - i - 2) * 13 + 5,12);

#219 RtlCopyMemory(pSlots[i].name11_12,DirContext.LongNameU.Buffer + (nbSlots - i - 2) * 13 + 11,4);

#220 }

#221 }

#222 /* try to find nbSlots contiguous entries frees in directory */

在这个目录里找到空闲位置。

#223 if (!vfatFindDirSpace(DeviceExt,nbSlots,&DirContext.StartIndex))

#224 {

#225 ExFreePoolWithTag(Buffer,TAG_VFAT);

#226 return STATUS_DISK_FULL;

#227 }

#228 DirContext.DirIndex = DirContext.StartIndex + nbSlots - 1;

#229 if (RequestedOptions & FILE_DIRECTORY_FILE)

#230 {

#231 CurrentCluster = 0;

#232 Status = NextCluster(DeviceExt,&CurrentCluster,TRUE);

#233 if (CurrentCluster == 0xffffffff || !NT_SUCCESS(Status))

#234 {

#235 ExFreePoolWithTag(Buffer,TAG_VFAT);

#236 if (!NT_SUCCESS(Status))

#237 {

#238 return Status;

#239 }

#240 return STATUS_DISK_FULL;

#241 }

#242 if (DeviceExt->FatInfo.FatType == FAT32)

#243 {

#244 DirContext.DirEntry.Fat.FirstClusterHigh = (unsigned short)(CurrentCluster >> 16);

#245 }

#246 DirContext.DirEntry.Fat.FirstCluster = (unsigned short)CurrentCluster;

#247 }

#248

#249 i = DeviceExt->FatInfo.BytesPerCluster / sizeof(FAT_DIR_ENTRY);

#250 FileOffset.u.HighPart = 0;

#251 FileOffset.u.LowPart = DirContext.StartIndex * sizeof(FAT_DIR_ENTRY);

#252 if (DirContext.StartIndex / i == DirContext.DirIndex / i)

#253 {

一个簇的处理。

#254 /* one cluster */

#255 CcPinRead(ParentFcb->FileObject,&FileOffset,nbSlots * sizeof(FAT_DIR_ENTRY),

#256 TRUE,&Context,(PVOID*)&pFatEntry);

#257 if (nbSlots > 1)

#258 {

#259 RtlCopyMemory(pFatEntry,Buffer,(nbSlots - 1) * sizeof(FAT_DIR_ENTRY));

#260 }

#261 RtlCopyMemory(pFatEntry + (nbSlots - 1),&DirContext.DirEntry.Fat,sizeof(FAT_DIR_ENTRY));

#262 }

#263 else

#264 {

二个簇的处理。

#265 /* two clusters */

#266 size = DeviceExt->FatInfo.BytesPerCluster -

#267 (DirContext.StartIndex * sizeof(FAT_DIR_ENTRY)) % DeviceExt->FatInfo.BytesPerCluster;

#268 i = size / sizeof(FAT_DIR_ENTRY);

#269 CcPinRead(ParentFcb->FileObject,size,TRUE,

#270 &Context,(PVOID*)&pFatEntry);

#271 RtlCopyMemory(pFatEntry,size);

#272 CcSetDirtyPinnedData(Context,NULL);

#273 CcUnpinData(Context);

#274 FileOffset.u.LowPart += size;

#275 CcPinRead(ParentFcb->FileObject,

#276 nbSlots * sizeof(FAT_DIR_ENTRY) - size,

#277 TRUE,(PVOID*)&pFatEntry);

#278 if (nbSlots - 1 > i)

#279 {

#280 RtlCopyMemory(pFatEntry,(PVOID)(Buffer + size),(nbSlots - 1 - i) * sizeof(FAT_DIR_ENTRY));

#281 }

#282 RtlCopyMemory(pFatEntry + nbSlots - 1 - i,sizeof(FAT_DIR_ENTRY));

#283 }

#284 CcSetDirtyPinnedData(Context,NULL);

#285 CcUnpinData(Context);

#286

#287 /* FIXME: check status */

#288 vfatMakeFCBFromDirEntry(DeviceExt,&DirContext,Fcb);

#289

#290 DPRINT("new : entry=%11.11s/n",(*Fcb)->entry.Fat.Filename);

#291 DPRINT("new : entry=%11.11s/n",DirContext.DirEntry.Fat.Filename);

#292

检查是否目录文件

#293 if (RequestedOptions & FILE_DIRECTORY_FILE)

#294 {

#295 FileOffset.QuadPart = 0;

#296 CcPinRead((*Fcb)->FileObject,DeviceExt->FatInfo.BytesPerCluster,

#297 &Context,(PVOID*)&pFatEntry);

#298 /* clear the new directory cluster */

#299 RtlZeroMemory(pFatEntry,DeviceExt->FatInfo.BytesPerCluster);

文件目录里创建缺省目录'.' '..'

#300 /* create '.' and '..' */

#301 RtlCopyMemory(&pFatEntry[0].Attrib,&DirContext.DirEntry.Fat.Attrib,sizeof(FAT_DIR_ENTRY) - 11);

#302 RtlCopyMemory(pFatEntry[0].ShortName,". ",11);

#303 RtlCopyMemory(&pFatEntry[1].Attrib,sizeof(FAT_DIR_ENTRY) - 11);

#304 RtlCopyMemory(pFatEntry[1].ShortName,".. ",11);

#305 pFatEntry[1].FirstCluster = ParentFcb->entry.Fat.FirstCluster;

#306 pFatEntry[1].FirstClusterHigh = ParentFcb->entry.Fat.FirstClusterHigh;

如果这里根目录,就设置父目录为空,不能再往上查看。

#307 if (vfatFCBIsRoot(ParentFcb))

#308 {

#309 pFatEntry[1].FirstCluster = 0;

#310 pFatEntry[1].FirstClusterHigh = 0;

#311 }

#312 CcSetDirtyPinnedData(Context,NULL);

#313 CcUnpinData(Context);

#314 }

#315 ExFreePoolWithTag(Buffer,TAG_VFAT);

#316 DPRINT("addentry ok/n");

#317 return STATUS_SUCCESS;

#318}

原文链接:https://www.f2er.com/react/308397.html

猜你在找的React相关文章