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