mirror of
https://github.com/reactos/reactos.git
synced 2025-08-03 18:35:41 +00:00
new file for driver from Jean
svn path=/trunk/; revision=139
This commit is contained in:
parent
43fd2f2579
commit
6ce4528a80
1 changed files with 318 additions and 0 deletions
318
reactos/drivers/fs/vfat/dir.c
Normal file
318
reactos/drivers/fs/vfat/dir.c
Normal file
|
@ -0,0 +1,318 @@
|
||||||
|
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS kernel
|
||||||
|
* FILE: services/fs/vfat/dir.c
|
||||||
|
* PURPOSE: VFAT Filesystem : directory control
|
||||||
|
* UPDATE HISTORY:
|
||||||
|
19-12-1998 : created
|
||||||
|
|
||||||
|
*/
|
||||||
|
#include <ddk/ntddk.h>
|
||||||
|
#include <internal/string.h>
|
||||||
|
#include <wstring.h>
|
||||||
|
#include <ddk/cctypes.h>
|
||||||
|
#include <ddk/zwtypes.h>
|
||||||
|
|
||||||
|
#define NDEBUG
|
||||||
|
#include <internal/debug.h>
|
||||||
|
|
||||||
|
#include "vfat.h"
|
||||||
|
|
||||||
|
// buggy function, waiting the real function
|
||||||
|
BOOL fsdDosDateTimeToFileTime(WORD wDosDate,WORD wDosTime, TIME *FileTime)
|
||||||
|
{
|
||||||
|
WORD Day,Month,Year,Second,Minute,Hour;
|
||||||
|
long long int *pTime=(long long int *)FileTime;
|
||||||
|
long long int mult;
|
||||||
|
Day=wDosDate&0x001f;
|
||||||
|
Month= (wDosDate&0x00e0)>>5;//1=January
|
||||||
|
Year= ((wDosDate&0xff00)>>8)+1980;
|
||||||
|
Second=(wDosTime&0x001f)<<1;
|
||||||
|
Minute=(wDosTime&0x07e0)>>5;
|
||||||
|
Hour= (wDosTime&0xf100)>>11;
|
||||||
|
mult=10000000;
|
||||||
|
*pTime=Second*mult;
|
||||||
|
mult *=60;
|
||||||
|
*pTime +=Minute*mult;
|
||||||
|
mult *=60;
|
||||||
|
*pTime +=Hour*mult;
|
||||||
|
mult *=24;
|
||||||
|
*pTime +=(Day-1)*mult;
|
||||||
|
*pTime +=(Month-1)*mult*30;//FIXME : not always 30 days in a month
|
||||||
|
*pTime +=(Year-1601)*mult*365;//FIXME : not always 365 days in a year
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
#define DosDateTimeToFileTime fsdDosDateTimeToFileTime
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
unsigned long vfat_wstrlen(PWSTR s)
|
||||||
|
{
|
||||||
|
WCHAR c=' ';
|
||||||
|
unsigned int len=0;
|
||||||
|
|
||||||
|
while(c!=0) {
|
||||||
|
c=*s;
|
||||||
|
s++;
|
||||||
|
len++;
|
||||||
|
};
|
||||||
|
s-=len;
|
||||||
|
|
||||||
|
return len-1;
|
||||||
|
}
|
||||||
|
#define DWORD_ROUND_UP(x) ( (((ULONG)(x))%32) ? ((((ULONG)x)&(~0x1f))+0x20) : ((ULONG)x) )
|
||||||
|
|
||||||
|
NTSTATUS FsdGetFileNameInformation(PFCB pFcb,
|
||||||
|
PFILE_NAMES_INFORMATION pInfo,ULONG BufferLength)
|
||||||
|
{
|
||||||
|
ULONG Length;
|
||||||
|
Length=vfat_wstrlen(pFcb->ObjectName);
|
||||||
|
if( (sizeof(FILE_DIRECTORY_INFORMATION)+Length) >BufferLength)
|
||||||
|
return STATUS_BUFFER_OVERFLOW;
|
||||||
|
pInfo->FileNameLength=Length;
|
||||||
|
pInfo->NextEntryOffset=DWORD_ROUND_UP(sizeof(FILE_DIRECTORY_INFORMATION)+Length);
|
||||||
|
memcpy(pInfo->FileName,pFcb->ObjectName
|
||||||
|
,sizeof(WCHAR)*(pInfo->FileNameLength));
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS FsdGetFileDirectoryInformation(PFCB pFcb,
|
||||||
|
PDEVICE_EXTENSION DeviceExt,
|
||||||
|
PFILE_DIRECTORY_INFORMATION pInfo,ULONG BufferLength)
|
||||||
|
{
|
||||||
|
unsigned long long AllocSize;
|
||||||
|
ULONG Length;
|
||||||
|
Length=vfat_wstrlen(pFcb->ObjectName);
|
||||||
|
if( (sizeof(FILE_DIRECTORY_INFORMATION)+Length) >BufferLength)
|
||||||
|
return STATUS_BUFFER_OVERFLOW;
|
||||||
|
pInfo->FileNameLength=Length;
|
||||||
|
pInfo->NextEntryOffset=DWORD_ROUND_UP(sizeof(FILE_DIRECTORY_INFORMATION)+Length);
|
||||||
|
memcpy(pInfo->FileName,pFcb->ObjectName
|
||||||
|
,sizeof(WCHAR)*(pInfo->FileNameLength));
|
||||||
|
// pInfo->FileIndex=;
|
||||||
|
DosDateTimeToFileTime(pFcb->entry.CreationDate,pFcb->entry.CreationTime
|
||||||
|
,&pInfo->CreationTime);
|
||||||
|
DosDateTimeToFileTime(pFcb->entry.AccessDate,0
|
||||||
|
,&pInfo->LastAccessTime);
|
||||||
|
DosDateTimeToFileTime(pFcb->entry.UpdateDate,pFcb->entry.UpdateTime
|
||||||
|
,&pInfo->LastWriteTime);
|
||||||
|
DosDateTimeToFileTime(pFcb->entry.UpdateDate,pFcb->entry.UpdateTime
|
||||||
|
,&pInfo->ChangeTime);
|
||||||
|
pInfo->EndOfFile=RtlConvertUlongToLargeInteger(pFcb->entry.FileSize);
|
||||||
|
/* Make allocsize a rounded up multiple of BytesPerCluster */
|
||||||
|
AllocSize = ((pFcb->entry.FileSize + DeviceExt->BytesPerCluster - 1) /
|
||||||
|
DeviceExt->BytesPerCluster) *
|
||||||
|
DeviceExt->BytesPerCluster;
|
||||||
|
pInfo->AllocationSize.LowPart= AllocSize;
|
||||||
|
pInfo->AllocationSize.HighPart= AllocSize >>32;
|
||||||
|
pInfo->FileAttributes=pFcb->entry.Attrib;
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS FsdGetFileFullDirectoryInformation(PFCB pFcb,
|
||||||
|
PDEVICE_EXTENSION DeviceExt,
|
||||||
|
PFILE_FULL_DIRECTORY_INFORMATION pInfo,ULONG BufferLength)
|
||||||
|
{
|
||||||
|
unsigned long long AllocSize;
|
||||||
|
ULONG Length;
|
||||||
|
Length=vfat_wstrlen(pFcb->ObjectName);
|
||||||
|
if( (sizeof(FILE_FULL_DIRECTORY_INFORMATION)+Length) >BufferLength)
|
||||||
|
return STATUS_BUFFER_OVERFLOW;
|
||||||
|
pInfo->FileNameLength=Length;
|
||||||
|
pInfo->NextEntryOffset=DWORD_ROUND_UP(sizeof(FILE_FULL_DIRECTORY_INFORMATION)+Length);
|
||||||
|
memcpy(pInfo->FileName,pFcb->ObjectName
|
||||||
|
,sizeof(WCHAR)*(pInfo->FileNameLength));
|
||||||
|
// pInfo->FileIndex=;
|
||||||
|
DosDateTimeToFileTime(pFcb->entry.CreationDate,pFcb->entry.CreationTime
|
||||||
|
,&pInfo->CreationTime);
|
||||||
|
DosDateTimeToFileTime(pFcb->entry.AccessDate,0
|
||||||
|
,&pInfo->LastAccessTime);
|
||||||
|
DosDateTimeToFileTime(pFcb->entry.UpdateDate,pFcb->entry.UpdateTime
|
||||||
|
,&pInfo->LastWriteTime);
|
||||||
|
DosDateTimeToFileTime(pFcb->entry.UpdateDate,pFcb->entry.UpdateTime
|
||||||
|
,&pInfo->ChangeTime);
|
||||||
|
pInfo->EndOfFile=RtlConvertUlongToLargeInteger(pFcb->entry.FileSize);
|
||||||
|
/* Make allocsize a rounded up multiple of BytesPerCluster */
|
||||||
|
AllocSize = ((pFcb->entry.FileSize + DeviceExt->BytesPerCluster - 1) /
|
||||||
|
DeviceExt->BytesPerCluster) *
|
||||||
|
DeviceExt->BytesPerCluster;
|
||||||
|
pInfo->AllocationSize.LowPart= AllocSize;
|
||||||
|
pInfo->AllocationSize.HighPart= (AllocSize >>32);
|
||||||
|
pInfo->FileAttributes=pFcb->entry.Attrib;
|
||||||
|
// pInfo->EaSize=;
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS FsdGetFileBothInformation(PFCB pFcb,
|
||||||
|
PDEVICE_EXTENSION DeviceExt,
|
||||||
|
PFILE_BOTH_DIRECTORY_INFORMATION pInfo,ULONG BufferLength)
|
||||||
|
{
|
||||||
|
short i;
|
||||||
|
unsigned long long AllocSize;
|
||||||
|
ULONG Length;
|
||||||
|
Length=vfat_wstrlen(pFcb->ObjectName);
|
||||||
|
if( (sizeof(FILE_BOTH_DIRECTORY_INFORMATION)+Length) >BufferLength)
|
||||||
|
return STATUS_BUFFER_OVERFLOW;
|
||||||
|
pInfo->FileNameLength=Length;
|
||||||
|
pInfo->NextEntryOffset=DWORD_ROUND_UP(sizeof(FILE_BOTH_DIRECTORY_INFORMATION)+Length);
|
||||||
|
DPRINT("sizeof %d,Length %d, BufLength %d, Next %d\n"
|
||||||
|
,sizeof(FILE_BOTH_DIRECTORY_INFORMATION),Length,BufferLength
|
||||||
|
,pInfo->NextEntryOffset);
|
||||||
|
memcpy(pInfo->FileName,pFcb->ObjectName
|
||||||
|
,sizeof(WCHAR)*(pInfo->FileNameLength));
|
||||||
|
// pInfo->FileIndex=;
|
||||||
|
DosDateTimeToFileTime(pFcb->entry.CreationDate,pFcb->entry.CreationTime
|
||||||
|
,&pInfo->CreationTime);
|
||||||
|
DosDateTimeToFileTime(pFcb->entry.AccessDate,0
|
||||||
|
,&pInfo->LastAccessTime);
|
||||||
|
DosDateTimeToFileTime(pFcb->entry.UpdateDate,pFcb->entry.UpdateTime
|
||||||
|
,&pInfo->LastWriteTime);
|
||||||
|
DosDateTimeToFileTime(pFcb->entry.UpdateDate,pFcb->entry.UpdateTime
|
||||||
|
,&pInfo->ChangeTime);
|
||||||
|
pInfo->EndOfFile=RtlConvertUlongToLargeInteger(pFcb->entry.FileSize);
|
||||||
|
/* Make allocsize a rounded up multiple of BytesPerCluster */
|
||||||
|
AllocSize = ((pFcb->entry.FileSize + DeviceExt->BytesPerCluster - 1) /
|
||||||
|
DeviceExt->BytesPerCluster) *
|
||||||
|
DeviceExt->BytesPerCluster;
|
||||||
|
pInfo->AllocationSize.LowPart= AllocSize;
|
||||||
|
pInfo->AllocationSize.HighPart= AllocSize >>32;
|
||||||
|
pInfo->FileAttributes=pFcb->entry.Attrib;
|
||||||
|
// pInfo->EaSize=;
|
||||||
|
for (i=0;i<8 && (pFcb->entry.Filename[i]!=' ') ;i++)
|
||||||
|
pInfo->ShortName[i]=pFcb->entry.Filename[i];
|
||||||
|
pInfo->ShortNameLength=i;
|
||||||
|
pInfo->ShortName[i]='.';
|
||||||
|
for (i=0 ;i<3 && (pFcb->entry.Ext[i]!=' ') ;i++)
|
||||||
|
pInfo->ShortName[i+1+pInfo->ShortNameLength]=pFcb->entry.Ext[i];
|
||||||
|
if(i) pInfo->ShortNameLength += (i+1);
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS DoQuery(PDEVICE_OBJECT DeviceObject, PIRP Irp,PIO_STACK_LOCATION Stack)
|
||||||
|
{
|
||||||
|
NTSTATUS RC=STATUS_SUCCESS;
|
||||||
|
long BufferLength = 0;
|
||||||
|
PUNICODE_STRING pSearchPattern = NULL;
|
||||||
|
FILE_INFORMATION_CLASS FileInformationClass;
|
||||||
|
unsigned long FileIndex = 0;
|
||||||
|
unsigned char *Buffer = NULL;
|
||||||
|
PFILE_NAMES_INFORMATION Buffer0 = NULL;
|
||||||
|
PFILE_OBJECT pFileObject = NULL;
|
||||||
|
PFCB pFcb;
|
||||||
|
FCB tmpFcb;
|
||||||
|
PDEVICE_EXTENSION DeviceExt;
|
||||||
|
WCHAR star[5],*pCharPattern;
|
||||||
|
unsigned long OldEntry,OldSector;
|
||||||
|
DeviceExt = DeviceObject->DeviceExtension;
|
||||||
|
// Obtain the callers parameters
|
||||||
|
BufferLength = Stack->Parameters.QueryDirectory.BufferLength;
|
||||||
|
pSearchPattern = Stack->Parameters.QueryDirectory.FileName;
|
||||||
|
FileInformationClass = Stack->Parameters.QueryDirectory.FileInformationClass;
|
||||||
|
FileIndex = Stack->Parameters.QueryDirectory.FileIndex;
|
||||||
|
pFileObject = Stack->FileObject;
|
||||||
|
pFcb=(PFCB)(pFileObject->FsContext);
|
||||||
|
if(Stack->Parameters.QueryDirectory.RestartScan)
|
||||||
|
{
|
||||||
|
pFcb->StartEntry=pFcb->StartSector=0;
|
||||||
|
}
|
||||||
|
// determine Buffer for result :
|
||||||
|
if (Irp->MdlAddress)
|
||||||
|
Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
|
||||||
|
else
|
||||||
|
Buffer = Irp->UserBuffer;
|
||||||
|
if (pSearchPattern==NULL)
|
||||||
|
{
|
||||||
|
star[0]='*';
|
||||||
|
star[1]=0;
|
||||||
|
pCharPattern=star;
|
||||||
|
}
|
||||||
|
else pCharPattern=pSearchPattern->Buffer;
|
||||||
|
while(RC==STATUS_SUCCESS && BufferLength >0)
|
||||||
|
{
|
||||||
|
OldSector=pFcb->StartSector;
|
||||||
|
OldEntry=pFcb->StartEntry;
|
||||||
|
if(OldSector)pFcb->StartEntry++;
|
||||||
|
RC=FindFile(DeviceExt,&tmpFcb,pFcb,pCharPattern,&pFcb->StartSector,&pFcb->StartEntry);
|
||||||
|
DPRINT("Found %w\n",tmpFcb.ObjectName);
|
||||||
|
if (NT_SUCCESS(RC))
|
||||||
|
{
|
||||||
|
switch(FileInformationClass)
|
||||||
|
{
|
||||||
|
case FileNameInformation:
|
||||||
|
RC=FsdGetFileNameInformation(&tmpFcb
|
||||||
|
,(PFILE_NAMES_INFORMATION)Buffer,BufferLength);
|
||||||
|
break;
|
||||||
|
case FileDirectoryInformation:
|
||||||
|
RC= FsdGetFileDirectoryInformation(&tmpFcb
|
||||||
|
,DeviceExt,(PFILE_DIRECTORY_INFORMATION)Buffer,BufferLength);
|
||||||
|
break;
|
||||||
|
case FileFullDirectoryInformation :
|
||||||
|
RC= FsdGetFileFullDirectoryInformation(&tmpFcb
|
||||||
|
,DeviceExt,(PFILE_FULL_DIRECTORY_INFORMATION)Buffer,BufferLength);
|
||||||
|
break;
|
||||||
|
case FileBothDirectoryInformation :
|
||||||
|
RC=FsdGetFileBothInformation(&tmpFcb
|
||||||
|
,DeviceExt,(PFILE_BOTH_DIRECTORY_INFORMATION)Buffer,BufferLength);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
RC=STATUS_INVALID_INFO_CLASS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(Buffer0) Buffer0->NextEntryOffset=0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(RC==STATUS_BUFFER_OVERFLOW)
|
||||||
|
{
|
||||||
|
if(Buffer0) Buffer0->NextEntryOffset=0;
|
||||||
|
pFcb->StartSector=OldSector;
|
||||||
|
pFcb->StartEntry=OldEntry;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Buffer0=(PFILE_NAMES_INFORMATION)Buffer;
|
||||||
|
Buffer0->FileIndex=FileIndex++;
|
||||||
|
if(Stack->Parameters.QueryDirectory.ReturnSingleEntry) break;
|
||||||
|
BufferLength -= Buffer0->NextEntryOffset;
|
||||||
|
Buffer += Buffer0->NextEntryOffset;
|
||||||
|
}
|
||||||
|
if(Buffer0) Buffer0->NextEntryOffset=0;
|
||||||
|
if(FileIndex>0) return STATUS_SUCCESS;
|
||||||
|
return RC;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
NTSTATUS FsdDirectoryControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
||||||
|
/*
|
||||||
|
* FUNCTION: directory control : read/write directory informations
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
NTSTATUS RC = STATUS_SUCCESS;
|
||||||
|
PFILE_OBJECT FileObject = NULL;
|
||||||
|
PIO_STACK_LOCATION Stack;
|
||||||
|
Stack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
CHECKPOINT;
|
||||||
|
FileObject = Stack->FileObject;
|
||||||
|
switch (Stack->MinorFunction)
|
||||||
|
{
|
||||||
|
case IRP_MN_QUERY_DIRECTORY:
|
||||||
|
RC=DoQuery(DeviceObject,Irp,Stack);
|
||||||
|
break;
|
||||||
|
case IRP_MN_NOTIFY_CHANGE_DIRECTORY:
|
||||||
|
DPRINT(" vfat, dir : change\n");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// error
|
||||||
|
DbgPrint("unexpected minor function %x in VFAT driver\n",Stack->MinorFunction);
|
||||||
|
RC = STATUS_INVALID_DEVICE_REQUEST;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Irp->IoStatus.Status = RC;
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
return RC;
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue