微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

reactos操作系统实现(126)

VfatCreateFile函数主要用来创建或者打开一个文件,具体实现如下:

#001 static NTSTATUS

#002 VfatCreateFile ( PDEVICE_OBJECT DeviceObject,PIRP Irp )

#003 /*

#004 * FUNCTION: Create or open a file

#005 */

#006 {

#007 PIO_STACK_LOCATION Stack;

#008 PFILE_OBJECT FileObject;

#009 NTSTATUS Status = STATUS_SUCCESS;

#010 PDEVICE_EXTENSION DeviceExt;

#011 ULONG Requesteddisposition,RequestedOptions;

#012 PVFATCCB pCcb;

#013 PVFATFCB pFcb = NULL;

#014 PVFATFCB ParentFcb = NULL;

#015 PWCHAR c,last;

#016 BOOLEAN PagingFileCreate = FALSE;

#017 BOOLEAN Dots;

#018 UNICODE_STRING FileNameU;

#019 UNICODE_STRING PathNameU;

#020

#021 /* Unpack the varIoUs parameters. */

获取当前IRP栈位置。

#022 Stack = IoGetCurrentIrpStackLocation (Irp);

获取请求的参数。

#023 Requesteddisposition = ((Stack->Parameters.Create.Options >> 24) & 0xff);

#024 RequestedOptions =

#025 Stack->Parameters.Create.Options & FILE_VALID_OPTION_FLAGS;

#026 PagingFileCreate = (Stack->Flags & SL_OPEN_PAGING_FILE) ? TRUE : FALSE;

#027 FileObject = Stack->FileObject;

#028 DeviceExt = DeviceObject->DeviceExtension;

#029

检查参数是否有效。

#030 /* Check their validity. */

#031 if (RequestedOptions & FILE_DIRECTORY_FILE &&

#032 Requesteddisposition == FILE_SUPERSEDE)

#033 {

#034 return(STATUS_INVALID_ParaMETER);

#035 }

#036

#037 if (RequestedOptions & FILE_DIRECTORY_FILE &&

#038 RequestedOptions & FILE_NON_DIRECTORY_FILE)

#039 {

#040 return(STATUS_INVALID_ParaMETER);

#041 }

#042

#043 /* This a open operation for the volume itself */

文件卷的操作。

#044 if (FileObject->FileName.Length == 0 &&

#045 FileObject->RelatedFileObject == NULL)

#046 {

#047 if (Requesteddisposition == FILE_CREATE ||

#048 Requesteddisposition == FILE_OVERWRITE_IF ||

#049 Requesteddisposition == FILE_SUPERSEDE)

#050 {

#051 return(STATUS_ACCESS_DENIED);

#052 }

#053 if (RequestedOptions & FILE_DIRECTORY_FILE)

#054 {

#055 return(STATUS_NOT_A_DIRECTORY);

#056 }

获取当前设备的文件卷。

#057 pFcb = DeviceExt->VolumeFcb;

#058 pCcb = ExAllocateFromNPagedLookasideList(&VfatglobalData->CcbLookasideList);

#059 if (pCcb == NULL)

#060 {

#061 return (STATUS_INSUFFICIENT_RESOURCES);

#062 }

#063 RtlZeroMemory(pCcb,sizeof(VFATCCB));

#064 FileObject->SectionObjectPointer = &pFcb->SectionObjectPointers;

#065 FileObject->FsContext = pFcb;

#066 FileObject->FsContext2 = pCcb;

#067 pFcb->RefCount++;

#068

#069 Irp->IoStatus.information = FILE_OPENED;

打开当前设备的文件卷成功返回、

#070 return(STATUS_SUCCESS);

#071 }

#072

#073 /*

#074 * Check for illegal characters and illegale dot sequences in the file name

#075 */

检查文件名称是否合法。

#076 PathNameU = FileObject->FileName;

#077 c = PathNameU.Buffer + PathNameU.Length / sizeof(WCHAR);

#078 last = c - 1;

#079 Dots = TRUE;

#080 while (c-- > PathNameU.Buffer)

#081 {

#082 if (*c == L'//' || c == PathNameU.Buffer)

#083 {

#084 if (Dots && last > c)

#085 {

#086 return(STATUS_OBJECT_NAME_INVALID);

#087 }

#088 last = c - 1;

#089 Dots = TRUE;

#090 }

#091 else if (*c != L'.')

#092 {

#093 Dots = FALSE;

#094 }

#095

#096 if (*c != '//' && vfatIsLongIllegal(*c))

#097 {

#098 return(STATUS_OBJECT_NAME_INVALID);

#099 }

#100 }

#101 if (FileObject->RelatedFileObject && PathNameU.Buffer[0] == L'//')

#102 {

#103 return(STATUS_OBJECT_NAME_INVALID);

#104 }

#105 if (PathNameU.Length > sizeof(WCHAR) && PathNameU.Buffer[PathNameU.Length/sizeof(WCHAR)-1] == L'//')

#106 {

#107 PathNameU.Length -= sizeof(WCHAR);

#108 }

#109

