Fixed LARGE_INTEGER hack.
[reactos.git] / reactos / drivers / fs / vfat / iface.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: services/fs/vfat/iface.c
5 * PURPOSE: VFAT Filesystem
6 * PROGRAMMER: Jason Filby (jasonfilby@yahoo.com)
7 * UPDATE HISTORY:
8 ?? Created
9 24-10-1998 Fixed bugs in long filename support
10 Fixed a bug that prevented unsuccessful file open requests being reported
11 Now works with long filenames that span over a sector boundary
12 28-10-1998 Reads entire FAT into memory
13 VFatReadSector modified to read in more than one sector at a time
14 7-11-1998 Fixed bug that assumed that directory data could be fragmented
15 8-12-1998 Added FAT32 support
16 Added initial writability functions
17 WARNING: DO NOT ATTEMPT TO TEST WRITABILITY FUNCTIONS!!!
18 12-12-1998 Added basic support for FILE_STANDARD_INFORMATION request
19
20 */
21
22 /* INCLUDES *****************************************************************/
23
24 #include <wchar.h>
25 #include <internal/string.h>
26 #include <ddk/ntddk.h>
27 #include <ddk/cctypes.h>
28
29 #define NDEBUG
30 #include <internal/debug.h>
31
32 #include "vfat.h"
33
34 //#include "dbgpool.c"
35
36 /* GLOBALS *****************************************************************/
37
38 static PDRIVER_OBJECT VFATDriverObject;
39 PVfatFCB pFirstFcb;
40
41 /* FUNCTIONS ****************************************************************/
42
43 ULONG Fat32GetNextCluster(PDEVICE_EXTENSION DeviceExt, ULONG CurrentCluster)
44 /*
45 * FUNCTION: Retrieve the next FAT32 cluster from the FAT table via a physical
46 * disk read
47 */
48 {
49 ULONG FATsector;
50 ULONG FATeis;
51 PULONG Block;
52
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;
61 ExFreePool(Block);
62 return(CurrentCluster);
63 }
64
65 ULONG Fat16GetNextCluster(PDEVICE_EXTENSION DeviceExt, ULONG CurrentCluster)
66 /*
67 * FUNCTION: Retrieve the next FAT16 cluster from the FAT table from the
68 * in-memory FAT
69 */
70 {
71 PUSHORT Block;
72 Block=(PUSHORT)DeviceExt->FAT;
73 CurrentCluster = Block[CurrentCluster];
74 if (CurrentCluster >= 0xfff8 && CurrentCluster <= 0xffff)
75 CurrentCluster = 0xffffffff;
76 DPRINT("Returning %x\n",CurrentCluster);
77 return(CurrentCluster);
78 }
79
80 ULONG Fat12GetNextCluster(PDEVICE_EXTENSION DeviceExt, ULONG CurrentCluster)
81 /*
82 * FUNCTION: Retrieve the next FAT12 cluster from the FAT table from the
83 * in-memory FAT
84 */
85 {
86 unsigned char* CBlock;
87 ULONG FATOffset;
88 ULONG Entry;
89 CBlock = DeviceExt->FAT;
90 FATOffset = (CurrentCluster * 12)/ 8;//first byte containing value
91 if ((CurrentCluster % 2) == 0)
92 {
93 Entry = CBlock[FATOffset];
94 Entry |= ((CBlock[FATOffset+1] & 0xf)<<8);
95 }
96 else
97 {
98 Entry = (CBlock[FATOffset] >> 4);
99 Entry |= (CBlock[FATOffset+1] << 4);
100 }
101 DPRINT("Entry %x\n",Entry);
102 if (Entry >= 0xff8 && Entry <= 0xfff)
103 Entry = 0xffffffff;
104 DPRINT("Returning %x\n",Entry);
105 return(Entry);
106 }
107
108 ULONG GetNextCluster(PDEVICE_EXTENSION DeviceExt, ULONG CurrentCluster)
109 /*
110 * FUNCTION: Retrieve the next cluster depending on the FAT type
111 */
112 {
113
114 DPRINT("GetNextCluster(DeviceExt %x, CurrentCluster %x)\n",
115 DeviceExt,CurrentCluster);
116 if (DeviceExt->FatType == FAT16)
117 return(Fat16GetNextCluster(DeviceExt, CurrentCluster));
118 else if (DeviceExt->FatType == FAT32)
119 return(Fat32GetNextCluster(DeviceExt, CurrentCluster));
120 else
121 return(Fat12GetNextCluster(DeviceExt, CurrentCluster));
122 }
123
124 ULONG FAT16FindAvailableCluster(PDEVICE_EXTENSION DeviceExt)
125 /*
126 * FUNCTION: Finds the first available cluster in a FAT16 table
127 */
128 {
129 PUSHORT Block;
130 int i;
131 Block=(PUSHORT)DeviceExt->FAT;
132 for(i=2;i<(DeviceExt->Boot->FATSectors*256) ;i++)
133 if(Block[i]==0)
134 return (i);
135 /* Give an error message (out of disk space) if we reach here) */
136 return 0;
137 }
138
139 ULONG FAT12FindAvailableCluster(PDEVICE_EXTENSION DeviceExt)
140 /*
141 * FUNCTION: Finds the first available cluster in a FAT12 table
142 */
143 {
144 ULONG FATOffset;
145 ULONG Entry;
146 PUCHAR CBlock=DeviceExt->FAT;
147 ULONG i;
148 for(i=2;i<((DeviceExt->Boot->FATSectors*512*8)/12) ;i++)
149 {
150 FATOffset = (i * 12)/8;
151 if ((i % 2) == 0)
152 {
153 Entry = CBlock[FATOffset];
154 Entry |= ((CBlock[FATOffset + 1] & 0xf)<<8);
155 }
156 else
157 {
158 Entry = (CBlock[FATOffset] >> 4);
159 Entry |= (CBlock[FATOffset + 1] << 4);
160 }
161 if(Entry==0)
162 return (i);
163 }
164 /* Give an error message (out of disk space) if we reach here) */
165 DbgPrint("Disk full, %d clusters used\n",i);
166 return 0;
167 }
168
169 ULONG FAT32FindAvailableCluster(PDEVICE_EXTENSION DeviceExt)
170 /*
171 * FUNCTION: Finds the first available cluster in a FAT32 table
172 */
173 {
174 ULONG sector;
175 PULONG Block;
176 int i;
177 Block = ExAllocatePool(NonPagedPool,BLOCKSIZE);
178 for(sector=0
179 ;sector< ((struct _BootSector32*)(DeviceExt->Boot))->FATSectors32
180 ;sector++)
181 {
182 VFATReadSectors(DeviceExt->StorageDevice
183 ,(ULONG)(DeviceExt->FATStart+sector), 1,(UCHAR*) Block);
184
185 for(i=0; i<512; i++)
186 {
187 if(Block[i]==0)
188 {
189 ExFreePool(Block);
190 return (i+sector*128);
191 }
192 }
193 }
194 /* Give an error message (out of disk space) if we reach here) */
195 ExFreePool(Block);
196 return 0;
197 }
198
199 ULONG FAT12CountAvailableClusters(PDEVICE_EXTENSION DeviceExt)
200 /*
201 * FUNCTION: Counts free cluster in a FAT12 table
202 */
203 {
204 ULONG FATOffset;
205 ULONG Entry;
206 PUCHAR CBlock=DeviceExt->FAT;
207 ULONG ulCount = 0;
208 ULONG i;
209
210 for(i=2;i<((DeviceExt->Boot->FATSectors*512*8)/12) ;i++)
211 {
212 FATOffset = (i * 12)/8;
213 if ((i % 2) == 0)
214 {
215 Entry = CBlock[FATOffset];
216 Entry |= ((CBlock[FATOffset + 1] & 0xf)<<8);
217 }
218 else
219 {
220 Entry = (CBlock[FATOffset] >> 4);
221 Entry |= (CBlock[FATOffset + 1] << 4);
222 }
223 if(Entry==0)
224 ulCount++;
225 }
226 return ulCount;
227 }
228
229 ULONG FAT16CountAvailableClusters(PDEVICE_EXTENSION DeviceExt)
230 /*
231 * FUNCTION: Counts free clusters in a FAT16 table
232 */
233 {
234 PUSHORT Block;
235 ULONG ulCount = 0;
236 ULONG i;
237
238 Block=(PUSHORT)DeviceExt->FAT;
239 for(i=2;i<(DeviceExt->Boot->FATSectors*256) ;i++)
240 if(Block[i]==0)
241 ulCount++;
242 return ulCount;
243 }
244
245 ULONG FAT32CountAvailableClusters(PDEVICE_EXTENSION DeviceExt)
246 /*
247 * FUNCTION: Counts free clusters in a FAT32 table
248 */
249 {
250 ULONG sector;
251 PULONG Block;
252 ULONG ulCount = 0;
253 ULONG i;
254
255 Block = ExAllocatePool(NonPagedPool,BLOCKSIZE);
256 for(sector=0
257 ;sector< ((struct _BootSector32*)(DeviceExt->Boot))->FATSectors32
258 ;sector++)
259 {
260 VFATReadSectors(DeviceExt->StorageDevice
261 ,(ULONG)(DeviceExt->FATStart+sector), 1,(UCHAR*) Block);
262
263 for(i=0; i<512; i++)
264 {
265 if(Block[i]==0)
266 ulCount++;
267 }
268 }
269 /* Give an error message (out of disk space) if we reach here) */
270 ExFreePool(Block);
271 return ulCount;
272 }
273
274 void FAT12WriteCluster(PDEVICE_EXTENSION DeviceExt, ULONG ClusterToWrite,
275 ULONG NewValue)
276 /*
277 * FUNCTION: Writes a cluster to the FAT12 physical and in-memory tables
278 */
279 {
280 ULONG FATsector;
281 ULONG FATOffset;
282 PUCHAR CBlock=DeviceExt->FAT;
283 int i;
284 FATOffset = (ClusterToWrite * 12)/8;
285 if ((ClusterToWrite % 2) == 0)
286 {
287 CBlock[FATOffset]=NewValue;
288 CBlock[FATOffset + 1] &=0xf0;
289 CBlock[FATOffset + 1]
290 |= (NewValue&0xf00)>>8;
291 }
292 else
293 {
294 CBlock[FATOffset] &=0x0f;
295 CBlock[FATOffset]
296 |= (NewValue&0xf)<<4;
297 CBlock[FATOffset+1]=NewValue>>4;
298 }
299 /* Write the changed FAT sector(s) to disk */
300 FATsector=FATOffset/BLOCKSIZE;
301 for(i=0;i<DeviceExt->Boot->FATCount;i++)
302 {
303 if( (FATOffset%BLOCKSIZE)==(BLOCKSIZE-1))//entry is on 2 sectors
304 {
305 VFATWriteSectors(DeviceExt->StorageDevice,
306 DeviceExt->FATStart+FATsector
307 +i*DeviceExt->Boot->FATSectors,
308 2,
309 CBlock+FATsector*512);
310 }
311 else
312 {
313 VFATWriteSectors(DeviceExt->StorageDevice,
314 DeviceExt->FATStart+FATsector
315 +i*DeviceExt->Boot->FATSectors,
316 1,
317 CBlock+FATsector*512);
318 }
319 }
320 }
321
322 void FAT16WriteCluster(PDEVICE_EXTENSION DeviceExt, ULONG ClusterToWrite,
323 ULONG NewValue)
324 /*
325 * FUNCTION: Writes a cluster to the FAT16 physical and in-memory tables
326 */
327 {
328 ULONG FATsector;
329 PUSHORT Block;
330 DbgPrint("FAT16WriteCluster %u : %u\n",ClusterToWrite,NewValue);
331 Block=(PUSHORT)DeviceExt->FAT;
332 FATsector=ClusterToWrite/(512/sizeof(USHORT));
333
334 /* Update the in-memory FAT */
335 Block[ClusterToWrite] = NewValue;
336 /* Write the changed FAT sector to disk */
337 VFATWriteSectors(DeviceExt->StorageDevice,
338 DeviceExt->FATStart+FATsector,
339 1,
340 (UCHAR *)Block);
341 }
342
343 void FAT32WriteCluster(PDEVICE_EXTENSION DeviceExt, ULONG ClusterToWrite,
344 ULONG NewValue)
345 /*
346 * FUNCTION: Writes a cluster to the FAT32 physical tables
347 */
348 {
349 ULONG FATsector;
350 ULONG FATeis;
351 PUSHORT Block;
352 DbgPrint("FAT32WriteCluster %u : %u\n",ClusterToWrite,NewValue);
353 Block = ExAllocatePool(NonPagedPool,BLOCKSIZE);
354 FATsector=ClusterToWrite/128;
355 FATeis=ClusterToWrite-(FATsector*128);
356 /* load sector, change value, then rewrite sector */
357 VFATReadSectors(DeviceExt->StorageDevice,
358 DeviceExt->FATStart+FATsector,
359 1,
360 (UCHAR *)Block);
361 Block[FATeis] = NewValue;
362 VFATWriteSectors(DeviceExt->StorageDevice,
363 DeviceExt->FATStart+FATsector,
364 1,
365 (UCHAR *)Block);
366 ExFreePool(Block);
367 }
368
369 void WriteCluster(PDEVICE_EXTENSION DeviceExt, ULONG ClusterToWrite,
370 ULONG NewValue)
371 /*
372 * FUNCTION: Write a changed FAT entry
373 */
374 {
375 if(DeviceExt->FatType==FAT16)
376 FAT16WriteCluster(DeviceExt, ClusterToWrite, NewValue);
377 else if(DeviceExt->FatType==FAT32)
378 FAT32WriteCluster(DeviceExt, ClusterToWrite, NewValue);
379 else
380 FAT12WriteCluster(DeviceExt, ClusterToWrite, NewValue);
381 }
382
383 ULONG GetNextWriteCluster(PDEVICE_EXTENSION DeviceExt, ULONG CurrentCluster)
384 /*
385 * FUNCTION: Determines the next cluster to be written
386 */
387 {
388 ULONG LastCluster, NewCluster;
389 DPRINT("GetNextWriteCluster(DeviceExt %x, CurrentCluster %x)\n",
390 DeviceExt,CurrentCluster);
391
392 /* Find out what was happening in the last cluster's AU */
393 LastCluster=GetNextCluster(DeviceExt,CurrentCluster);
394 /* Check to see if we must append or overwrite */
395 if (LastCluster==0xffffffff)
396 {//we are after last existing cluster : we must add one to file
397 /* Append */
398 /* Firstly, find the next available open allocation unit */
399 if(DeviceExt->FatType == FAT16)
400 NewCluster = FAT16FindAvailableCluster(DeviceExt);
401 else if(DeviceExt->FatType == FAT32)
402 NewCluster = FAT32FindAvailableCluster(DeviceExt);
403 else
404 NewCluster = FAT12FindAvailableCluster(DeviceExt);
405 /* Mark the new AU as the EOF */
406 WriteCluster(DeviceExt, NewCluster, 0xFFFFFFFF);
407 /* Now, write the AU of the LastCluster with the value of the newly
408 found AU */
409 if(CurrentCluster)
410 WriteCluster(DeviceExt, CurrentCluster, NewCluster);
411 /* Return NewCluster as CurrentCluster */
412 return NewCluster;
413 }
414 else
415 {
416 /* Overwrite: Return LastCluster as CurrentCluster */
417 return LastCluster;
418 }
419 }
420
421 ULONG ClusterToSector(PDEVICE_EXTENSION DeviceExt,
422 unsigned long Cluster)
423 /*
424 * FUNCTION: Converts the cluster number to a sector number for this physical
425 * device
426 */
427 {
428 return DeviceExt->dataStart+((Cluster-2)*DeviceExt->Boot->SectorsPerCluster);
429 }
430
431 void RtlAnsiToUnicode(PWSTR Dest, PCH Source, ULONG Length)
432 /*
433 * FUNCTION: Convert an ANSI string to it's Unicode equivalent
434 */
435 {
436 int i;
437
438 for (i=0; (i<Length && Source[i] != ' '); i++)
439 {
440 Dest[i] = Source[i];
441 }
442 Dest[i]=0;
443 }
444
445 void RtlCatAnsiToUnicode(PWSTR Dest, PCH Source, ULONG Length)
446 /*
447 * FUNCTION: Appends a converted ANSI to Unicode string to the end of an
448 * existing Unicode string
449 */
450 {
451 ULONG i;
452
453 while((*Dest)!=0)
454 {
455 Dest++;
456 }
457 for (i=0; (i<Length && Source[i] != ' '); i++)
458 {
459 Dest[i] = Source[i];
460 }
461 Dest[i]=0;
462 }
463
464 void vfat_initstr(wchar_t *wstr, ULONG wsize)
465 /*
466 * FUNCTION: Initialize a string for use with a long file name
467 */
468 {
469 int i;
470 wchar_t nc=0;
471 for(i=0; i<wsize; i++)
472 {
473 *wstr=nc;
474 wstr++;
475 }
476 wstr=wstr-wsize;
477 }
478
479 wchar_t * vfat_wcsncat(wchar_t * dest, const wchar_t * src,size_t wstart, size_t wcount)
480 /*
481 * FUNCTION: Append a string for use with a long file name
482 */
483 {
484 int i;
485
486 dest+=wstart;
487 for(i=0; i<wcount; i++)
488 {
489 *dest=src[i];
490 dest++;
491 }
492 dest=dest-(wcount+wstart);
493
494 return dest;
495 }
496
497 wchar_t * vfat_wcsncpy(wchar_t * dest, const wchar_t *src,size_t wcount)
498 /*
499 * FUNCTION: Copy a string for use with long file names
500 */
501 {
502 int i;
503
504 for (i=0;i<wcount;i++)
505 {
506 dest[i]=src[i];
507 if(!dest[i]) break;
508 }
509 return(dest);
510 }
511
512 wchar_t * vfat_movstr(const wchar_t *src, ULONG dpos,
513 ULONG spos, ULONG len)
514 /*
515 * FUNCTION: Move the characters in a string to a new position in the same
516 * string
517 */
518 {
519 int i;
520
521 if(dpos<=spos)
522 {
523 for(i=0; i<len; i++)
524 {
525 src[dpos++]=src[spos++];
526 }
527 }
528 else
529 {
530 dpos+=len-1;
531 spos+=len-1;
532 for(i=0; i<len; i++)
533 {
534 src[dpos--]=src[spos--];
535 }
536 }
537
538 return(src);
539 }
540
541 BOOLEAN IsLastEntry(PVOID Block, ULONG Offset)
542 /*
543 * FUNCTION: Determine if the given directory entry is the last
544 */
545 {
546 return(((FATDirEntry *)Block)[Offset].Filename[0] == 0);
547 }
548
549 BOOLEAN IsVolEntry(PVOID Block, ULONG Offset)
550 /*
551 * FUNCTION: Determine if the given directory entry is a vol entry
552 */
553 {
554 if( (((FATDirEntry *)Block)[Offset].Attrib)==0x28 ) return TRUE;
555 else return FALSE;
556 }
557
558 BOOLEAN IsDeletedEntry(PVOID Block, ULONG Offset)
559 /*
560 * FUNCTION: Determines if the given entry is a deleted one
561 */
562 {
563 /* Checks special character */
564
565 return ((((FATDirEntry *)Block)[Offset].Filename[0] == 0xe5));
566 }
567
568 BOOLEAN GetEntryName(PVOID Block, PULONG _Offset, PWSTR Name, PULONG _jloop,
569 PDEVICE_EXTENSION DeviceExt, ULONG * _StartingSector)
570 /*
571 * FUNCTION: Retrieves the file name, be it in short or long file name format
572 */
573 {
574 FATDirEntry* test;
575 slot* test2;
576 ULONG Offset = *_Offset;
577 ULONG StartingSector = *_StartingSector;
578 ULONG jloop = *_jloop;
579 ULONG cpos;
580 WCHAR tmp[256];
581
582 test = (FATDirEntry *)Block;
583 test2 = (slot *)Block;
584
585 *Name = 0;
586
587 if (IsDeletedEntry(Block,Offset))
588 {
589 return(FALSE);
590 }
591
592 if(test2[Offset].attr == 0x0f)
593 {
594 vfat_initstr(Name, 256);
595 vfat_wcsncpy(Name,test2[Offset].name0_4,5);
596 vfat_wcsncat(Name,test2[Offset].name5_10,5,6);
597 vfat_wcsncat(Name,test2[Offset].name11_12,11,2);
598
599 cpos=0;
600 while((test2[Offset].id!=0x41) && (test2[Offset].id!=0x01) &&
601 (test2[Offset].attr>0))
602 {
603 Offset++;
604 if(Offset==ENTRIES_PER_SECTOR) {
605 Offset=0;
606 StartingSector++;//FIXME : nor always the next sector
607 jloop++;
608 VFATReadSectors(DeviceExt->StorageDevice,StartingSector,1,Block);
609 test2 = (slot *)Block;
610 }
611 cpos++;
612 vfat_movstr(Name, 13, 0, cpos*13);
613 vfat_wcsncpy(Name, test2[Offset].name0_4, 5);
614 vfat_wcsncat(Name,test2[Offset].name5_10,5,6);
615 vfat_wcsncat(Name,test2[Offset].name11_12,11,2);
616
617 }
618
619 if (IsDeletedEntry(Block,Offset+1))
620 {
621 Offset++;
622 *_Offset = Offset;
623 *_jloop = jloop;
624 *_StartingSector = StartingSector;
625 return(FALSE);
626 }
627
628 *_Offset = Offset;
629 *_jloop = jloop;
630 *_StartingSector = StartingSector;
631
632 return(TRUE);
633 }
634
635 RtlAnsiToUnicode(Name,test[Offset].Filename,8);
636 if (test[Offset].Ext[0]!=' ')
637 {
638 RtlCatAnsiToUnicode(Name,".",1);
639 }
640 RtlCatAnsiToUnicode(Name,test[Offset].Ext,3);
641
642 *_Offset = Offset;
643
644 return(TRUE);
645 }
646
647 BOOLEAN wstrcmpi(PWSTR s1, PWSTR s2)
648 /*
649 * FUNCTION: Compare to wide character strings
650 * return TRUE if s1==s2
651 */
652 {
653 while (towlower(*s1)==towlower(*s2))
654 {
655 if ((*s1)==0 && (*s2)==0)
656 {
657 return(TRUE);
658 }
659
660 s1++;
661 s2++;
662 }
663 return(FALSE);
664 }
665 BOOLEAN wstrcmpjoki(PWSTR s1, PWSTR s2)
666 /*
667 * FUNCTION: Compare to wide character strings, s2 with jokers (* or ?)
668 * return TRUE if s1 like s2
669 */
670 {
671 while ((*s2=='?')||(towlower(*s1)==towlower(*s2)))
672 {
673 if ((*s1)==0 && (*s2)==0)
674 return(TRUE);
675 s1++;
676 s2++;
677 }
678 if(*s2=='*')
679 {
680 s2++;
681 while (*s1)
682 if (wstrcmpjoki(s1,s2)) return TRUE;
683 else s1++;
684 }
685 if ((*s1)==0 && (*s2)==0)
686 return(TRUE);
687 return(FALSE);
688 }
689
690 NTSTATUS FindFile(PDEVICE_EXTENSION DeviceExt, PVfatFCB Fcb,
691 PVfatFCB Parent, PWSTR FileToFind,ULONG *StartSector,ULONG *Entry)
692 /*
693 * FUNCTION: Find a file
694 */
695 {
696 ULONG i, j;
697 ULONG Size;
698 char* block;
699 WCHAR name[256];
700 ULONG StartingSector;
701 ULONG NextCluster;
702 WCHAR TempStr[2];
703
704 DPRINT("FindFile(Parent %x, FileToFind '%w')\n",Parent,FileToFind);
705
706 if (wcslen(FileToFind)==0)
707 {
708 TempStr[0] = (WCHAR)'.';
709 TempStr[1] = 0;
710 FileToFind=&TempStr;
711 }
712 if (Parent != NULL)
713 {
714 DPRINT("Parent->entry.FirstCluster %d\n",Parent->entry.FirstCluster);
715 }
716
717 if (Parent == NULL||Parent->entry.FirstCluster==1)
718 {
719 Size = DeviceExt->rootDirectorySectors;//FIXME : in fat32, no limit
720 StartingSector = DeviceExt->rootStart;
721 NextCluster=0;
722 if(FileToFind[0]==0 ||(FileToFind[0]=='\\' && FileToFind[1]==0) ||
723 (FileToFind[0]=='.' && FileToFind[1]==0))
724 {// it's root : complete essentials fields then return ok
725 memset(Fcb,0,sizeof(VfatFCB));
726 memset(Fcb->entry.Filename,' ',11);
727 Fcb->entry.FileSize=DeviceExt->rootDirectorySectors*BLOCKSIZE;
728 Fcb->entry.Attrib=FILE_ATTRIBUTE_DIRECTORY;
729 if (DeviceExt->FatType == FAT32)
730 Fcb->entry.FirstCluster=2;
731 else Fcb->entry.FirstCluster=1;//FIXME : is 1 the good value for mark root?
732 if(StartSector) *StartSector=StartingSector;
733 if(Entry) *Entry=0;
734 return(STATUS_SUCCESS);
735 }
736 }
737 else
738 {
739 DPRINT("Parent->entry.FileSize %x\n",Parent->entry.FileSize);
740
741 Size = ULONG_MAX;
742 if (DeviceExt->FatType == FAT32)
743 NextCluster = Parent->entry.FirstCluster
744 +Parent->entry.FirstClusterHigh*65536;
745 else
746 NextCluster = Parent->entry.FirstCluster;
747 StartingSector = ClusterToSector(DeviceExt, NextCluster);
748 if(Parent->entry.FirstCluster==1 && DeviceExt->FatType!=FAT32)
749 {// read of root directory in FAT16 or FAT12
750 StartingSector=DeviceExt->rootStart;
751 }
752 }
753 block = ExAllocatePool(NonPagedPool,BLOCKSIZE);
754 if (StartSector && (*StartSector)) StartingSector=*StartSector;
755 i=(Entry)?(*Entry):0;
756 DPRINT("FindFile : start at sector %lx, entry %ld\n",StartingSector,i);
757 for (j=0; j<Size; j++)
758 {
759 VFATReadSectors(DeviceExt->StorageDevice,StartingSector,1,block);
760
761 for (i=(Entry)?(*Entry):0; i<ENTRIES_PER_SECTOR; i++)
762 {
763 if (IsVolEntry((PVOID)block,i))
764 continue;
765 if (IsLastEntry((PVOID)block,i))
766 {
767 ExFreePool(block);
768 if(StartSector) *StartSector=StartingSector;
769 if(Entry) *Entry=i;
770 return(STATUS_UNSUCCESSFUL);
771 }
772 if (GetEntryName((PVOID)block,&i,name,&j,DeviceExt,&StartingSector))
773 {
774 DPRINT("Comparing '%w' '%w'\n",name,FileToFind);
775 if (wstrcmpjoki(name,FileToFind))
776 {
777 /* In the case of a long filename, the firstcluster is stored in
778 the next record -- where it's short name is */
779 if(((FATDirEntry *)block)[i].Attrib==0x0f) i++;
780 if( i==(ENTRIES_PER_SECTOR))
781 {// entry is in next sector
782 StartingSector++;
783 //FIXME : treat case of next sector fragmented
784 VFATReadSectors(DeviceExt->StorageDevice,StartingSector,1,block);
785 i=0;
786 }
787 memcpy(&Fcb->entry,&((FATDirEntry *)block)[i],
788 sizeof(FATDirEntry));
789 vfat_wcsncpy(Fcb->ObjectName,name,MAX_PATH);
790 ExFreePool(block);
791 if(StartSector) *StartSector=StartingSector;
792 if(Entry) *Entry=i;
793 return(STATUS_SUCCESS);
794 }
795 }
796 }
797 // not found in this sector, try next :
798
799 /* directory can be fragmented although it is best to keep them
800 unfragmented */
801 if(Entry) *Entry=0;
802 StartingSector++;
803 if ((Parent != NULL && Parent->entry.FirstCluster!=1)
804 || DeviceExt->FatType ==FAT32)
805 {
806 if(StartingSector==ClusterToSector(DeviceExt,NextCluster+1))
807 {
808 NextCluster = GetNextCluster(DeviceExt,NextCluster);
809 if (NextCluster == 0||NextCluster==0xffffffff)
810 {
811 if(StartSector) *StartSector=StartingSector;
812 if(Entry) *Entry=i;
813 ExFreePool(block);
814 return(STATUS_UNSUCCESSFUL);
815 }
816 StartingSector = ClusterToSector(DeviceExt,NextCluster);
817 }
818 }
819 }
820 ExFreePool(block);
821 if(StartSector) *StartSector=StartingSector;
822 if(Entry) *Entry=i;
823 return(STATUS_UNSUCCESSFUL);
824 }
825
826
827 NTSTATUS FsdCloseFile(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject)
828 /*
829 * FUNCTION: Closes a file
830 */
831 {
832 PVfatFCB pFcb;
833 PVfatCCB pCcb;
834
835 DPRINT("FsdCloseFile(DeviceExt %x, FileObject %x)\n",
836 DeviceExt,FileObject);
837
838 //FIXME : update entry in directory ?
839 pCcb = (PVfatCCB)(FileObject->FsContext2);
840
841 DPRINT("pCcb %x\n",pCcb);
842 if (pCcb == NULL)
843 {
844 return(STATUS_SUCCESS);
845 }
846
847 pFcb = pCcb->pFcb;
848
849 pFcb->RefCount--;
850 if(pFcb->RefCount<=0)
851 {
852 if(pFcb->prevFcb)
853 pFcb->prevFcb->nextFcb=pFcb->nextFcb;
854 else
855 pFirstFcb=pFcb->nextFcb;
856 if(pFcb->nextFcb)
857 pFcb->nextFcb->prevFcb=pFcb->prevFcb;
858 ExFreePool(pFcb);
859 }
860 ExFreePool(pCcb);
861 return STATUS_SUCCESS;
862 }
863
864 NTSTATUS FsdOpenFile(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject,
865 PWSTR FileName)
866 /*
867 * FUNCTION: Opens a file
868 */
869 {
870 PWSTR current;
871 PWSTR next;
872 PWSTR string;
873 PVfatFCB ParentFcb;
874 PVfatFCB Fcb,pRelFcb;
875 PVfatFCB Temp;
876 PVfatCCB newCCB,pRelCcb;
877 NTSTATUS Status;
878 PFILE_OBJECT pRelFileObject;
879 PWSTR AbsFileName=NULL;
880 short i,j;
881
882 DPRINT("FsdOpenFile(%08lx, %08lx, %w)\n",
883 DeviceExt,
884 FileObject,
885 FileName);
886
887 //FIXME : treat relative name
888 if(FileObject->RelatedFileObject)
889 {
890 DbgPrint("try related for %w\n",FileName);
891 pRelFileObject=FileObject->RelatedFileObject;
892 pRelCcb=pRelFileObject->FsContext2;
893 assert(pRelCcb);
894 pRelFcb=pRelCcb->pFcb;
895 assert(pRelFcb);
896 // verify related object is a directory and target name don't start with \.
897 if( !(pRelFcb->entry.Attrib & FILE_ATTRIBUTE_DIRECTORY)
898 || (FileName[0]!= '\\') )
899 {
900 Status=STATUS_INVALID_PARAMETER;
901 return Status;
902 }
903 // construct absolute path name
904 AbsFileName=ExAllocatePool(NonPagedPool,MAX_PATH);
905 for (i=0;pRelFcb->PathName[i];i++)
906 AbsFileName[i]=pRelFcb->PathName[i];
907 AbsFileName[i++]='\\';
908 for (j=0;FileName[j]&&i<MAX_PATH;j++)
909 AbsFileName[i++]=FileName[j];
910 assert(i<MAX_PATH);
911 AbsFileName[i]=0;
912 FileName=AbsFileName;
913 }
914 // try first to find an existing FCB in memory
915 for (Fcb=pFirstFcb;Fcb; Fcb=Fcb->nextFcb)
916 {
917 if (DeviceExt==Fcb->pDevExt
918 && wstrcmpi(FileName,Fcb->PathName))
919 {
920 Fcb->RefCount++;
921 FileObject->FsContext =(PVOID) &Fcb->NTRequiredFCB;
922 newCCB = ExAllocatePool(NonPagedPool,sizeof(VfatCCB));
923 memset(newCCB,0,sizeof(VfatCCB));
924 FileObject->FsContext2 = newCCB;
925 newCCB->pFcb=Fcb;
926 newCCB->PtrFileObject=FileObject;
927 if(AbsFileName)ExFreePool(AbsFileName);
928 return(STATUS_SUCCESS);
929 }
930 }
931 string = FileName;
932 ParentFcb = NULL;
933 Fcb = ExAllocatePool(NonPagedPool, sizeof(VfatFCB));
934 memset(Fcb,0,sizeof(VfatFCB));
935 Fcb->ObjectName=Fcb->PathName;
936 next = &string[0];
937
938 while (next!=NULL)
939 {
940 *next = '\\';
941 current = next+1;
942 next = wcschr(next+1,'\\');
943 if (next!=NULL)
944 {
945 *next=0;
946 }
947 DPRINT("current '%w'\n",current);
948 Status = FindFile(DeviceExt,Fcb,ParentFcb,current,NULL,NULL);
949 if (Status != STATUS_SUCCESS)
950 {
951 if (Fcb != NULL)
952 ExFreePool(Fcb);
953 if (ParentFcb != NULL)
954 ExFreePool(ParentFcb);
955 if(AbsFileName)ExFreePool(AbsFileName);
956 return(Status);
957 }
958 Temp = Fcb;
959 if (ParentFcb == NULL)
960 {
961 Fcb = ExAllocatePool(NonPagedPool,sizeof(VfatFCB));
962 memset(Fcb,0,sizeof(VfatFCB));
963 Fcb->ObjectName=Fcb->PathName;
964 }
965 else Fcb = ParentFcb;
966 ParentFcb = Temp;
967 }
968 FileObject->FsContext =(PVOID) &ParentFcb->NTRequiredFCB;
969 newCCB = ExAllocatePool(NonPagedPool,sizeof(VfatCCB));
970 memset(newCCB,0,sizeof(VfatCCB));
971 FileObject->FsContext2 = newCCB;
972 newCCB->pFcb=ParentFcb;
973 newCCB->PtrFileObject=FileObject;
974 ParentFcb->RefCount++;
975 //FIXME : initialize all fields in FCB and CCB
976 ParentFcb->nextFcb=pFirstFcb;
977 pFirstFcb=ParentFcb;
978 vfat_wcsncpy(ParentFcb->PathName,FileName,MAX_PATH);
979 ParentFcb->ObjectName=ParentFcb->PathName+(current-FileName);
980 ParentFcb->pDevExt=DeviceExt;
981 DPRINT("file open, fcb=%x\n",ParentFcb);
982 DPRINT("FileSize %d\n",ParentFcb->entry.FileSize);
983 if(Fcb) ExFreePool(Fcb);
984 if(AbsFileName)ExFreePool(AbsFileName);
985 return(STATUS_SUCCESS);
986 }
987
988
989 BOOLEAN FsdHasFileSystem(PDEVICE_OBJECT DeviceToMount)
990 /*
991 * FUNCTION: Tests if the device contains a filesystem that can be mounted
992 * by this fsd
993 */
994 {
995 BootSector* Boot;
996
997 Boot = ExAllocatePool(NonPagedPool,512);
998
999 VFATReadSectors(DeviceToMount, 0, 1, (UCHAR *)Boot);
1000
1001 if (strncmp(Boot->SysType,"FAT12",5)==0 ||
1002 strncmp(Boot->SysType,"FAT16",5)==0 ||
1003 strncmp(((struct _BootSector32 *)(Boot))->SysType,"FAT32",5)==0)
1004 {
1005 ExFreePool(Boot);
1006 return(TRUE);
1007 }
1008 ExFreePool(Boot);
1009 return(FALSE);
1010 }
1011
1012 NTSTATUS FsdMountDevice(PDEVICE_EXTENSION DeviceExt,
1013 PDEVICE_OBJECT DeviceToMount)
1014 /*
1015 * FUNCTION: Mounts the device
1016 */
1017 {
1018 DPRINT("Mounting VFAT device...");
1019 DPRINT("DeviceExt %x\n",DeviceExt);
1020
1021 DeviceExt->Boot = ExAllocatePool(NonPagedPool,512);
1022 VFATReadSectors(DeviceToMount, 0, 1, (UCHAR *)DeviceExt->Boot);
1023
1024 DPRINT("DeviceExt->Boot->BytesPerSector %x\n",
1025 DeviceExt->Boot->BytesPerSector);
1026
1027 DeviceExt->FATStart=DeviceExt->Boot->ReservedSectors;
1028 DeviceExt->rootDirectorySectors=
1029 (DeviceExt->Boot->RootEntries*32)/DeviceExt->Boot->BytesPerSector;
1030 DeviceExt->rootStart=
1031 DeviceExt->FATStart+DeviceExt->Boot->FATCount*DeviceExt->Boot->FATSectors;
1032 DeviceExt->dataStart=DeviceExt->rootStart+DeviceExt->rootDirectorySectors;
1033 DeviceExt->FATEntriesPerSector=DeviceExt->Boot->BytesPerSector/32;
1034 DeviceExt->BytesPerCluster = DeviceExt->Boot->SectorsPerCluster *
1035 DeviceExt->Boot->BytesPerSector;
1036
1037 if (strncmp(DeviceExt->Boot->SysType,"FAT12",5)==0)
1038 {
1039 DeviceExt->FatType = FAT12;
1040 }
1041 else if (strncmp(((struct _BootSector32 *)(DeviceExt->Boot))->SysType,"FAT32",5)==0)
1042 {
1043 DeviceExt->FatType = FAT32;
1044 DeviceExt->rootDirectorySectors=DeviceExt->Boot->SectorsPerCluster;
1045 DeviceExt->rootStart=
1046 DeviceExt->FATStart+DeviceExt->Boot->FATCount
1047 * ((struct _BootSector32 *)( DeviceExt->Boot))->FATSectors32;
1048 DeviceExt->dataStart=DeviceExt->rootStart;
1049 }
1050 else
1051 {
1052 DeviceExt->FatType = FAT16;
1053 }
1054
1055 // with FAT32 it's not a good idea to load always fat in memory
1056 // because on a 8GB partition with 2 KO clusters, the fat = 8 MO
1057 if(DeviceExt->FatType!=FAT32)
1058 {
1059 DeviceExt->FAT = ExAllocatePool(NonPagedPool, BLOCKSIZE*DeviceExt->Boot->FATSectors);
1060 VFATReadSectors(DeviceToMount, DeviceExt->FATStart, DeviceExt->Boot->FATSectors, (UCHAR *)DeviceExt->FAT);
1061 }
1062 return STATUS_SUCCESS;
1063 }
1064
1065 void VFATLoadCluster(PDEVICE_EXTENSION DeviceExt, PVOID Buffer, ULONG Cluster)
1066 /*
1067 * FUNCTION: Load a cluster from the physical device
1068 */
1069 {
1070 ULONG Sector;
1071
1072 DPRINT("VFATLoadCluster(DeviceExt %x, Buffer %x, Cluster %d)\n",
1073 DeviceExt,Buffer,Cluster);
1074
1075 Sector = ClusterToSector(DeviceExt, Cluster);
1076
1077 VFATReadSectors(DeviceExt->StorageDevice,
1078 Sector,
1079 DeviceExt->Boot->SectorsPerCluster,
1080 Buffer);
1081 }
1082
1083 void VFATWriteCluster(PDEVICE_EXTENSION DeviceExt, PVOID Buffer, ULONG Cluster)
1084 /*
1085 * FUNCTION: Write a cluster to the physical device
1086 */
1087 {
1088 ULONG Sector;
1089 DPRINT("VFATWriteCluster(DeviceExt %x, Buffer %x, Cluster %d)\n",
1090 DeviceExt,Buffer,Cluster);
1091
1092 Sector = ClusterToSector(DeviceExt, Cluster);
1093
1094 VFATWriteSectors(DeviceExt->StorageDevice,
1095 Sector,
1096 DeviceExt->Boot->SectorsPerCluster,
1097 Buffer);
1098 }
1099
1100 NTSTATUS FsdReadFile(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject,
1101 PVOID Buffer, ULONG Length, ULONG ReadOffset,
1102 PULONG LengthRead)
1103 /*
1104 * FUNCTION: Reads data from a file
1105 */
1106 {
1107 ULONG CurrentCluster;
1108 ULONG FileOffset;
1109 ULONG FirstCluster;
1110 PVfatFCB Fcb;
1111 PVOID Temp;
1112 ULONG TempLength;
1113
1114 /* PRECONDITION */
1115 assert(DeviceExt != NULL);
1116 assert(DeviceExt->BytesPerCluster != 0);
1117 assert(FileObject != NULL);
1118 assert(FileObject->FsContext != NULL);
1119
1120 DPRINT("FsdReadFile(DeviceExt %x, FileObject %x, Buffer %x, "
1121 "Length %d, ReadOffset %d)\n",DeviceExt,FileObject,Buffer,
1122 Length,ReadOffset);
1123
1124 Fcb = ((PVfatCCB)(FileObject->FsContext2))->pFcb;
1125 if (DeviceExt->FatType == FAT32)
1126 CurrentCluster = Fcb->entry.FirstCluster
1127 +Fcb->entry.FirstClusterHigh*65536;
1128 else
1129 CurrentCluster = Fcb->entry.FirstCluster;
1130 FirstCluster=CurrentCluster;
1131 DPRINT("DeviceExt->BytesPerCluster %x\n",DeviceExt->BytesPerCluster);
1132
1133 if (ReadOffset >= Fcb->entry.FileSize
1134 && !(Fcb->entry.Attrib & FILE_ATTRIBUTE_DIRECTORY))
1135 {
1136 return(STATUS_END_OF_FILE);
1137 }
1138 if ((ReadOffset + Length) > Fcb->entry.FileSize
1139 && !(Fcb->entry.Attrib & FILE_ATTRIBUTE_DIRECTORY))
1140 {
1141 Length = Fcb->entry.FileSize - ReadOffset;
1142 }
1143 *LengthRead = 0;
1144 /* FIXME: optimize by remembering the last cluster read and using if possible */
1145 Temp = ExAllocatePool(NonPagedPool,DeviceExt->BytesPerCluster);
1146 if(!Temp) return STATUS_UNSUCCESSFUL;
1147 if (FirstCluster==1)
1148 { //root of FAT16 or FAT12
1149 CurrentCluster=DeviceExt->rootStart+ReadOffset
1150 /(DeviceExt->BytesPerCluster)*DeviceExt->Boot->SectorsPerCluster;
1151 }
1152 else
1153 for (FileOffset=0; FileOffset < ReadOffset / DeviceExt->BytesPerCluster
1154 ; FileOffset++)
1155 {
1156 CurrentCluster = GetNextCluster(DeviceExt,CurrentCluster);
1157 }
1158 CHECKPOINT;
1159 if ((ReadOffset % DeviceExt->BytesPerCluster)!=0)
1160 {
1161 if (FirstCluster==1)
1162 {
1163 VFATReadSectors(DeviceExt->StorageDevice,CurrentCluster
1164 ,DeviceExt->Boot->SectorsPerCluster,Temp);
1165 CurrentCluster += DeviceExt->Boot->SectorsPerCluster;
1166 }
1167 else
1168 {
1169 VFATLoadCluster(DeviceExt,Temp,CurrentCluster);
1170 CurrentCluster = GetNextCluster(DeviceExt, CurrentCluster);
1171 }
1172 TempLength = min(Length,DeviceExt->BytesPerCluster -
1173 (ReadOffset % DeviceExt->BytesPerCluster));
1174
1175 memcpy(Buffer, Temp + ReadOffset % DeviceExt->BytesPerCluster,
1176 TempLength);
1177
1178 (*LengthRead) = (*LengthRead) + TempLength;
1179 Length = Length - TempLength;
1180 Buffer = Buffer + TempLength;
1181 }
1182 CHECKPOINT;
1183 while (Length >= DeviceExt->BytesPerCluster)
1184 {
1185 if (FirstCluster==1)
1186 {
1187 VFATReadSectors(DeviceExt->StorageDevice,CurrentCluster
1188 ,DeviceExt->Boot->SectorsPerCluster,Buffer);
1189 CurrentCluster += DeviceExt->Boot->SectorsPerCluster;
1190 }
1191 else
1192 {
1193 VFATLoadCluster(DeviceExt,Buffer,CurrentCluster);
1194 CurrentCluster = GetNextCluster(DeviceExt, CurrentCluster);
1195 }
1196 if (CurrentCluster == 0xffffffff)
1197 {
1198 ExFreePool(Temp);
1199 return(STATUS_SUCCESS);
1200 }
1201
1202 (*LengthRead) = (*LengthRead) + DeviceExt->BytesPerCluster;
1203 Buffer = Buffer + DeviceExt->BytesPerCluster;
1204 Length = Length - DeviceExt->BytesPerCluster;
1205 }
1206 CHECKPOINT;
1207 if (Length > 0)
1208 {
1209 (*LengthRead) = (*LengthRead) + Length;
1210 if (FirstCluster==1)
1211 {
1212 VFATReadSectors(DeviceExt->StorageDevice,CurrentCluster
1213 ,DeviceExt->Boot->SectorsPerCluster,Temp);
1214 CurrentCluster += DeviceExt->Boot->SectorsPerCluster;
1215 }
1216 else
1217 {
1218 VFATLoadCluster(DeviceExt,Temp,CurrentCluster);
1219 CurrentCluster = GetNextCluster(DeviceExt, CurrentCluster);
1220 }
1221 memcpy(Buffer, Temp, Length);
1222 }
1223 ExFreePool(Temp);
1224 return(STATUS_SUCCESS);
1225 }
1226
1227 NTSTATUS FsdWriteFile(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject,
1228 PVOID Buffer, ULONG Length, ULONG WriteOffset)
1229 /*
1230 * FUNCTION: Writes data to file
1231 */
1232 {
1233 ULONG CurrentCluster;
1234 ULONG FileOffset;
1235 ULONG FirstCluster;
1236 PVfatFCB Fcb;
1237 PVfatCCB pCcb;
1238 PVOID Temp;
1239 ULONG TempLength,Length2=Length;
1240
1241 /* Locate the first cluster of the file */
1242 assert(FileObject);
1243 pCcb=(PVfatCCB)(FileObject->FsContext2);
1244 assert(pCcb);
1245 Fcb = pCcb->pFcb;
1246 assert(Fcb);
1247 if (DeviceExt->FatType == FAT32)
1248 CurrentCluster = Fcb->entry.FirstCluster+Fcb->entry.FirstClusterHigh*65536;
1249 else
1250 CurrentCluster = Fcb->entry.FirstCluster;
1251 FirstCluster=CurrentCluster;
1252 /* Allocate a buffer to hold 1 cluster of data */
1253
1254 Temp = ExAllocatePool(NonPagedPool,DeviceExt->BytesPerCluster);
1255 assert(Temp);
1256
1257 /* Find the cluster according to the offset in the file */
1258
1259 if (CurrentCluster==1)
1260 { //root of FAT16 or FAT12
1261 CurrentCluster=DeviceExt->rootStart+WriteOffset
1262 /DeviceExt->BytesPerCluster*DeviceExt->Boot->SectorsPerCluster;
1263 }
1264 else
1265 if (CurrentCluster==0)
1266 {// file of size 0 : allocate first cluster
1267 CurrentCluster=GetNextWriteCluster(DeviceExt,0);
1268 if (DeviceExt->FatType == FAT32)
1269 {
1270 Fcb->entry.FirstClusterHigh=CurrentCluster>>16;
1271 Fcb->entry.FirstCluster=CurrentCluster;
1272 }
1273 else
1274 Fcb->entry.FirstCluster=CurrentCluster;
1275 }
1276 else
1277 for (FileOffset=0; FileOffset < WriteOffset / DeviceExt->BytesPerCluster; FileOffset++)
1278 {
1279 CurrentCluster = GetNextCluster(DeviceExt,CurrentCluster);
1280 }
1281 CHECKPOINT;
1282
1283 /*
1284 If the offset in the cluster doesn't fall on the cluster boundary then
1285 we have to write only from the specified offset
1286 */
1287
1288 if ((WriteOffset % DeviceExt->BytesPerCluster)!=0)
1289 {
1290 CHECKPOINT;
1291 TempLength = min(Length,DeviceExt->BytesPerCluster -
1292 (WriteOffset % DeviceExt->BytesPerCluster));
1293 /* Read in the existing cluster data */
1294 if (FirstCluster==1)
1295 VFATReadSectors(DeviceExt->StorageDevice,CurrentCluster
1296 ,DeviceExt->Boot->SectorsPerCluster,Temp);
1297 else
1298 VFATLoadCluster(DeviceExt,Temp,CurrentCluster);
1299
1300 /* Overwrite the last parts of the data as necessary */
1301 memcpy(Temp + (WriteOffset % DeviceExt->BytesPerCluster), Buffer,
1302 TempLength);
1303
1304 /* Write the cluster back */
1305 if (FirstCluster==1)
1306 {
1307 VFATWriteSectors(DeviceExt->StorageDevice,CurrentCluster
1308 ,DeviceExt->Boot->SectorsPerCluster,Temp);
1309 CurrentCluster += DeviceExt->Boot->SectorsPerCluster;
1310 }
1311 else
1312 {
1313 VFATWriteCluster(DeviceExt,Temp,CurrentCluster);
1314 CurrentCluster = GetNextCluster(DeviceExt, CurrentCluster);
1315 }
1316 Length2 -= TempLength;
1317 Buffer = Buffer + TempLength;
1318 }
1319 CHECKPOINT;
1320
1321 /* Write the buffer in chunks of 1 cluster */
1322
1323 while (Length2 >= DeviceExt->BytesPerCluster)
1324 {
1325 CHECKPOINT;
1326 if (CurrentCluster == 0)
1327 {
1328 ExFreePool(Temp);
1329 return(STATUS_UNSUCCESSFUL);
1330 }
1331 if (FirstCluster==1)
1332 {
1333 VFATWriteSectors(DeviceExt->StorageDevice,CurrentCluster
1334 ,DeviceExt->Boot->SectorsPerCluster,Buffer);
1335 CurrentCluster += DeviceExt->Boot->SectorsPerCluster;
1336 }
1337 else
1338 {
1339 VFATWriteCluster(DeviceExt,Buffer,CurrentCluster);
1340 CurrentCluster = GetNextCluster(DeviceExt, CurrentCluster);
1341 }
1342 Buffer = Buffer + DeviceExt->BytesPerCluster;
1343 Length2 -= DeviceExt->BytesPerCluster;
1344 }
1345 CHECKPOINT;
1346
1347 /* Write the remainder */
1348
1349 if (Length2 > 0)
1350 {
1351 CHECKPOINT;
1352 if (CurrentCluster == 0)
1353 {
1354 ExFreePool(Temp);
1355 return(STATUS_UNSUCCESSFUL);
1356 }
1357 CHECKPOINT;
1358 /* Read in the existing cluster data */
1359 if (FirstCluster==1)
1360 VFATReadSectors(DeviceExt->StorageDevice,CurrentCluster
1361 ,DeviceExt->Boot->SectorsPerCluster,Temp);
1362 else
1363 VFATLoadCluster(DeviceExt,Temp,CurrentCluster);
1364 CHECKPOINT;
1365 memcpy(Temp, Buffer, Length2);
1366 CHECKPOINT;
1367 if (FirstCluster==1)
1368 {
1369 VFATWriteSectors(DeviceExt->StorageDevice,CurrentCluster
1370 ,DeviceExt->Boot->SectorsPerCluster,Temp);
1371 }
1372 else
1373 VFATWriteCluster(DeviceExt,Temp,CurrentCluster);
1374 }
1375 CHECKPOINT;
1376 //FIXME : set last write time and date
1377 if(Fcb->entry.FileSize<WriteOffset+Length
1378 && !(Fcb->entry.Attrib &FILE_ATTRIBUTE_DIRECTORY))
1379 {
1380 Fcb->entry.FileSize=WriteOffset+Length;
1381 // update entry in directory
1382 updEntry(DeviceExt,FileObject);
1383 }
1384 ExFreePool(Temp);
1385 return(STATUS_SUCCESS);
1386 }
1387
1388 NTSTATUS FsdClose(PDEVICE_OBJECT DeviceObject, PIRP Irp)
1389 /*
1390 * FUNCTION: Close a file
1391 */
1392 {
1393 PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
1394 PFILE_OBJECT FileObject = Stack->FileObject;
1395 PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
1396 NTSTATUS Status;
1397
1398 DPRINT("FsdClose(DeviceObject %x, Irp %x)\n",DeviceObject, Irp);
1399
1400 Status = FsdCloseFile(DeviceExtension,FileObject);
1401
1402 Irp->IoStatus.Status = Status;
1403 Irp->IoStatus.Information = 0;
1404
1405 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1406 return(Status);
1407 }
1408
1409 NTSTATUS FsdCreate(PDEVICE_OBJECT DeviceObject, PIRP Irp)
1410 /*
1411 * FUNCTION: Create or open a file
1412 */
1413 {
1414 PIO_STACK_LOCATION Stack;
1415 PFILE_OBJECT FileObject;
1416 NTSTATUS Status=STATUS_SUCCESS;
1417 PDEVICE_EXTENSION DeviceExt;
1418 ULONG RequestedDisposition,RequestedOptions;
1419 PVfatCCB pCcb;
1420 PVfatFCB pFcb;
1421
1422 assert(DeviceObject);
1423 assert(Irp);
1424 if(DeviceObject->Size==sizeof(DEVICE_OBJECT))
1425 {// DevieObject represent FileSystem instead of logical volume
1426 DbgPrint("FsdCreate called with file system\n");
1427 Irp->IoStatus.Status=Status;
1428 Irp->IoStatus.Information=FILE_OPENED;
1429 IoCompleteRequest(Irp,IO_NO_INCREMENT);
1430 return(Status);
1431 }
1432 Stack = IoGetCurrentIrpStackLocation(Irp);
1433 assert(Stack);
1434 RequestedDisposition = ((Stack->Parameters.Create.Options>>24)&0xff);
1435 RequestedOptions=Stack->Parameters.Create.Options&FILE_VALID_OPTION_FLAGS;
1436 FileObject = Stack->FileObject;
1437 DeviceExt = DeviceObject->DeviceExtension;
1438 assert(DeviceExt);
1439 ExAcquireResourceExclusiveLite(&(DeviceExt->Resource),TRUE);
1440 Status = FsdOpenFile(DeviceExt,FileObject,FileObject->FileName.Buffer);
1441 Irp->IoStatus.Information = 0;
1442 if(!NT_SUCCESS(Status))
1443 {
1444 if(RequestedDisposition==FILE_CREATE
1445 ||RequestedDisposition==FILE_OPEN_IF
1446 ||RequestedDisposition==FILE_OVERWRITE_IF)
1447 {
1448 Status=addEntry(DeviceExt,FileObject,RequestedOptions
1449 ,(Stack->Parameters.Create.FileAttributes & FILE_ATTRIBUTE_VALID_FLAGS));
1450 if(NT_SUCCESS(Status))
1451 Irp->IoStatus.Information = FILE_CREATED;
1452 // FIXME set size if AllocationSize requested
1453 // FIXME set extended attributes ?
1454 // FIXME set share access
1455 // IoSetShareAccess(DesiredAccess,ShareAccess,FileObject
1456 // ,((PVfatCCB)(FileObject->FsContext2))->pFcb->FCBShareAccess);
1457 }
1458 }
1459 else
1460 {
1461 if(RequestedDisposition==FILE_CREATE)
1462 {
1463 Irp->IoStatus.Information = FILE_EXISTS;
1464 Status=STATUS_OBJECT_NAME_COLLISION;
1465 }
1466 pCcb=FileObject->FsContext2;
1467 pFcb=pCcb->pFcb;
1468 if( (RequestedOptions&FILE_NON_DIRECTORY_FILE)
1469 && (pFcb->entry.Attrib & FILE_ATTRIBUTE_DIRECTORY))
1470 {
1471 Status=STATUS_FILE_IS_A_DIRECTORY;
1472 }
1473 if( (RequestedOptions&FILE_DIRECTORY_FILE)
1474 && !(pFcb->entry.Attrib & FILE_ATTRIBUTE_DIRECTORY))
1475 {
1476 Status=STATUS_NOT_A_DIRECTORY;
1477 }
1478 // FIXME : test share access
1479 // FIXME : test write access if requested
1480 if(!NT_SUCCESS(Status))
1481 FsdCloseFile(DeviceExt,FileObject);
1482 else Irp->IoStatus.Information = FILE_OPENED;
1483 // FIXME : make supersed or overwrite if requested
1484 }
1485
1486 Irp->IoStatus.Status = Status;
1487
1488 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1489 ExReleaseResourceForThreadLite(&(DeviceExt->Resource),ExGetCurrentResourceThread());
1490 return Status;
1491 }
1492
1493
1494 NTSTATUS FsdWrite(PDEVICE_OBJECT DeviceObject, PIRP Irp)
1495 /*
1496 * FUNCTION: Write to a file
1497 */
1498 {
1499 ULONG Length;
1500 PVOID Buffer;
1501 ULONG Offset;
1502 PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
1503 PFILE_OBJECT FileObject = Stack->FileObject;
1504 PDEVICE_EXTENSION DeviceExt = DeviceObject->DeviceExtension;
1505 NTSTATUS Status;
1506
1507 DPRINT("FsdWrite(DeviceObject %x Irp %x)\n",DeviceObject,Irp);
1508
1509 Length = Stack->Parameters.Write.Length;
1510 Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
1511 Offset = Stack->Parameters.Write.ByteOffset.u.LowPart;
1512
1513 Status = FsdWriteFile(DeviceExt,FileObject,Buffer,Length,Offset);
1514
1515 Irp->IoStatus.Status = Status;
1516 Irp->IoStatus.Information = Length;
1517 IoCompleteRequest(Irp,IO_NO_INCREMENT);
1518
1519 return(Status);
1520 }
1521
1522 NTSTATUS FsdRead(PDEVICE_OBJECT DeviceObject, PIRP Irp)
1523 /*
1524 * FUNCTION: Read from a file
1525 */
1526 {
1527 ULONG Length;
1528 PVOID Buffer;
1529 ULONG Offset;
1530 PIO_STACK_LOCATION Stack;
1531 PFILE_OBJECT FileObject;
1532 PDEVICE_EXTENSION DeviceExt;
1533 NTSTATUS Status;
1534 ULONG LengthRead;
1535
1536 DPRINT("FsdRead(DeviceObject %x, Irp %x)\n",DeviceObject,Irp);
1537
1538 /* Precondition / Initialization */
1539 assert(Irp != NULL);
1540 Stack = IoGetCurrentIrpStackLocation(Irp);
1541 assert(Stack != NULL);
1542 FileObject = Stack->FileObject;
1543 assert(FileObject != NULL);
1544 DeviceExt = DeviceObject->DeviceExtension;
1545 assert(DeviceExt != NULL);
1546
1547 Length = Stack->Parameters.Read.Length;
1548 Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
1549 Offset = Stack->Parameters.Read.ByteOffset.u.LowPart;
1550
1551 Status = FsdReadFile(DeviceExt,FileObject,Buffer,Length,Offset,
1552 &LengthRead);
1553
1554 Irp->IoStatus.Status = Status;
1555 Irp->IoStatus.Information = LengthRead;
1556 IoCompleteRequest(Irp,IO_NO_INCREMENT);
1557
1558 return(Status);
1559 }
1560
1561
1562 NTSTATUS FsdMount(PDEVICE_OBJECT DeviceToMount)
1563 /*
1564 * FUNCTION: Mount the filesystem
1565 */
1566 {
1567 PDEVICE_OBJECT DeviceObject;
1568 PDEVICE_EXTENSION DeviceExt;
1569
1570 IoCreateDevice(VFATDriverObject,
1571 sizeof(DEVICE_EXTENSION),
1572 NULL,
1573 FILE_DEVICE_FILE_SYSTEM,
1574 0,
1575 FALSE,
1576 &DeviceObject);
1577 DeviceObject->Flags = DeviceObject->Flags | DO_DIRECT_IO;
1578 DeviceExt = (PVOID)DeviceObject->DeviceExtension;
1579 // use same vpb as device disk
1580 DeviceObject->Vpb=DeviceToMount->Vpb;
1581 FsdMountDevice(DeviceExt,DeviceToMount);
1582 DeviceObject->Vpb->Flags |= VPB_MOUNTED;
1583 DeviceExt->StorageDevice = IoAttachDeviceToDeviceStack(DeviceObject,
1584 DeviceToMount);
1585
1586 // fill in missing information in vpb
1587 if (DeviceExt->FatType == FAT12 || DeviceExt->FatType == FAT16)
1588 {
1589 struct _BootSector *BootSect = (PVOID)DeviceExt->Boot;
1590 PSTR s = BootSect->VolumeLabel;
1591 PWSTR w = DeviceObject->Vpb->VolumeLabel;
1592 int n=0;
1593
1594 // get serial number
1595 DeviceObject->Vpb->SerialNumber = BootSect->VolumeID;
1596
1597 // copy drive label
1598 while (*s != ' ' && n < 11)
1599 {
1600 *w++ = *s++;
1601 n++;
1602 }
1603 *w = 0;
1604 DeviceObject->Vpb->VolumeLabelLength = n;
1605 }
1606 else if (DeviceExt->FatType == FAT32)
1607 {
1608 struct _BootSector32 *BootSect = (PVOID)DeviceExt->Boot;
1609 PSTR s = BootSect->VolumeLabel;
1610 PWSTR w = DeviceObject->Vpb->VolumeLabel;
1611 int n=0;
1612
1613 // get serial number
1614 DeviceObject->Vpb->SerialNumber = BootSect->VolumeID;
1615
1616 // copy drive label
1617 while (*s != ' ' && n < 11)
1618 {
1619 *w++ = *s++;
1620 n++;
1621 }
1622 *w = 0;
1623 DeviceObject->Vpb->VolumeLabelLength = n;
1624 }
1625
1626 return(STATUS_SUCCESS);
1627 }
1628
1629 NTSTATUS FsdFileSystemControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
1630 /*
1631 * FUNCTION: File system control
1632 */
1633 {
1634 PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
1635 // PVPB vpb = Stack->Parameters.Mount.Vpb;
1636 PDEVICE_OBJECT DeviceToMount = Stack->Parameters.Mount.DeviceObject;
1637 NTSTATUS Status;
1638
1639 DPRINT("VFAT FSC\n");
1640
1641 /* FIXME: should make sure that this is actually a mount request! */
1642
1643 if (FsdHasFileSystem(DeviceToMount))
1644 {
1645 Status = FsdMount(DeviceToMount);
1646 }
1647 else
1648 {
1649 DPRINT("VFAT: Unrecognized Volume\n");
1650 Status = STATUS_UNRECOGNIZED_VOLUME;
1651 }
1652 DPRINT("VFAT File system successfully mounted\n");
1653
1654 Irp->IoStatus.Status = Status;
1655 Irp->IoStatus.Information = 0;
1656
1657 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1658 return(Status);
1659 }
1660
1661 NTSTATUS FsdGetStandardInformation(PVfatFCB FCB, PDEVICE_OBJECT DeviceObject,
1662 PFILE_STANDARD_INFORMATION StandardInfo)
1663 /*
1664 * FUNCTION: Retrieve the standard file information
1665 */
1666 {
1667 PDEVICE_EXTENSION DeviceExtension;
1668 unsigned long AllocSize;
1669
1670 DeviceExtension = DeviceObject->DeviceExtension;
1671 /* PRECONDITION */
1672 assert(DeviceExtension != NULL);
1673 assert(DeviceExtension->BytesPerCluster != 0);
1674 assert(StandardInfo != NULL);
1675 assert(FCB != NULL);
1676
1677 RtlZeroMemory(StandardInfo, sizeof(FILE_STANDARD_INFORMATION));
1678
1679 /* Make allocsize a rounded up multiple of BytesPerCluster */
1680 AllocSize = ((FCB->entry.FileSize + DeviceExtension->BytesPerCluster - 1) /
1681 DeviceExtension->BytesPerCluster) *
1682 DeviceExtension->BytesPerCluster;
1683
1684 StandardInfo->AllocationSize = RtlConvertUlongToLargeInteger(AllocSize);
1685 StandardInfo->EndOfFile = RtlConvertUlongToLargeInteger(FCB->entry.FileSize);
1686 StandardInfo->NumberOfLinks = 0;
1687 StandardInfo->DeletePending = FALSE;
1688 if((FCB->entry.Attrib & 0x10)>0) {
1689 StandardInfo->Directory = TRUE;
1690 } else {
1691 StandardInfo->Directory = FALSE;
1692 }
1693
1694 return STATUS_SUCCESS;
1695 }
1696
1697 NTSTATUS FsdSetPositionInformation(PFILE_OBJECT FileObject,
1698 PVfatFCB FCB,
1699 PDEVICE_OBJECT DeviceObject,
1700 PFILE_POSITION_INFORMATION PositionInfo)
1701 {
1702 DPRINT("FsdSetPositionInformation()\n");
1703
1704 DPRINT("PositionInfo %x\n", PositionInfo);
1705 DPRINT("Setting position %d\n", PositionInfo->CurrentByteOffset.LowPart);
1706 memcpy(&FileObject->CurrentByteOffset,&PositionInfo->CurrentByteOffset,
1707 sizeof(LARGE_INTEGER));
1708
1709 return(STATUS_SUCCESS);
1710 }
1711
1712 NTSTATUS FsdGetPositionInformation(PFILE_OBJECT FileObject,
1713 PVfatFCB FCB,
1714 PDEVICE_OBJECT DeviceObject,
1715 PFILE_POSITION_INFORMATION PositionInfo)
1716 {
1717 DPRINT("FsdGetPositionInformation()\n");
1718
1719 memcpy(&PositionInfo->CurrentByteOffset, &FileObject->CurrentByteOffset,
1720 sizeof(LARGE_INTEGER));
1721 DPRINT("Getting position %x\n", PositionInfo->CurrentByteOffset.LowPart);
1722 return(STATUS_SUCCESS);
1723 }
1724
1725 NTSTATUS FsdGetBasicInformation(PFILE_OBJECT FileObject,
1726 PVfatFCB FCB,
1727 PDEVICE_OBJECT DeviceObject,
1728 PFILE_BASIC_INFORMATION BasicInfo)
1729 {
1730 DPRINT("FsdGetBasicInformation()\n");
1731
1732 // BasicInfo->CreationTime =
1733 // BasicInfo->LastAccessTime =
1734 // BasicInfo->LastWriteTime =
1735 // BasicInfo->ChangeTime =
1736
1737 BasicInfo->FileAttributes = FCB->entry.Attrib;
1738
1739 DPRINT("Getting attributes %x\n", BasicInfo->FileAttributes);
1740
1741 return(STATUS_SUCCESS);
1742 }
1743
1744
1745 NTSTATUS FsdQueryInformation(PDEVICE_OBJECT DeviceObject, PIRP Irp)
1746 /*
1747 * FUNCTION: Retrieve the specified file information
1748 */
1749 {
1750 PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
1751 FILE_INFORMATION_CLASS FileInformationClass =
1752 Stack->Parameters.QueryFile.FileInformationClass;
1753 PFILE_OBJECT FileObject = NULL;
1754 PVfatFCB FCB = NULL;
1755 // PVfatCCB CCB = NULL;
1756
1757 NTSTATUS RC = STATUS_SUCCESS;
1758 void *SystemBuffer;
1759
1760 /* PRECONDITION */
1761 assert(DeviceObject != NULL);
1762 assert(Irp != NULL);
1763
1764 /* INITIALIZATION */
1765 Stack = IoGetCurrentIrpStackLocation(Irp);
1766 FileInformationClass = Stack->Parameters.QueryFile.FileInformationClass;
1767 FileObject = Stack->FileObject;
1768 // CCB = (PVfatCCB)(FileObject->FsContext2);
1769 // FCB = CCB->Buffer; // Should be CCB->FCB???
1770 FCB = ((PVfatCCB)(FileObject->FsContext2))->pFcb;
1771
1772 // FIXME : determine Buffer for result :
1773 if (Irp->MdlAddress)
1774 SystemBuffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
1775 else
1776 SystemBuffer = Irp->UserBuffer;
1777 // SystemBuffer = Irp->AssociatedIrp.SystemBuffer;
1778
1779 switch(FileInformationClass) {
1780 case FileStandardInformation:
1781 RC = FsdGetStandardInformation(FCB, DeviceObject, SystemBuffer);
1782 break;
1783 case FilePositionInformation:
1784 RC = FsdGetPositionInformation(FileObject,
1785 FCB,
1786 DeviceObject,
1787 SystemBuffer);
1788 break;
1789 case FileBasicInformation:
1790 RC = FsdGetBasicInformation(FileObject,
1791 FCB,
1792 DeviceObject,
1793 SystemBuffer);
1794 break;
1795 default:
1796 RC=STATUS_NOT_IMPLEMENTED;
1797 }
1798
1799 Irp->IoStatus.Status = RC;
1800 Irp->IoStatus.Information = 0;
1801 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1802
1803 return RC;
1804 }
1805
1806 NTSTATUS FsdSetInformation(PDEVICE_OBJECT DeviceObject, PIRP Irp)
1807 /*
1808 * FUNCTION: Retrieve the specified file information
1809 */
1810 {
1811 PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
1812 FILE_INFORMATION_CLASS FileInformationClass;
1813 PFILE_OBJECT FileObject = NULL;
1814 PVfatFCB FCB = NULL;
1815 // PVfatCCB CCB = NULL;
1816 NTSTATUS RC = STATUS_SUCCESS;
1817 PVOID SystemBuffer;
1818
1819 /* PRECONDITION */
1820 assert(DeviceObject != NULL);
1821 assert(Irp != NULL);
1822
1823 DPRINT("FsdSetInformation(DeviceObject %x, Irp %x)\n",
1824 DeviceObject,Irp);
1825
1826 /* INITIALIZATION */
1827 Stack = IoGetCurrentIrpStackLocation(Irp);
1828 FileInformationClass = Stack->Parameters.SetFile.FileInformationClass;
1829 FileObject = Stack->FileObject;
1830 FCB = ((PVfatCCB)(FileObject->FsContext2))->pFcb;
1831
1832 // FIXME : determine Buffer for result :
1833 if (Irp->MdlAddress)
1834 SystemBuffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
1835 else
1836 SystemBuffer = Irp->UserBuffer;
1837 // SystemBuffer = Irp->AssociatedIrp.SystemBuffer;
1838
1839 DPRINT("FileInformationClass %d\n",FileInformationClass);
1840 DPRINT("SystemBuffer %x\n",SystemBuffer);
1841
1842 switch(FileInformationClass)
1843 {
1844 case FilePositionInformation:
1845 RC = FsdSetPositionInformation(FileObject,
1846 FCB,
1847 DeviceObject,
1848 SystemBuffer);
1849 break;
1850 default:
1851 RC = STATUS_NOT_IMPLEMENTED;
1852 }
1853
1854 Irp->IoStatus.Status = RC;
1855 Irp->IoStatus.Information = 0;
1856 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1857
1858 return RC;
1859 }
1860
1861
1862
1863 NTSTATUS FsdGetFsVolumeInformation(PFILE_OBJECT FileObject,
1864 PVfatFCB FCB,
1865 PDEVICE_OBJECT DeviceObject,
1866 PFILE_FS_VOLUME_INFORMATION FsVolumeInfo)
1867 {
1868 DPRINT("FsdGetFsVolumeInformation()\n");
1869 DPRINT("FsVolumeInfo = %p\n", FsVolumeInfo);
1870
1871 if (!FsVolumeInfo)
1872 return(STATUS_SUCCESS);
1873
1874
1875 /* valid entries */
1876 FsVolumeInfo->VolumeSerialNumber = DeviceObject->Vpb->SerialNumber;
1877 FsVolumeInfo->VolumeLabelLength = DeviceObject->Vpb->VolumeLabelLength;
1878 wcscpy (FsVolumeInfo->VolumeLabel, DeviceObject->Vpb->VolumeLabel);
1879
1880 /* dummy entries */
1881 FsVolumeInfo->VolumeCreationTime.QuadPart = 0;
1882 FsVolumeInfo->SupportsObjects = FALSE;
1883
1884 DPRINT("Finished FsdGetFsVolumeInformation()\n");
1885
1886 return(STATUS_SUCCESS);
1887 }
1888
1889
1890 NTSTATUS FsdGetFsAttributeInformation(PFILE_FS_ATTRIBUTE_INFORMATION FsAttributeInfo)
1891 {
1892 DPRINT("FsdGetFsAttributeInformation()\n");
1893 DPRINT("FsAttributeInfo = %p\n", FsAttributeInfo);
1894
1895 if (!FsAttributeInfo)
1896 return(STATUS_SUCCESS);
1897
1898 FsAttributeInfo->FileSystemAttributes = FS_CASE_IS_PRESERVED;
1899 FsAttributeInfo->MaximumComponentNameLength = 255;
1900 FsAttributeInfo->FileSystemNameLength = 3;
1901 wcscpy (FsAttributeInfo->FileSystemName, L"FAT");
1902
1903 DPRINT("Finished FsdGetFsAttributeInformation()\n");
1904
1905 return(STATUS_SUCCESS);
1906 }
1907
1908 NTSTATUS FsdGetFsSizeInformation(PDEVICE_OBJECT DeviceObject,
1909 PFILE_FS_SIZE_INFORMATION FsSizeInfo)
1910 {
1911 PDEVICE_EXTENSION DeviceExt = DeviceObject->DeviceExtension;
1912
1913 DPRINT("FsdGetFsSizeInformation()\n");
1914 DPRINT("FsSizeInfo = %p\n", FsSizeInfo);
1915
1916 if (!FsSizeInfo)
1917 return(STATUS_SUCCESS);
1918
1919 if (DeviceExt->FatType == FAT32)
1920 {
1921 struct _BootSector32 *BootSect = (struct _BootSector32 *)DeviceExt->Boot;
1922
1923 if (BootSect->Sectors)
1924 FsSizeInfo->TotalAllocationUnits.QuadPart = BootSect->Sectors;
1925 else
1926 FsSizeInfo->TotalAllocationUnits.QuadPart = BootSect->SectorsHuge;
1927
1928 FsSizeInfo->AvailableAllocationUnits.QuadPart =
1929 FAT32CountAvailableClusters(DeviceExt);
1930
1931 FsSizeInfo->SectorsPerAllocationUnit = BootSect->SectorsPerCluster;
1932 FsSizeInfo->BytesPerSector = BootSect->BytesPerSector;
1933 }
1934 else
1935 {
1936 struct _BootSector *BootSect = (struct _BootSector *)DeviceExt->Boot;
1937
1938 if (BootSect->Sectors)
1939 FsSizeInfo->TotalAllocationUnits.QuadPart = BootSect->Sectors;
1940 else
1941 FsSizeInfo->TotalAllocationUnits.QuadPart = BootSect->SectorsHuge;
1942
1943 if (DeviceExt->FatType == FAT16)
1944 FsSizeInfo->AvailableAllocationUnits.QuadPart =
1945 FAT16CountAvailableClusters(DeviceExt);
1946 else
1947 FsSizeInfo->AvailableAllocationUnits.QuadPart =
1948 FAT12CountAvailableClusters(DeviceExt);
1949
1950 FsSizeInfo->SectorsPerAllocationUnit = BootSect->SectorsPerCluster;
1951 FsSizeInfo->BytesPerSector = BootSect->BytesPerSector;
1952 }
1953
1954 DPRINT("Finished FsdGetFsSizeInformation()\n");
1955
1956 return(STATUS_SUCCESS);
1957 }
1958
1959
1960 NTSTATUS FsdQueryVolumeInformation(PDEVICE_OBJECT DeviceObject, PIRP Irp)
1961 /*
1962 * FUNCTION: Retrieve the specified file information
1963 */
1964 {
1965 PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
1966 FILE_INFORMATION_CLASS FileInformationClass =
1967 Stack->Parameters.QueryVolume.FileInformationClass;
1968 PFILE_OBJECT FileObject = NULL;
1969 PVfatFCB FCB = NULL;
1970 // PVfatCCB CCB = NULL;
1971
1972 NTSTATUS RC = STATUS_SUCCESS;
1973 void *SystemBuffer;
1974
1975 /* PRECONDITION */
1976 assert(DeviceObject != NULL);
1977 assert(Irp != NULL);
1978
1979 DPRINT("FsdQueryVolumeInformation(DeviceObject %x, Irp %x)\n",
1980 DeviceObject,Irp);
1981
1982 /* INITIALIZATION */
1983 Stack = IoGetCurrentIrpStackLocation(Irp);
1984 FileInformationClass = Stack->Parameters.QueryVolume.FileInformationClass;
1985 FileObject = Stack->FileObject;
1986 // CCB = (PVfatCCB)(FileObject->FsContext2);
1987 // FCB = CCB->Buffer; // Should be CCB->FCB???
1988 FCB = ((PVfatCCB)(FileObject->FsContext2))->pFcb;
1989
1990 // FIXME : determine Buffer for result :
1991 if (Irp->MdlAddress)
1992 SystemBuffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
1993 else
1994 SystemBuffer = Irp->UserBuffer;
1995 // SystemBuffer = Irp->AssociatedIrp.SystemBuffer;
1996
1997 DPRINT("FileInformationClass %d\n",FileInformationClass);
1998 DPRINT("SystemBuffer %x\n",SystemBuffer);
1999
2000 switch (FileInformationClass)
2001 {
2002 case FileFsVolumeInformation:
2003 RC = FsdGetFsVolumeInformation(FileObject,
2004 FCB,
2005 DeviceObject,
2006 SystemBuffer);
2007 break;
2008
2009 case FileFsAttributeInformation:
2010 RC = FsdGetFsAttributeInformation(SystemBuffer);
2011 break;
2012
2013 case FileFsSizeInformation:
2014 RC = FsdGetFsSizeInformation(DeviceObject, SystemBuffer);
2015 break;
2016
2017 default:
2018 RC=STATUS_NOT_IMPLEMENTED;
2019 }
2020
2021 Irp->IoStatus.Status = RC;
2022 Irp->IoStatus.Information = 0;
2023 IoCompleteRequest(Irp, IO_NO_INCREMENT);
2024
2025 return RC;
2026 }
2027
2028
2029 STDCALL NTSTATUS DriverEntry(PDRIVER_OBJECT _DriverObject,
2030 PUNICODE_STRING RegistryPath)
2031 /*
2032 * FUNCTION: Called by the system to initalize the driver
2033 * ARGUMENTS:
2034 * DriverObject = object describing this driver
2035 * RegistryPath = path to our configuration entries
2036 * RETURNS: Success or failure
2037 */
2038 {
2039 PDEVICE_OBJECT DeviceObject;
2040 NTSTATUS ret;
2041 UNICODE_STRING ustr;
2042 ANSI_STRING astr;
2043
2044 DbgPrint("VFAT 0.0.6\n");
2045 pFirstFcb=NULL;
2046 VFATDriverObject = _DriverObject;
2047
2048 RtlInitAnsiString(&astr,"\\Device\\VFAT");
2049 RtlAnsiStringToUnicodeString(&ustr,&astr,TRUE);
2050 ret = IoCreateDevice(VFATDriverObject,0,&ustr,
2051 FILE_DEVICE_FILE_SYSTEM,0,FALSE,&DeviceObject);
2052 if (ret!=STATUS_SUCCESS)
2053 {
2054 return(ret);
2055 }
2056
2057 DeviceObject->Flags = DO_DIRECT_IO;
2058 VFATDriverObject->MajorFunction[IRP_MJ_CLOSE] = FsdClose;
2059 VFATDriverObject->MajorFunction[IRP_MJ_CREATE] = FsdCreate;
2060 VFATDriverObject->MajorFunction[IRP_MJ_READ] = FsdRead;
2061 VFATDriverObject->MajorFunction[IRP_MJ_WRITE] = FsdWrite;
2062 VFATDriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] =
2063 FsdFileSystemControl;
2064 VFATDriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] =
2065 FsdQueryInformation;
2066 VFATDriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] =
2067 FsdSetInformation;
2068 VFATDriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] =
2069 FsdDirectoryControl;
2070 VFATDriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] =
2071 FsdQueryVolumeInformation;
2072
2073 VFATDriverObject->DriverUnload = NULL;
2074
2075 IoRegisterFileSystem(DeviceObject);
2076
2077 return(STATUS_SUCCESS);
2078 }
2079