fcb.c

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

C
687
字号
}


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 (!NtfsFCBIsRoot(DirectoryFCB))
    {
      wcscat(pathName, L"\\");
    }

  if (Name[0] != 0)
    {
      wcscat(pathName, Name);
    }
  else
    {
      WCHAR entryName[MAX_PATH];

      NtfsGetDirEntryName(Vcb, Record, entryName);
      wcscat(pathName, entryName);
    }

  rcFCB = NtfsCreateFCB(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);
  NtfsFCBInitializeCache(Vcb, rcFCB);
  rcFCB->RefCount++;
  NtfsAddFCBToTable(Vcb, rcFCB);
  *fileFCB = rcFCB;

  return(STATUS_SUCCESS);
}
#endif


NTSTATUS
NtfsAttachFCBToFileObject(PDEVICE_EXTENSION Vcb,
			  PFCB Fcb,
			  PFILE_OBJECT FileObject)
{
  PCCB  newCCB;

  newCCB = ExAllocatePoolWithTag(NonPagedPool, sizeof(CCB), TAG_CCB);
  if (newCCB == NULL)
    {
      return(STATUS_INSUFFICIENT_RESOURCES);
    }
  memset(newCCB, 0, sizeof(CCB));

  FileObject->SectionObjectPointer = &Fcb->SectionObjectPointers;
  FileObject->FsContext = Fcb;
  FileObject->FsContext2 = newCCB;
  newCCB->PtrFileObject = FileObject;
  Fcb->DevExt = Vcb;

  if (!(Fcb->Flags & FCB_CACHE_INITIALIZED))
    {
#ifdef ROS_USE_CC_AND_FS
      NTSTATUS Status;
      Status = CcRosInitializeFileCache(FileObject,
					CACHEPAGESIZE(Vcb));
      if (!NT_SUCCESS(Status))
	{
	  DbgPrint("CcRosInitializeFileCache failed\n");
	  KEBUGCHECK(0);
	}
#else
  CcInitializeCacheMap(FileObject,
                       (PCC_FILE_SIZES)(&Fcb->RFCB.AllocationSize),
                       FALSE,
                       NULL,
                       NULL);
#endif
      Fcb->Flags |= FCB_CACHE_INITIALIZED;
    }

  //DPRINT("file open: fcb:%x file size: %d\n", Fcb, Fcb->Entry.DataLengthL);

  return(STATUS_SUCCESS);
}


static NTSTATUS
NtfsDirFindFile(PDEVICE_EXTENSION DeviceExt,
		PFCB DirectoryFcb,
		PWSTR FileToFind,
		PFCB *FoundFCB)
{
#if 0
  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("NtfsDirFindFile(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);

      NtfsGetDirEntryName(DeviceExt, Record, Name);
      DPRINT("Name '%S'\n", Name);

      if (wstrcmpjoki(Name, FileToFind))
	{
	  DPRINT("Match found, %S\n", Name);
	  Status = NtfsMakeFCBFromDirEntry(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);
#endif
  return(STATUS_OBJECT_NAME_NOT_FOUND);
}


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 1
  /* 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 = NtfsOpenRootFCB (Vcb);
    }
  parentFCB = NULL;

  /* Parse filename and check each path element for existance and access */
  while (NtfsGetNextPathElement(currentElement) != 0)
    {
      /*  Skip blank directory levels */
      if ((NtfsGetNextPathElement(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)
	{
	  NtfsReleaseFCB(Vcb, parentFCB);
	  parentFCB = NULL;
	}

      /* fail if element in FCB is not a directory */
      if (!NtfsFCBIsDirectory(FCB))
	{
	  DPRINT("Element in requested path is not a directory\n");

	  NtfsReleaseFCB(Vcb, FCB);
	  FCB = 0;
	  *pParentFCB = NULL;
	  *pFCB = NULL;

	  return(STATUS_OBJECT_PATH_NOT_FOUND);
	}
      parentFCB = FCB;

      /* Extract next directory level into dirName */
      NtfsWSubString(pathName,
		     pFileName,
		     NtfsGetNextPathElement(currentElement) - pFileName);
      DPRINT("  pathName:%S\n", pathName);

      FCB = NtfsGrabFCBFromTable(Vcb, pathName);
      if (FCB == NULL)
	{
	  NtfsWSubString(elementName,
			 currentElement,
			 NtfsGetNextPathElement(currentElement) - currentElement);
	  DPRINT("  elementName:%S\n", elementName);

	  Status = NtfsDirFindFile(Vcb, parentFCB, elementName, &FCB);
	  if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
	    {
	      *pParentFCB = parentFCB;
	      *pFCB = NULL;
	      currentElement = NtfsGetNextPathElement(currentElement);
	      if (*currentElement == L'\0' || NtfsGetNextPathElement(currentElement + 1) == 0)
		{
		  return(STATUS_OBJECT_NAME_NOT_FOUND);
		}
	      else
		{
		  return(STATUS_OBJECT_PATH_NOT_FOUND);
		}
	    }
	  else if (!NT_SUCCESS(Status))
	    {
	      NtfsReleaseFCB(Vcb, parentFCB);
	      *pParentFCB = NULL;
	      *pFCB = NULL;

	      return(Status);
	    }
	}
      currentElement = NtfsGetNextPathElement(currentElement);
    }

  *pParentFCB = parentFCB;
  *pFCB = FCB;
#endif

  return(STATUS_SUCCESS);
}

/* EOF */

⌨️ 快捷键说明

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