#110 /* Try opening the file. */

尝试打开文件

#111 Status = VfatOpenFile (DeviceExt,&PathNameU,FileObject,&ParentFcb);

#112

#113 /*

#114 * If the directory containing the file to open doesn't exist then

#115 * fail immediately

#116 */

如果包括这个文件的目录都不存在,就立即返回出错。

#117 if (Status == STATUS_OBJECT_PATH_NOT_FOUND ||

#118 Status == STATUS_INVALID_ParaMETER ||

#119 Status == STATUS_DELETE_PENDING)

#120 {

#121 if (ParentFcb)

#122 {

#123 vfatReleaseFCB (DeviceExt,ParentFcb);

#124 }

#125 return(Status);

#126 }

如果获取状态和父目录控制块出错就返回。

#127 if (!NT_SUCCESS(Status) && ParentFcb == NULL)

#128 {

#129 DPRINT1("VfatOpenFile faild for '%wZ',status %x/n",Status);

#130 return Status;

#131 }

#132

#133 /*

#134 * If the file open Failed then create the required file

#135 */

如果打开文件失败,就尝试创建文件

#136 if (!NT_SUCCESS (Status))

#137 {

如果还设置可以创建文件的标志,就进入创建文件的过程。

#138 if (Requesteddisposition == FILE_CREATE ||

#139 Requesteddisposition == FILE_OPEN_IF ||

#140 Requesteddisposition == FILE_OVERWRITE_IF ||

#141 Requesteddisposition == FILE_SUPERSEDE)

#142 {

获取文件属性

#143 ULONG Attributes;

#144 Attributes = Stack->Parameters.Create.FileAttributes;

#145

从路径里分离出文件名称

#146 vfatSplitPathName(&PathNameU,NULL,&FileNameU);

为这个文件添加一个FAT的入口项。

#147 Status = VfatAddEntry (DeviceExt,&FileNameU,&pFcb,ParentFcb,RequestedOptions,

#148 (UCHAR)(Attributes & FILE_ATTRIBUTE_VALID_FLAGS));

删除父目录分配的文件控制块。

#149 vfatReleaseFCB (DeviceExt,ParentFcb);

#150 if (NT_SUCCESS (Status))

#151 {

绑定文件控制块到这个文件对象里。

#152 Status = vfatAttachFCBToFileObject (DeviceExt,pFcb,FileObject);

#153 if ( !NT_SUCCESS(Status) )

#154 {

#155 vfatReleaseFCB (DeviceExt,pFcb);

#156 return Status;

#157 }

#158

设置IRP返回创建文件成功。

#159 Irp->IoStatus.information = FILE_CREATED;

分配文件大小。

#160 VfatSetAllocationSizeinformation(FileObject,

#161 pFcb,

#162 DeviceExt,

#163 &Irp->Overlay.AllocationSize);

设置文件的扩展属性

#164 VfatSetExtendedAttributes(FileObject,

#165 Irp->AssociatedIrp.SystemBuffer,

#166 Stack->Parameters.Create.EaLength);

#167

如果文件分页文件,就置相应的标志位。

#168 if (PagingFileCreate)

#169 {

#170 pFcb->Flags |= FCB_IS_PAGE_FILE;

#171 }

#172 }

#173 else

#174 {

#175 return(Status);

#176 }

#177 }

#178 else

#179 {

#180 if (ParentFcb)

#181 {

#182 vfatReleaseFCB (DeviceExt,ParentFcb);

#183 }

#184 return(Status);

#185 }

#186 }

#187 else

#188 {

打开文件成功。

#189 if (ParentFcb)

#190 {

#191 vfatReleaseFCB (DeviceExt,ParentFcb);

#192 }

#193 /* Otherwise fail if the caller wanted to create a new file */

如果还是创建相同的文件,那么再创建相同的文件就会失败。

#194 if (Requesteddisposition == FILE_CREATE)

#195 {

#196 Irp->IoStatus.information = FILE_EXISTS;

#197 VfatCloseFile (DeviceExt,FileObject);

#198 return(STATUS_OBJECT_NAME_COLLISION);

#199 }

#200

#201 pFcb = FileObject->FsContext;

#202

如果打开这个文件次数不为0,说明这个文件已经有一个打开的实例,检查文件是否允许共享打开。

#203 if (pFcb->OpenHandleCount != 0)

#204 {

检查文件安全属性

#205 Status = IoCheckshareAccess(Stack->Parameters.Create.SecurityContext->DesiredAccess,

#206 Stack->Parameters.Create.ShareAccess,

#207 FileObject,

#208 &pFcb->FCBShareAccess,

#209 FALSE);

如果不允许共享打开,就出错返回。

#210 if (!NT_SUCCESS(Status))

#211 {

#212 VfatCloseFile (DeviceExt,FileObject);

#213 return(Status);

#214 }

#215 }

#216

#217 /*

#218 * Check the file has the requested attributes

#219 */

如果请求打开的不是目录文件,但当前的文件控制块是目录,那么就与请求的不一致出错。

#220 if (RequestedOptions & FILE_NON_DIRECTORY_FILE &&

