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} (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |