3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: services/fs/vfat/iface.c
6 * PURPOSE: VFAT Filesystem
7 * PROGRAMMER: Jason Filby (jasonfilby@yahoo.com)
10 24-10-1998 Fixed bugs in long filename support
11 Fixed a bug that prevented unsuccessful file open requests being reported
12 Now works with long filenames that span over a sector boundary
13 28-10-1998 Reads entire FAT into memory
14 VFatReadSector modified to read in more than one sector at a time
15 7-11-1998 Fixed bug that assumed that directory data could be fragmented
16 8-12-1998 Added FAT32 support
17 Added initial writability functions
18 WARNING: DO NOT ATTEMPT TO TEST WRITABILITY FUNCTIONS!!!
19 12-12-1998 Added basic support for FILE_STANDARD_INFORMATION request
23 /* INCLUDES *****************************************************************/
25 #include <ddk/ntddk.h>
26 #include <internal/string.h>
28 #include <ddk/cctypes.h>
31 #include <internal/debug.h>
36 /* GLOBALS *****************************************************************/
38 static PDRIVER_OBJECT VFATDriverObject
;
41 /* FUNCTIONS ****************************************************************/
43 ULONG
Fat32GetNextCluster(PDEVICE_EXTENSION DeviceExt
, ULONG CurrentCluster
)
45 * FUNCTION: Retrieve the next FAT32 cluster from the FAT table via a physical
53 Block
= ExAllocatePool(NonPagedPool
,1024);
54 FATsector
=CurrentCluster
/(512/sizeof(ULONG
));
55 FATeis
=CurrentCluster
-(FATsector
*(512/sizeof(ULONG
)));
56 VFATReadSectors(DeviceExt
->StorageDevice
57 ,(ULONG
)(DeviceExt
->FATStart
+FATsector
), 1,(UCHAR
*) Block
);
58 CurrentCluster
= Block
[FATeis
];
59 if (CurrentCluster
>= 0xffffff8 && CurrentCluster
<= 0xfffffff)
60 CurrentCluster
= 0xffffffff;
62 return(CurrentCluster
);
65 ULONG
Fat16GetNextCluster(PDEVICE_EXTENSION DeviceExt
, ULONG CurrentCluster
)
67 * FUNCTION: Retrieve the next FAT16 cluster from the FAT table from the
72 Block
=(PUSHORT
)DeviceExt
->FAT
;
73 CurrentCluster
= Block
[CurrentCluster
];
74 if (CurrentCluster
>= 0xfff8 && CurrentCluster
<= 0xffff)
75 CurrentCluster
= 0xffffffff;
76 return(CurrentCluster
);
79 ULONG
Fat12GetNextCluster(PDEVICE_EXTENSION DeviceExt
, ULONG CurrentCluster
)
81 * FUNCTION: Retrieve the next FAT12 cluster from the FAT table from the
85 unsigned char* CBlock
;
88 CBlock
= DeviceExt
->FAT
;
89 FATOffset
= (CurrentCluster
* 12)/ 8;//first byte containing value
90 if ((CurrentCluster
% 2) == 0)
92 Entry
= CBlock
[FATOffset
];
93 Entry
|= ((CBlock
[FATOffset
+1] & 0xf)<<8);
97 Entry
= (CBlock
[FATOffset
] >> 4);
98 Entry
|= (CBlock
[FATOffset
+1] << 4);
100 if (Entry
>= 0xff8 && Entry
<= 0xfff)
105 ULONG
GetNextCluster(PDEVICE_EXTENSION DeviceExt
, ULONG CurrentCluster
)
107 * FUNCTION: Retrieve the next cluster depending on the FAT type
111 if (DeviceExt
->FatType
== FAT16
)
112 return(Fat16GetNextCluster(DeviceExt
, CurrentCluster
));
113 else if (DeviceExt
->FatType
== FAT32
)
114 return(Fat32GetNextCluster(DeviceExt
, CurrentCluster
));
116 return(Fat12GetNextCluster(DeviceExt
, CurrentCluster
));
119 ULONG
FAT16FindAvailableCluster(PDEVICE_EXTENSION DeviceExt
)
121 * FUNCTION: Finds the first available cluster in a FAT16 table
126 Block
=(PUSHORT
)DeviceExt
->FAT
;
127 for(i
=2;i
<(DeviceExt
->Boot
->FATSectors
*256) ;i
++)
130 /* Give an error message (out of disk space) if we reach here) */
134 ULONG
FAT12FindAvailableCluster(PDEVICE_EXTENSION DeviceExt
)
136 * FUNCTION: Finds the first available cluster in a FAT12 table
141 PUCHAR CBlock
=DeviceExt
->FAT
;
143 for(i
=2;i
<((DeviceExt
->Boot
->FATSectors
*512*8)/12) ;i
++)
145 FATOffset
= (i
* 12)/8;
148 Entry
= CBlock
[FATOffset
];
149 Entry
|= ((CBlock
[FATOffset
+ 1] & 0xf)<<8);
153 Entry
= (CBlock
[FATOffset
] >> 4);
154 Entry
|= (CBlock
[FATOffset
+ 1] << 4);
159 /* Give an error message (out of disk space) if we reach here) */
160 DbgPrint("Disk full, %d clusters used\n",i
);
164 ULONG
FAT32FindAvailableCluster(PDEVICE_EXTENSION DeviceExt
)
166 * FUNCTION: Finds the first available cluster in a FAT32 table
172 Block
= ExAllocatePool(NonPagedPool
,BLOCKSIZE
);
174 ;sector
< ((struct _BootSector32
*)(DeviceExt
->Boot
))->FATSectors32
177 VFATReadSectors(DeviceExt
->StorageDevice
178 ,(ULONG
)(DeviceExt
->FATStart
+sector
), 1,(UCHAR
*) Block
);
185 return (i
+sector
*128);
189 /* Give an error message (out of disk space) if we reach here) */
194 void FAT12WriteCluster(PDEVICE_EXTENSION DeviceExt
, ULONG ClusterToWrite
,
197 * FUNCTION: Writes a cluster to the FAT12 physical and in-memory tables
202 PUCHAR CBlock
=DeviceExt
->FAT
;
204 FATOffset
= (ClusterToWrite
* 12)/8;
205 if ((ClusterToWrite
% 2) == 0)
207 CBlock
[FATOffset
]=NewValue
;
208 CBlock
[FATOffset
+ 1] &=0xf0;
209 CBlock
[FATOffset
+ 1]
210 |= (NewValue
&0xf00)>>8;
214 CBlock
[FATOffset
] &=0x0f;
216 |= (NewValue
&0xf)<<4;
217 CBlock
[FATOffset
+1]=NewValue
>>4;
219 /* Write the changed FAT sector(s) to disk */
220 FATsector
=FATOffset
/BLOCKSIZE
;
221 for(i
=0;i
<DeviceExt
->Boot
->FATCount
;i
++)
223 if( (FATOffset
%BLOCKSIZE
)==(BLOCKSIZE
-1))//entry is on 2 sectors
225 VFATWriteSectors(DeviceExt
->StorageDevice
,
226 DeviceExt
->FATStart
+FATsector
227 +i
*DeviceExt
->Boot
->FATSectors
,
229 CBlock
+FATsector
*512);
233 VFATWriteSectors(DeviceExt
->StorageDevice
,
234 DeviceExt
->FATStart
+FATsector
235 +i
*DeviceExt
->Boot
->FATSectors
,
237 CBlock
+FATsector
*512);
242 void FAT16WriteCluster(PDEVICE_EXTENSION DeviceExt
, ULONG ClusterToWrite
,
245 * FUNCTION: Writes a cluster to the FAT16 physical and in-memory tables
250 DbgPrint("FAT16WriteCluster %u : %u\n",ClusterToWrite
,NewValue
);
251 Block
=(PUSHORT
)DeviceExt
->FAT
;
252 FATsector
=ClusterToWrite
/(512/sizeof(USHORT
));
254 /* Update the in-memory FAT */
255 Block
[ClusterToWrite
] = NewValue
;
256 /* Write the changed FAT sector to disk */
257 VFATWriteSectors(DeviceExt
->StorageDevice
,
258 DeviceExt
->FATStart
+FATsector
,
263 void FAT32WriteCluster(PDEVICE_EXTENSION DeviceExt
, ULONG ClusterToWrite
,
266 * FUNCTION: Writes a cluster to the FAT32 physical tables
272 DbgPrint("FAT32WriteCluster %u : %u\n",ClusterToWrite
,NewValue
);
273 Block
= ExAllocatePool(NonPagedPool
,BLOCKSIZE
);
274 FATsector
=ClusterToWrite
/128;
275 FATeis
=ClusterToWrite
-(FATsector
*128);
276 /* load sector, change value, then rewrite sector */
277 VFATReadSectors(DeviceExt
->StorageDevice
,
278 DeviceExt
->FATStart
+FATsector
,
281 Block
[FATeis
] = NewValue
;
282 VFATWriteSectors(DeviceExt
->StorageDevice
,
283 DeviceExt
->FATStart
+FATsector
,
289 void WriteCluster(PDEVICE_EXTENSION DeviceExt
, ULONG ClusterToWrite
,
292 * FUNCTION: Write a changed FAT entry
295 if(DeviceExt
->FatType
==FAT16
)
296 FAT16WriteCluster(DeviceExt
, ClusterToWrite
, NewValue
);
297 else if(DeviceExt
->FatType
==FAT32
)
298 FAT32WriteCluster(DeviceExt
, ClusterToWrite
, NewValue
);
300 FAT12WriteCluster(DeviceExt
, ClusterToWrite
, NewValue
);
303 ULONG
GetNextWriteCluster(PDEVICE_EXTENSION DeviceExt
, ULONG CurrentCluster
)
305 * FUNCTION: Determines the next cluster to be written
308 ULONG LastCluster
, NewCluster
;
310 /* Find out what was happening in the last cluster's AU */
311 LastCluster
=GetNextCluster(DeviceExt
,CurrentCluster
);
312 /* Check to see if we must append or overwrite */
313 if (LastCluster
==0xffffffff)
314 {//we are after last existing cluster : we must add one to file
316 /* Firstly, find the next available open allocation unit */
317 if(DeviceExt
->FatType
== FAT16
)
318 NewCluster
= FAT16FindAvailableCluster(DeviceExt
);
319 else if(DeviceExt
->FatType
== FAT32
)
320 NewCluster
= FAT32FindAvailableCluster(DeviceExt
);
322 NewCluster
= FAT12FindAvailableCluster(DeviceExt
);
323 /* Mark the new AU as the EOF */
324 WriteCluster(DeviceExt
, NewCluster
, 0xFFFFFFFF);
325 /* Now, write the AU of the LastCluster with the value of the newly
328 WriteCluster(DeviceExt
, CurrentCluster
, NewCluster
);
329 // fill cluster with zero : essential for directories, not for file
330 Buffer2
=ExAllocatePool(NonPagedPool
,DeviceExt
->BytesPerCluster
);
331 memset(Buffer2
,0,DeviceExt
->BytesPerCluster
);
332 VFATWriteCluster(DeviceExt
,Buffer2
,NewCluster
);
334 /* Return NewCluster as CurrentCluster */
339 /* Overwrite: Return LastCluster as CurrentCluster */
344 ULONG
ClusterToSector(PDEVICE_EXTENSION DeviceExt
,
345 unsigned long Cluster
)
347 * FUNCTION: Converts the cluster number to a sector number for this physical
351 return DeviceExt
->dataStart
+((Cluster
-2)*DeviceExt
->Boot
->SectorsPerCluster
);
354 void RtlAnsiToUnicode(PWSTR Dest
, PCH Source
, ULONG Length
)
356 * FUNCTION: Convert an ANSI string to it's Unicode equivalent
361 for (i
=0; (i
<Length
&& Source
[i
] != ' '); i
++)
368 void RtlCatAnsiToUnicode(PWSTR Dest
, PCH Source
, ULONG Length
)
370 * FUNCTION: Appends a converted ANSI to Unicode string to the end of an
371 * existing Unicode string
380 for (i
=0; (i
<Length
&& Source
[i
] != ' '); i
++)
387 void vfat_initstr(wchar_t *wstr
, ULONG wsize
)
389 * FUNCTION: Initialize a string for use with a long file name
394 for(i
=0; i
<wsize
; i
++)
402 wchar_t * vfat_wcsncat(wchar_t * dest
, const wchar_t * src
,size_t wstart
, size_t wcount
)
404 * FUNCTION: Append a string for use with a long file name
410 for(i
=0; i
<wcount
; i
++)
415 dest
=dest
-(wcount
+wstart
);
420 wchar_t * vfat_wcsncpy(wchar_t * dest
, const wchar_t *src
,size_t wcount
)
422 * FUNCTION: Copy a string for use with long file names
427 for (i
=0;i
<wcount
;i
++)
435 wchar_t * vfat_movstr(wchar_t *src
, ULONG dpos
,
436 ULONG spos
, ULONG len
)
438 * FUNCTION: Move the characters in a string to a new position in the same
448 src
[dpos
++]=src
[spos
++];
457 src
[dpos
--]=src
[spos
--];
464 BOOLEAN
IsLastEntry(FATDirEntry
*pEntry
)
466 * FUNCTION: Determine if the given directory entry is the last
469 return(pEntry
->Filename
[0] == 0);
472 BOOLEAN
IsVolEntry(FATDirEntry
*pEntry
)
474 * FUNCTION: Determine if the given directory entry is a vol entry
477 if( (pEntry
->Attrib
)==0x28 ) return TRUE
;
481 BOOLEAN
IsDeletedEntry(FATDirEntry
*pEntry
)
483 * FUNCTION: Determines if the given entry is a deleted one
486 /* Checks special character */
487 return (pEntry
->Filename
[0] == 0xe5);
490 BOOLEAN
GetEntryName(PDEVICE_EXTENSION DeviceExt
,PVfatFCB pFcb
,PULONG pEntry
491 , PWSTR Name
,FATDirEntry
*pFatEntry
)
493 * FUNCTION: Retrieves the file name, be it in short or long file name format
497 ULONG cpos
,LengthRead
;
500 test2
= (slot
*)pFatEntry
;
504 if (IsDeletedEntry(pFatEntry
))
509 if(test2
->attr
== 0x0f)
510 { // long name : we read the long name, then we read the entry
511 vfat_initstr(Name
, 256);
512 vfat_wcsncpy(Name
,test2
->name0_4
,5);
513 vfat_wcsncat(Name
,test2
->name5_10
,5,6);
514 vfat_wcsncat(Name
,test2
->name11_12
,11,2);
517 while((test2
->id
!=0x41) && (test2
->id
!=0x01) &&
521 Status
=FsdReadFile(DeviceExt
,pFcb
,pFatEntry
,sizeof(FATDirEntry
)
522 ,(*pEntry
)*sizeof(FATDirEntry
),&LengthRead
);
523 if(!(NT_SUCCESS(Status
))) return FALSE
;
525 vfat_movstr(Name
, 13, 0, cpos
*13);
526 vfat_wcsncpy(Name
,test2
->name0_4
, 5);
527 vfat_wcsncat(Name
,test2
->name5_10
,5,6);
528 vfat_wcsncat(Name
,test2
->name11_12
,11,2);
530 // now read the entry
532 Status
=FsdReadFile(DeviceExt
,pFcb
,pFatEntry
,sizeof(FATDirEntry
)
533 ,(*pEntry
)*sizeof(FATDirEntry
),&LengthRead
);
534 if (IsDeletedEntry(pFatEntry
))
539 RtlAnsiToUnicode(Name
,pFatEntry
->Filename
,8);
540 if (pFatEntry
->Ext
[0]!=' ')
542 RtlCatAnsiToUnicode(Name
,".",1);
544 RtlCatAnsiToUnicode(Name
,pFatEntry
->Ext
,3);
548 BOOLEAN
wstrcmpi(PWSTR s1
, PWSTR s2
)
550 * FUNCTION: Compare to wide character strings
551 * return TRUE if s1==s2
554 while (wtolower(*s1
)==wtolower(*s2
))
556 if ((*s1
)==0 && (*s2
)==0)
566 BOOLEAN
wstrcmpjoki(PWSTR s1
, PWSTR s2
)
568 * FUNCTION: Compare to wide character strings, s2 with jokers (* or ?)
569 * return TRUE if s1 like s2
572 while ((*s2
=='?')||(wtolower(*s1
)==wtolower(*s2
)))
574 if ((*s1
)==0 && (*s2
)==0)
583 if (wstrcmpjoki(s1
,s2
)) return TRUE
;
586 if ((*s1
)==0 && (*s2
)==0)
591 NTSTATUS
FindFile(PDEVICE_EXTENSION DeviceExt
, PVfatFCB Fcb
,
592 PVfatFCB Parent
, PWSTR FileToFind
,ULONG
*Entry
)
594 * FUNCTION: Find a file
600 FATDirEntry FatEntry
;
604 if (Parent
== NULL
||Parent
->entry
.FirstCluster
==1)
606 Size
= DeviceExt
->rootDirectorySectors
;//FIXME : in fat32, no limit
607 if(FileToFind
[0]==0 ||(FileToFind
[0]=='\\' && FileToFind
[1]==0))
608 {// it's root : complete essentials fields then return ok
609 memset(Fcb
,0,sizeof(VfatFCB
));
610 memset(Fcb
->entry
.Filename
,' ',11);
611 Fcb
->entry
.FileSize
=DeviceExt
->rootDirectorySectors
*BLOCKSIZE
;
612 Fcb
->entry
.Attrib
=FILE_ATTRIBUTE_DIRECTORY
;
613 if (DeviceExt
->FatType
== FAT32
)
614 Fcb
->entry
.FirstCluster
=2;
615 else Fcb
->entry
.FirstCluster
=1;//FIXME : is 1 the good value for mark root?
617 return(STATUS_SUCCESS
);
622 memset(&TempFcb
,0,sizeof(VfatFCB
));
623 memset(TempFcb
.entry
.Filename
,' ',11);
624 TempFcb
.entry
.FileSize
=DeviceExt
->rootDirectorySectors
*BLOCKSIZE
;
625 TempFcb
.entry
.Attrib
=FILE_ATTRIBUTE_DIRECTORY
;
626 if (DeviceExt
->FatType
== FAT32
)
627 TempFcb
.entry
.FirstCluster
=2;
629 TempFcb
.entry
.FirstCluster
=1;//FIXME : is 1 the good value for mark root?
632 i
=(Entry
)?(*Entry
):0;
635 Status
=FsdReadFile(DeviceExt
,Parent
,&FatEntry
,sizeof(FATDirEntry
)
636 ,i
*sizeof(FATDirEntry
),&LengthRead
);
637 if(!NT_SUCCESS(Status
))
639 if (IsVolEntry(&FatEntry
))
641 if (IsLastEntry(&FatEntry
))
644 return(STATUS_UNSUCCESSFUL
);
646 if (GetEntryName(DeviceExt
,Parent
,&i
,name
,&FatEntry
))
648 if (wstrcmpjoki(name
,FileToFind
))
650 memcpy(&Fcb
->entry
,&FatEntry
,sizeof(FATDirEntry
));
651 vfat_wcsncpy(Fcb
->ObjectName
,name
,MAX_PATH
);
653 return(STATUS_SUCCESS
);
658 return(STATUS_UNSUCCESSFUL
);
662 NTSTATUS
FsdCloseFile(PDEVICE_EXTENSION DeviceExt
, PFILE_OBJECT FileObject
)
664 * FUNCTION: Closes a file
669 //FIXME : update entry in directory ?
670 pCcb
= (PVfatCCB
)(FileObject
->FsContext2
);
673 if(pFcb
->RefCount
<=0)
676 pFcb
->prevFcb
->nextFcb
=pFcb
->nextFcb
;
678 pFirstFcb
=pFcb
->nextFcb
;
680 pFcb
->nextFcb
->prevFcb
=pFcb
->prevFcb
;
684 return STATUS_SUCCESS
;
687 NTSTATUS
FsdOpenFile(PDEVICE_EXTENSION DeviceExt
, PFILE_OBJECT FileObject
,
690 * FUNCTION: Opens a file
697 PVfatFCB Fcb
,pRelFcb
;
699 PVfatCCB newCCB
,pRelCcb
;
701 PFILE_OBJECT pRelFileObject
;
702 PWSTR AbsFileName
=NULL
;
704 if(FileObject
->FileName
.Length
>0
705 && FileName
[FileObject
->FileName
.Length
-1]=='\\')
706 FileName
[FileObject
->FileName
.Length
-1]=0;
707 // treat relative name
708 if(FileObject
->RelatedFileObject
)
710 DbgPrint("try related for %w\n",FileName
);
711 pRelFileObject
=FileObject
->RelatedFileObject
;
712 pRelCcb
=pRelFileObject
->FsContext2
;
714 pRelFcb
=pRelCcb
->pFcb
;
716 // verify related object is a directory and target name don't start with \.
717 if( !(pRelFcb
->entry
.Attrib
& FILE_ATTRIBUTE_DIRECTORY
)
718 || (FileName
[0]!= '\\') )
720 Status
=STATUS_INVALID_PARAMETER
;
723 // construct absolute path name
724 AbsFileName
=ExAllocatePool(NonPagedPool
,MAX_PATH
*sizeof(WCHAR
));
725 for (i
=0;pRelFcb
->PathName
[i
];i
++)
726 AbsFileName
[i
]=pRelFcb
->PathName
[i
];
727 AbsFileName
[i
++]='\\';
728 for (j
=0;FileName
[j
]&&i
<MAX_PATH
;j
++)
729 AbsFileName
[i
++]=FileName
[j
];
732 FileName
=AbsFileName
;
734 // try first to find an existing FCB in memory
735 for (Fcb
=pFirstFcb
;Fcb
; Fcb
=Fcb
->nextFcb
)
737 if (DeviceExt
==Fcb
->pDevExt
738 && wstrcmpi(FileName
,Fcb
->PathName
))
741 FileObject
->FsContext
=(PVOID
) &Fcb
->NTRequiredFCB
;
742 newCCB
= ExAllocatePool(NonPagedPool
,sizeof(VfatCCB
));
743 memset(newCCB
,0,sizeof(VfatCCB
));
744 FileObject
->FsContext2
= newCCB
;
746 newCCB
->PtrFileObject
=FileObject
;
747 if(AbsFileName
)ExFreePool(AbsFileName
);
748 return(STATUS_SUCCESS
);
753 Fcb
= ExAllocatePool(NonPagedPool
, sizeof(VfatFCB
));
754 memset(Fcb
,0,sizeof(VfatFCB
));
755 Fcb
->ObjectName
=Fcb
->PathName
;
761 Status
= FindFile(DeviceExt
,Fcb
,ParentFcb
,next
,NULL
);
770 next
= wcschr(next
+1,'\\');
773 Status
= FindFile(DeviceExt
,Fcb
,ParentFcb
,current
,NULL
);
774 if (Status
!= STATUS_SUCCESS
)
778 if (ParentFcb
!= NULL
)
779 ExFreePool(ParentFcb
);
780 if(AbsFileName
)ExFreePool(AbsFileName
);
784 if (ParentFcb
== NULL
)
786 Fcb
= ExAllocatePool(NonPagedPool
,sizeof(VfatFCB
));
787 memset(Fcb
,0,sizeof(VfatFCB
));
788 Fcb
->ObjectName
=Fcb
->PathName
;
790 else Fcb
= ParentFcb
;
794 FileObject
->FsContext
=(PVOID
) &ParentFcb
->NTRequiredFCB
;
795 newCCB
= ExAllocatePool(NonPagedPool
,sizeof(VfatCCB
));
796 memset(newCCB
,0,sizeof(VfatCCB
));
797 FileObject
->FsContext2
= newCCB
;
798 newCCB
->pFcb
=ParentFcb
;
799 newCCB
->PtrFileObject
=FileObject
;
800 ParentFcb
->RefCount
++;
801 //FIXME : initialize all fields in FCB and CCB
802 ParentFcb
->nextFcb
=pFirstFcb
;
804 vfat_wcsncpy(ParentFcb
->PathName
,FileName
,MAX_PATH
);
805 ParentFcb
->ObjectName
=ParentFcb
->PathName
+(current
-FileName
);
806 ParentFcb
->pDevExt
=DeviceExt
;
807 if(Fcb
) ExFreePool(Fcb
);
808 if(AbsFileName
)ExFreePool(AbsFileName
);
809 return(STATUS_SUCCESS
);
812 BOOLEAN
FsdHasFileSystem(PDEVICE_OBJECT DeviceToMount
)
814 * FUNCTION: Tests if the device contains a filesystem that can be mounted
820 Boot
= ExAllocatePool(NonPagedPool
,BLOCKSIZE
);
822 VFATReadSectors(DeviceToMount
, 0, 1, (UCHAR
*)Boot
);
824 if (strncmp(Boot
->SysType
,"FAT12",5)==0 ||
825 strncmp(Boot
->SysType
,"FAT16",5)==0 ||
826 strncmp(((struct _BootSector32
*)(Boot
))->SysType
,"FAT32",5)==0)
835 NTSTATUS
FsdMountDevice(PDEVICE_EXTENSION DeviceExt
,
836 PDEVICE_OBJECT DeviceToMount
)
838 * FUNCTION: Mounts the device
841 DPRINT("Mounting VFAT device...");
842 DPRINT("DeviceExt %x\n",DeviceExt
);
843 DeviceExt
->Boot
= ExAllocatePool(NonPagedPool
,BLOCKSIZE
);
844 VFATReadSectors(DeviceToMount
, 0, 1, (UCHAR
*)DeviceExt
->Boot
);
846 DPRINT("DeviceExt->Boot->BytesPerSector %x\n",
847 DeviceExt
->Boot
->BytesPerSector
);
849 DeviceExt
->FATStart
=DeviceExt
->Boot
->ReservedSectors
;
850 DeviceExt
->rootDirectorySectors
=
851 (DeviceExt
->Boot
->RootEntries
*32)/DeviceExt
->Boot
->BytesPerSector
;
852 DeviceExt
->rootStart
=
853 DeviceExt
->FATStart
+DeviceExt
->Boot
->FATCount
*DeviceExt
->Boot
->FATSectors
;
854 DeviceExt
->dataStart
=DeviceExt
->rootStart
+DeviceExt
->rootDirectorySectors
;
855 DeviceExt
->FATEntriesPerSector
=DeviceExt
->Boot
->BytesPerSector
/32;
856 DeviceExt
->BytesPerCluster
= DeviceExt
->Boot
->SectorsPerCluster
*
857 DeviceExt
->Boot
->BytesPerSector
;
859 if (strncmp(DeviceExt
->Boot
->SysType
,"FAT12",5)==0)
861 DeviceExt
->FatType
= FAT12
;
863 else if (strncmp(((struct _BootSector32
*)(DeviceExt
->Boot
))->SysType
,"FAT32",5)==0)
865 DeviceExt
->FatType
= FAT32
;
866 DeviceExt
->rootDirectorySectors
=DeviceExt
->Boot
->SectorsPerCluster
;
867 DeviceExt
->rootStart
=
868 DeviceExt
->FATStart
+DeviceExt
->Boot
->FATCount
869 * ((struct _BootSector32
*)( DeviceExt
->Boot
))->FATSectors32
;
870 DeviceExt
->dataStart
=DeviceExt
->rootStart
;
874 DeviceExt
->FatType
= FAT16
;
877 // with FAT32 it's not a good idea to load always fat in memory
878 // because on a 8GB partition with 2 KO clusters, the fat = 8 MO
879 if(DeviceExt
->FatType
!=FAT32
)
881 DeviceExt
->FAT
= ExAllocatePool(NonPagedPool
, BLOCKSIZE
*DeviceExt
->Boot
->FATSectors
);
882 VFATReadSectors(DeviceToMount
, DeviceExt
->FATStart
, DeviceExt
->Boot
->FATSectors
, (UCHAR
*)DeviceExt
->FAT
);
884 return STATUS_SUCCESS
;
887 void VFATLoadCluster(PDEVICE_EXTENSION DeviceExt
, PVOID Buffer
, ULONG Cluster
)
889 * FUNCTION: Load a cluster from the physical device
893 Sector
= ClusterToSector(DeviceExt
, Cluster
);
895 VFATReadSectors(DeviceExt
->StorageDevice
,
897 DeviceExt
->Boot
->SectorsPerCluster
,
901 void VFATWriteCluster(PDEVICE_EXTENSION DeviceExt
, PVOID Buffer
, ULONG Cluster
)
903 * FUNCTION: Write a cluster to the physical device
907 Sector
= ClusterToSector(DeviceExt
, Cluster
);
909 VFATWriteSectors(DeviceExt
->StorageDevice
,
911 DeviceExt
->Boot
->SectorsPerCluster
,
915 NTSTATUS
FsdReadFile(PDEVICE_EXTENSION DeviceExt
, PVfatFCB Fcb
,
916 PVOID Buffer
, ULONG Length
, ULONG ReadOffset
,
919 * FUNCTION: Reads data from a file
922 ULONG CurrentCluster
;
929 assert(DeviceExt
!= NULL
);
930 assert(DeviceExt
->BytesPerCluster
!= 0);
932 if (DeviceExt
->FatType
== FAT32
)
933 CurrentCluster
= Fcb
->entry
.FirstCluster
934 +Fcb
->entry
.FirstClusterHigh
*65536;
936 CurrentCluster
= Fcb
->entry
.FirstCluster
;
937 FirstCluster
=CurrentCluster
;
938 if (ReadOffset
>= Fcb
->entry
.FileSize
939 && !(Fcb
->entry
.Attrib
& FILE_ATTRIBUTE_DIRECTORY
))
941 return(STATUS_END_OF_FILE
);
943 if ((ReadOffset
+ Length
) > Fcb
->entry
.FileSize
944 && !(Fcb
->entry
.Attrib
& FILE_ATTRIBUTE_DIRECTORY
))
946 Length
= Fcb
->entry
.FileSize
- ReadOffset
;
949 /* FIXME: optimize by remembering the last cluster read and using if possible */
950 Temp
= ExAllocatePool(NonPagedPool
,DeviceExt
->BytesPerCluster
);
951 if(!Temp
) return STATUS_UNSUCCESSFUL
;
953 { //root of FAT16 or FAT12
954 CurrentCluster
=DeviceExt
->rootStart
+ReadOffset
955 /(DeviceExt
->BytesPerCluster
)*DeviceExt
->Boot
->SectorsPerCluster
;
958 for (FileOffset
=0; FileOffset
< ReadOffset
/ DeviceExt
->BytesPerCluster
961 CurrentCluster
= GetNextCluster(DeviceExt
,CurrentCluster
);
963 if ((ReadOffset
% DeviceExt
->BytesPerCluster
)!=0)
967 VFATReadSectors(DeviceExt
->StorageDevice
,CurrentCluster
968 ,DeviceExt
->Boot
->SectorsPerCluster
,Temp
);
969 CurrentCluster
+= DeviceExt
->Boot
->SectorsPerCluster
;
973 VFATLoadCluster(DeviceExt
,Temp
,CurrentCluster
);
974 CurrentCluster
= GetNextCluster(DeviceExt
, CurrentCluster
);
976 TempLength
= min(Length
,DeviceExt
->BytesPerCluster
-
977 (ReadOffset
% DeviceExt
->BytesPerCluster
));
979 memcpy(Buffer
, Temp
+ ReadOffset
% DeviceExt
->BytesPerCluster
,
982 (*LengthRead
) = (*LengthRead
) + TempLength
;
983 Length
= Length
- TempLength
;
984 Buffer
= Buffer
+ TempLength
;
986 while (Length
>= DeviceExt
->BytesPerCluster
)
990 VFATReadSectors(DeviceExt
->StorageDevice
,CurrentCluster
991 ,DeviceExt
->Boot
->SectorsPerCluster
,Buffer
);
992 CurrentCluster
+= DeviceExt
->Boot
->SectorsPerCluster
;
996 VFATLoadCluster(DeviceExt
,Buffer
,CurrentCluster
);
997 CurrentCluster
= GetNextCluster(DeviceExt
, CurrentCluster
);
999 if (CurrentCluster
== 0xffffffff)
1002 return(STATUS_SUCCESS
);
1005 (*LengthRead
) = (*LengthRead
) + DeviceExt
->BytesPerCluster
;
1006 Buffer
= Buffer
+ DeviceExt
->BytesPerCluster
;
1007 Length
= Length
- DeviceExt
->BytesPerCluster
;
1011 (*LengthRead
) = (*LengthRead
) + Length
;
1012 if (FirstCluster
==1)
1014 VFATReadSectors(DeviceExt
->StorageDevice
,CurrentCluster
1015 ,DeviceExt
->Boot
->SectorsPerCluster
,Temp
);
1016 CurrentCluster
+= DeviceExt
->Boot
->SectorsPerCluster
;
1020 VFATLoadCluster(DeviceExt
,Temp
,CurrentCluster
);
1021 CurrentCluster
= GetNextCluster(DeviceExt
, CurrentCluster
);
1023 memcpy(Buffer
, Temp
, Length
);
1026 return(STATUS_SUCCESS
);
1029 NTSTATUS
FsdWriteFile(PDEVICE_EXTENSION DeviceExt
, PVfatFCB Fcb
,
1030 PVOID Buffer
, ULONG Length
, ULONG WriteOffset
)
1032 * FUNCTION: Writes data to file
1035 ULONG CurrentCluster
;
1039 ULONG TempLength
,Length2
=Length
;
1042 /* Locate the first cluster of the file */
1044 if(WriteOffset
==FILE_WRITE_TO_END_OF_FILE
)
1045 WriteOffset
=Fcb
->entry
.FileSize
;
1046 if(!(Fcb
->entry
.Attrib
& FILE_ATTRIBUTE_DIRECTORY
) && WriteOffset
>Fcb
->entry
.FileSize
)
1048 //FIXME : we must extend the file with null bytes then write buffer
1049 return STATUS_UNSUCCESSFUL
;
1051 if (DeviceExt
->FatType
== FAT32
)
1052 CurrentCluster
= Fcb
->entry
.FirstCluster
+Fcb
->entry
.FirstClusterHigh
*65536;
1054 CurrentCluster
= Fcb
->entry
.FirstCluster
;
1055 FirstCluster
=CurrentCluster
;
1056 /* Allocate a buffer to hold 1 cluster of data */
1058 Temp
= ExAllocatePool(NonPagedPool
,DeviceExt
->BytesPerCluster
);
1061 /* Find the cluster according to the offset in the file */
1063 if (CurrentCluster
==1)
1064 { //root of FAT16 or FAT12
1065 CurrentCluster
=DeviceExt
->rootStart
+WriteOffset
1066 /DeviceExt
->BytesPerCluster
*DeviceExt
->Boot
->SectorsPerCluster
;
1069 if (CurrentCluster
==0)
1070 {// file of size 0 : allocate first cluster
1071 CurrentCluster
=GetNextWriteCluster(DeviceExt
,0);
1072 if (DeviceExt
->FatType
== FAT32
)
1074 Fcb
->entry
.FirstClusterHigh
=CurrentCluster
>>16;
1075 Fcb
->entry
.FirstCluster
=CurrentCluster
;
1078 Fcb
->entry
.FirstCluster
=CurrentCluster
;
1081 for (FileOffset
=0; FileOffset
< WriteOffset
/ DeviceExt
->BytesPerCluster
; FileOffset
++)
1083 CurrentCluster
= GetNextCluster(DeviceExt
,CurrentCluster
);
1088 If the offset in the cluster doesn't fall on the cluster boundary then
1089 we have to write only from the specified offset
1092 if ((WriteOffset
% DeviceExt
->BytesPerCluster
)!=0)
1095 TempLength
= min(Length
,DeviceExt
->BytesPerCluster
-
1096 (WriteOffset
% DeviceExt
->BytesPerCluster
));
1097 /* Read in the existing cluster data */
1098 if (FirstCluster
==1)
1099 VFATReadSectors(DeviceExt
->StorageDevice
,CurrentCluster
1100 ,DeviceExt
->Boot
->SectorsPerCluster
,Temp
);
1102 VFATLoadCluster(DeviceExt
,Temp
,CurrentCluster
);
1104 /* Overwrite the last parts of the data as necessary */
1105 memcpy(Temp
+ (WriteOffset
% DeviceExt
->BytesPerCluster
), Buffer
,
1108 /* Write the cluster back */
1109 if (FirstCluster
==1)
1111 VFATWriteSectors(DeviceExt
->StorageDevice
,CurrentCluster
1112 ,DeviceExt
->Boot
->SectorsPerCluster
,Temp
);
1113 CurrentCluster
+= DeviceExt
->Boot
->SectorsPerCluster
;
1117 VFATWriteCluster(DeviceExt
,Temp
,CurrentCluster
);
1118 CurrentCluster
= GetNextCluster(DeviceExt
, CurrentCluster
);
1120 Length2
-= TempLength
;
1121 Buffer
= Buffer
+ TempLength
;
1125 /* Write the buffer in chunks of 1 cluster */
1127 while (Length2
>= DeviceExt
->BytesPerCluster
)
1130 if (CurrentCluster
== 0)
1133 return(STATUS_UNSUCCESSFUL
);
1135 if (FirstCluster
==1)
1137 VFATWriteSectors(DeviceExt
->StorageDevice
,CurrentCluster
1138 ,DeviceExt
->Boot
->SectorsPerCluster
,Buffer
);
1139 CurrentCluster
+= DeviceExt
->Boot
->SectorsPerCluster
;
1143 VFATWriteCluster(DeviceExt
,Buffer
,CurrentCluster
);
1144 CurrentCluster
= GetNextCluster(DeviceExt
, CurrentCluster
);
1146 Buffer
= Buffer
+ DeviceExt
->BytesPerCluster
;
1147 Length2
-= DeviceExt
->BytesPerCluster
;
1151 /* Write the remainder */
1155 if (CurrentCluster
== 0)
1158 return(STATUS_UNSUCCESSFUL
);
1160 /* Read in the existing cluster data */
1161 if (FirstCluster
==1)
1162 VFATReadSectors(DeviceExt
->StorageDevice
,CurrentCluster
1163 ,DeviceExt
->Boot
->SectorsPerCluster
,Temp
);
1165 VFATLoadCluster(DeviceExt
,Temp
,CurrentCluster
);
1166 memcpy(Temp
, Buffer
, Length2
);
1167 if (FirstCluster
==1)
1169 VFATWriteSectors(DeviceExt
->StorageDevice
,CurrentCluster
1170 ,DeviceExt
->Boot
->SectorsPerCluster
,Temp
);
1173 VFATWriteCluster(DeviceExt
,Temp
,CurrentCluster
);
1175 //FIXME : set last write time and date
1176 if(Fcb
->entry
.FileSize
<WriteOffset
+Length
1177 && !(Fcb
->entry
.Attrib
&FILE_ATTRIBUTE_DIRECTORY
))
1179 Fcb
->entry
.FileSize
=WriteOffset
+Length
;
1180 // update entry in directory
1181 updEntry(DeviceExt
,Fcb
);
1184 return(STATUS_SUCCESS
);
1187 NTSTATUS
FsdClose(PDEVICE_OBJECT DeviceObject
, PIRP Irp
)
1189 * FUNCTION: Close a file
1192 PIO_STACK_LOCATION Stack
= IoGetCurrentIrpStackLocation(Irp
);
1193 PFILE_OBJECT FileObject
= Stack
->FileObject
;
1194 PDEVICE_EXTENSION DeviceExtension
= DeviceObject
->DeviceExtension
;
1197 Status
= FsdCloseFile(DeviceExtension
,FileObject
);
1199 Irp
->IoStatus
.Status
= Status
;
1200 Irp
->IoStatus
.Information
= 0;
1202 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1206 NTSTATUS
FsdCreate(PDEVICE_OBJECT DeviceObject
, PIRP Irp
)
1208 * FUNCTION: Create or open a file
1211 PIO_STACK_LOCATION Stack
;
1212 PFILE_OBJECT FileObject
;
1213 NTSTATUS Status
=STATUS_SUCCESS
;
1214 PDEVICE_EXTENSION DeviceExt
;
1215 ULONG RequestedDisposition
,RequestedOptions
;
1218 assert(DeviceObject
);
1220 if(DeviceObject
->Size
==sizeof(DEVICE_OBJECT
))
1221 {// DevieObject represent FileSystem instead of logical volume
1222 DbgPrint("FsdCreate called with file system\n");
1223 Irp
->IoStatus
.Status
=Status
;
1224 Irp
->IoStatus
.Information
=FILE_OPENED
;
1225 IoCompleteRequest(Irp
,IO_NO_INCREMENT
);
1228 Stack
= IoGetCurrentIrpStackLocation(Irp
);
1230 RequestedDisposition
= ((Stack
->Parameters
.Create
.Options
>>24)&0xff);
1231 RequestedOptions
=Stack
->Parameters
.Create
.Options
&FILE_VALID_OPTION_FLAGS
;
1232 FileObject
= Stack
->FileObject
;
1233 DeviceExt
= DeviceObject
->DeviceExtension
;
1235 ExAcquireResourceExclusiveLite(&(DeviceExt
->Resource
),TRUE
);
1236 Status
= FsdOpenFile(DeviceExt
,FileObject
,FileObject
->FileName
.Buffer
);
1237 Irp
->IoStatus
.Information
= 0;
1238 if(!NT_SUCCESS(Status
))
1240 if(RequestedDisposition
==FILE_CREATE
1241 ||RequestedDisposition
==FILE_OPEN_IF
1242 ||RequestedDisposition
==FILE_OVERWRITE_IF
)
1244 Status
=addEntry(DeviceExt
,FileObject
,RequestedOptions
1245 ,(Stack
->Parameters
.Create
.FileAttributes
& FILE_ATTRIBUTE_VALID_FLAGS
));
1246 if(NT_SUCCESS(Status
))
1247 Irp
->IoStatus
.Information
= FILE_CREATED
;
1248 // FIXME set size if AllocationSize requested
1249 // FIXME set extended attributes ?
1250 // FIXME set share access
1251 // IoSetShareAccess(DesiredAccess,ShareAccess,FileObject
1252 // ,((PVfatCCB)(FileObject->FsContext2))->pFcb->FCBShareAccess);
1257 if(RequestedDisposition
==FILE_CREATE
)
1259 Irp
->IoStatus
.Information
= FILE_EXISTS
;
1260 Status
=STATUS_OBJECT_NAME_COLLISION
;
1262 pCcb
=FileObject
->FsContext2
;
1264 if( (RequestedOptions
&FILE_NON_DIRECTORY_FILE
)
1265 && (pFcb
->entry
.Attrib
& FILE_ATTRIBUTE_DIRECTORY
))
1267 Status
=STATUS_FILE_IS_A_DIRECTORY
;
1269 if( (RequestedOptions
&FILE_DIRECTORY_FILE
)
1270 && !(pFcb
->entry
.Attrib
& FILE_ATTRIBUTE_DIRECTORY
))
1272 Status
=STATUS_NOT_A_DIRECTORY
;
1274 // FIXME : test share access
1275 // FIXME : test write access if requested
1276 if(!NT_SUCCESS(Status
))
1277 FsdCloseFile(DeviceExt
,FileObject
);
1278 else Irp
->IoStatus
.Information
= FILE_OPENED
;
1279 // FIXME : make supersed or overwrite if requested
1282 Irp
->IoStatus
.Status
= Status
;
1284 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1285 ExReleaseResourceForThreadLite(&(DeviceExt
->Resource
),ExGetCurrentResourceThread());
1290 NTSTATUS
FsdWrite(PDEVICE_OBJECT DeviceObject
, PIRP Irp
)
1292 * FUNCTION: Write to a file
1298 PIO_STACK_LOCATION Stack
= IoGetCurrentIrpStackLocation(Irp
);
1299 PFILE_OBJECT FileObject
= Stack
->FileObject
;
1300 PDEVICE_EXTENSION DeviceExt
= DeviceObject
->DeviceExtension
;
1304 DPRINT("FsdWrite(DeviceObject %x Irp %x)\n",DeviceObject
,Irp
);
1306 Length
= Stack
->Parameters
.Write
.Length
;
1307 Buffer
= MmGetSystemAddressForMdl(Irp
->MdlAddress
);
1308 Offset
= GET_LARGE_INTEGER_LOW_PART(Stack
->Parameters
.Write
.ByteOffset
);
1310 assert(FileObject
->FsContext2
!= NULL
);
1311 pFcb
= ((PVfatCCB
)(FileObject
->FsContext2
))->pFcb
;
1312 Status
= FsdWriteFile(DeviceExt
,pFcb
,Buffer
,Length
,Offset
);
1314 Irp
->IoStatus
.Status
= Status
;
1315 Irp
->IoStatus
.Information
= Length
;
1316 IoCompleteRequest(Irp
,IO_NO_INCREMENT
);
1321 NTSTATUS
FsdRead(PDEVICE_OBJECT DeviceObject
, PIRP Irp
)
1323 * FUNCTION: Read from a file
1329 PIO_STACK_LOCATION Stack
;
1330 PFILE_OBJECT FileObject
;
1331 PDEVICE_EXTENSION DeviceExt
;
1336 /* Precondition / Initialization */
1337 assert(Irp
!= NULL
);
1338 Stack
= IoGetCurrentIrpStackLocation(Irp
);
1339 assert(Stack
!= NULL
);
1340 FileObject
= Stack
->FileObject
;
1341 assert(FileObject
!= NULL
);
1342 DeviceExt
= DeviceObject
->DeviceExtension
;
1343 assert(DeviceExt
!= NULL
);
1345 Length
= Stack
->Parameters
.Read
.Length
;
1346 Buffer
= MmGetSystemAddressForMdl(Irp
->MdlAddress
);
1347 Offset
= GET_LARGE_INTEGER_LOW_PART(Stack
->Parameters
.Read
.ByteOffset
);
1349 assert(FileObject
->FsContext2
!= NULL
);
1350 pFcb
= ((PVfatCCB
)(FileObject
->FsContext2
))->pFcb
;
1351 Status
= FsdReadFile(DeviceExt
,pFcb
,Buffer
,Length
,Offset
,
1354 Irp
->IoStatus
.Status
= Status
;
1355 Irp
->IoStatus
.Information
= LengthRead
;
1356 IoCompleteRequest(Irp
,IO_NO_INCREMENT
);
1362 NTSTATUS
FsdMount(PDEVICE_OBJECT DeviceToMount
)
1364 * FUNCTION: Mount the filesystem
1367 PDEVICE_OBJECT DeviceObject
;
1368 PDEVICE_EXTENSION DeviceExt
;
1370 IoCreateDevice(VFATDriverObject
,
1371 sizeof(DEVICE_EXTENSION
),
1373 FILE_DEVICE_FILE_SYSTEM
,
1377 DeviceObject
->Flags
= DeviceObject
->Flags
| DO_DIRECT_IO
;
1378 DeviceExt
= (PVOID
)DeviceObject
->DeviceExtension
;
1379 // use same vpb as device disk
1380 DeviceObject
->Vpb
=DeviceToMount
->Vpb
;
1381 FsdMountDevice(DeviceExt
,DeviceToMount
);
1382 DeviceObject
->Vpb
->Flags
|= VPB_MOUNTED
;
1383 DeviceExt
->StorageDevice
= IoAttachDeviceToDeviceStack(DeviceObject
,
1385 return(STATUS_SUCCESS
);
1388 NTSTATUS
FsdFileSystemControl(PDEVICE_OBJECT DeviceObject
, PIRP Irp
)
1390 * FUNCTION: File system control
1393 PIO_STACK_LOCATION Stack
= IoGetCurrentIrpStackLocation(Irp
);
1394 // PVPB vpb = Stack->Parameters.Mount.Vpb;
1395 PDEVICE_OBJECT DeviceToMount
= Stack
->Parameters
.Mount
.DeviceObject
;
1398 DPRINT("VFAT FSC\n");
1400 /* FIXME: should make sure that this is actually a mount request! */
1402 if (FsdHasFileSystem(DeviceToMount
))
1404 Status
= FsdMount(DeviceToMount
);
1408 DPRINT("VFAT: Unrecognized Volume\n");
1409 Status
= STATUS_UNRECOGNIZED_VOLUME
;
1411 DPRINT("VFAT File system successfully mounted\n");
1413 Irp
->IoStatus
.Status
= Status
;
1414 Irp
->IoStatus
.Information
= 0;
1415 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1419 NTSTATUS
FsdGetStandardInformation(PVfatFCB FCB
, PDEVICE_OBJECT DeviceObject
,
1420 PFILE_STANDARD_INFORMATION StandardInfo
)
1422 * FUNCTION: Retrieve the standard file information
1425 PDEVICE_EXTENSION DeviceExtension
;
1426 unsigned long AllocSize
;
1428 DeviceExtension
= DeviceObject
->DeviceExtension
;
1430 assert(DeviceExtension
!= NULL
);
1431 assert(DeviceExtension
->BytesPerCluster
!= 0);
1432 assert(StandardInfo
!= NULL
);
1433 assert(FCB
!= NULL
);
1435 RtlZeroMemory(StandardInfo
, sizeof(FILE_STANDARD_INFORMATION
));
1437 /* Make allocsize a rounded up multiple of BytesPerCluster */
1438 AllocSize
= ((FCB
->entry
.FileSize
+ DeviceExtension
->BytesPerCluster
- 1) /
1439 DeviceExtension
->BytesPerCluster
) *
1440 DeviceExtension
->BytesPerCluster
;
1442 StandardInfo
->AllocationSize
= RtlConvertUlongToLargeInteger(AllocSize
);
1443 StandardInfo
->EndOfFile
= RtlConvertUlongToLargeInteger(FCB
->entry
.FileSize
);
1444 StandardInfo
->NumberOfLinks
= 0;
1445 StandardInfo
->DeletePending
= FALSE
;
1446 if((FCB
->entry
.Attrib
& 0x10)>0) {
1447 StandardInfo
->Directory
= TRUE
;
1449 StandardInfo
->Directory
= FALSE
;
1452 return STATUS_SUCCESS
;
1455 NTSTATUS
FsdQueryInformation(PDEVICE_OBJECT DeviceObject
, PIRP Irp
)
1457 * FUNCTION: Retrieve the specified file information
1460 PIO_STACK_LOCATION Stack
= IoGetCurrentIrpStackLocation(Irp
);
1461 FILE_INFORMATION_CLASS FileInformationClass
=
1462 Stack
->Parameters
.QueryFile
.FileInformationClass
;
1463 PFILE_OBJECT FileObject
= NULL
;
1464 PVfatFCB FCB
= NULL
;
1465 // PVfatCCB CCB = NULL;
1467 NTSTATUS RC
= STATUS_SUCCESS
;
1471 assert(DeviceObject
!= NULL
);
1472 assert(Irp
!= NULL
);
1474 /* INITIALIZATION */
1475 Stack
= IoGetCurrentIrpStackLocation(Irp
);
1476 FileInformationClass
= Stack
->Parameters
.QueryFile
.FileInformationClass
;
1477 FileObject
= Stack
->FileObject
;
1478 // CCB = (PVfatCCB)(FileObject->FsContext2);
1479 // FCB = CCB->Buffer; // Should be CCB->FCB???
1480 FCB
= ((PVfatCCB
)(FileObject
->FsContext2
))->pFcb
;
1482 // FIXME : determine Buffer for result :
1483 if (Irp
->MdlAddress
)
1484 SystemBuffer
= MmGetSystemAddressForMdl(Irp
->MdlAddress
);
1486 SystemBuffer
= Irp
->UserBuffer
;
1487 // SystemBuffer = Irp->AssociatedIrp.SystemBuffer;
1489 switch(FileInformationClass
) {
1490 case FileStandardInformation
:
1491 RC
= FsdGetStandardInformation(FCB
, DeviceObject
, SystemBuffer
);
1494 RC
=STATUS_NOT_IMPLEMENTED
;
1500 NTSTATUS
DriverEntry(PDRIVER_OBJECT _DriverObject
,
1501 PUNICODE_STRING RegistryPath
)
1503 * FUNCTION: Called by the system to initalize the driver
1505 * DriverObject = object describing this driver
1506 * RegistryPath = path to our configuration entries
1507 * RETURNS: Success or failure
1510 PDEVICE_OBJECT DeviceObject
;
1512 UNICODE_STRING ustr
;
1515 DbgPrint("VFAT 0.0.6\n");
1517 VFATDriverObject
= _DriverObject
;
1519 RtlInitAnsiString(&astr
,"\\Device\\VFAT");
1520 RtlAnsiStringToUnicodeString(&ustr
,&astr
,TRUE
);
1521 ret
= IoCreateDevice(VFATDriverObject
,0,&ustr
,
1522 FILE_DEVICE_FILE_SYSTEM
,0,FALSE
,&DeviceObject
);
1523 if (ret
!=STATUS_SUCCESS
)
1528 DeviceObject
->Flags
= DO_DIRECT_IO
;
1529 VFATDriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = FsdClose
;
1530 VFATDriverObject
->MajorFunction
[IRP_MJ_CREATE
] = FsdCreate
;
1531 VFATDriverObject
->MajorFunction
[IRP_MJ_READ
] = FsdRead
;
1532 VFATDriverObject
->MajorFunction
[IRP_MJ_WRITE
] = FsdWrite
;
1533 VFATDriverObject
->MajorFunction
[IRP_MJ_FILE_SYSTEM_CONTROL
] =
1534 FsdFileSystemControl
;
1535 VFATDriverObject
->MajorFunction
[IRP_MJ_QUERY_INFORMATION
] =
1536 FsdQueryInformation
;
1537 VFATDriverObject
->MajorFunction
[IRP_MJ_DIRECTORY_CONTROL
] =
1538 FsdDirectoryControl
;
1540 VFATDriverObject
->DriverUnload
= NULL
;
1542 IoRegisterFileSystem(DeviceObject
);
1544 return(STATUS_SUCCESS
);