#221 *pFcb->Attributes & FILE_ATTRIBUTE_DIRECTORY)

#222 {

#223 VfatCloseFile (DeviceExt,FileObject);

#224 return(STATUS_FILE_IS_A_DIRECTORY);

#225 }

如果请求的是目录,但文件控制块不是目录,那么也是出错的情况。

#226 if (RequestedOptions & FILE_DIRECTORY_FILE &&

#227 !(*pFcb->Attributes & FILE_ATTRIBUTE_DIRECTORY))

#228 {

#229 VfatCloseFile (DeviceExt,FileObject);

#230 return(STATUS_NOT_A_DIRECTORY);

#231 }

#232 #ifndef USE_ROS_CC_AND_FS

#233 if (!(*pFcb->Attributes & FILE_ATTRIBUTE_DIRECTORY))

#234 {

#235 if (Stack->Parameters.Create.SecurityContext->DesiredAccess & FILE_WRITE_DATA ||

#236 Requesteddisposition == FILE_OVERWRITE ||

#237 Requesteddisposition == FILE_OVERWRITE_IF)

#238 {

#239 if (!MmFlushImageSection(&pFcb->SectionObjectPointers,MmFlushForWrite))

#240 {

#241 DPRINT1("%wZ/n",&pFcb->PathNameU);

#242 DPRINT1("%d %d %d/n",Stack->Parameters.Create.SecurityContext->DesiredAccess &

#243 FILE_WRITE_DATA,

#244 Requesteddisposition == FILE_OVERWRITE,Requesteddisposition

#245 == FILE_OVERWRITE_IF);

#246 VfatCloseFile (DeviceExt,FileObject);

#247 return STATUS_SHARING_VIOLATION;

#248 }

#249 }

#250 }

#251 #endif

创建分页文件

#252 if (PagingFileCreate)

#253 {

#254 /* FIXME:

#255 * Do more checking for page files. It is possible,

#256 * that the file was opened and closed prevIoUsly

#257 * as a normal cached file. In this case,the cache

#258 * manager has referenced the fileobject and the fcb

#259 * is held in memory. Try to remove the fileobject

#260 * from cache manager and use the fcb.

#261 */

#262 if (pFcb->RefCount > 1)

#263 {

#264 if(!(pFcb->Flags & FCB_IS_PAGE_FILE))

#265 {

#266 VfatCloseFile(DeviceExt,FileObject);

#267 return(STATUS_INVALID_ParaMETER);

#268 }

#269 }

#270 else

#271 {

#272 pFcb->Flags |= FCB_IS_PAGE_FILE;

#273 }

#274 }

#275 else

#276 {

#277 if (pFcb->Flags & FCB_IS_PAGE_FILE)

#278 {

#279 VfatCloseFile(DeviceExt,FileObject);

#280 return(STATUS_INVALID_ParaMETER);

#281 }

#282 }

#283

#284

如果请求的文件需要覆盖写入,就设置文件的大小。

#285 if (Requesteddisposition == FILE_OVERWRITE ||

#286 Requesteddisposition == FILE_OVERWRITE_IF ||

#287 Requesteddisposition == FILE_SUPERSEDE)

#288 {

#289 ExAcquireResourceExclusiveLite(&(pFcb->MainResource),TRUE);

#290 Status = VfatSetAllocationSizeinformation (FileObject,

#291 pFcb,

#292 DeviceExt,

#293 &Irp->Overlay.AllocationSize);

#294 ExReleaseResourceLite(&(pFcb->MainResource));

#295 if (!NT_SUCCESS (Status))

#296 {

#297 VfatCloseFile (DeviceExt,FileObject);

#298 return(Status);

#299 }

#300 }

#301

#302 if (Requesteddisposition == FILE_SUPERSEDE)

#303 {

#304 Irp->IoStatus.information = FILE_SUPERSEDED;

#305 }

#306 else if (Requesteddisposition == FILE_OVERWRITE ||

#307 Requesteddisposition == FILE_OVERWRITE_IF)

#308 {

#309 Irp->IoStatus.information = FILE_OVERWRITTEN;

#310 }

#311 else

#312 {

#313 Irp->IoStatus.information = FILE_OPENED;

#314 }

#315 }

#316

如果文件是第一次打开,就设置相应的文件共享属性

#317 if (pFcb->OpenHandleCount == 0)

#318 {

#319 IoSetShareAccess(Stack->Parameters.Create.SecurityContext->DesiredAccess,

#320 Stack->Parameters.Create.ShareAccess,

#321 FileObject,

#322 &pFcb->FCBShareAccess);

#323 }

#324 else

#325 {

否则更新当前文件共享属性

#326 IoUpdateShareAccess(

#327 FileObject,

#328 &pFcb->FCBShareAccess

#329 );

#330

#331 }

#332

文件已经成功打开,增加引用计数。

#333 pFcb->OpenHandleCount++;

#334

#335 /* FIXME : test write access if requested */

#336

#337 return(Status);

#338}

原文地址:https://www.jb51.cc/react/308398.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