mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 01:55:19 +00:00
Added NTFS driver stub.
svn path=/trunk/; revision=3146
This commit is contained in:
parent
ef401a1081
commit
24c84ca4b7
12 changed files with 3329 additions and 0 deletions
6
reactos/drivers/fs/ntfs/.cvsignore
Normal file
6
reactos/drivers/fs/ntfs/.cvsignore
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
base.tmp
|
||||||
|
junk.tmp
|
||||||
|
temp.exp
|
||||||
|
ntfs.coff
|
||||||
|
ntfs.sys.unstripped
|
||||||
|
*.d
|
255
reactos/drivers/fs/ntfs/blockdev.c
Normal file
255
reactos/drivers/fs/ntfs/blockdev.c
Normal file
|
@ -0,0 +1,255 @@
|
||||||
|
/*
|
||||||
|
* ReactOS kernel
|
||||||
|
* Copyright (C) 2002 ReactOS Team
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
/* $Id: blockdev.c,v 1.1 2002/06/25 22:23:05 ekohl Exp $
|
||||||
|
*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS kernel
|
||||||
|
* FILE: services/fs/ntfs/blockdev.c
|
||||||
|
* PURPOSE: NTFS filesystem driver
|
||||||
|
* PROGRAMMER: Eric Kohl
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* INCLUDES *****************************************************************/
|
||||||
|
|
||||||
|
#include <ddk/ntddk.h>
|
||||||
|
|
||||||
|
#define NDEBUG
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
|
#include "ntfs.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* FUNCTIONS ****************************************************************/
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NtfsReadSectors(IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN ULONG DiskSector,
|
||||||
|
IN ULONG SectorCount,
|
||||||
|
IN ULONG SectorSize,
|
||||||
|
IN OUT PUCHAR Buffer)
|
||||||
|
{
|
||||||
|
IO_STATUS_BLOCK IoStatus;
|
||||||
|
LARGE_INTEGER Offset;
|
||||||
|
ULONG BlockSize;
|
||||||
|
KEVENT Event;
|
||||||
|
PIRP Irp;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
KeInitializeEvent(&Event,
|
||||||
|
NotificationEvent,
|
||||||
|
FALSE);
|
||||||
|
|
||||||
|
Offset.QuadPart = (LONGLONG)DiskSector * (LONGLONG)SectorSize;
|
||||||
|
BlockSize = SectorCount * SectorSize;
|
||||||
|
|
||||||
|
DPRINT("NtfsReadSectors(DeviceObject %x, DiskSector %d, Buffer %x)\n",
|
||||||
|
DeviceObject, DiskSector, Buffer);
|
||||||
|
DPRINT("Offset %I64x BlockSize %ld\n",
|
||||||
|
Offset.QuadPart,
|
||||||
|
BlockSize);
|
||||||
|
|
||||||
|
DPRINT("Building synchronous FSD Request...\n");
|
||||||
|
Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ,
|
||||||
|
DeviceObject,
|
||||||
|
Buffer,
|
||||||
|
BlockSize,
|
||||||
|
&Offset,
|
||||||
|
&Event,
|
||||||
|
&IoStatus);
|
||||||
|
if (Irp == NULL)
|
||||||
|
{
|
||||||
|
DPRINT("IoBuildSynchronousFsdRequest failed\n");
|
||||||
|
return(STATUS_INSUFFICIENT_RESOURCES);
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINT("Calling IO Driver... with irp %x\n", Irp);
|
||||||
|
Status = IoCallDriver(DeviceObject, Irp);
|
||||||
|
|
||||||
|
DPRINT("Waiting for IO Operation for %x\n", Irp);
|
||||||
|
if (Status == STATUS_PENDING)
|
||||||
|
{
|
||||||
|
DPRINT("Operation pending\n");
|
||||||
|
KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
|
||||||
|
DPRINT("Getting IO Status... for %x\n", Irp);
|
||||||
|
Status = IoStatus.Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
if (Status == STATUS_VERIFY_REQUIRED)
|
||||||
|
{
|
||||||
|
PDEVICE_OBJECT DeviceToVerify;
|
||||||
|
NTSTATUS NewStatus;
|
||||||
|
|
||||||
|
DPRINT1("STATUS_VERIFY_REQUIRED\n");
|
||||||
|
DeviceToVerify = IoGetDeviceToVerify(PsGetCurrentThread());
|
||||||
|
IoSetDeviceToVerify(PsGetCurrentThread(), NULL);
|
||||||
|
|
||||||
|
NewStatus = IoVerifyVolume(DeviceToVerify, FALSE);
|
||||||
|
DPRINT1("IoVerifyVolume() retuned (Status %lx)\n", NewStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINT("NtfsReadSectors() failed (Status %x)\n", Status);
|
||||||
|
DPRINT("(DeviceObject %x, DiskSector %x, Buffer %x, Offset 0x%I64x)\n",
|
||||||
|
DeviceObject, DiskSector, Buffer,
|
||||||
|
Offset.QuadPart);
|
||||||
|
return(Status);
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINT("Block request succeeded for %x\n", Irp);
|
||||||
|
|
||||||
|
return(STATUS_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NtfsReadRawSectors(IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN ULONG DiskSector,
|
||||||
|
IN ULONG SectorCount,
|
||||||
|
IN ULONG SectorSize,
|
||||||
|
IN OUT PUCHAR Buffer)
|
||||||
|
{
|
||||||
|
PIO_STACK_LOCATION Stack;
|
||||||
|
IO_STATUS_BLOCK IoStatus;
|
||||||
|
LARGE_INTEGER Offset;
|
||||||
|
ULONG BlockSize;
|
||||||
|
KEVENT Event;
|
||||||
|
PIRP Irp;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
KeInitializeEvent(&Event,
|
||||||
|
NotificationEvent,
|
||||||
|
FALSE);
|
||||||
|
|
||||||
|
Offset.QuadPart = (LONGLONG)DiskSector * (LONGLONG)SectorSize;
|
||||||
|
BlockSize = SectorCount * SectorSize;
|
||||||
|
|
||||||
|
DPRINT("NtfsReadSectors(DeviceObject %x, DiskSector %d, Buffer %x)\n",
|
||||||
|
DeviceObject, DiskSector, Buffer);
|
||||||
|
DPRINT("Offset %I64x BlockSize %ld\n",
|
||||||
|
Offset.QuadPart,
|
||||||
|
BlockSize);
|
||||||
|
|
||||||
|
DPRINT("Building synchronous FSD Request...\n");
|
||||||
|
Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ,
|
||||||
|
DeviceObject,
|
||||||
|
Buffer,
|
||||||
|
BlockSize,
|
||||||
|
&Offset,
|
||||||
|
&Event,
|
||||||
|
&IoStatus);
|
||||||
|
if (Irp == NULL)
|
||||||
|
{
|
||||||
|
DPRINT("IoBuildSynchronousFsdRequest failed\n");
|
||||||
|
return(STATUS_INSUFFICIENT_RESOURCES);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
// Stack->Flags |= SL_OVERRIDE_VERIFY_VOLUME;
|
||||||
|
|
||||||
|
DPRINT("Calling IO Driver... with irp %x\n", Irp);
|
||||||
|
Status = IoCallDriver(DeviceObject, Irp);
|
||||||
|
|
||||||
|
DPRINT("Waiting for IO Operation for %x\n", Irp);
|
||||||
|
if (Status == STATUS_PENDING)
|
||||||
|
{
|
||||||
|
DPRINT("Operation pending\n");
|
||||||
|
KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
|
||||||
|
DPRINT("Getting IO Status... for %x\n", Irp);
|
||||||
|
Status = IoStatus.Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT("NtfsReadSectors() failed (Status %x)\n", Status);
|
||||||
|
DPRINT("(DeviceObject %x, DiskSector %x, Buffer %x, Offset 0x%I64x)\n",
|
||||||
|
DeviceObject, DiskSector, Buffer,
|
||||||
|
Offset.QuadPart);
|
||||||
|
return(Status);
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINT("Block request succeeded for %x\n", Irp);
|
||||||
|
|
||||||
|
return(STATUS_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NtfsDeviceIoControl(IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN ULONG ControlCode,
|
||||||
|
IN PVOID InputBuffer,
|
||||||
|
IN ULONG InputBufferSize,
|
||||||
|
IN OUT PVOID OutputBuffer,
|
||||||
|
IN OUT PULONG OutputBufferSize)
|
||||||
|
{
|
||||||
|
ULONG BufferSize = 0;
|
||||||
|
PKEVENT Event;
|
||||||
|
PIRP Irp;
|
||||||
|
IO_STATUS_BLOCK IoStatus;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
if (OutputBufferSize != NULL)
|
||||||
|
{
|
||||||
|
BufferSize = *OutputBufferSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
Event = ExAllocatePool(NonPagedPool, sizeof(KEVENT));
|
||||||
|
if (Event == NULL)
|
||||||
|
{
|
||||||
|
return(STATUS_INSUFFICIENT_RESOURCES);
|
||||||
|
}
|
||||||
|
|
||||||
|
KeInitializeEvent(Event, NotificationEvent, FALSE);
|
||||||
|
|
||||||
|
DPRINT("Building device I/O control request ...\n");
|
||||||
|
Irp = IoBuildDeviceIoControlRequest(ControlCode,
|
||||||
|
DeviceObject,
|
||||||
|
InputBuffer,
|
||||||
|
InputBufferSize,
|
||||||
|
OutputBuffer,
|
||||||
|
BufferSize,
|
||||||
|
FALSE,
|
||||||
|
Event,
|
||||||
|
&IoStatus);
|
||||||
|
if (Irp == NULL)
|
||||||
|
{
|
||||||
|
DPRINT("IoBuildDeviceIoControlRequest() failed\n");
|
||||||
|
ExFreePool(Event);
|
||||||
|
return(STATUS_INSUFFICIENT_RESOURCES);
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINT("Calling IO Driver... with irp %x\n", Irp);
|
||||||
|
Status = IoCallDriver(DeviceObject, Irp);
|
||||||
|
if (Status == STATUS_PENDING)
|
||||||
|
{
|
||||||
|
KeWaitForSingleObject(Event, Suspended, KernelMode, FALSE, NULL);
|
||||||
|
Status = IoStatus.Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (OutputBufferSize)
|
||||||
|
{
|
||||||
|
*OutputBufferSize = BufferSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
ExFreePool(Event);
|
||||||
|
|
||||||
|
return(Status);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* EOF */
|
243
reactos/drivers/fs/ntfs/create.c
Normal file
243
reactos/drivers/fs/ntfs/create.c
Normal file
|
@ -0,0 +1,243 @@
|
||||||
|
/*
|
||||||
|
* ReactOS kernel
|
||||||
|
* Copyright (C) 2002 ReactOS Team
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
/* $Id: create.c,v 1.1 2002/06/25 22:23:05 ekohl Exp $
|
||||||
|
*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS kernel
|
||||||
|
* FILE: services/fs/ntfs/create.c
|
||||||
|
* PURPOSE: NTFS filesystem driver
|
||||||
|
* PROGRAMMER: Eric Kohl
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* INCLUDES *****************************************************************/
|
||||||
|
|
||||||
|
#include <ddk/ntddk.h>
|
||||||
|
|
||||||
|
//#define NDEBUG
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
|
#include "ntfs.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* FUNCTIONS ****************************************************************/
|
||||||
|
|
||||||
|
static NTSTATUS
|
||||||
|
NtfsMakeAbsoluteFilename(PFILE_OBJECT pFileObject,
|
||||||
|
PWSTR pRelativeFileName,
|
||||||
|
PWSTR *pAbsoluteFilename)
|
||||||
|
{
|
||||||
|
PWSTR rcName;
|
||||||
|
PFCB Fcb;
|
||||||
|
PCCB Ccb;
|
||||||
|
|
||||||
|
DPRINT("try related for %S\n", pRelativeFileName);
|
||||||
|
Ccb = pFileObject->FsContext2;
|
||||||
|
assert(Ccb);
|
||||||
|
Fcb = Ccb->Fcb;
|
||||||
|
assert(Fcb);
|
||||||
|
|
||||||
|
/* verify related object is a directory and target name
|
||||||
|
don't start with \. */
|
||||||
|
if (NtfsFCBIsDirectory(Fcb) == FALSE ||
|
||||||
|
pRelativeFileName[0] == L'\\')
|
||||||
|
{
|
||||||
|
return(STATUS_INVALID_PARAMETER);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* construct absolute path name */
|
||||||
|
assert(wcslen (Fcb->PathName) + 1 + wcslen (pRelativeFileName) + 1
|
||||||
|
<= MAX_PATH);
|
||||||
|
rcName = ExAllocatePool(NonPagedPool, MAX_PATH * sizeof(WCHAR));
|
||||||
|
if (!rcName)
|
||||||
|
{
|
||||||
|
return(STATUS_INSUFFICIENT_RESOURCES);
|
||||||
|
}
|
||||||
|
|
||||||
|
wcscpy(rcName, Fcb->PathName);
|
||||||
|
if (!NtfsFCBIsRoot(Fcb))
|
||||||
|
wcscat (rcName, L"\\");
|
||||||
|
wcscat (rcName, pRelativeFileName);
|
||||||
|
*pAbsoluteFilename = rcName;
|
||||||
|
|
||||||
|
return(STATUS_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static NTSTATUS
|
||||||
|
NtfsOpenFile(PDEVICE_EXTENSION DeviceExt,
|
||||||
|
PFILE_OBJECT FileObject,
|
||||||
|
PWSTR FileName)
|
||||||
|
/*
|
||||||
|
* FUNCTION: Opens a file
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
PFCB ParentFcb;
|
||||||
|
PFCB Fcb;
|
||||||
|
NTSTATUS Status;
|
||||||
|
PWSTR AbsFileName = NULL;
|
||||||
|
|
||||||
|
DPRINT("NtfsOpenFile(%08lx, %08lx, %S)\n", DeviceExt, FileObject, FileName);
|
||||||
|
|
||||||
|
if (FileObject->RelatedFileObject)
|
||||||
|
{
|
||||||
|
DPRINT("Converting relative filename to absolute filename\n");
|
||||||
|
|
||||||
|
Status = NtfsMakeAbsoluteFilename(FileObject->RelatedFileObject,
|
||||||
|
FileName,
|
||||||
|
&AbsFileName);
|
||||||
|
FileName = AbsFileName;
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
return(Status);
|
||||||
|
}
|
||||||
|
return(STATUS_UNSUCCESSFUL);
|
||||||
|
}
|
||||||
|
|
||||||
|
//FIXME: Get cannonical path name (remove .'s, ..'s and extra separators)
|
||||||
|
|
||||||
|
DPRINT("PathName to open: %S\n", FileName);
|
||||||
|
|
||||||
|
/* try first to find an existing FCB in memory */
|
||||||
|
DPRINT("Checking for existing FCB in memory\n");
|
||||||
|
Fcb = NtfsGrabFCBFromTable(DeviceExt,
|
||||||
|
FileName);
|
||||||
|
if (Fcb == NULL)
|
||||||
|
{
|
||||||
|
DPRINT("No existing FCB found, making a new one if file exists.\n");
|
||||||
|
Status = NtfsGetFCBForFile(DeviceExt,
|
||||||
|
&ParentFcb,
|
||||||
|
&Fcb,
|
||||||
|
FileName);
|
||||||
|
if (ParentFcb != NULL)
|
||||||
|
{
|
||||||
|
NtfsReleaseFCB(DeviceExt,
|
||||||
|
ParentFcb);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!NT_SUCCESS (Status))
|
||||||
|
{
|
||||||
|
DPRINT("Could not make a new FCB, status: %x\n", Status);
|
||||||
|
|
||||||
|
if (AbsFileName)
|
||||||
|
ExFreePool(AbsFileName);
|
||||||
|
|
||||||
|
return(Status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINT("Attaching FCB to fileObject\n");
|
||||||
|
Status = NtfsAttachFCBToFileObject(DeviceExt,
|
||||||
|
Fcb,
|
||||||
|
FileObject);
|
||||||
|
|
||||||
|
if (AbsFileName)
|
||||||
|
ExFreePool (AbsFileName);
|
||||||
|
|
||||||
|
return(Status);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static NTSTATUS
|
||||||
|
NtfsCreateFile(PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp)
|
||||||
|
/*
|
||||||
|
* FUNCTION: Opens a file
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
PDEVICE_EXTENSION DeviceExt;
|
||||||
|
PIO_STACK_LOCATION Stack;
|
||||||
|
PFILE_OBJECT FileObject;
|
||||||
|
ULONG RequestedDisposition;
|
||||||
|
ULONG RequestedOptions;
|
||||||
|
PFCB Fcb;
|
||||||
|
// PWSTR FileName;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
DPRINT("NtfsCreateFile() called\n");
|
||||||
|
|
||||||
|
DeviceExt = DeviceObject->DeviceExtension;
|
||||||
|
assert (DeviceExt);
|
||||||
|
Stack = IoGetCurrentIrpStackLocation (Irp);
|
||||||
|
assert (Stack);
|
||||||
|
|
||||||
|
RequestedDisposition = ((Stack->Parameters.Create.Options >> 24) & 0xff);
|
||||||
|
// RequestedOptions =
|
||||||
|
// Stack->Parameters.Create.Options & FILE_VALID_OPTION_FLAGS;
|
||||||
|
// PagingFileCreate = (Stack->Flags & SL_OPEN_PAGING_FILE) ? TRUE : FALSE;
|
||||||
|
// if ((RequestedOptions & FILE_DIRECTORY_FILE)
|
||||||
|
// && RequestedDisposition == FILE_SUPERSEDE)
|
||||||
|
// return STATUS_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
FileObject = Stack->FileObject;
|
||||||
|
|
||||||
|
if (RequestedDisposition == FILE_CREATE ||
|
||||||
|
RequestedDisposition == FILE_OVERWRITE_IF ||
|
||||||
|
RequestedDisposition == FILE_SUPERSEDE)
|
||||||
|
{
|
||||||
|
return(STATUS_ACCESS_DENIED);
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = NtfsOpenFile(DeviceExt,
|
||||||
|
FileObject,
|
||||||
|
FileObject->FileName.Buffer);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the directory containing the file to open doesn't exist then
|
||||||
|
* fail immediately
|
||||||
|
*/
|
||||||
|
Irp->IoStatus.Information = (NT_SUCCESS(Status)) ? FILE_OPENED : 0;
|
||||||
|
Irp->IoStatus.Status = Status;
|
||||||
|
|
||||||
|
return(Status);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
NTSTATUS STDCALL
|
||||||
|
NtfsCreate(PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp)
|
||||||
|
{
|
||||||
|
PDEVICE_EXTENSION DeviceExt;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
if (DeviceObject == NtfsGlobalData->DeviceObject)
|
||||||
|
{
|
||||||
|
/* DeviceObject represents FileSystem instead of logical volume */
|
||||||
|
DPRINT("Opening file system\n");
|
||||||
|
Irp->IoStatus.Information = FILE_OPENED;
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
|
goto ByeBye;
|
||||||
|
}
|
||||||
|
|
||||||
|
DeviceExt = DeviceObject->DeviceExtension;
|
||||||
|
|
||||||
|
ExAcquireResourceExclusiveLite(&DeviceExt->DirResource,
|
||||||
|
TRUE);
|
||||||
|
Status = NtfsCreateFile(DeviceObject,
|
||||||
|
Irp);
|
||||||
|
ExReleaseResourceLite(&DeviceExt->DirResource);
|
||||||
|
|
||||||
|
ByeBye:
|
||||||
|
Irp->IoStatus.Status = Status;
|
||||||
|
IoCompleteRequest(Irp,
|
||||||
|
NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT);
|
||||||
|
|
||||||
|
return(Status);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* EOF */
|
709
reactos/drivers/fs/ntfs/dirctl.c
Normal file
709
reactos/drivers/fs/ntfs/dirctl.c
Normal file
|
@ -0,0 +1,709 @@
|
||||||
|
/*
|
||||||
|
* ReactOS kernel
|
||||||
|
* Copyright (C) 2002 ReactOS Team
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
/* $Id: dirctl.c,v 1.1 2002/06/25 22:23:05 ekohl Exp $
|
||||||
|
*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS kernel
|
||||||
|
* FILE: services/fs/ntfs/dirctl.c
|
||||||
|
* PURPOSE: NTFS filesystem driver
|
||||||
|
* PROGRAMMER: Eric Kohl
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* INCLUDES *****************************************************************/
|
||||||
|
|
||||||
|
#include <ddk/ntddk.h>
|
||||||
|
|
||||||
|
//#define NDEBUG
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
|
#include "ntfs.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* FUNCTIONS ****************************************************************/
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
static NTSTATUS
|
||||||
|
CdfsGetEntryName(PDEVICE_EXTENSION DeviceExt,
|
||||||
|
PVOID *Context,
|
||||||
|
PVOID *Block,
|
||||||
|
PLARGE_INTEGER StreamOffset,
|
||||||
|
ULONG DirLength,
|
||||||
|
PVOID *Ptr,
|
||||||
|
PWSTR Name,
|
||||||
|
PULONG pIndex,
|
||||||
|
PULONG pIndex2)
|
||||||
|
/*
|
||||||
|
* FUNCTION: Retrieves the file name, be it in short or long file name format
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
PDIR_RECORD Record;
|
||||||
|
NTSTATUS Status;
|
||||||
|
ULONG Index = 0;
|
||||||
|
ULONG Offset = 0;
|
||||||
|
ULONG BlockOffset = 0;
|
||||||
|
|
||||||
|
Record = (PDIR_RECORD)*Block;
|
||||||
|
while(Index < *pIndex)
|
||||||
|
{
|
||||||
|
BlockOffset += Record->RecordLength;
|
||||||
|
Offset += Record->RecordLength;
|
||||||
|
|
||||||
|
Record = (PDIR_RECORD)(*Block + BlockOffset);
|
||||||
|
if (BlockOffset >= BLOCKSIZE || Record->RecordLength == 0)
|
||||||
|
{
|
||||||
|
DPRINT("Map next sector\n");
|
||||||
|
CcUnpinData(*Context);
|
||||||
|
StreamOffset->QuadPart += BLOCKSIZE;
|
||||||
|
Offset = ROUND_UP(Offset, BLOCKSIZE);
|
||||||
|
BlockOffset = 0;
|
||||||
|
|
||||||
|
if (!CcMapData(DeviceExt->StreamFileObject,
|
||||||
|
StreamOffset,
|
||||||
|
BLOCKSIZE, TRUE,
|
||||||
|
Context, Block))
|
||||||
|
{
|
||||||
|
DPRINT("CcMapData() failed\n");
|
||||||
|
return(STATUS_UNSUCCESSFUL);
|
||||||
|
}
|
||||||
|
Record = (PDIR_RECORD)(*Block + BlockOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Offset >= DirLength)
|
||||||
|
return(STATUS_NO_MORE_ENTRIES);
|
||||||
|
|
||||||
|
Index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINT("Index %lu RecordLength %lu Offset %lu\n",
|
||||||
|
Index, Record->RecordLength, Offset);
|
||||||
|
|
||||||
|
if (Record->FileIdLength == 1 && Record->FileId[0] == 0)
|
||||||
|
{
|
||||||
|
wcscpy(Name, L".");
|
||||||
|
}
|
||||||
|
else if (Record->FileIdLength == 1 && Record->FileId[0] == 1)
|
||||||
|
{
|
||||||
|
wcscpy(Name, L"..");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (DeviceExt->CdInfo.JolietLevel == 0)
|
||||||
|
{
|
||||||
|
ULONG i;
|
||||||
|
|
||||||
|
for (i = 0; i < Record->FileIdLength && Record->FileId[i] != ';'; i++)
|
||||||
|
Name[i] = (WCHAR)Record->FileId[i];
|
||||||
|
Name[i] = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CdfsSwapString(Name, Record->FileId, Record->FileIdLength);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINT("Name '%S'\n", Name);
|
||||||
|
|
||||||
|
*Ptr = Record;
|
||||||
|
|
||||||
|
*pIndex = Index;
|
||||||
|
|
||||||
|
return(STATUS_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static NTSTATUS
|
||||||
|
CdfsFindFile(PDEVICE_EXTENSION DeviceExt,
|
||||||
|
PFCB Fcb,
|
||||||
|
PFCB Parent,
|
||||||
|
PWSTR FileToFind,
|
||||||
|
PULONG pDirIndex,
|
||||||
|
PULONG pDirIndex2)
|
||||||
|
/*
|
||||||
|
* FUNCTION: Find a file
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
WCHAR name[256];
|
||||||
|
WCHAR TempStr[2];
|
||||||
|
PVOID Block;
|
||||||
|
NTSTATUS Status;
|
||||||
|
ULONG len;
|
||||||
|
ULONG DirIndex;
|
||||||
|
ULONG Offset;
|
||||||
|
ULONG Read;
|
||||||
|
BOOLEAN IsRoot;
|
||||||
|
PVOID Context = NULL;
|
||||||
|
ULONG DirSize;
|
||||||
|
PUCHAR Ptr;
|
||||||
|
PDIR_RECORD Record;
|
||||||
|
LARGE_INTEGER StreamOffset;
|
||||||
|
|
||||||
|
DPRINT("FindFile(Parent %x, FileToFind '%S', DirIndex: %d)\n",
|
||||||
|
Parent, FileToFind, pDirIndex ? *pDirIndex : 0);
|
||||||
|
DPRINT("FindFile: old Pathname %x, old Objectname %x)\n",
|
||||||
|
Fcb->PathName, Fcb->ObjectName);
|
||||||
|
|
||||||
|
IsRoot = FALSE;
|
||||||
|
DirIndex = 0;
|
||||||
|
if (wcslen (FileToFind) == 0)
|
||||||
|
{
|
||||||
|
CHECKPOINT;
|
||||||
|
TempStr[0] = (WCHAR) '.';
|
||||||
|
TempStr[1] = 0;
|
||||||
|
FileToFind = (PWSTR)&TempStr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Parent)
|
||||||
|
{
|
||||||
|
if (Parent->Entry.ExtentLocationL == DeviceExt->CdInfo.RootStart)
|
||||||
|
{
|
||||||
|
IsRoot = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
IsRoot = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsRoot == TRUE)
|
||||||
|
{
|
||||||
|
StreamOffset.QuadPart = (LONGLONG)DeviceExt->CdInfo.RootStart * (LONGLONG)BLOCKSIZE;
|
||||||
|
DirSize = DeviceExt->CdInfo.RootSize;
|
||||||
|
|
||||||
|
|
||||||
|
if (FileToFind[0] == 0 || (FileToFind[0] == '\\' && FileToFind[1] == 0)
|
||||||
|
|| (FileToFind[0] == '.' && FileToFind[1] == 0))
|
||||||
|
{
|
||||||
|
/* it's root : complete essentials fields then return ok */
|
||||||
|
RtlZeroMemory(Fcb, sizeof(FCB));
|
||||||
|
|
||||||
|
Fcb->PathName[0]='\\';
|
||||||
|
Fcb->ObjectName = &Fcb->PathName[1];
|
||||||
|
Fcb->Entry.ExtentLocationL = DeviceExt->CdInfo.RootStart;
|
||||||
|
Fcb->Entry.DataLengthL = DeviceExt->CdInfo.RootSize;
|
||||||
|
Fcb->Entry.FileFlags = 0x02; //FILE_ATTRIBUTE_DIRECTORY;
|
||||||
|
|
||||||
|
if (pDirIndex)
|
||||||
|
*pDirIndex = 0;
|
||||||
|
if (pDirIndex2)
|
||||||
|
*pDirIndex2 = 0;
|
||||||
|
DPRINT("CdfsFindFile: new Pathname %S, new Objectname %S)\n",Fcb->PathName, Fcb->ObjectName);
|
||||||
|
return (STATUS_SUCCESS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
StreamOffset.QuadPart = (LONGLONG)Parent->Entry.ExtentLocationL * (LONGLONG)BLOCKSIZE;
|
||||||
|
DirSize = Parent->Entry.DataLengthL;
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINT("StreamOffset %I64u DirSize %lu\n", StreamOffset.QuadPart, DirSize);
|
||||||
|
|
||||||
|
if (pDirIndex && (*pDirIndex))
|
||||||
|
DirIndex = *pDirIndex;
|
||||||
|
|
||||||
|
if(!CcMapData(DeviceExt->StreamFileObject, &StreamOffset,
|
||||||
|
BLOCKSIZE, TRUE, &Context, &Block))
|
||||||
|
{
|
||||||
|
DPRINT("CcMapData() failed\n");
|
||||||
|
return(STATUS_UNSUCCESSFUL);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ptr = (PUCHAR)Block;
|
||||||
|
while(TRUE)
|
||||||
|
{
|
||||||
|
Record = (PDIR_RECORD)Ptr;
|
||||||
|
if (Record->RecordLength == 0)
|
||||||
|
{
|
||||||
|
DPRINT1("Stopped!\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINT("RecordLength %u ExtAttrRecordLength %u NameLength %u\n",
|
||||||
|
Record->RecordLength, Record->ExtAttrRecordLength, Record->FileIdLength);
|
||||||
|
|
||||||
|
Status = CdfsGetEntryName(DeviceExt, &Context, &Block, &StreamOffset,
|
||||||
|
DirSize, (PVOID*)&Ptr, name, &DirIndex, pDirIndex2);
|
||||||
|
if (Status == STATUS_NO_MORE_ENTRIES)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (Status == STATUS_UNSUCCESSFUL)
|
||||||
|
{
|
||||||
|
/* Note: the directory cache has already been unpinned */
|
||||||
|
return(Status);
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINT("Name '%S'\n", name);
|
||||||
|
|
||||||
|
if (wstrcmpjoki(name, FileToFind)) /* || wstrcmpjoki (name2, FileToFind)) */
|
||||||
|
{
|
||||||
|
if (Parent && Parent->PathName)
|
||||||
|
{
|
||||||
|
len = wcslen(Parent->PathName);
|
||||||
|
memcpy(Fcb->PathName, Parent->PathName, len*sizeof(WCHAR));
|
||||||
|
Fcb->ObjectName=&Fcb->PathName[len];
|
||||||
|
if (len != 1 || Fcb->PathName[0] != '\\')
|
||||||
|
{
|
||||||
|
Fcb->ObjectName[0] = '\\';
|
||||||
|
Fcb->ObjectName = &Fcb->ObjectName[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Fcb->ObjectName=Fcb->PathName;
|
||||||
|
Fcb->ObjectName[0]='\\';
|
||||||
|
Fcb->ObjectName=&Fcb->ObjectName[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINT("PathName '%S' ObjectName '%S'\n", Fcb->PathName, Fcb->ObjectName);
|
||||||
|
|
||||||
|
memcpy(&Fcb->Entry, Ptr, sizeof(DIR_RECORD));
|
||||||
|
wcsncpy(Fcb->ObjectName, name, MAX_PATH);
|
||||||
|
if (pDirIndex)
|
||||||
|
*pDirIndex = DirIndex;
|
||||||
|
|
||||||
|
DPRINT("FindFile: new Pathname %S, new Objectname %S, DirIndex %d\n",
|
||||||
|
Fcb->PathName, Fcb->ObjectName, DirIndex);
|
||||||
|
|
||||||
|
CcUnpinData(Context);
|
||||||
|
|
||||||
|
return(STATUS_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Ptr = Ptr + Record->RecordLength;
|
||||||
|
DirIndex++;
|
||||||
|
|
||||||
|
if (((ULONG)Ptr - (ULONG)Block) >= DirSize)
|
||||||
|
{
|
||||||
|
DPRINT("Stopped!\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CcUnpinData(Context);
|
||||||
|
|
||||||
|
if (pDirIndex)
|
||||||
|
*pDirIndex = DirIndex;
|
||||||
|
|
||||||
|
return(STATUS_UNSUCCESSFUL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static NTSTATUS
|
||||||
|
CdfsGetNameInformation(PFCB Fcb,
|
||||||
|
PDEVICE_EXTENSION DeviceExt,
|
||||||
|
PFILE_NAMES_INFORMATION Info,
|
||||||
|
ULONG BufferLength)
|
||||||
|
{
|
||||||
|
ULONG Length;
|
||||||
|
|
||||||
|
DPRINT("CdfsGetNameInformation() called\n");
|
||||||
|
|
||||||
|
Length = wcslen(Fcb->ObjectName) * sizeof(WCHAR);
|
||||||
|
if ((sizeof (FILE_BOTH_DIRECTORY_INFORMATION) + Length) > BufferLength)
|
||||||
|
return(STATUS_BUFFER_OVERFLOW);
|
||||||
|
|
||||||
|
Info->FileNameLength = Length;
|
||||||
|
Info->NextEntryOffset =
|
||||||
|
ROUND_UP(sizeof(FILE_BOTH_DIRECTORY_INFORMATION) + Length, 4);
|
||||||
|
memcpy(Info->FileName, Fcb->ObjectName, Length);
|
||||||
|
|
||||||
|
return(STATUS_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static NTSTATUS
|
||||||
|
CdfsGetDirectoryInformation(PFCB Fcb,
|
||||||
|
PDEVICE_EXTENSION DeviceExt,
|
||||||
|
PFILE_DIRECTORY_INFORMATION Info,
|
||||||
|
ULONG BufferLength)
|
||||||
|
{
|
||||||
|
ULONG Length;
|
||||||
|
|
||||||
|
DPRINT("CdfsGetDirectoryInformation() called\n");
|
||||||
|
|
||||||
|
Length = wcslen(Fcb->ObjectName) * sizeof(WCHAR);
|
||||||
|
if ((sizeof (FILE_BOTH_DIRECTORY_INFORMATION) + Length) > BufferLength)
|
||||||
|
return(STATUS_BUFFER_OVERFLOW);
|
||||||
|
|
||||||
|
Info->FileNameLength = Length;
|
||||||
|
Info->NextEntryOffset =
|
||||||
|
ROUND_UP(sizeof(FILE_BOTH_DIRECTORY_INFORMATION) + Length, 4);
|
||||||
|
memcpy(Info->FileName, Fcb->ObjectName, Length);
|
||||||
|
|
||||||
|
/* Convert file times */
|
||||||
|
CdfsDateTimeToFileTime(Fcb,
|
||||||
|
&Info->CreationTime);
|
||||||
|
CdfsDateTimeToFileTime(Fcb,
|
||||||
|
&Info->LastAccessTime);
|
||||||
|
CdfsDateTimeToFileTime(Fcb,
|
||||||
|
&Info->LastWriteTime);
|
||||||
|
CdfsDateTimeToFileTime(Fcb,
|
||||||
|
&Info->ChangeTime);
|
||||||
|
|
||||||
|
/* Convert file flags */
|
||||||
|
CdfsFileFlagsToAttributes(Fcb,
|
||||||
|
&Info->FileAttributes);
|
||||||
|
|
||||||
|
Info->EndOfFile.QuadPart = Fcb->Entry.DataLengthL;
|
||||||
|
|
||||||
|
/* Make AllocSize a rounded up multiple of the sector size */
|
||||||
|
Info->AllocationSize.QuadPart = ROUND_UP(Fcb->Entry.DataLengthL, BLOCKSIZE);
|
||||||
|
|
||||||
|
// Info->FileIndex=;
|
||||||
|
|
||||||
|
return(STATUS_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static NTSTATUS
|
||||||
|
CdfsGetFullDirectoryInformation(PFCB Fcb,
|
||||||
|
PDEVICE_EXTENSION DeviceExt,
|
||||||
|
PFILE_FULL_DIRECTORY_INFORMATION Info,
|
||||||
|
ULONG BufferLength)
|
||||||
|
{
|
||||||
|
ULONG Length;
|
||||||
|
|
||||||
|
DPRINT("CdfsGetFullDirectoryInformation() called\n");
|
||||||
|
|
||||||
|
Length = wcslen(Fcb->ObjectName) * sizeof(WCHAR);
|
||||||
|
if ((sizeof (FILE_BOTH_DIRECTORY_INFORMATION) + Length) > BufferLength)
|
||||||
|
return(STATUS_BUFFER_OVERFLOW);
|
||||||
|
|
||||||
|
Info->FileNameLength = Length;
|
||||||
|
Info->NextEntryOffset =
|
||||||
|
ROUND_UP(sizeof(FILE_BOTH_DIRECTORY_INFORMATION) + Length, 4);
|
||||||
|
memcpy(Info->FileName, Fcb->ObjectName, Length);
|
||||||
|
|
||||||
|
/* Convert file times */
|
||||||
|
CdfsDateTimeToFileTime(Fcb,
|
||||||
|
&Info->CreationTime);
|
||||||
|
CdfsDateTimeToFileTime(Fcb,
|
||||||
|
&Info->LastAccessTime);
|
||||||
|
CdfsDateTimeToFileTime(Fcb,
|
||||||
|
&Info->LastWriteTime);
|
||||||
|
CdfsDateTimeToFileTime(Fcb,
|
||||||
|
&Info->ChangeTime);
|
||||||
|
|
||||||
|
/* Convert file flags */
|
||||||
|
CdfsFileFlagsToAttributes(Fcb,
|
||||||
|
&Info->FileAttributes);
|
||||||
|
|
||||||
|
Info->EndOfFile.QuadPart = Fcb->Entry.DataLengthL;
|
||||||
|
|
||||||
|
/* Make AllocSize a rounded up multiple of the sector size */
|
||||||
|
Info->AllocationSize.QuadPart = ROUND_UP(Fcb->Entry.DataLengthL, BLOCKSIZE);
|
||||||
|
|
||||||
|
// Info->FileIndex=;
|
||||||
|
Info->EaSize = 0;
|
||||||
|
|
||||||
|
return(STATUS_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static NTSTATUS
|
||||||
|
CdfsGetBothDirectoryInformation(PFCB Fcb,
|
||||||
|
PDEVICE_EXTENSION DeviceExt,
|
||||||
|
PFILE_BOTH_DIRECTORY_INFORMATION Info,
|
||||||
|
ULONG BufferLength)
|
||||||
|
{
|
||||||
|
ULONG Length;
|
||||||
|
|
||||||
|
DPRINT("CdfsGetBothDirectoryInformation() called\n");
|
||||||
|
|
||||||
|
Length = wcslen(Fcb->ObjectName) * sizeof(WCHAR);
|
||||||
|
if ((sizeof (FILE_BOTH_DIRECTORY_INFORMATION) + Length) > BufferLength)
|
||||||
|
return(STATUS_BUFFER_OVERFLOW);
|
||||||
|
|
||||||
|
Info->FileNameLength = Length;
|
||||||
|
Info->NextEntryOffset =
|
||||||
|
ROUND_UP(sizeof(FILE_BOTH_DIRECTORY_INFORMATION) + Length, 4);
|
||||||
|
memcpy(Info->FileName, Fcb->ObjectName, Length);
|
||||||
|
|
||||||
|
/* Convert file times */
|
||||||
|
CdfsDateTimeToFileTime(Fcb,
|
||||||
|
&Info->CreationTime);
|
||||||
|
CdfsDateTimeToFileTime(Fcb,
|
||||||
|
&Info->LastAccessTime);
|
||||||
|
CdfsDateTimeToFileTime(Fcb,
|
||||||
|
&Info->LastWriteTime);
|
||||||
|
CdfsDateTimeToFileTime(Fcb,
|
||||||
|
&Info->ChangeTime);
|
||||||
|
|
||||||
|
/* Convert file flags */
|
||||||
|
CdfsFileFlagsToAttributes(Fcb,
|
||||||
|
&Info->FileAttributes);
|
||||||
|
|
||||||
|
Info->EndOfFile.QuadPart = Fcb->Entry.DataLengthL;
|
||||||
|
|
||||||
|
/* Make AllocSize a rounded up multiple of the sector size */
|
||||||
|
Info->AllocationSize.QuadPart = ROUND_UP(Fcb->Entry.DataLengthL, BLOCKSIZE);
|
||||||
|
|
||||||
|
// Info->FileIndex=;
|
||||||
|
Info->EaSize = 0;
|
||||||
|
|
||||||
|
if (DeviceExt->CdInfo.JolietLevel == 0)
|
||||||
|
{
|
||||||
|
/* Standard ISO-9660 format */
|
||||||
|
Info->ShortNameLength = Length;
|
||||||
|
memcpy(Info->ShortName, Fcb->ObjectName, Length);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Joliet extension */
|
||||||
|
|
||||||
|
/* FIXME: Copy or create a short file name */
|
||||||
|
|
||||||
|
Info->ShortName[0] = 0;
|
||||||
|
Info->ShortNameLength = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return(STATUS_SUCCESS);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static NTSTATUS
|
||||||
|
NtfsQueryDirectory(PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp)
|
||||||
|
{
|
||||||
|
PDEVICE_EXTENSION DeviceExtension;
|
||||||
|
LONG BufferLength = 0;
|
||||||
|
PUNICODE_STRING SearchPattern = NULL;
|
||||||
|
FILE_INFORMATION_CLASS FileInformationClass;
|
||||||
|
ULONG FileIndex = 0;
|
||||||
|
PUCHAR Buffer = NULL;
|
||||||
|
PFILE_NAMES_INFORMATION Buffer0 = NULL;
|
||||||
|
PFCB Fcb;
|
||||||
|
PCCB Ccb;
|
||||||
|
FCB TempFcb;
|
||||||
|
BOOLEAN First = FALSE;
|
||||||
|
PIO_STACK_LOCATION Stack;
|
||||||
|
PFILE_OBJECT FileObject;
|
||||||
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
DPRINT1("NtfsQueryDirectory() called\n");
|
||||||
|
|
||||||
|
DeviceExtension = DeviceObject->DeviceExtension;
|
||||||
|
Stack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
FileObject = Stack->FileObject;
|
||||||
|
|
||||||
|
Ccb = (PCCB)FileObject->FsContext2;
|
||||||
|
Fcb = Ccb->Fcb;
|
||||||
|
|
||||||
|
/* Obtain the callers parameters */
|
||||||
|
BufferLength = Stack->Parameters.QueryDirectory.Length;
|
||||||
|
SearchPattern = Stack->Parameters.QueryDirectory.FileName;
|
||||||
|
FileInformationClass =
|
||||||
|
Stack->Parameters.QueryDirectory.FileInformationClass;
|
||||||
|
FileIndex = Stack->Parameters.QueryDirectory.FileIndex;
|
||||||
|
|
||||||
|
|
||||||
|
if (SearchPattern != NULL)
|
||||||
|
{
|
||||||
|
if (!Ccb->DirectorySearchPattern)
|
||||||
|
{
|
||||||
|
First = TRUE;
|
||||||
|
Ccb->DirectorySearchPattern =
|
||||||
|
ExAllocatePool(NonPagedPool, SearchPattern->Length + sizeof(WCHAR));
|
||||||
|
if (!Ccb->DirectorySearchPattern)
|
||||||
|
{
|
||||||
|
return(STATUS_INSUFFICIENT_RESOURCES);
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(Ccb->DirectorySearchPattern,
|
||||||
|
SearchPattern->Buffer,
|
||||||
|
SearchPattern->Length);
|
||||||
|
Ccb->DirectorySearchPattern[SearchPattern->Length / sizeof(WCHAR)] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!Ccb->DirectorySearchPattern)
|
||||||
|
{
|
||||||
|
First = TRUE;
|
||||||
|
Ccb->DirectorySearchPattern = ExAllocatePool(NonPagedPool, 2 * sizeof(WCHAR));
|
||||||
|
if (!Ccb->DirectorySearchPattern)
|
||||||
|
{
|
||||||
|
return(STATUS_INSUFFICIENT_RESOURCES);
|
||||||
|
}
|
||||||
|
Ccb->DirectorySearchPattern[0] = L'*';
|
||||||
|
Ccb->DirectorySearchPattern[1] = 0;
|
||||||
|
}
|
||||||
|
DPRINT("Search pattern '%S'\n", Ccb->DirectorySearchPattern);
|
||||||
|
|
||||||
|
/* Determine directory index */
|
||||||
|
if (Stack->Flags & SL_INDEX_SPECIFIED)
|
||||||
|
{
|
||||||
|
Ccb->Entry = Ccb->CurrentByteOffset.u.LowPart;
|
||||||
|
}
|
||||||
|
else if (First || (Stack->Flags & SL_RESTART_SCAN))
|
||||||
|
{
|
||||||
|
Ccb->Entry = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Determine Buffer for result */
|
||||||
|
if (Irp->MdlAddress)
|
||||||
|
{
|
||||||
|
Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Buffer = Irp->UserBuffer;
|
||||||
|
}
|
||||||
|
DPRINT("Buffer=%x tofind=%S\n", Buffer, Ccb->DirectorySearchPattern);
|
||||||
|
#if 0
|
||||||
|
TempFcb.ObjectName = TempFcb.PathName;
|
||||||
|
while (Status == STATUS_SUCCESS && BufferLength > 0)
|
||||||
|
{
|
||||||
|
Status = CdfsFindFile(DeviceExtension,
|
||||||
|
&TempFcb,
|
||||||
|
Fcb,
|
||||||
|
Ccb->DirectorySearchPattern,
|
||||||
|
&Ccb->Entry,
|
||||||
|
NULL);
|
||||||
|
DPRINT("Found %S, Status=%x, entry %x\n", TempFcb.ObjectName, Status, Ccb->Entry);
|
||||||
|
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
switch (FileInformationClass)
|
||||||
|
{
|
||||||
|
case FileNameInformation:
|
||||||
|
Status = CdfsGetNameInformation(&TempFcb,
|
||||||
|
DeviceExtension,
|
||||||
|
(PFILE_NAMES_INFORMATION)Buffer,
|
||||||
|
BufferLength);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FileDirectoryInformation:
|
||||||
|
Status = CdfsGetDirectoryInformation(&TempFcb,
|
||||||
|
DeviceExtension,
|
||||||
|
(PFILE_DIRECTORY_INFORMATION)Buffer,
|
||||||
|
BufferLength);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FileFullDirectoryInformation:
|
||||||
|
Status = CdfsGetFullDirectoryInformation(&TempFcb,
|
||||||
|
DeviceExtension,
|
||||||
|
(PFILE_FULL_DIRECTORY_INFORMATION)Buffer,
|
||||||
|
BufferLength);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FileBothDirectoryInformation:
|
||||||
|
Status = NtfsGetBothDirectoryInformation(&TempFcb,
|
||||||
|
DeviceExtension,
|
||||||
|
(PFILE_BOTH_DIRECTORY_INFORMATION)Buffer,
|
||||||
|
BufferLength);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
Status = STATUS_INVALID_INFO_CLASS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Status == STATUS_BUFFER_OVERFLOW)
|
||||||
|
{
|
||||||
|
if (Buffer0)
|
||||||
|
{
|
||||||
|
Buffer0->NextEntryOffset = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (Buffer0)
|
||||||
|
{
|
||||||
|
Buffer0->NextEntryOffset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (First)
|
||||||
|
{
|
||||||
|
Status = STATUS_NO_SUCH_FILE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Status = STATUS_NO_MORE_FILES;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Buffer0 = (PFILE_NAMES_INFORMATION)Buffer;
|
||||||
|
Buffer0->FileIndex = FileIndex++;
|
||||||
|
Ccb->Entry++;
|
||||||
|
|
||||||
|
if (Stack->Flags & SL_RETURN_SINGLE_ENTRY)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
BufferLength -= Buffer0->NextEntryOffset;
|
||||||
|
Buffer += Buffer0->NextEntryOffset;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (Buffer0)
|
||||||
|
{
|
||||||
|
Buffer0->NextEntryOffset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FileIndex > 0)
|
||||||
|
{
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
return(Status);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
NTSTATUS STDCALL
|
||||||
|
NtfsDirectoryControl(PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp)
|
||||||
|
{
|
||||||
|
PIO_STACK_LOCATION Stack;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
DPRINT1("NtfsDirectoryControl() called\n");
|
||||||
|
|
||||||
|
Stack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
|
||||||
|
switch (Stack->MinorFunction)
|
||||||
|
{
|
||||||
|
case IRP_MN_QUERY_DIRECTORY:
|
||||||
|
Status = NtfsQueryDirectory(DeviceObject,
|
||||||
|
Irp);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IRP_MN_NOTIFY_CHANGE_DIRECTORY:
|
||||||
|
DPRINT1("IRP_MN_NOTIFY_CHANGE_DIRECTORY\n");
|
||||||
|
Status = STATUS_NOT_IMPLEMENTED;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
DPRINT1("NTFS: MinorFunction %d\n", Stack->MinorFunction);
|
||||||
|
Status = STATUS_INVALID_DEVICE_REQUEST;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Irp->IoStatus.Status = Status;
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
|
||||||
|
return(Status);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* EOF */
|
674
reactos/drivers/fs/ntfs/fcb.c
Normal file
674
reactos/drivers/fs/ntfs/fcb.c
Normal file
|
@ -0,0 +1,674 @@
|
||||||
|
/*
|
||||||
|
* ReactOS kernel
|
||||||
|
* Copyright (C) 2002 ReactOS Team
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
/* $Id: fcb.c,v 1.1 2002/06/25 22:23:05 ekohl Exp $
|
||||||
|
*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS kernel
|
||||||
|
* FILE: services/fs/ntfs/fcb.c
|
||||||
|
* PURPOSE: NTFS filesystem driver
|
||||||
|
* PROGRAMMER: Eric Kohl
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* INCLUDES *****************************************************************/
|
||||||
|
|
||||||
|
#include <ddk/ntddk.h>
|
||||||
|
|
||||||
|
#define NDEBUG
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
|
#include "ntfs.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* MACROS *******************************************************************/
|
||||||
|
|
||||||
|
#define TAG_FCB TAG('I', 'F', 'C', 'B')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* FUNCTIONS ****************************************************************/
|
||||||
|
|
||||||
|
static PWCHAR
|
||||||
|
NtfsGetNextPathElement(PWCHAR FileName)
|
||||||
|
{
|
||||||
|
if (*FileName == L'\0')
|
||||||
|
{
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (*FileName != L'\0' && *FileName != L'\\')
|
||||||
|
{
|
||||||
|
FileName++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return(FileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static VOID
|
||||||
|
NtfsWSubString(PWCHAR pTarget, const PWCHAR pSource, size_t pLength)
|
||||||
|
{
|
||||||
|
wcsncpy (pTarget, pSource, pLength);
|
||||||
|
pTarget [pLength] = L'\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PFCB
|
||||||
|
NtfsCreateFCB(PWSTR FileName)
|
||||||
|
{
|
||||||
|
PFCB Fcb;
|
||||||
|
|
||||||
|
Fcb = ExAllocatePoolWithTag(NonPagedPool, sizeof(FCB), TAG_FCB);
|
||||||
|
RtlZeroMemory(Fcb, sizeof(FCB));
|
||||||
|
|
||||||
|
if (FileName)
|
||||||
|
{
|
||||||
|
wcscpy(Fcb->PathName, FileName);
|
||||||
|
if (wcsrchr(Fcb->PathName, '\\') != 0)
|
||||||
|
{
|
||||||
|
Fcb->ObjectName = wcsrchr(Fcb->PathName, '\\');
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Fcb->ObjectName = Fcb->PathName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ExInitializeResourceLite(&Fcb->MainResource);
|
||||||
|
|
||||||
|
return(Fcb);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NtfsDestroyFCB(PFCB Fcb)
|
||||||
|
{
|
||||||
|
ExDeleteResourceLite(&Fcb->MainResource);
|
||||||
|
|
||||||
|
ExFreePool(Fcb);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
NtfsFCBIsDirectory(PFCB Fcb)
|
||||||
|
{
|
||||||
|
// return(Fcb->entry.Attrib & FILE_ATTRIBUTE_DIRECTORY);
|
||||||
|
// return(Fcb->Entry.FileFlags & 0x02);
|
||||||
|
return(TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
NtfsFCBIsRoot(PFCB Fcb)
|
||||||
|
{
|
||||||
|
return(wcscmp(Fcb->PathName, L"\\") == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NtfsGrabFCB(PDEVICE_EXTENSION Vcb,
|
||||||
|
PFCB Fcb)
|
||||||
|
{
|
||||||
|
KIRQL oldIrql;
|
||||||
|
|
||||||
|
DPRINT("grabbing FCB at %x: %S, refCount:%d\n",
|
||||||
|
Fcb,
|
||||||
|
Fcb->PathName,
|
||||||
|
Fcb->RefCount);
|
||||||
|
|
||||||
|
KeAcquireSpinLock(&Vcb->FcbListLock, &oldIrql);
|
||||||
|
Fcb->RefCount++;
|
||||||
|
KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NtfsReleaseFCB(PDEVICE_EXTENSION Vcb,
|
||||||
|
PFCB Fcb)
|
||||||
|
{
|
||||||
|
KIRQL oldIrql;
|
||||||
|
|
||||||
|
DPRINT("releasing FCB at %x: %S, refCount:%d\n",
|
||||||
|
Fcb,
|
||||||
|
Fcb->PathName,
|
||||||
|
Fcb->RefCount);
|
||||||
|
|
||||||
|
KeAcquireSpinLock(&Vcb->FcbListLock, &oldIrql);
|
||||||
|
Fcb->RefCount--;
|
||||||
|
if (Fcb->RefCount <= 0 && !NtfsFCBIsDirectory(Fcb))
|
||||||
|
{
|
||||||
|
RemoveEntryList(&Fcb->FcbListEntry);
|
||||||
|
CcRosReleaseFileCache(NULL, Fcb->RFCB.Bcb);
|
||||||
|
NtfsDestroyFCB(Fcb);
|
||||||
|
}
|
||||||
|
KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NtfsAddFCBToTable(PDEVICE_EXTENSION Vcb,
|
||||||
|
PFCB Fcb)
|
||||||
|
{
|
||||||
|
KIRQL oldIrql;
|
||||||
|
|
||||||
|
KeAcquireSpinLock(&Vcb->FcbListLock, &oldIrql);
|
||||||
|
Fcb->DevExt = Vcb;
|
||||||
|
InsertTailList(&Vcb->FcbListHead, &Fcb->FcbListEntry);
|
||||||
|
KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PFCB
|
||||||
|
NtfsGrabFCBFromTable(PDEVICE_EXTENSION Vcb,
|
||||||
|
PWSTR FileName)
|
||||||
|
{
|
||||||
|
KIRQL oldIrql;
|
||||||
|
PFCB Fcb;
|
||||||
|
PLIST_ENTRY current_entry;
|
||||||
|
|
||||||
|
KeAcquireSpinLock(&Vcb->FcbListLock, &oldIrql);
|
||||||
|
|
||||||
|
if (FileName == NULL || *FileName == 0)
|
||||||
|
{
|
||||||
|
DPRINT("Return FCB for stream file object\n");
|
||||||
|
Fcb = ((PCCB)Vcb->StreamFileObject->FsContext2)->Fcb;
|
||||||
|
Fcb->RefCount++;
|
||||||
|
KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql);
|
||||||
|
return(Fcb);
|
||||||
|
}
|
||||||
|
|
||||||
|
current_entry = Vcb->FcbListHead.Flink;
|
||||||
|
while (current_entry != &Vcb->FcbListHead)
|
||||||
|
{
|
||||||
|
Fcb = CONTAINING_RECORD(current_entry, FCB, FcbListEntry);
|
||||||
|
|
||||||
|
DPRINT("Comparing '%S' and '%S'\n", FileName, Fcb->PathName);
|
||||||
|
if (_wcsicmp(FileName, Fcb->PathName) == 0)
|
||||||
|
{
|
||||||
|
Fcb->RefCount++;
|
||||||
|
KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql);
|
||||||
|
return(Fcb);
|
||||||
|
}
|
||||||
|
|
||||||
|
//FIXME: need to compare against short name in FCB here
|
||||||
|
|
||||||
|
current_entry = current_entry->Flink;
|
||||||
|
}
|
||||||
|
KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql);
|
||||||
|
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NtfsFCBInitializeCache(PVCB Vcb,
|
||||||
|
PFCB Fcb)
|
||||||
|
{
|
||||||
|
PFILE_OBJECT FileObject;
|
||||||
|
NTSTATUS Status;
|
||||||
|
PCCB newCCB;
|
||||||
|
|
||||||
|
FileObject = IoCreateStreamFileObject(NULL, Vcb->StorageDevice);
|
||||||
|
|
||||||
|
newCCB = ExAllocatePoolWithTag(NonPagedPool, sizeof(CCB), TAG_CCB);
|
||||||
|
if (newCCB == NULL)
|
||||||
|
{
|
||||||
|
return(STATUS_INSUFFICIENT_RESOURCES);
|
||||||
|
}
|
||||||
|
RtlZeroMemory(newCCB,
|
||||||
|
sizeof(CCB));
|
||||||
|
|
||||||
|
FileObject->Flags = FileObject->Flags | FO_FCB_IS_VALID |
|
||||||
|
FO_DIRECT_CACHE_PAGING_READ;
|
||||||
|
FileObject->SectionObjectPointers = &Fcb->SectionObjectPointers;
|
||||||
|
FileObject->FsContext = (PVOID) &Fcb->RFCB;
|
||||||
|
FileObject->FsContext2 = newCCB;
|
||||||
|
newCCB->Fcb = Fcb;
|
||||||
|
newCCB->PtrFileObject = FileObject;
|
||||||
|
Fcb->FileObject = FileObject;
|
||||||
|
Fcb->DevExt = Vcb;
|
||||||
|
|
||||||
|
Status = CcRosInitializeFileCache(FileObject,
|
||||||
|
&Fcb->RFCB.Bcb,
|
||||||
|
CACHEPAGESIZE(Vcb));
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DbgPrint("CcRosInitializeFileCache failed\n");
|
||||||
|
KeBugCheck(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
ObDereferenceObject(FileObject);
|
||||||
|
Fcb->Flags |= FCB_CACHE_INITIALIZED;
|
||||||
|
|
||||||
|
return(Status);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PFCB
|
||||||
|
NtfsMakeRootFCB(PDEVICE_EXTENSION Vcb)
|
||||||
|
{
|
||||||
|
PFCB Fcb;
|
||||||
|
|
||||||
|
Fcb = NtfsCreateFCB(L"\\");
|
||||||
|
|
||||||
|
// memset(Fcb->entry.Filename, ' ', 11);
|
||||||
|
|
||||||
|
// Fcb->Entry.DataLengthL = Vcb->CdInfo.RootSize;
|
||||||
|
// Fcb->Entry.ExtentLocationL = Vcb->CdInfo.RootStart;
|
||||||
|
// Fcb->Entry.FileFlags = 0x02; // FILE_ATTRIBUTE_DIRECTORY;
|
||||||
|
Fcb->RefCount = 1;
|
||||||
|
Fcb->DirIndex = 0;
|
||||||
|
Fcb->RFCB.FileSize.QuadPart = PAGESIZE;//Vcb->CdInfo.RootSize;
|
||||||
|
Fcb->RFCB.ValidDataLength.QuadPart = PAGESIZE;//Vcb->CdInfo.RootSize;
|
||||||
|
Fcb->RFCB.AllocationSize.QuadPart = PAGESIZE;//Vcb->CdInfo.RootSize;
|
||||||
|
|
||||||
|
NtfsFCBInitializeCache(Vcb, Fcb);
|
||||||
|
NtfsAddFCBToTable(Vcb, Fcb);
|
||||||
|
NtfsGrabFCB(Vcb, Fcb);
|
||||||
|
|
||||||
|
return(Fcb);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PFCB
|
||||||
|
NtfsOpenRootFCB(PDEVICE_EXTENSION Vcb)
|
||||||
|
{
|
||||||
|
PFCB Fcb;
|
||||||
|
|
||||||
|
Fcb = NtfsGrabFCBFromTable(Vcb, L"\\");
|
||||||
|
if (Fcb == NULL)
|
||||||
|
{
|
||||||
|
Fcb = NtfsMakeRootFCB(Vcb);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(Fcb);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
static VOID
|
||||||
|
NtfsGetDirEntryName(PDEVICE_EXTENSION DeviceExt,
|
||||||
|
PDIR_RECORD Record,
|
||||||
|
PWSTR Name)
|
||||||
|
/*
|
||||||
|
* FUNCTION: Retrieves the file name, be it in short or long file name format
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
if (Record->FileIdLength == 1 && Record->FileId[0] == 0)
|
||||||
|
{
|
||||||
|
wcscpy(Name, L".");
|
||||||
|
}
|
||||||
|
else if (Record->FileIdLength == 1 && Record->FileId[0] == 1)
|
||||||
|
{
|
||||||
|
wcscpy(Name, L"..");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (DeviceExt->CdInfo.JolietLevel == 0)
|
||||||
|
{
|
||||||
|
ULONG i;
|
||||||
|
|
||||||
|
for (i = 0; i < Record->FileIdLength && Record->FileId[i] != ';'; i++)
|
||||||
|
Name[i] = (WCHAR)Record->FileId[i];
|
||||||
|
Name[i] = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CdfsSwapString(Name, Record->FileId, Record->FileIdLength);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINT("Name '%S'\n", Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NtfsMakeFCBFromDirEntry(PVCB Vcb,
|
||||||
|
PFCB DirectoryFCB,
|
||||||
|
PWSTR Name,
|
||||||
|
PDIR_RECORD Record,
|
||||||
|
PFCB * fileFCB)
|
||||||
|
{
|
||||||
|
WCHAR pathName[MAX_PATH];
|
||||||
|
PFCB rcFCB;
|
||||||
|
ULONG Size;
|
||||||
|
|
||||||
|
if (Name [0] != 0 && wcslen (DirectoryFCB->PathName) +
|
||||||
|
sizeof(WCHAR) + wcslen (Name) > MAX_PATH)
|
||||||
|
{
|
||||||
|
return(STATUS_OBJECT_NAME_INVALID);
|
||||||
|
}
|
||||||
|
|
||||||
|
wcscpy(pathName, DirectoryFCB->PathName);
|
||||||
|
if (!CdfsFCBIsRoot(DirectoryFCB))
|
||||||
|
{
|
||||||
|
wcscat(pathName, L"\\");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Name[0] != 0)
|
||||||
|
{
|
||||||
|
wcscat(pathName, Name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
WCHAR entryName[MAX_PATH];
|
||||||
|
|
||||||
|
CdfsGetDirEntryName(Vcb, Record, entryName);
|
||||||
|
wcscat(pathName, entryName);
|
||||||
|
}
|
||||||
|
|
||||||
|
rcFCB = CdfsCreateFCB(pathName);
|
||||||
|
memcpy(&rcFCB->Entry, Record, sizeof(DIR_RECORD));
|
||||||
|
|
||||||
|
Size = rcFCB->Entry.DataLengthL;
|
||||||
|
|
||||||
|
rcFCB->RFCB.FileSize.QuadPart = Size;
|
||||||
|
rcFCB->RFCB.ValidDataLength.QuadPart = Size;
|
||||||
|
rcFCB->RFCB.AllocationSize.QuadPart = ROUND_UP(Size, BLOCKSIZE);
|
||||||
|
// DPRINT1("%S %d %d\n", longName, Size, (ULONG)rcFCB->RFCB.AllocationSize.QuadPart);
|
||||||
|
CdfsFCBInitializeCache(Vcb, rcFCB);
|
||||||
|
rcFCB->RefCount++;
|
||||||
|
CdfsAddFCBToTable(Vcb, rcFCB);
|
||||||
|
*fileFCB = rcFCB;
|
||||||
|
|
||||||
|
return(STATUS_SUCCESS);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NtfsAttachFCBToFileObject(PDEVICE_EXTENSION Vcb,
|
||||||
|
PFCB Fcb,
|
||||||
|
PFILE_OBJECT FileObject)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
PCCB newCCB;
|
||||||
|
|
||||||
|
newCCB = ExAllocatePoolWithTag(NonPagedPool, sizeof(CCB), TAG_CCB);
|
||||||
|
if (newCCB == NULL)
|
||||||
|
{
|
||||||
|
return(STATUS_INSUFFICIENT_RESOURCES);
|
||||||
|
}
|
||||||
|
memset(newCCB, 0, sizeof(CCB));
|
||||||
|
|
||||||
|
FileObject->Flags = FileObject->Flags | FO_FCB_IS_VALID |
|
||||||
|
FO_DIRECT_CACHE_PAGING_READ;
|
||||||
|
FileObject->SectionObjectPointers = &Fcb->SectionObjectPointers;
|
||||||
|
FileObject->FsContext = (PVOID)&Fcb->RFCB;
|
||||||
|
FileObject->FsContext2 = newCCB;
|
||||||
|
newCCB->Fcb = Fcb;
|
||||||
|
newCCB->PtrFileObject = FileObject;
|
||||||
|
Fcb->DevExt = Vcb;
|
||||||
|
|
||||||
|
if (!(Fcb->Flags & FCB_CACHE_INITIALIZED))
|
||||||
|
{
|
||||||
|
Status = CcRosInitializeFileCache(FileObject,
|
||||||
|
&Fcb->RFCB.Bcb,
|
||||||
|
CACHEPAGESIZE(Vcb));
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DbgPrint("CcRosInitializeFileCache failed\n");
|
||||||
|
KeBugCheck(0);
|
||||||
|
}
|
||||||
|
Fcb->Flags |= FCB_CACHE_INITIALIZED;
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINT("file open: fcb:%x file size: %d\n", Fcb, Fcb->Entry.DataLengthL);
|
||||||
|
|
||||||
|
return(STATUS_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
NTSTATUS
|
||||||
|
NtfsDirFindFile(PDEVICE_EXTENSION DeviceExt,
|
||||||
|
PFCB DirectoryFcb,
|
||||||
|
PWSTR FileToFind,
|
||||||
|
PFCB *FoundFCB)
|
||||||
|
{
|
||||||
|
WCHAR TempName[2];
|
||||||
|
WCHAR Name[256];
|
||||||
|
PVOID Block;
|
||||||
|
ULONG FirstSector;
|
||||||
|
ULONG DirSize;
|
||||||
|
PDIR_RECORD Record;
|
||||||
|
ULONG Offset;
|
||||||
|
ULONG BlockOffset;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
LARGE_INTEGER StreamOffset;
|
||||||
|
PVOID Context;
|
||||||
|
|
||||||
|
assert(DeviceExt);
|
||||||
|
assert(DirectoryFcb);
|
||||||
|
assert(FileToFind);
|
||||||
|
|
||||||
|
DPRINT("CdfsDirFindFile(VCB:%08x, dirFCB:%08x, File:%S)\n",
|
||||||
|
DeviceExt,
|
||||||
|
DirectoryFcb,
|
||||||
|
FileToFind);
|
||||||
|
DPRINT("Dir Path:%S\n", DirectoryFcb->PathName);
|
||||||
|
|
||||||
|
/* default to '.' if no filename specified */
|
||||||
|
if (wcslen(FileToFind) == 0)
|
||||||
|
{
|
||||||
|
TempName[0] = L'.';
|
||||||
|
TempName[1] = 0;
|
||||||
|
FileToFind = TempName;
|
||||||
|
}
|
||||||
|
|
||||||
|
DirSize = DirectoryFcb->Entry.DataLengthL;
|
||||||
|
StreamOffset.QuadPart = (LONGLONG)DirectoryFcb->Entry.ExtentLocationL * (LONGLONG)BLOCKSIZE;
|
||||||
|
|
||||||
|
if(!CcMapData(DeviceExt->StreamFileObject, &StreamOffset,
|
||||||
|
BLOCKSIZE, TRUE, &Context, &Block))
|
||||||
|
{
|
||||||
|
DPRINT("CcMapData() failed\n");
|
||||||
|
return(STATUS_UNSUCCESSFUL);
|
||||||
|
}
|
||||||
|
|
||||||
|
Offset = 0;
|
||||||
|
BlockOffset = 0;
|
||||||
|
Record = (PDIR_RECORD)Block;
|
||||||
|
while(TRUE)
|
||||||
|
{
|
||||||
|
if (Record->RecordLength == 0)
|
||||||
|
{
|
||||||
|
DPRINT("RecordLength == 0 Stopped!\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINT("RecordLength %u ExtAttrRecordLength %u NameLength %u\n",
|
||||||
|
Record->RecordLength, Record->ExtAttrRecordLength, Record->FileIdLength);
|
||||||
|
|
||||||
|
CdfsGetDirEntryName(DeviceExt, Record, Name);
|
||||||
|
DPRINT("Name '%S'\n", Name);
|
||||||
|
|
||||||
|
if (wstrcmpjoki(Name, FileToFind))
|
||||||
|
{
|
||||||
|
DPRINT("Match found, %S\n", Name);
|
||||||
|
Status = CdfsMakeFCBFromDirEntry(DeviceExt,
|
||||||
|
DirectoryFcb,
|
||||||
|
Name,
|
||||||
|
Record,
|
||||||
|
FoundFCB);
|
||||||
|
|
||||||
|
CcUnpinData(Context);
|
||||||
|
|
||||||
|
return(Status);
|
||||||
|
}
|
||||||
|
|
||||||
|
Offset += Record->RecordLength;
|
||||||
|
BlockOffset += Record->RecordLength;
|
||||||
|
Record = (PDIR_RECORD)(Block + BlockOffset);
|
||||||
|
if (BlockOffset >= BLOCKSIZE || Record->RecordLength == 0)
|
||||||
|
{
|
||||||
|
DPRINT("Map next sector\n");
|
||||||
|
CcUnpinData(Context);
|
||||||
|
StreamOffset.QuadPart += BLOCKSIZE;
|
||||||
|
Offset = ROUND_UP(Offset, BLOCKSIZE);
|
||||||
|
BlockOffset = 0;
|
||||||
|
|
||||||
|
if (!CcMapData(DeviceExt->StreamFileObject,
|
||||||
|
&StreamOffset,
|
||||||
|
BLOCKSIZE, TRUE,
|
||||||
|
&Context, &Block))
|
||||||
|
{
|
||||||
|
DPRINT("CcMapData() failed\n");
|
||||||
|
return(STATUS_UNSUCCESSFUL);
|
||||||
|
}
|
||||||
|
Record = (PDIR_RECORD)(Block + BlockOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Offset >= DirSize)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
CcUnpinData(Context);
|
||||||
|
|
||||||
|
return(STATUS_OBJECT_NAME_NOT_FOUND);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NtfsGetFCBForFile(PDEVICE_EXTENSION Vcb,
|
||||||
|
PFCB *pParentFCB,
|
||||||
|
PFCB *pFCB,
|
||||||
|
const PWSTR pFileName)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
WCHAR pathName [MAX_PATH];
|
||||||
|
WCHAR elementName [MAX_PATH];
|
||||||
|
PWCHAR currentElement;
|
||||||
|
PFCB FCB;
|
||||||
|
PFCB parentFCB;
|
||||||
|
|
||||||
|
DPRINT("NtfsGetFCBForFile(%x, %x, %x, '%S')\n",
|
||||||
|
Vcb,
|
||||||
|
pParentFCB,
|
||||||
|
pFCB,
|
||||||
|
pFileName);
|
||||||
|
|
||||||
|
/* Dummy code */
|
||||||
|
FCB = NtfsOpenRootFCB(Vcb);
|
||||||
|
*pFCB = FCB;
|
||||||
|
*pParentFCB = NULL;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/* Trivial case, open of the root directory on volume */
|
||||||
|
if (pFileName [0] == L'\0' || wcscmp(pFileName, L"\\") == 0)
|
||||||
|
{
|
||||||
|
DPRINT("returning root FCB\n");
|
||||||
|
|
||||||
|
FCB = NtfsOpenRootFCB(Vcb);
|
||||||
|
*pFCB = FCB;
|
||||||
|
*pParentFCB = NULL;
|
||||||
|
|
||||||
|
return((FCB != NULL) ? STATUS_SUCCESS : STATUS_OBJECT_PATH_NOT_FOUND);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
currentElement = pFileName + 1;
|
||||||
|
wcscpy (pathName, L"\\");
|
||||||
|
FCB = CdfsOpenRootFCB (Vcb);
|
||||||
|
}
|
||||||
|
parentFCB = NULL;
|
||||||
|
|
||||||
|
/* Parse filename and check each path element for existance and access */
|
||||||
|
while (CdfsGetNextPathElement(currentElement) != 0)
|
||||||
|
{
|
||||||
|
/* Skip blank directory levels */
|
||||||
|
if ((CdfsGetNextPathElement(currentElement) - currentElement) == 0)
|
||||||
|
{
|
||||||
|
currentElement++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINT("Parsing, currentElement:%S\n", currentElement);
|
||||||
|
DPRINT(" parentFCB:%x FCB:%x\n", parentFCB, FCB);
|
||||||
|
|
||||||
|
/* Descend to next directory level */
|
||||||
|
if (parentFCB)
|
||||||
|
{
|
||||||
|
CdfsReleaseFCB(Vcb, parentFCB);
|
||||||
|
parentFCB = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fail if element in FCB is not a directory */
|
||||||
|
if (!CdfsFCBIsDirectory(FCB))
|
||||||
|
{
|
||||||
|
DPRINT("Element in requested path is not a directory\n");
|
||||||
|
|
||||||
|
CdfsReleaseFCB(Vcb, FCB);
|
||||||
|
FCB = 0;
|
||||||
|
*pParentFCB = NULL;
|
||||||
|
*pFCB = NULL;
|
||||||
|
|
||||||
|
return(STATUS_OBJECT_PATH_NOT_FOUND);
|
||||||
|
}
|
||||||
|
parentFCB = FCB;
|
||||||
|
|
||||||
|
/* Extract next directory level into dirName */
|
||||||
|
CdfsWSubString(pathName,
|
||||||
|
pFileName,
|
||||||
|
CdfsGetNextPathElement(currentElement) - pFileName);
|
||||||
|
DPRINT(" pathName:%S\n", pathName);
|
||||||
|
|
||||||
|
FCB = CdfsGrabFCBFromTable(Vcb, pathName);
|
||||||
|
if (FCB == NULL)
|
||||||
|
{
|
||||||
|
CdfsWSubString(elementName,
|
||||||
|
currentElement,
|
||||||
|
CdfsGetNextPathElement(currentElement) - currentElement);
|
||||||
|
DPRINT(" elementName:%S\n", elementName);
|
||||||
|
|
||||||
|
Status = CdfsDirFindFile(Vcb, parentFCB, elementName, &FCB);
|
||||||
|
if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
|
||||||
|
{
|
||||||
|
*pParentFCB = parentFCB;
|
||||||
|
*pFCB = NULL;
|
||||||
|
currentElement = CdfsGetNextPathElement(currentElement);
|
||||||
|
if (*currentElement == L'\0' || CdfsGetNextPathElement(currentElement + 1) == 0)
|
||||||
|
{
|
||||||
|
return(STATUS_OBJECT_NAME_NOT_FOUND);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return(STATUS_OBJECT_PATH_NOT_FOUND);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
CdfsReleaseFCB(Vcb, parentFCB);
|
||||||
|
*pParentFCB = NULL;
|
||||||
|
*pFCB = NULL;
|
||||||
|
|
||||||
|
return(Status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
currentElement = CdfsGetNextPathElement(currentElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
*pParentFCB = parentFCB;
|
||||||
|
*pFCB = FCB;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return(STATUS_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* EOF */
|
268
reactos/drivers/fs/ntfs/finfo.c
Normal file
268
reactos/drivers/fs/ntfs/finfo.c
Normal file
|
@ -0,0 +1,268 @@
|
||||||
|
/*
|
||||||
|
* ReactOS kernel
|
||||||
|
* Copyright (C) 2002 ReactOS Team
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
/* $Id: finfo.c,v 1.1 2002/06/25 22:23:05 ekohl Exp $
|
||||||
|
*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS kernel
|
||||||
|
* FILE: services/fs/ntfs/dirctl.c
|
||||||
|
* PURPOSE: NTFS filesystem driver
|
||||||
|
* PROGRAMMER: Eric Kohl
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* INCLUDES *****************************************************************/
|
||||||
|
|
||||||
|
#include <ddk/ntddk.h>
|
||||||
|
|
||||||
|
//#define NDEBUG
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
|
#include "ntfs.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* FUNCTIONS ****************************************************************/
|
||||||
|
|
||||||
|
static NTSTATUS
|
||||||
|
NtfsGetStandardInformation(PFCB Fcb,
|
||||||
|
PDEVICE_OBJECT DeviceObject,
|
||||||
|
PFILE_STANDARD_INFORMATION StandardInfo,
|
||||||
|
PULONG BufferLength)
|
||||||
|
/*
|
||||||
|
* FUNCTION: Retrieve the standard file information
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
DPRINT("NtfsGetStandardInformation() called\n");
|
||||||
|
|
||||||
|
if (*BufferLength < sizeof(FILE_STANDARD_INFORMATION))
|
||||||
|
return(STATUS_BUFFER_OVERFLOW);
|
||||||
|
|
||||||
|
/* PRECONDITION */
|
||||||
|
assert(StandardInfo != NULL);
|
||||||
|
assert(Fcb != NULL);
|
||||||
|
|
||||||
|
RtlZeroMemory(StandardInfo,
|
||||||
|
sizeof(FILE_STANDARD_INFORMATION));
|
||||||
|
|
||||||
|
StandardInfo->AllocationSize = Fcb->RFCB.AllocationSize;
|
||||||
|
StandardInfo->EndOfFile = Fcb->RFCB.FileSize;
|
||||||
|
StandardInfo->NumberOfLinks = 0;
|
||||||
|
StandardInfo->DeletePending = FALSE;
|
||||||
|
StandardInfo->Directory = NtfsFCBIsDirectory(Fcb);
|
||||||
|
|
||||||
|
*BufferLength -= sizeof(FILE_STANDARD_INFORMATION);
|
||||||
|
return(STATUS_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static NTSTATUS
|
||||||
|
NtfsGetPositionInformation(PFILE_OBJECT FileObject,
|
||||||
|
PFILE_POSITION_INFORMATION PositionInfo,
|
||||||
|
PULONG BufferLength)
|
||||||
|
{
|
||||||
|
DPRINT("NtfsGetPositionInformation() called\n");
|
||||||
|
|
||||||
|
if (*BufferLength < sizeof(FILE_POSITION_INFORMATION))
|
||||||
|
return(STATUS_BUFFER_OVERFLOW);
|
||||||
|
|
||||||
|
PositionInfo->CurrentByteOffset.QuadPart =
|
||||||
|
0;
|
||||||
|
// FileObject->CurrentByteOffset.QuadPart;
|
||||||
|
|
||||||
|
DPRINT("Getting position %I64x\n",
|
||||||
|
PositionInfo->CurrentByteOffset.QuadPart);
|
||||||
|
|
||||||
|
*BufferLength -= sizeof(FILE_POSITION_INFORMATION);
|
||||||
|
return(STATUS_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static NTSTATUS
|
||||||
|
NtfsGetBasicInformation(PFILE_OBJECT FileObject,
|
||||||
|
PFCB Fcb,
|
||||||
|
PDEVICE_OBJECT DeviceObject,
|
||||||
|
PFILE_BASIC_INFORMATION BasicInfo,
|
||||||
|
PULONG BufferLength)
|
||||||
|
{
|
||||||
|
DPRINT("NtfsGetBasicInformation() called\n");
|
||||||
|
|
||||||
|
if (*BufferLength < sizeof(FILE_BASIC_INFORMATION))
|
||||||
|
return(STATUS_BUFFER_OVERFLOW);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
CdfsDateTimeToFileTime(Fcb,
|
||||||
|
&BasicInfo->CreationTime);
|
||||||
|
CdfsDateTimeToFileTime(Fcb,
|
||||||
|
&BasicInfo->LastAccessTime);
|
||||||
|
CdfsDateTimeToFileTime(Fcb,
|
||||||
|
&BasicInfo->LastWriteTime);
|
||||||
|
CdfsDateTimeToFileTime(Fcb,
|
||||||
|
&BasicInfo->ChangeTime);
|
||||||
|
|
||||||
|
CdfsFileFlagsToAttributes(Fcb,
|
||||||
|
&BasicInfo->FileAttributes);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
*BufferLength -= sizeof(FILE_BASIC_INFORMATION);
|
||||||
|
|
||||||
|
return(STATUS_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static NTSTATUS
|
||||||
|
NtfsGetNameInformation(PFILE_OBJECT FileObject,
|
||||||
|
PFCB Fcb,
|
||||||
|
PDEVICE_OBJECT DeviceObject,
|
||||||
|
PFILE_NAME_INFORMATION NameInfo,
|
||||||
|
PULONG BufferLength)
|
||||||
|
/*
|
||||||
|
* FUNCTION: Retrieve the file name information
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
ULONG NameLength;
|
||||||
|
|
||||||
|
DPRINT("NtfsGetNameInformation() called\n");
|
||||||
|
|
||||||
|
assert(NameInfo != NULL);
|
||||||
|
assert(Fcb != NULL);
|
||||||
|
|
||||||
|
// NameLength = wcslen(Fcb->PathName) * sizeof(WCHAR);
|
||||||
|
NameLength = 2;
|
||||||
|
if (*BufferLength < sizeof(FILE_NAME_INFORMATION) + NameLength)
|
||||||
|
return(STATUS_BUFFER_OVERFLOW);
|
||||||
|
|
||||||
|
NameInfo->FileNameLength = NameLength;
|
||||||
|
// memcpy(NameInfo->FileName,
|
||||||
|
// Fcb->PathName,
|
||||||
|
// NameLength + sizeof(WCHAR));
|
||||||
|
wcscpy(NameInfo->FileName, L"\\");
|
||||||
|
|
||||||
|
*BufferLength -=
|
||||||
|
(sizeof(FILE_NAME_INFORMATION) + NameLength + sizeof(WCHAR));
|
||||||
|
|
||||||
|
return(STATUS_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static NTSTATUS
|
||||||
|
NtfsGetInternalInformation(PFCB Fcb,
|
||||||
|
PFILE_INTERNAL_INFORMATION InternalInfo,
|
||||||
|
PULONG BufferLength)
|
||||||
|
{
|
||||||
|
DPRINT("NtfsGetInternalInformation() called\n");
|
||||||
|
|
||||||
|
assert(InternalInfo);
|
||||||
|
assert(Fcb);
|
||||||
|
|
||||||
|
if (*BufferLength < sizeof(FILE_INTERNAL_INFORMATION))
|
||||||
|
return(STATUS_BUFFER_OVERFLOW);
|
||||||
|
|
||||||
|
/* FIXME: get a real index, that can be used in a create operation */
|
||||||
|
InternalInfo->IndexNumber.QuadPart = 0;
|
||||||
|
|
||||||
|
*BufferLength -= sizeof(FILE_INTERNAL_INFORMATION);
|
||||||
|
|
||||||
|
return(STATUS_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
NTSTATUS STDCALL
|
||||||
|
NtfsQueryInformation(PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp)
|
||||||
|
/*
|
||||||
|
* FUNCTION: Retrieve the specified file information
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
FILE_INFORMATION_CLASS FileInformationClass;
|
||||||
|
PIO_STACK_LOCATION Stack;
|
||||||
|
PFILE_OBJECT FileObject;
|
||||||
|
PFCB Fcb;
|
||||||
|
PVOID SystemBuffer;
|
||||||
|
ULONG BufferLength;
|
||||||
|
|
||||||
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
DPRINT("NtfsQueryInformation() called\n");
|
||||||
|
|
||||||
|
Stack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
FileInformationClass = Stack->Parameters.QueryFile.FileInformationClass;
|
||||||
|
FileObject = Stack->FileObject;
|
||||||
|
Fcb = FileObject->FsContext;
|
||||||
|
|
||||||
|
SystemBuffer = Irp->AssociatedIrp.SystemBuffer;
|
||||||
|
BufferLength = Stack->Parameters.QueryFile.Length;
|
||||||
|
|
||||||
|
switch (FileInformationClass)
|
||||||
|
{
|
||||||
|
case FileStandardInformation:
|
||||||
|
Status = NtfsGetStandardInformation(Fcb,
|
||||||
|
DeviceObject,
|
||||||
|
SystemBuffer,
|
||||||
|
&BufferLength);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FilePositionInformation:
|
||||||
|
Status = NtfsGetPositionInformation(FileObject,
|
||||||
|
SystemBuffer,
|
||||||
|
&BufferLength);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FileBasicInformation:
|
||||||
|
Status = NtfsGetBasicInformation(FileObject,
|
||||||
|
Fcb,
|
||||||
|
DeviceObject,
|
||||||
|
SystemBuffer,
|
||||||
|
&BufferLength);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FileNameInformation:
|
||||||
|
Status = NtfsGetNameInformation(FileObject,
|
||||||
|
Fcb,
|
||||||
|
DeviceObject,
|
||||||
|
SystemBuffer,
|
||||||
|
&BufferLength);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FileInternalInformation:
|
||||||
|
Status = NtfsGetInternalInformation(Fcb,
|
||||||
|
SystemBuffer,
|
||||||
|
&BufferLength);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FileAlternateNameInformation:
|
||||||
|
case FileAllInformation:
|
||||||
|
Status = STATUS_NOT_IMPLEMENTED;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
DPRINT("Unimplemented information class %u\n", FileInformationClass);
|
||||||
|
Status = STATUS_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
Irp->IoStatus.Status = Status;
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
Irp->IoStatus.Information =
|
||||||
|
Stack->Parameters.QueryFile.Length - BufferLength;
|
||||||
|
else
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
|
||||||
|
return(Status);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* EOF */
|
476
reactos/drivers/fs/ntfs/fsctl.c
Normal file
476
reactos/drivers/fs/ntfs/fsctl.c
Normal file
|
@ -0,0 +1,476 @@
|
||||||
|
/*
|
||||||
|
* ReactOS kernel
|
||||||
|
* Copyright (C) 2002 ReactOS Team
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
/* $Id: fsctl.c,v 1.1 2002/06/25 22:23:06 ekohl Exp $
|
||||||
|
*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS kernel
|
||||||
|
* FILE: services/fs/ntfs/fsctl.c
|
||||||
|
* PURPOSE: NTFS filesystem driver
|
||||||
|
* PROGRAMMER: Eric Kohl
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* INCLUDES *****************************************************************/
|
||||||
|
|
||||||
|
#include <ddk/ntddk.h>
|
||||||
|
|
||||||
|
#define NDEBUG
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
|
#include "ntfs.h"
|
||||||
|
|
||||||
|
/* FUNCTIONS ****************************************************************/
|
||||||
|
|
||||||
|
static NTSTATUS
|
||||||
|
NtfsHasFileSystem(PDEVICE_OBJECT DeviceToMount)
|
||||||
|
/*
|
||||||
|
* FUNCTION: Tests if the device contains a filesystem that can be mounted
|
||||||
|
* by this fsd
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
PARTITION_INFORMATION PartitionInfo;
|
||||||
|
DISK_GEOMETRY DiskGeometry;
|
||||||
|
ULONG Size;
|
||||||
|
PBOOT_SECTOR BootSector;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
DPRINT("NtfsHasFileSystem() called\n");
|
||||||
|
|
||||||
|
Size = sizeof(DISK_GEOMETRY);
|
||||||
|
Status = NtfsDeviceIoControl(DeviceToMount,
|
||||||
|
IOCTL_DISK_GET_DRIVE_GEOMETRY,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
&DiskGeometry,
|
||||||
|
&Size);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT("NtfsDeviceIoControl() failed (Status %lx)\n", Status);
|
||||||
|
return(Status);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DiskGeometry.MediaType == FixedMedia)
|
||||||
|
{
|
||||||
|
/* We have found a hard disk */
|
||||||
|
Size = sizeof(PARTITION_INFORMATION);
|
||||||
|
Status = NtfsDeviceIoControl(DeviceToMount,
|
||||||
|
IOCTL_DISK_GET_PARTITION_INFO,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
&PartitionInfo,
|
||||||
|
&Size);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT("NtfsDeviceIoControl() failed (Status %lx)\n", Status);
|
||||||
|
return(Status);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PartitionInfo.PartitionType != PARTITION_IFS)
|
||||||
|
{
|
||||||
|
return(STATUS_UNRECOGNIZED_VOLUME);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINT("BytesPerSector: %lu\n", DiskGeometry.BytesPerSector);
|
||||||
|
BootSector = ExAllocatePool(NonPagedPool,
|
||||||
|
DiskGeometry.BytesPerSector);
|
||||||
|
if (BootSector == NULL)
|
||||||
|
{
|
||||||
|
return(STATUS_INSUFFICIENT_RESOURCES);
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = NtfsReadRawSectors(DeviceToMount,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
DiskGeometry.BytesPerSector,
|
||||||
|
(PVOID)BootSector);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT("NTFS-identifier: [%.8s]\n", BootSector->OemName);
|
||||||
|
if (strncmp(BootSector->OemName, "NTFS ", 8) != 0)
|
||||||
|
{
|
||||||
|
Status = STATUS_UNRECOGNIZED_VOLUME;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ExFreePool(BootSector);
|
||||||
|
|
||||||
|
return(Status);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static NTSTATUS
|
||||||
|
NtfsGetVolumeData(PDEVICE_OBJECT DeviceObject,
|
||||||
|
PDEVICE_EXTENSION Vcb)
|
||||||
|
{
|
||||||
|
DISK_GEOMETRY DiskGeometry;
|
||||||
|
PUCHAR Buffer;
|
||||||
|
ULONG Size;
|
||||||
|
NTSTATUS Status;
|
||||||
|
PBOOT_SECTOR BootSector;
|
||||||
|
|
||||||
|
DPRINT("NtfsGetVolumeData() called\n");
|
||||||
|
|
||||||
|
Size = sizeof(DISK_GEOMETRY);
|
||||||
|
Status = NtfsDeviceIoControl(DeviceObject,
|
||||||
|
IOCTL_DISK_GET_DRIVE_GEOMETRY,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
&DiskGeometry,
|
||||||
|
&Size);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT("NtfsDeviceIoControl() failed (Status %lx)\n", Status);
|
||||||
|
return(Status);
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINT("BytesPerSector: %lu\n", DiskGeometry.BytesPerSector);
|
||||||
|
BootSector = ExAllocatePool(NonPagedPool,
|
||||||
|
DiskGeometry.BytesPerSector);
|
||||||
|
if (BootSector == NULL)
|
||||||
|
{
|
||||||
|
return(STATUS_INSUFFICIENT_RESOURCES);
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = NtfsReadRawSectors(DeviceObject,
|
||||||
|
0, /* Partition boot sector */
|
||||||
|
1,
|
||||||
|
DiskGeometry.BytesPerSector,
|
||||||
|
(PVOID)BootSector);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* Read data from the bootsector */
|
||||||
|
Vcb->NtfsInfo.BytesPerSector = BootSector->BytesPerSector;
|
||||||
|
Vcb->NtfsInfo.SectorsPerCluster = BootSector->SectorsPerCluster;
|
||||||
|
Vcb->NtfsInfo.BytesPerCluster = BootSector->BytesPerSector * BootSector->SectorsPerCluster;
|
||||||
|
Vcb->NtfsInfo.SectorCount = BootSector->SectorCount;
|
||||||
|
|
||||||
|
Vcb->NtfsInfo.MftStart = BootSector->MftLocation;
|
||||||
|
Vcb->NtfsInfo.MftMirrStart = BootSector->MftMirrLocation;
|
||||||
|
Vcb->NtfsInfo.SerialNumber = BootSector->SerialNumber;
|
||||||
|
|
||||||
|
//#indef NDEBUG
|
||||||
|
DbgPrint("Boot sector information:\n");
|
||||||
|
DbgPrint(" BytesPerSector: %hu\n", BootSector->BytesPerSector);
|
||||||
|
DbgPrint(" SectorsPerCluster: %hu\n", BootSector->SectorsPerCluster);
|
||||||
|
|
||||||
|
DbgPrint(" SectorCount: %I64u\n", BootSector->SectorCount);
|
||||||
|
|
||||||
|
DbgPrint(" MftStart: %I64u\n", BootSector->MftLocation);
|
||||||
|
DbgPrint(" MftMirrStart: %I64u\n", BootSector->MftMirrLocation);
|
||||||
|
|
||||||
|
DbgPrint(" ClustersPerMftRecord: %lx\n", BootSector->ClustersPerMftRecord);
|
||||||
|
DbgPrint(" ClustersPerIndexRecord: %lx\n", BootSector->ClustersPerIndexRecord);
|
||||||
|
|
||||||
|
DbgPrint(" SerialNumber: %I64x\n", BootSector->SerialNumber);
|
||||||
|
//#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
ExFreePool(Buffer);
|
||||||
|
|
||||||
|
return(Status);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static NTSTATUS
|
||||||
|
NtfsMountVolume(PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp)
|
||||||
|
{
|
||||||
|
PDEVICE_EXTENSION DeviceExt = NULL;
|
||||||
|
PDEVICE_OBJECT NewDeviceObject = NULL;
|
||||||
|
PDEVICE_OBJECT DeviceToMount;
|
||||||
|
PIO_STACK_LOCATION Stack;
|
||||||
|
PFCB Fcb = NULL;
|
||||||
|
PCCB Ccb = NULL;
|
||||||
|
PVPB Vpb;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
DPRINT("NtfsMountVolume() called\n");
|
||||||
|
|
||||||
|
if (DeviceObject != NtfsGlobalData->DeviceObject)
|
||||||
|
{
|
||||||
|
Status = STATUS_INVALID_DEVICE_REQUEST;
|
||||||
|
goto ByeBye;
|
||||||
|
}
|
||||||
|
|
||||||
|
Stack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
DeviceToMount = Stack->Parameters.MountVolume.DeviceObject;
|
||||||
|
Vpb = Stack->Parameters.MountVolume.Vpb;
|
||||||
|
|
||||||
|
Status = NtfsHasFileSystem(DeviceToMount);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
goto ByeBye;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = IoCreateDevice(NtfsGlobalData->DriverObject,
|
||||||
|
sizeof(DEVICE_EXTENSION),
|
||||||
|
NULL,
|
||||||
|
FILE_DEVICE_FILE_SYSTEM,
|
||||||
|
// FILE_DEVICE_DISK_FILE_SYSTEM,
|
||||||
|
0,
|
||||||
|
FALSE,
|
||||||
|
&NewDeviceObject);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
goto ByeBye;
|
||||||
|
|
||||||
|
NewDeviceObject->Flags = NewDeviceObject->Flags | DO_DIRECT_IO;
|
||||||
|
DeviceExt = (PVOID)NewDeviceObject->DeviceExtension;
|
||||||
|
RtlZeroMemory(DeviceExt,
|
||||||
|
sizeof(DEVICE_EXTENSION));
|
||||||
|
|
||||||
|
Status = NtfsGetVolumeData(DeviceToMount,
|
||||||
|
DeviceExt);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
goto ByeBye;
|
||||||
|
|
||||||
|
NewDeviceObject->Vpb = DeviceToMount->Vpb;
|
||||||
|
|
||||||
|
DeviceExt->StorageDevice = DeviceToMount;
|
||||||
|
DeviceExt->StorageDevice->Vpb->DeviceObject = NewDeviceObject;
|
||||||
|
DeviceExt->StorageDevice->Vpb->RealDevice = DeviceExt->StorageDevice;
|
||||||
|
DeviceExt->StorageDevice->Vpb->Flags |= VPB_MOUNTED;
|
||||||
|
NewDeviceObject->StackSize = DeviceExt->StorageDevice->StackSize + 1;
|
||||||
|
NewDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
|
||||||
|
|
||||||
|
DeviceExt->StreamFileObject = IoCreateStreamFileObject(NULL,
|
||||||
|
DeviceExt->StorageDevice);
|
||||||
|
|
||||||
|
|
||||||
|
Fcb = NtfsCreateFCB(NULL);
|
||||||
|
if (Fcb == NULL)
|
||||||
|
{
|
||||||
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
goto ByeBye;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ccb = ExAllocatePoolWithTag(NonPagedPool,
|
||||||
|
sizeof(CCB),
|
||||||
|
TAG_CCB);
|
||||||
|
if (Ccb == NULL)
|
||||||
|
{
|
||||||
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
goto ByeBye;
|
||||||
|
}
|
||||||
|
RtlZeroMemory(Ccb,
|
||||||
|
sizeof(CCB));
|
||||||
|
|
||||||
|
DeviceExt->StreamFileObject->Flags = DeviceExt->StreamFileObject->Flags | FO_FCB_IS_VALID | FO_DIRECT_CACHE_PAGING_READ;
|
||||||
|
DeviceExt->StreamFileObject->FsContext = (PVOID)&Fcb->RFCB;
|
||||||
|
DeviceExt->StreamFileObject->FsContext2 = Ccb;
|
||||||
|
DeviceExt->StreamFileObject->SectionObjectPointers = &Fcb->SectionObjectPointers;
|
||||||
|
DeviceExt->StreamFileObject->PrivateCacheMap = NULL;
|
||||||
|
DeviceExt->StreamFileObject->Vpb = DeviceExt->Vpb;
|
||||||
|
Ccb->Fcb = Fcb;
|
||||||
|
Ccb->PtrFileObject = DeviceExt->StreamFileObject;
|
||||||
|
Fcb->FileObject = DeviceExt->StreamFileObject;
|
||||||
|
Fcb->DevExt = (PDEVICE_EXTENSION)DeviceExt->StorageDevice;
|
||||||
|
|
||||||
|
Fcb->Flags = FCB_IS_VOLUME_STREAM;
|
||||||
|
|
||||||
|
Fcb->RFCB.FileSize.QuadPart = DeviceExt->NtfsInfo.SectorCount * DeviceExt->NtfsInfo.BytesPerSector;
|
||||||
|
Fcb->RFCB.ValidDataLength.QuadPart = DeviceExt->NtfsInfo.SectorCount * DeviceExt->NtfsInfo.BytesPerSector;
|
||||||
|
Fcb->RFCB.AllocationSize.QuadPart = DeviceExt->NtfsInfo.SectorCount * DeviceExt->NtfsInfo.BytesPerSector; /* Correct? */
|
||||||
|
|
||||||
|
// Fcb->Entry.ExtentLocationL = 0;
|
||||||
|
// Fcb->Entry.DataLengthL = DeviceExt->CdInfo.VolumeSpaceSize * BLOCKSIZE;
|
||||||
|
|
||||||
|
Status = CcRosInitializeFileCache(DeviceExt->StreamFileObject,
|
||||||
|
&Fcb->RFCB.Bcb,
|
||||||
|
CACHEPAGESIZE(DeviceExt));
|
||||||
|
if (!NT_SUCCESS (Status))
|
||||||
|
{
|
||||||
|
DbgPrint("CcRosInitializeFileCache() failed (Status %lx)\n", Status);
|
||||||
|
goto ByeBye;
|
||||||
|
}
|
||||||
|
|
||||||
|
ExInitializeResourceLite(&DeviceExt->DirResource);
|
||||||
|
// ExInitializeResourceLite(&DeviceExt->FatResource);
|
||||||
|
|
||||||
|
KeInitializeSpinLock(&DeviceExt->FcbListLock);
|
||||||
|
InitializeListHead(&DeviceExt->FcbListHead);
|
||||||
|
|
||||||
|
/* Read serial number */
|
||||||
|
NewDeviceObject->Vpb->SerialNumber = DeviceExt->NtfsInfo.SerialNumber;
|
||||||
|
|
||||||
|
/* Read volume label */
|
||||||
|
// NtfsReadVolumeLabel(DeviceExt,
|
||||||
|
// NewDeviceObject->Vpb);
|
||||||
|
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
ByeBye:
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* Cleanup */
|
||||||
|
if (DeviceExt && DeviceExt->StreamFileObject)
|
||||||
|
ObDereferenceObject(DeviceExt->StreamFileObject);
|
||||||
|
if (Fcb)
|
||||||
|
ExFreePool(Fcb);
|
||||||
|
if (Ccb)
|
||||||
|
ExFreePool(Ccb);
|
||||||
|
if (NewDeviceObject)
|
||||||
|
IoDeleteDevice(NewDeviceObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINT("NtfsMountVolume() done (Status: %lx)\n", Status);
|
||||||
|
|
||||||
|
return(Status);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static NTSTATUS
|
||||||
|
NtfsVerifyVolume(PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp)
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
PDEVICE_OBJECT DeviceToVerify;
|
||||||
|
PIO_STACK_LOCATION Stack;
|
||||||
|
PUCHAR Buffer;
|
||||||
|
ULONG Sector;
|
||||||
|
ULONG i;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
union
|
||||||
|
{
|
||||||
|
ULONG Value;
|
||||||
|
UCHAR Part[4];
|
||||||
|
} Serial;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
DPRINT1("NtfsVerifyVolume() called\n");
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
Stack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
DeviceToVerify = Stack->Parameters.VerifyVolume.DeviceObject;
|
||||||
|
|
||||||
|
DPRINT("Device object %p Device to verify %p\n", DeviceObject, DeviceToVerify);
|
||||||
|
|
||||||
|
Sector = CDFS_PRIMARY_DESCRIPTOR_LOCATION;
|
||||||
|
|
||||||
|
Buffer = ExAllocatePool(NonPagedPool,
|
||||||
|
CDFS_BASIC_SECTOR);
|
||||||
|
if (Buffer == NULL)
|
||||||
|
{
|
||||||
|
return(STATUS_INSUFFICIENT_RESOURCES);
|
||||||
|
}
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
/* Read the Primary Volume Descriptor (PVD) */
|
||||||
|
Status = CdfsReadRawSectors(DeviceToVerify,
|
||||||
|
Sector,
|
||||||
|
1,
|
||||||
|
Buffer);
|
||||||
|
DPRINT("CdfsReadRawSectors() status %lx\n", Status);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
goto ByeBye;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Buffer[0] == 1 &&
|
||||||
|
Buffer[1] == 'C' &&
|
||||||
|
Buffer[2] == 'D' &&
|
||||||
|
Buffer[3] == '0' &&
|
||||||
|
Buffer[4] == '0' &&
|
||||||
|
Buffer[5] == '1')
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Sector++;
|
||||||
|
}
|
||||||
|
while (Buffer[0] != 255);
|
||||||
|
|
||||||
|
if (Buffer[0] == 255)
|
||||||
|
goto ByeBye;
|
||||||
|
|
||||||
|
Status = STATUS_WRONG_VOLUME;
|
||||||
|
|
||||||
|
/* Calculate the volume serial number */
|
||||||
|
Serial.Value = 0;
|
||||||
|
for (i = 0; i < 2048; i += 4)
|
||||||
|
{
|
||||||
|
/* DON'T optimize this to ULONG!!! (breaks overflow) */
|
||||||
|
Serial.Part[0] += Buffer[i+3];
|
||||||
|
Serial.Part[1] += Buffer[i+2];
|
||||||
|
Serial.Part[2] += Buffer[i+1];
|
||||||
|
Serial.Part[3] += Buffer[i+0];
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINT("Current serial number %08lx Vpb serial number %08lx\n",
|
||||||
|
Serial.Value, DeviceToVerify->Vpb->SerialNumber);
|
||||||
|
|
||||||
|
if (Serial.Value == DeviceToVerify->Vpb->SerialNumber)
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
ByeBye:
|
||||||
|
ExFreePool(Buffer);
|
||||||
|
|
||||||
|
DPRINT("CdfsVerifyVolume() done (Status: %lx)\n", Status);
|
||||||
|
|
||||||
|
return(Status);
|
||||||
|
#endif
|
||||||
|
return(STATUS_UNSUCCESSFUL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
NTSTATUS STDCALL
|
||||||
|
NtfsFileSystemControl(PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp)
|
||||||
|
{
|
||||||
|
PIO_STACK_LOCATION Stack;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
DPRINT("NtfsFileSystemControl() called\n");
|
||||||
|
|
||||||
|
Stack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
|
||||||
|
switch (Stack->MinorFunction)
|
||||||
|
{
|
||||||
|
case IRP_MN_USER_FS_REQUEST:
|
||||||
|
DPRINT("NTFS: IRP_MN_USER_FS_REQUEST\n");
|
||||||
|
Status = STATUS_INVALID_DEVICE_REQUEST;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IRP_MN_MOUNT_VOLUME:
|
||||||
|
DPRINT("NTFS: IRP_MN_MOUNT_VOLUME\n");
|
||||||
|
Status = NtfsMountVolume(DeviceObject, Irp);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IRP_MN_VERIFY_VOLUME:
|
||||||
|
DPRINT1("NTFS: IRP_MN_VERIFY_VOLUME\n");
|
||||||
|
Status = NtfsVerifyVolume(DeviceObject, Irp);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
DPRINT("NTFS FSC: MinorFunction %d\n", Stack->MinorFunction);
|
||||||
|
Status = STATUS_INVALID_DEVICE_REQUEST;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Irp->IoStatus.Status = Status;
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
|
||||||
|
return(Status);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* EOF */
|
16
reactos/drivers/fs/ntfs/makefile
Normal file
16
reactos/drivers/fs/ntfs/makefile
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
# $Id: makefile,v 1.1 2002/06/25 22:23:06 ekohl Exp $
|
||||||
|
|
||||||
|
PATH_TO_TOP = ../../..
|
||||||
|
|
||||||
|
TARGET_TYPE = driver
|
||||||
|
|
||||||
|
TARGET_NAME = ntfs
|
||||||
|
|
||||||
|
TARGET_OBJECTS = $(TARGET_NAME).o blockdev.o create.o dirctl.o fcb.o finfo.o \
|
||||||
|
fsctl.o volinfo.o
|
||||||
|
|
||||||
|
include $(PATH_TO_TOP)/rules.mak
|
||||||
|
|
||||||
|
include $(TOOLS_PATH)/helper.mk
|
||||||
|
|
||||||
|
# EOF
|
106
reactos/drivers/fs/ntfs/ntfs.c
Normal file
106
reactos/drivers/fs/ntfs/ntfs.c
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
/*
|
||||||
|
* ReactOS kernel
|
||||||
|
* Copyright (C) 2002 ReactOS Team
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
/* $Id: ntfs.c,v 1.1 2002/06/25 22:23:06 ekohl Exp $
|
||||||
|
*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS kernel
|
||||||
|
* FILE: services/fs/ntfs/ntfs.c
|
||||||
|
* PURPOSE: NTFS filesystem driver
|
||||||
|
* PROGRAMMER: Eric Kohl
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* INCLUDES *****************************************************************/
|
||||||
|
|
||||||
|
#include <ddk/ntddk.h>
|
||||||
|
|
||||||
|
#define NDEBUG
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
|
#include "ntfs.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* GLOBALS *****************************************************************/
|
||||||
|
|
||||||
|
PNTFS_GLOBAL_DATA NtfsGlobalData;
|
||||||
|
|
||||||
|
|
||||||
|
/* FUNCTIONS ****************************************************************/
|
||||||
|
|
||||||
|
NTSTATUS STDCALL
|
||||||
|
DriverEntry(PDRIVER_OBJECT DriverObject,
|
||||||
|
PUNICODE_STRING RegistryPath)
|
||||||
|
/*
|
||||||
|
* FUNCTION: Called by the system to initalize the driver
|
||||||
|
* ARGUMENTS:
|
||||||
|
* DriverObject = object describing this driver
|
||||||
|
* RegistryPath = path to our configuration entries
|
||||||
|
* RETURNS: Success or failure
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
PDEVICE_OBJECT DeviceObject;
|
||||||
|
NTSTATUS Status;
|
||||||
|
UNICODE_STRING DeviceName;
|
||||||
|
|
||||||
|
DPRINT("NTFS 0.0.1\n");
|
||||||
|
|
||||||
|
RtlInitUnicodeString(&DeviceName,
|
||||||
|
L"\\Ntfs");
|
||||||
|
Status = IoCreateDevice(DriverObject,
|
||||||
|
sizeof(NTFS_GLOBAL_DATA),
|
||||||
|
&DeviceName,
|
||||||
|
FILE_DEVICE_DISK_FILE_SYSTEM,
|
||||||
|
0,
|
||||||
|
FALSE,
|
||||||
|
&DeviceObject);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
return(Status);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize global data */
|
||||||
|
NtfsGlobalData = DeviceObject->DeviceExtension;
|
||||||
|
RtlZeroMemory(NtfsGlobalData,
|
||||||
|
sizeof(NTFS_GLOBAL_DATA));
|
||||||
|
NtfsGlobalData->DriverObject = DriverObject;
|
||||||
|
NtfsGlobalData->DeviceObject = DeviceObject;
|
||||||
|
|
||||||
|
/* Initialize driver data */
|
||||||
|
DeviceObject->Flags = DO_DIRECT_IO;
|
||||||
|
// DriverObject->MajorFunction[IRP_MJ_CLOSE] = NtfsClose;
|
||||||
|
DriverObject->MajorFunction[IRP_MJ_CREATE] = NtfsCreate;
|
||||||
|
// DriverObject->MajorFunction[IRP_MJ_READ] = NtfsRead;
|
||||||
|
// DriverObject->MajorFunction[IRP_MJ_WRITE] = NtfsWrite;
|
||||||
|
DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] =
|
||||||
|
NtfsFileSystemControl;
|
||||||
|
DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] =
|
||||||
|
NtfsDirectoryControl;
|
||||||
|
DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] =
|
||||||
|
NtfsQueryInformation;
|
||||||
|
// DriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] =
|
||||||
|
// NtfsQueryVolumeInformation;
|
||||||
|
// DriverObject->MajorFunction[IRP_MJ_SET_VOLUME_INFORMATION] =
|
||||||
|
// NtfsSetVolumeInformation;
|
||||||
|
|
||||||
|
DriverObject->DriverUnload = NULL;
|
||||||
|
|
||||||
|
IoRegisterFileSystem(DeviceObject);
|
||||||
|
|
||||||
|
return(STATUS_SUCCESS);
|
||||||
|
}
|
||||||
|
|
295
reactos/drivers/fs/ntfs/ntfs.h
Normal file
295
reactos/drivers/fs/ntfs/ntfs.h
Normal file
|
@ -0,0 +1,295 @@
|
||||||
|
#ifndef NTFS_H
|
||||||
|
#define NTFS_H
|
||||||
|
|
||||||
|
#include <ddk/ntifs.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define CACHEPAGESIZE(pDeviceExt) \
|
||||||
|
((pDeviceExt)->NtfsInfo.BytesPerCluster > PAGESIZE ? \
|
||||||
|
(pDeviceExt)->NtfsInfo.BytesPerCluster : PAGESIZE)
|
||||||
|
|
||||||
|
#define TAG(A, B, C, D) (ULONG)(((A)<<0) + ((B)<<8) + ((C)<<16) + ((D)<<24))
|
||||||
|
|
||||||
|
#define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S))
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct _BOOT_SECTOR
|
||||||
|
{
|
||||||
|
UCHAR Magic[3]; // 0x00
|
||||||
|
UCHAR OemName[8]; // 0x03
|
||||||
|
USHORT BytesPerSector; // 0x0B
|
||||||
|
UCHAR SectorsPerCluster; // 0x0D
|
||||||
|
UCHAR Unused0[7]; // 0x0E
|
||||||
|
UCHAR MediaId; // 0x15
|
||||||
|
UCHAR Unused1[2]; // 0x16
|
||||||
|
USHORT SectorsPerTrack;
|
||||||
|
USHORT Heads;
|
||||||
|
UCHAR Unused2[8];
|
||||||
|
UCHAR Unknown0[4]; /* always 80 00 80 00 */
|
||||||
|
ULONGLONG SectorCount;
|
||||||
|
ULONGLONG MftLocation;
|
||||||
|
ULONGLONG MftMirrLocation;
|
||||||
|
ULONG ClustersPerMftRecord;
|
||||||
|
ULONG ClustersPerIndexRecord;
|
||||||
|
ULONGLONG SerialNumber; // 0x48
|
||||||
|
UCHAR BootCode[432]; // 0x50
|
||||||
|
} __attribute__((packed)) BOOT_SECTOR, *PBOOT_SECTOR;
|
||||||
|
|
||||||
|
//typedef struct _BootSector BootSector;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct _NTFS_INFO
|
||||||
|
{
|
||||||
|
ULONG BytesPerSector;
|
||||||
|
ULONG SectorsPerCluster;
|
||||||
|
ULONG BytesPerCluster;
|
||||||
|
ULONGLONG SectorCount;
|
||||||
|
ULONGLONG MftStart;
|
||||||
|
ULONGLONG MftMirrStart;
|
||||||
|
ULONGLONG SerialNumber;
|
||||||
|
|
||||||
|
} NTFS_INFO, *PNTFS_INFO;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
ERESOURCE DirResource;
|
||||||
|
// ERESOURCE FatResource;
|
||||||
|
|
||||||
|
KSPIN_LOCK FcbListLock;
|
||||||
|
LIST_ENTRY FcbListHead;
|
||||||
|
|
||||||
|
PVPB Vpb;
|
||||||
|
PDEVICE_OBJECT StorageDevice;
|
||||||
|
PFILE_OBJECT StreamFileObject;
|
||||||
|
|
||||||
|
NTFS_INFO NtfsInfo;
|
||||||
|
|
||||||
|
|
||||||
|
} DEVICE_EXTENSION, *PDEVICE_EXTENSION, VCB, *PVCB;
|
||||||
|
|
||||||
|
|
||||||
|
#define FCB_CACHE_INITIALIZED 0x0001
|
||||||
|
#define FCB_IS_VOLUME_STREAM 0x0002
|
||||||
|
#define FCB_IS_VOLUME 0x0004
|
||||||
|
|
||||||
|
typedef struct _FCB
|
||||||
|
{
|
||||||
|
REACTOS_COMMON_FCB_HEADER RFCB;
|
||||||
|
SECTION_OBJECT_POINTERS SectionObjectPointers;
|
||||||
|
|
||||||
|
PFILE_OBJECT FileObject;
|
||||||
|
PDEVICE_EXTENSION DevExt;
|
||||||
|
|
||||||
|
WCHAR *ObjectName; /* point on filename (250 chars max) in PathName */
|
||||||
|
WCHAR PathName[MAX_PATH]; /* path+filename 260 max */
|
||||||
|
|
||||||
|
ERESOURCE PagingIoResource;
|
||||||
|
ERESOURCE MainResource;
|
||||||
|
|
||||||
|
LIST_ENTRY FcbListEntry;
|
||||||
|
struct _FCB* ParentFcb;
|
||||||
|
|
||||||
|
ULONG DirIndex;
|
||||||
|
|
||||||
|
LONG RefCount;
|
||||||
|
ULONG Flags;
|
||||||
|
|
||||||
|
// DIR_RECORD Entry;
|
||||||
|
|
||||||
|
|
||||||
|
} FCB, *PFCB;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct _CCB
|
||||||
|
{
|
||||||
|
PFCB Fcb;
|
||||||
|
LIST_ENTRY NextCCB;
|
||||||
|
PFILE_OBJECT PtrFileObject;
|
||||||
|
LARGE_INTEGER CurrentByteOffset;
|
||||||
|
/* for DirectoryControl */
|
||||||
|
ULONG Entry;
|
||||||
|
/* for DirectoryControl */
|
||||||
|
PWCHAR DirectorySearchPattern;
|
||||||
|
ULONG LastCluster;
|
||||||
|
ULONG LastOffset;
|
||||||
|
} CCB, *PCCB;
|
||||||
|
|
||||||
|
#define TAG(A, B, C, D) (ULONG)(((A)<<0) + ((B)<<8) + ((C)<<16) + ((D)<<24))
|
||||||
|
|
||||||
|
#define TAG_CCB TAG('I', 'C', 'C', 'B')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
PDRIVER_OBJECT DriverObject;
|
||||||
|
PDEVICE_OBJECT DeviceObject;
|
||||||
|
ULONG Flags;
|
||||||
|
} NTFS_GLOBAL_DATA, *PNTFS_GLOBAL_DATA;
|
||||||
|
|
||||||
|
extern PNTFS_GLOBAL_DATA NtfsGlobalData;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//int CdfsStrcmpi( wchar_t *str1, wchar_t *str2 );
|
||||||
|
//void CdfsWstrcpy( wchar_t *str1, wchar_t *str2, int max );
|
||||||
|
|
||||||
|
|
||||||
|
/* blockdev.c */
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NtfsReadSectors(IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN ULONG DiskSector,
|
||||||
|
IN ULONG SectorCount,
|
||||||
|
IN ULONG SectorSize,
|
||||||
|
IN OUT PUCHAR Buffer);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NtfsReadRawSectors(IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN ULONG DiskSector,
|
||||||
|
IN ULONG SectorCount,
|
||||||
|
IN ULONG SectorSize,
|
||||||
|
IN OUT PUCHAR Buffer);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NtfsDeviceIoControl(IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN ULONG ControlCode,
|
||||||
|
IN PVOID InputBuffer,
|
||||||
|
IN ULONG InputBufferSize,
|
||||||
|
IN OUT PVOID OutputBuffer,
|
||||||
|
IN OUT PULONG OutputBufferSize);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/* close.c */
|
||||||
|
|
||||||
|
NTSTATUS STDCALL
|
||||||
|
CdfsClose(PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* create.c */
|
||||||
|
|
||||||
|
NTSTATUS STDCALL
|
||||||
|
NtfsCreate(PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp);
|
||||||
|
|
||||||
|
|
||||||
|
/* dirctl.c */
|
||||||
|
|
||||||
|
NTSTATUS STDCALL
|
||||||
|
NtfsDirectoryControl(PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp);
|
||||||
|
|
||||||
|
|
||||||
|
/* fcb.c */
|
||||||
|
|
||||||
|
PFCB
|
||||||
|
NtfsCreateFCB(PWCHAR FileName);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NtfsDestroyFCB(PFCB Fcb);
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
NtfsFCBIsDirectory(PFCB Fcb);
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
NtfsFCBIsRoot(PFCB Fcb);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NtfsGrabFCB(PDEVICE_EXTENSION Vcb,
|
||||||
|
PFCB Fcb);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NtfsReleaseFCB(PDEVICE_EXTENSION Vcb,
|
||||||
|
PFCB Fcb);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NtfsAddFCBToTable(PDEVICE_EXTENSION Vcb,
|
||||||
|
PFCB Fcb);
|
||||||
|
|
||||||
|
PFCB
|
||||||
|
NtfsGrabFCBFromTable(PDEVICE_EXTENSION Vcb,
|
||||||
|
PWSTR FileName);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NtfsFCBInitializeCache(PVCB Vcb,
|
||||||
|
PFCB Fcb);
|
||||||
|
|
||||||
|
PFCB
|
||||||
|
NtfsMakeRootFCB(PDEVICE_EXTENSION Vcb);
|
||||||
|
|
||||||
|
PFCB
|
||||||
|
NtfsOpenRootFCB(PDEVICE_EXTENSION Vcb);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NtfsAttachFCBToFileObject(PDEVICE_EXTENSION Vcb,
|
||||||
|
PFCB Fcb,
|
||||||
|
PFILE_OBJECT FileObject);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NtfsGetFCBForFile(PDEVICE_EXTENSION Vcb,
|
||||||
|
PFCB *pParentFCB,
|
||||||
|
PFCB *pFCB,
|
||||||
|
const PWSTR pFileName);
|
||||||
|
|
||||||
|
|
||||||
|
/* finfo.c */
|
||||||
|
|
||||||
|
NTSTATUS STDCALL
|
||||||
|
NtfsQueryInformation(PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp);
|
||||||
|
|
||||||
|
|
||||||
|
/* fsctl.c */
|
||||||
|
|
||||||
|
NTSTATUS STDCALL
|
||||||
|
NtfsFileSystemControl(PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/* misc.c */
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
wstrcmpjoki(PWSTR s1, PWSTR s2);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
CdfsSwapString(PWCHAR Out,
|
||||||
|
PUCHAR In,
|
||||||
|
ULONG Count);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
CdfsDateTimeToFileTime(PFCB Fcb,
|
||||||
|
TIME *FileTime);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
CdfsFileFlagsToAttributes(PFCB Fcb,
|
||||||
|
PULONG FileAttributes);
|
||||||
|
|
||||||
|
/* rw.c */
|
||||||
|
|
||||||
|
NTSTATUS STDCALL
|
||||||
|
CdfsRead(PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp);
|
||||||
|
|
||||||
|
NTSTATUS STDCALL
|
||||||
|
CdfsWrite(PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* volinfo.c */
|
||||||
|
|
||||||
|
NTSTATUS STDCALL
|
||||||
|
NtfsQueryVolumeInformation(PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp);
|
||||||
|
|
||||||
|
NTSTATUS STDCALL
|
||||||
|
NtfsSetVolumeInformation(PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp);
|
||||||
|
|
||||||
|
#endif /* NTFS_H */
|
39
reactos/drivers/fs/ntfs/ntfs.rc
Normal file
39
reactos/drivers/fs/ntfs/ntfs.rc
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
|
||||||
|
#include <defines.h>
|
||||||
|
#include <reactos/resource.h>
|
||||||
|
|
||||||
|
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||||
|
|
||||||
|
VS_VERSION_INFO VERSIONINFO
|
||||||
|
FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD
|
||||||
|
PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD
|
||||||
|
FILEFLAGSMASK 0x3fL
|
||||||
|
#ifdef _DEBUG
|
||||||
|
FILEFLAGS 0x1L
|
||||||
|
#else
|
||||||
|
FILEFLAGS 0x0L
|
||||||
|
#endif
|
||||||
|
FILEOS 0x40004L
|
||||||
|
FILETYPE 0x2L
|
||||||
|
FILESUBTYPE 0x0L
|
||||||
|
BEGIN
|
||||||
|
BLOCK "StringFileInfo"
|
||||||
|
BEGIN
|
||||||
|
BLOCK "040904b0"
|
||||||
|
BEGIN
|
||||||
|
VALUE "CompanyName", RES_STR_COMPANY_NAME
|
||||||
|
VALUE "FileDescription", "NTFS Driver\0"
|
||||||
|
VALUE "FileVersion", "0.0.1\0"
|
||||||
|
VALUE "InternalName", "ntfs\0"
|
||||||
|
VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT
|
||||||
|
VALUE "OriginalFilename", "ntfs.sys\0"
|
||||||
|
VALUE "ProductName", RES_STR_PRODUCT_NAME
|
||||||
|
VALUE "ProductVersion", RES_STR_PRODUCT_VERSION
|
||||||
|
END
|
||||||
|
END
|
||||||
|
BLOCK "VarFileInfo"
|
||||||
|
BEGIN
|
||||||
|
VALUE "Translation", 0x409, 1200
|
||||||
|
END
|
||||||
|
END
|
||||||
|
|
242
reactos/drivers/fs/ntfs/volinfo.c
Normal file
242
reactos/drivers/fs/ntfs/volinfo.c
Normal file
|
@ -0,0 +1,242 @@
|
||||||
|
/*
|
||||||
|
* ReactOS kernel
|
||||||
|
* Copyright (C) 2002 ReactOS Team
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
/* $Id: volinfo.c,v 1.1 2002/06/25 22:23:06 ekohl Exp $
|
||||||
|
*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS kernel
|
||||||
|
* FILE: services/fs/ntfs/volume.c
|
||||||
|
* PURPOSE: NTFS filesystem driver
|
||||||
|
* PROGRAMMER: Eric Kohl
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* INCLUDES *****************************************************************/
|
||||||
|
|
||||||
|
#include <ddk/ntddk.h>
|
||||||
|
|
||||||
|
#define NDEBUG
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
|
#include "ntfs.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* FUNCTIONS ****************************************************************/
|
||||||
|
|
||||||
|
static NTSTATUS
|
||||||
|
NtfsGetFsVolumeInformation(PDEVICE_OBJECT DeviceObject,
|
||||||
|
PFILE_FS_VOLUME_INFORMATION FsVolumeInfo,
|
||||||
|
PULONG BufferLength)
|
||||||
|
{
|
||||||
|
ULONG LabelLength;
|
||||||
|
|
||||||
|
DPRINT("NtfsGetFsVolumeInformation() called\n");
|
||||||
|
DPRINT("FsVolumeInfo = %p\n", FsVolumeInfo);
|
||||||
|
DPRINT("BufferLength %lu\n", *BufferLength);
|
||||||
|
|
||||||
|
DPRINT("Vpb %p\n", DeviceObject->Vpb);
|
||||||
|
LabelLength = DeviceObject->Vpb->VolumeLabelLength;
|
||||||
|
|
||||||
|
DPRINT("Required length %lu\n", (sizeof(FILE_FS_VOLUME_INFORMATION) + LabelLength*sizeof(WCHAR)));
|
||||||
|
DPRINT("LabelLength %lu\n", LabelLength);
|
||||||
|
DPRINT("Label %S\n", DeviceObject->Vpb->VolumeLabel);
|
||||||
|
|
||||||
|
if (*BufferLength < sizeof(FILE_FS_VOLUME_INFORMATION))
|
||||||
|
return(STATUS_INFO_LENGTH_MISMATCH);
|
||||||
|
|
||||||
|
if (*BufferLength < (sizeof(FILE_FS_VOLUME_INFORMATION) + LabelLength*sizeof(WCHAR)))
|
||||||
|
return(STATUS_BUFFER_OVERFLOW);
|
||||||
|
|
||||||
|
/* valid entries */
|
||||||
|
FsVolumeInfo->VolumeSerialNumber = DeviceObject->Vpb->SerialNumber;
|
||||||
|
FsVolumeInfo->VolumeLabelLength = LabelLength * sizeof (WCHAR);
|
||||||
|
wcscpy(FsVolumeInfo->VolumeLabel, DeviceObject->Vpb->VolumeLabel);
|
||||||
|
|
||||||
|
/* dummy entries */
|
||||||
|
FsVolumeInfo->VolumeCreationTime.QuadPart = 0;
|
||||||
|
FsVolumeInfo->SupportsObjects = FALSE;
|
||||||
|
|
||||||
|
*BufferLength -= (sizeof(FILE_FS_VOLUME_INFORMATION) + LabelLength * sizeof(WCHAR));
|
||||||
|
|
||||||
|
DPRINT("BufferLength %lu\n", *BufferLength);
|
||||||
|
DPRINT("NtfsGetFsVolumeInformation() done\n");
|
||||||
|
|
||||||
|
return(STATUS_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static NTSTATUS
|
||||||
|
NtfsGetFsAttributeInformation(PDEVICE_EXTENSION DeviceExt,
|
||||||
|
PFILE_FS_ATTRIBUTE_INFORMATION FsAttributeInfo,
|
||||||
|
PULONG BufferLength)
|
||||||
|
{
|
||||||
|
DPRINT("NtfsGetFsAttributeInformation()\n");
|
||||||
|
DPRINT("FsAttributeInfo = %p\n", FsAttributeInfo);
|
||||||
|
DPRINT("BufferLength %lu\n", *BufferLength);
|
||||||
|
DPRINT("Required length %lu\n", (sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + 8));
|
||||||
|
|
||||||
|
if (*BufferLength < sizeof (FILE_FS_ATTRIBUTE_INFORMATION))
|
||||||
|
return(STATUS_INFO_LENGTH_MISMATCH);
|
||||||
|
|
||||||
|
if (*BufferLength < (sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + 8))
|
||||||
|
return(STATUS_BUFFER_OVERFLOW);
|
||||||
|
|
||||||
|
FsAttributeInfo->FileSystemAttributes =
|
||||||
|
FILE_CASE_PRESERVED_NAMES | FILE_UNICODE_ON_DISK;
|
||||||
|
FsAttributeInfo->MaximumComponentNameLength = 255;
|
||||||
|
FsAttributeInfo->FileSystemNameLength = 8;
|
||||||
|
|
||||||
|
memcpy(FsAttributeInfo->FileSystemName, L"NTFS", 8);
|
||||||
|
|
||||||
|
DPRINT("Finished NtfsGetFsAttributeInformation()\n");
|
||||||
|
|
||||||
|
*BufferLength -= (sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + 8);
|
||||||
|
DPRINT("BufferLength %lu\n", *BufferLength);
|
||||||
|
|
||||||
|
return(STATUS_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static NTSTATUS
|
||||||
|
NtfsGetFsSizeInformation(PDEVICE_OBJECT DeviceObject,
|
||||||
|
PFILE_FS_SIZE_INFORMATION FsSizeInfo,
|
||||||
|
PULONG BufferLength)
|
||||||
|
{
|
||||||
|
PDEVICE_EXTENSION DeviceExt;
|
||||||
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
DPRINT("NtfsGetFsSizeInformation()\n");
|
||||||
|
DPRINT("FsSizeInfo = %p\n", FsSizeInfo);
|
||||||
|
|
||||||
|
if (*BufferLength < sizeof(FILE_FS_SIZE_INFORMATION))
|
||||||
|
return(STATUS_BUFFER_OVERFLOW);
|
||||||
|
|
||||||
|
DeviceExt = DeviceObject->DeviceExtension;
|
||||||
|
|
||||||
|
FsSizeInfo->AvailableAllocationUnits.QuadPart = 0;
|
||||||
|
FsSizeInfo->TotalAllocationUnits.QuadPart = DeviceExt->NtfsInfo.SectorCount; /* ?? */
|
||||||
|
FsSizeInfo->SectorsPerAllocationUnit = DeviceExt->NtfsInfo.SectorsPerCluster;
|
||||||
|
FsSizeInfo->BytesPerSector = DeviceExt->NtfsInfo.BytesPerSector;
|
||||||
|
|
||||||
|
DPRINT("Finished NtfsGetFsSizeInformation()\n");
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
*BufferLength -= sizeof(FILE_FS_SIZE_INFORMATION);
|
||||||
|
|
||||||
|
return(Status);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static NTSTATUS
|
||||||
|
NtfsGetFsDeviceInformation(PFILE_FS_DEVICE_INFORMATION FsDeviceInfo,
|
||||||
|
PULONG BufferLength)
|
||||||
|
{
|
||||||
|
DPRINT("NtfsGetFsDeviceInformation()\n");
|
||||||
|
DPRINT("FsDeviceInfo = %p\n", FsDeviceInfo);
|
||||||
|
DPRINT("BufferLength %lu\n", *BufferLength);
|
||||||
|
DPRINT("Required length %lu\n", sizeof(FILE_FS_DEVICE_INFORMATION));
|
||||||
|
|
||||||
|
if (*BufferLength < sizeof(FILE_FS_DEVICE_INFORMATION))
|
||||||
|
return(STATUS_BUFFER_OVERFLOW);
|
||||||
|
|
||||||
|
FsDeviceInfo->DeviceType = FILE_DEVICE_DISK;
|
||||||
|
FsDeviceInfo->Characteristics = 0; /* FIXME: fix this !! */
|
||||||
|
|
||||||
|
DPRINT("NtfsGetFsDeviceInformation() finished.\n");
|
||||||
|
|
||||||
|
*BufferLength -= sizeof(FILE_FS_DEVICE_INFORMATION);
|
||||||
|
DPRINT("BufferLength %lu\n", *BufferLength);
|
||||||
|
|
||||||
|
return(STATUS_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
NTSTATUS STDCALL
|
||||||
|
NtfsQueryVolumeInformation(PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp)
|
||||||
|
{
|
||||||
|
FS_INFORMATION_CLASS FsInformationClass;
|
||||||
|
PIO_STACK_LOCATION Stack;
|
||||||
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
|
PVOID SystemBuffer;
|
||||||
|
ULONG BufferLength;
|
||||||
|
|
||||||
|
DPRINT("NtfsQueryVolumeInformation() called\n");
|
||||||
|
|
||||||
|
Stack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
FsInformationClass = Stack->Parameters.QueryVolume.FsInformationClass;
|
||||||
|
BufferLength = Stack->Parameters.QueryVolume.Length;
|
||||||
|
SystemBuffer = Irp->AssociatedIrp.SystemBuffer;
|
||||||
|
|
||||||
|
DPRINT("FsInformationClass %d\n", FsInformationClass);
|
||||||
|
DPRINT("SystemBuffer %x\n", SystemBuffer);
|
||||||
|
|
||||||
|
switch (FsInformationClass)
|
||||||
|
{
|
||||||
|
case FileFsVolumeInformation:
|
||||||
|
Status = NtfsGetFsVolumeInformation(DeviceObject,
|
||||||
|
SystemBuffer,
|
||||||
|
&BufferLength);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FileFsAttributeInformation:
|
||||||
|
Status = NtfsGetFsAttributeInformation(DeviceObject->DeviceExtension,
|
||||||
|
SystemBuffer,
|
||||||
|
&BufferLength);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FileFsSizeInformation:
|
||||||
|
Status = NtfsGetFsSizeInformation(DeviceObject,
|
||||||
|
SystemBuffer,
|
||||||
|
&BufferLength);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FileFsDeviceInformation:
|
||||||
|
Status = NtfsGetFsDeviceInformation(SystemBuffer,
|
||||||
|
&BufferLength);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
Status = STATUS_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
Irp->IoStatus.Status = Status;
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
Irp->IoStatus.Information =
|
||||||
|
Stack->Parameters.QueryVolume.Length - BufferLength;
|
||||||
|
else
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
|
||||||
|
return(Status);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
NTSTATUS STDCALL
|
||||||
|
NtfsSetVolumeInformation(PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp)
|
||||||
|
{
|
||||||
|
DPRINT("NtfsSetVolumeInformation() called\n");
|
||||||
|
|
||||||
|
Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
|
||||||
|
return(STATUS_NOT_SUPPORTED);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* EOF */
|
Loading…
Reference in a new issue