dirctl.c

来自「一个类似windows」· C语言 代码 · 共 711 行 · 第 1/2 页

C
711
字号
/*
 *  ReactOS kernel
 *  Copyright (C) 2002,2003 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 21707 2006-04-22 14:06:53Z tretiakov $
 *
 * COPYRIGHT:        See COPYING in the top level directory
 * PROJECT:          ReactOS kernel
 * FILE:             drivers/fs/ntfs/dirctl.c
 * PURPOSE:          NTFS filesystem driver
 * PROGRAMMER:       Eric Kohl
 */

/* INCLUDES *****************************************************************/

#include "ntfs.h"

#define NDEBUG
#include <debug.h>

/* GLOBALS *****************************************************************/


/* 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,

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?