Exemplo n.º 1
0
LOCAL_C void Test2()
//
// Reproduce old bugs
//
	{

	test.Next(_L("Regression Protection"));
	RFile f1,f2;
//
	TInt r=f1.Replace(TheFs,_L("BIGFILE1.TST"),EFileWrite);
	test_KErrNone(r);
	r=f2.Replace(TheFs,_L("BIGFILE2.TST"),EFileWrite);
	test_KErrNone(r);
//
	WriteCluster(f1,0);
	WriteCluster(f1,1);
	WriteCluster(f1,2);
	WriteCluster(f1,3);
	WriteCluster(f1,4);
	WriteCluster(f1,5);
	WriteCluster(f2,0);
	WriteCluster(f1,6);
//
	SeekToCluster(f1,6);
	SeekToCluster(f1,4);
//
	f1.Close();
	f2.Close();
	r=TheFs.Delete(_L("BIGFile1.tst"));
	test_KErrNone(r);
	r=TheFs.Delete(_L("BIGFile2.tst"));
	test_KErrNone(r);
	CheckDisk();
	}
Exemplo n.º 2
0
static NTSTATUS
VfatMarkVolumeDirty(PVFAT_IRP_CONTEXT IrpContext)
{
   ULONG eocMark;
   PDEVICE_EXTENSION DeviceExt;
   NTSTATUS Status = STATUS_SUCCESS;

   DPRINT("VfatMarkVolumeDirty(IrpContext %p)\n", IrpContext);
   DeviceExt = IrpContext->DeviceExt;

   if (!(DeviceExt->VolumeFcb->Flags & VCB_IS_DIRTY))
   {
      Status = GetNextCluster(DeviceExt, 1, &eocMark);
      if (NT_SUCCESS(Status))
      {
         /* unset clean shutdown bit */
         eocMark &= ~DeviceExt->CleanShutBitMask;
         Status = WriteCluster(DeviceExt, 1, eocMark);
      }
   }

   DeviceExt->VolumeFcb->Flags &= ~VCB_CLEAR_DIRTY;

   return Status;
}
Exemplo n.º 3
0
static NTSTATUS
VfatMount (PVFAT_IRP_CONTEXT IrpContext)
/*
 * FUNCTION: Mount the filesystem
 */
{
   PDEVICE_OBJECT DeviceObject = NULL;
   PDEVICE_EXTENSION DeviceExt = NULL;
   BOOLEAN RecognizedFS;
   NTSTATUS Status;
   PVFATFCB Fcb = NULL;
   PVFATFCB VolumeFcb = NULL;
   PVFATCCB Ccb = NULL;
   PDEVICE_OBJECT DeviceToMount;
   PVPB Vpb;
   UNICODE_STRING NameU = RTL_CONSTANT_STRING(L"\\$$Fat$$");
   UNICODE_STRING VolumeNameU = RTL_CONSTANT_STRING(L"\\$$Volume$$");
   ULONG HashTableSize;
   ULONG eocMark;
   FATINFO FatInfo;

   DPRINT("VfatMount(IrpContext %p)\n", IrpContext);

   ASSERT(IrpContext);

   if (IrpContext->DeviceObject != VfatGlobalData->DeviceObject)
   {
      Status = STATUS_INVALID_DEVICE_REQUEST;
      goto ByeBye;
   }

   DeviceToMount = IrpContext->Stack->Parameters.MountVolume.DeviceObject;
   Vpb = IrpContext->Stack->Parameters.MountVolume.Vpb;

   Status = VfatHasFileSystem (DeviceToMount, &RecognizedFS, &FatInfo);
   if (!NT_SUCCESS(Status))
   {
      goto ByeBye;
   }

   if (RecognizedFS == FALSE)
   {
      DPRINT("VFAT: Unrecognized Volume\n");
      Status = STATUS_UNRECOGNIZED_VOLUME;
      goto ByeBye;
   }

   /* Use prime numbers for the table size */
   if (FatInfo.FatType == FAT12)
   {
      HashTableSize = 4099; // 4096 = 4 * 1024
   }
   else if (FatInfo.FatType == FAT16 ||
            FatInfo.FatType == FATX16)
   {
      HashTableSize = 16411; // 16384 = 16 * 1024
   }
   else
   {
      HashTableSize = 65537; // 65536 = 64 * 1024;
   }
   HashTableSize = FCB_HASH_TABLE_SIZE;
   DPRINT("VFAT: Recognized volume\n");
   Status = IoCreateDevice(VfatGlobalData->DriverObject,
                           ROUND_UP(sizeof (DEVICE_EXTENSION), sizeof(ULONG)) + sizeof(HASHENTRY*) * HashTableSize,
                           NULL,
                           FILE_DEVICE_DISK_FILE_SYSTEM,
                           DeviceToMount->Characteristics,
                           FALSE,
                           &DeviceObject);
   if (!NT_SUCCESS(Status))
   {
      goto ByeBye;
   }

   DeviceObject->Flags = DeviceObject->Flags | DO_DIRECT_IO;
   DeviceExt = (PVOID) DeviceObject->DeviceExtension;
   RtlZeroMemory(DeviceExt, ROUND_UP(sizeof(DEVICE_EXTENSION), sizeof(ULONG)) + sizeof(HASHENTRY*) * HashTableSize);
   DeviceExt->FcbHashTable = (HASHENTRY**)((ULONG_PTR)DeviceExt + ROUND_UP(sizeof(DEVICE_EXTENSION), sizeof(ULONG)));
   DeviceExt->HashTableSize = HashTableSize;

   /* use same vpb as device disk */
   DeviceObject->Vpb = Vpb;
   DeviceToMount->Vpb = Vpb;

   Status = VfatMountDevice(DeviceExt, DeviceToMount);
   if (!NT_SUCCESS(Status))
   {
      /* FIXME: delete device object */
      goto ByeBye;
   }

   DPRINT("BytesPerSector:     %d\n", DeviceExt->FatInfo.BytesPerSector);
   DPRINT("SectorsPerCluster:  %d\n", DeviceExt->FatInfo.SectorsPerCluster);
   DPRINT("FATCount:           %d\n", DeviceExt->FatInfo.FATCount);
   DPRINT("FATSectors:         %d\n", DeviceExt->FatInfo.FATSectors);
   DPRINT("RootStart:          %d\n", DeviceExt->FatInfo.rootStart);
   DPRINT("DataStart:          %d\n", DeviceExt->FatInfo.dataStart);
   if (DeviceExt->FatInfo.FatType == FAT32)
   {
      DPRINT("RootCluster:        %d\n", DeviceExt->FatInfo.RootCluster);
   }

   switch (DeviceExt->FatInfo.FatType)
   {
      case FAT12:
         DeviceExt->GetNextCluster = FAT12GetNextCluster;
         DeviceExt->FindAndMarkAvailableCluster = FAT12FindAndMarkAvailableCluster;
         DeviceExt->WriteCluster = FAT12WriteCluster;
         DeviceExt->CleanShutBitMask = 0;
         break;

      case FAT16:
      case FATX16:
         DeviceExt->GetNextCluster = FAT16GetNextCluster;
         DeviceExt->FindAndMarkAvailableCluster = FAT16FindAndMarkAvailableCluster;
         DeviceExt->WriteCluster = FAT16WriteCluster;
         DeviceExt->CleanShutBitMask = 0x8000;
         break;

      case FAT32:
      case FATX32:
         DeviceExt->GetNextCluster = FAT32GetNextCluster;
         DeviceExt->FindAndMarkAvailableCluster = FAT32FindAndMarkAvailableCluster;
         DeviceExt->WriteCluster = FAT32WriteCluster;
         DeviceExt->CleanShutBitMask = 0x80000000;
         break;
   }

   if (DeviceExt->FatInfo.FatType == FATX16
      || DeviceExt->FatInfo.FatType == FATX32)
   {
      DeviceExt->Flags |= VCB_IS_FATX;
      DeviceExt->GetNextDirEntry = FATXGetNextDirEntry;
      DeviceExt->BaseDateYear = 2000;
   }
   else
   {
      DeviceExt->GetNextDirEntry = FATGetNextDirEntry;
      DeviceExt->BaseDateYear = 1980;
   }

   DeviceExt->StorageDevice = DeviceToMount;
   DeviceExt->StorageDevice->Vpb->DeviceObject = DeviceObject;
   DeviceExt->StorageDevice->Vpb->RealDevice = DeviceExt->StorageDevice;
   DeviceExt->StorageDevice->Vpb->Flags |= VPB_MOUNTED;
   DeviceObject->StackSize = DeviceExt->StorageDevice->StackSize + 1;
   DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;

   DPRINT("FsDeviceObject %p\n", DeviceObject);

   /* Initialize this resource early ... it's used in VfatCleanup */
   ExInitializeResourceLite(&DeviceExt->DirResource);

   DeviceExt->FATFileObject = IoCreateStreamFileObject(NULL, DeviceExt->StorageDevice);
   Fcb = vfatNewFCB(DeviceExt, &NameU);
   if (Fcb == NULL)
   {
      Status = STATUS_INSUFFICIENT_RESOURCES;
      goto ByeBye;
   }
   Ccb = ExAllocateFromNPagedLookasideList(&VfatGlobalData->CcbLookasideList);
   if (Ccb == NULL)
   {
      Status =  STATUS_INSUFFICIENT_RESOURCES;
      goto ByeBye;
   }

   RtlZeroMemory(Ccb, sizeof (VFATCCB));
   DeviceExt->FATFileObject->FsContext = Fcb;
   DeviceExt->FATFileObject->FsContext2 = Ccb;
   DeviceExt->FATFileObject->SectionObjectPointer = &Fcb->SectionObjectPointers;
   DeviceExt->FATFileObject->PrivateCacheMap = NULL;
   DeviceExt->FATFileObject->Vpb = DeviceObject->Vpb;
   Fcb->FileObject = DeviceExt->FATFileObject;

   Fcb->Flags |= FCB_IS_FAT;

   Fcb->RFCB.FileSize.QuadPart = DeviceExt->FatInfo.FATSectors * DeviceExt->FatInfo.BytesPerSector;
   Fcb->RFCB.ValidDataLength = Fcb->RFCB.FileSize;
   Fcb->RFCB.AllocationSize = Fcb->RFCB.FileSize;

   CcInitializeCacheMap(DeviceExt->FATFileObject,
                        (PCC_FILE_SIZES)(&Fcb->RFCB.AllocationSize),
                        TRUE,
                        &VfatGlobalData->CacheMgrCallbacks,
                        Fcb);

   DeviceExt->LastAvailableCluster = 2;
   ExInitializeResourceLite(&DeviceExt->FatResource);

   InitializeListHead(&DeviceExt->FcbListHead);

   VolumeFcb = vfatNewFCB(DeviceExt, &VolumeNameU);
   if (VolumeFcb == NULL)
   {
      Status = STATUS_INSUFFICIENT_RESOURCES;
      goto ByeBye;
   }
   VolumeFcb->Flags = FCB_IS_VOLUME;
   VolumeFcb->RFCB.FileSize.QuadPart = DeviceExt->FatInfo.Sectors * DeviceExt->FatInfo.BytesPerSector;
   VolumeFcb->RFCB.ValidDataLength = VolumeFcb->RFCB.FileSize;
   VolumeFcb->RFCB.AllocationSize = VolumeFcb->RFCB.FileSize;
   DeviceExt->VolumeFcb = VolumeFcb;

   ExAcquireResourceExclusiveLite(&VfatGlobalData->VolumeListLock, TRUE);
   InsertHeadList(&VfatGlobalData->VolumeListHead, &DeviceExt->VolumeListEntry);
   ExReleaseResourceLite(&VfatGlobalData->VolumeListLock);

   /* read serial number */
   DeviceObject->Vpb->SerialNumber = DeviceExt->FatInfo.VolumeID;

   /* read volume label */
   ReadVolumeLabel(DeviceExt,  DeviceObject->Vpb);

   /* read clean shutdown bit status */
   Status = GetNextCluster(DeviceExt, 1, &eocMark);
   if (NT_SUCCESS(Status))
   {
      if (eocMark & DeviceExt->CleanShutBitMask)
      {
         /* unset clean shutdown bit */
         eocMark &= ~DeviceExt->CleanShutBitMask;
         WriteCluster(DeviceExt, 1, eocMark);
         VolumeFcb->Flags |= VCB_CLEAR_DIRTY;
      }
   }
   VolumeFcb->Flags |= VCB_IS_DIRTY;

   FsRtlNotifyVolumeEvent(DeviceExt->FATFileObject, FSRTL_VOLUME_MOUNT);

   Status = STATUS_SUCCESS;
ByeBye:

  if (!NT_SUCCESS(Status))
  {
     // cleanup
     if (DeviceExt && DeviceExt->FATFileObject)
        ObDereferenceObject (DeviceExt->FATFileObject);
     if (Fcb)
        vfatDestroyFCB(Fcb);
     if (Ccb)
        vfatDestroyCCB(Ccb);
     if (DeviceObject)
       IoDeleteDevice(DeviceObject);
     if (VolumeFcb)
        vfatDestroyFCB(VolumeFcb);
  }
  return Status;
}
Exemplo n.º 4
0
LOCAL_C void Test1()
//
// Test openning a large file
//
	{

	test.Next(_L("Create interleaved files"));
	RFile f1,f2;
//
	TInt r=f1.Replace(TheFs,_L("BIGFILE1.TST"),EFileWrite);
	test_KErrNone(r);
	r=f2.Replace(TheFs,_L("BIGFILE2.TST"),EFileWrite);
	test_KErrNone(r);
//
	TInt maxListLength=4;
	TInt i=0,k=0;
	TInt countf1=0;
	TInt countf2=0;
	for (k=0;k<maxListLength;k++)
		{
		for (i=0;i<maxListLength;i++)
			{
			TInt j;
			for (j=0;j<=i;j++)
				WriteCluster(f1,countf1++);
			for (j=0;j<=k;j++)
				WriteCluster(f2,countf2++);
			test.Printf(_L("Written %d to file1 %d to file2\n"),i+1,k+1);
			}
		}

	ExhaustiveTest(f1,countf1);
	ExhaustiveTest(f2,countf2);

	SeekToCluster(f1,1,10);
	SeekToCluster(f1,6,3);
	SeekToCluster(f1,8,4);
	SeekToCluster(f1,12,3);
	SeekToCluster(f1,23,32);
	SeekToCluster(f1,5,8);
	SeekToCluster(f1,7,9);
	SeekToCluster(f1,12,1);
	SeekToCluster(f1,2,32);
	SeekToCluster(f1,16,8);
	SeekToCluster(f1,9,5);
	SeekToCluster(f1,33,6);
	SeekToCluster(f1,13,7);
	SeekToCluster(f1,9,17);
	SeekToCluster(f1,4,5);
	SeekToCluster(f1,5,31);
	SeekToCluster(f1,11,10);
	SeekToCluster(f1,1,2);
	SeekToCluster(f1,5,5);

	f1.Close();
	f2.Close();
	r=TheFs.Delete(_L("BIGFile1.tst"));
	test_KErrNone(r);
	r=TheFs.Delete(_L("BIGFile2.tst"));
	test_KErrNone(r);
	CheckDisk();
	}
Exemplo n.º 5
0
LOCAL_C void Test3()
//
// Change file size while seeking
//
	{

	test.Next(_L("Alter filesize"));
	RFile f1;
	TheSeed=917824;
	TInt i=0,j=0;
//
	TInt r=f1.Replace(TheFs,_L("BIGFILE1.TST"),EFileWrite);
	test_KErrNone(r);
	
	r=f1.SetSize(65534);
	test_KErrNone(r);

	for(i=0;i<=15;i++)
		WriteCluster(f1,i);

	for (j=0;j<100;j++)
		{
		TInt cluster1=Math::Rand(TheSeed)%15;
		TInt cluster2=Math::Rand(TheSeed)%15;
		SeekToCluster(f1,cluster2,cluster1);
		}

	test.Next(_L("Increase Size"));
	r=f1.SetSize(1048577);
	test_Value(r, r == KErrNone || r==KErrDiskFull);
	if (r==KErrDiskFull)
		{
		test.Printf(_L("File too big\n"));
		f1.Close();
		return;
		}

	test.Next(_L("Test data still present"));
	for (j=0;j<200;j++)
		{
		TInt cluster1=Math::Rand(TheSeed)%15;
		TInt cluster2=Math::Rand(TheSeed)%15;
		SeekToCluster(f1,cluster2,cluster1);
		}

	TInt newPos=8192;
	r=f1.Seek(ESeekStart,newPos);
	test_KErrNone(r);

	test.Next(_L("Write more data"));
	for(i=16;i<83;i++)
		WriteCluster(f1,i);

	test.Next(_L("Seek to new data"));
	for (j=0;j<200;j++)
		{
		TInt cluster1=Math::Rand(TheSeed)%83;
		TInt cluster2=Math::Rand(TheSeed)%83;
		SeekToCluster(f1,cluster2,cluster1);
		}

	test.Next(_L("Reduce file size"));
	r=f1.SetSize(135000);
	test_KErrNone(r);

	test.Next(_L("Test data still present"));
	for (j=0;j<200;j++)
		{
		TInt cluster1=Math::Rand(TheSeed)%31;
		TInt cluster2=Math::Rand(TheSeed)%31;
		SeekToCluster(f1,cluster2,cluster1);
		}

	f1.Close();
	}
Exemplo n.º 6
0
USHORT usWriteEAS(PVOLINFO pVolInfo, ULONG ulDirCluster, PSZ pszFileName, PFEALIST pFEAL)
{
    ULONG ulCluster, ulNextCluster;
    PBYTE  pszEAName;
    PBYTE pWrite;
    USHORT rc;
    USHORT usClustersNeeded;
    DIRENTRY DirEntry;
    DIRENTRY DirNew;
    BOOL     fCritical;
    PFEA     pFea, pFeaEnd;

    if (pFEAL->cbList > MAX_EA_SIZE)
        return ERROR_EA_LIST_TOO_LONG;

    rc = GetEASName(pVolInfo, ulDirCluster, pszFileName, &pszEAName);
    if (rc)
        return rc;

    usClustersNeeded = (USHORT)pFEAL->cbList / pVolInfo->usClusterSize;
    if (pFEAL->cbList % pVolInfo->usClusterSize)
        usClustersNeeded++;

    ulCluster = FindPathCluster(pVolInfo, ulDirCluster, pszEAName, &DirEntry, NULL);
    if (!ulCluster || ulCluster == FAT_EOF)
    {
        BOOL fNew = FALSE;

        if (ulCluster == FAT_EOF)
        {
            fNew = TRUE;
            memset(&DirNew, 0, sizeof DirNew);
            DirNew.bAttr  = FILE_HIDDEN | FILE_SYSTEM | FILE_READONLY;
            DirNew.ulFileSize = pFEAL->cbList;
        }
        else
            memcpy(&DirNew, &DirEntry, sizeof DirEntry);

        ulCluster = MakeFatChain(pVolInfo, FAT_EOF, (ULONG)usClustersNeeded, NULL);
        if (ulCluster == FAT_EOF)
        {
            free(pszEAName);
            return ERROR_DISK_FULL;
        }

        DirNew.wCluster = LOUSHORT(ulCluster);
        DirNew.wClusterHigh = HIUSHORT(ulCluster);

        if (fNew)
            rc = MakeDirEntry(pVolInfo, ulDirCluster, &DirNew, pszEAName);
        else
            rc = ModifyDirectory(pVolInfo, ulDirCluster,
                                 MODIFY_DIR_UPDATE, &DirEntry, &DirNew, NULL, 0);
        if (rc)
        {
            free(pszEAName);
            return rc;
        }
    }
    else
    {
        memcpy(&DirNew, &DirEntry, sizeof (DIRENTRY));
        DirNew.ulFileSize = pFEAL->cbList;
        rc = ModifyDirectory(pVolInfo, ulDirCluster, MODIFY_DIR_UPDATE,
                             &DirEntry, &DirNew, NULL, 0);
        if (rc)
        {
            free(pszEAName);
            return rc;
        }
    }

    free(pszEAName);

    pWrite = (PBYTE)pFEAL;
    ulNextCluster = FAT_EOF;
    while (usClustersNeeded)
    {
        ulNextCluster = GetNextCluster(pVolInfo, ulCluster);
        if (!ulNextCluster)
            ulNextCluster = FAT_EOF;
        rc = WriteCluster(pVolInfo, ulCluster, pWrite, 0);
        if (rc)
            return rc;
        usClustersNeeded --;
        pWrite += pVolInfo->usClusterSize;

        if (usClustersNeeded)
        {
            if (ulNextCluster == FAT_EOF)
                ulCluster = MakeFatChain(pVolInfo, ulCluster, (ULONG)usClustersNeeded, NULL);
            else
                ulCluster = ulNextCluster;
            if (ulCluster == FAT_EOF)
                return ERROR_DISK_FULL;
        }
    }
    if (ulNextCluster != FAT_EOF)
    {
        SetNextCluster(pVolInfo, ulCluster, FAT_EOF);
        DeleteFatChain(pVolInfo, ulNextCluster);
    }

    pFea = pFEAL->list;
    pFeaEnd = (PFEA)((PBYTE)pFEAL + pFEAL->cbList);
    fCritical = FALSE;
    while (pFea < pFeaEnd)
    {
        if (pFea->fEA & FEA_NEEDEA)
            fCritical = TRUE;
        pFea = (PFEA)((PBYTE)pFea + sizeof (FEA) + (USHORT)pFea->cbName + 1 + pFea->cbValue);
    }


    if (fCritical)
        rc = MarkFileEAS(pVolInfo, ulDirCluster, pszFileName, FILE_HAS_CRITICAL_EAS);
    else
        rc = MarkFileEAS(pVolInfo, ulDirCluster, pszFileName, FILE_HAS_EAS);

    return rc;
}
Exemplo n.º 7
0
NTSTATUS NTAPI
VfatShutdown(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
   NTSTATUS Status;
   PLIST_ENTRY ListEntry;
   PDEVICE_EXTENSION DeviceExt;
   ULONG eocMark;

   DPRINT("VfatShutdown(DeviceObject %p, Irp %p)\n",DeviceObject, Irp);

   FsRtlEnterFileSystem();

   /* FIXME: block new mount requests */

   if (DeviceObject == VfatGlobalData->DeviceObject)
   {
      Irp->IoStatus.Status = STATUS_SUCCESS;
      ExAcquireResourceExclusiveLite(&VfatGlobalData->VolumeListLock, TRUE);
      ListEntry = VfatGlobalData->VolumeListHead.Flink;
      while (ListEntry != &VfatGlobalData->VolumeListHead)
      {
         DeviceExt = CONTAINING_RECORD(ListEntry, VCB, VolumeListEntry);
         ListEntry = ListEntry->Flink;

	 ExAcquireResourceExclusiveLite(&DeviceExt->DirResource, TRUE);
         if (DeviceExt->VolumeFcb->Flags & VCB_CLEAR_DIRTY)
         {
            /* set clean shutdown bit */
            Status = GetNextCluster(DeviceExt, 1, &eocMark);
            if (NT_SUCCESS(Status))
            {
               eocMark |= DeviceExt->CleanShutBitMask;
               if (NT_SUCCESS(WriteCluster(DeviceExt, 1, eocMark)))
                  DeviceExt->VolumeFcb->Flags &= ~VCB_IS_DIRTY;
            }
         }
         Status = VfatFlushVolume(DeviceExt, DeviceExt->VolumeFcb);
         if (NT_SUCCESS(Status))
         {
            Status = VfatDiskShutDown(DeviceExt);
            if (!NT_SUCCESS(Status))
	       DPRINT1("VfatDiskShutDown failed, status = %x\n", Status);
         }
         else
         {
	    DPRINT1("VfatFlushVolume failed, status = %x\n", Status);
	 }
         ExReleaseResourceLite(&DeviceExt->DirResource);

         /* FIXME: Unmount the logical volume */

         if (!NT_SUCCESS(Status))
            Irp->IoStatus.Status = Status;
      }
      ExReleaseResourceLite(&VfatGlobalData->VolumeListLock);

      /* FIXME: Free all global acquired resources */

      Status = Irp->IoStatus.Status;
   }
   else
   {
      Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
      Status = STATUS_INVALID_DEVICE_REQUEST;
   }

   Irp->IoStatus.Information = 0;
   IoCompleteRequest(Irp, IO_NO_INCREMENT);

   FsRtlExitFileSystem();

   return(Status);
}
Exemplo n.º 8
0
static
NTSTATUS
VfatDismountVolume(
    PVFAT_IRP_CONTEXT IrpContext)
{
    PDEVICE_EXTENSION DeviceExt;
    PLIST_ENTRY NextEntry;
    PVFATFCB Fcb;
    PFILE_OBJECT FileObject;
    ULONG eocMark;
    NTSTATUS Status;

    DPRINT("VfatDismountVolume(%p)\n", IrpContext);

    DeviceExt = IrpContext->DeviceExt;
    FileObject = IrpContext->FileObject;

    /* We HAVE to be locked. Windows also allows dismount with no lock
     * but we're here mainly for 1st stage, so KISS
     */
    if (!(DeviceExt->Flags & VCB_VOLUME_LOCKED))
    {
        return STATUS_ACCESS_DENIED;
    }

    /* Race condition? */
    if (DeviceExt->Flags & VCB_DISMOUNT_PENDING)
    {
        return STATUS_VOLUME_DISMOUNTED;
    }

    /* Notify we'll dismount. Pass that point there's no reason we fail */
    FsRtlNotifyVolumeEvent(IrpContext->Stack->FileObject, FSRTL_VOLUME_DISMOUNT);

    ExAcquireResourceExclusiveLite(&DeviceExt->FatResource, TRUE);

    if (DeviceExt->VolumeFcb->Flags & VCB_CLEAR_DIRTY)
    {
        /* Set clean shutdown bit */
        Status = GetNextCluster(DeviceExt, 1, &eocMark);
        if (NT_SUCCESS(Status))
        {
            eocMark |= DeviceExt->CleanShutBitMask;
            if (NT_SUCCESS(WriteCluster(DeviceExt, 1, eocMark)))
                DeviceExt->VolumeFcb->Flags &= ~VCB_IS_DIRTY;
        }
    }

    /* Flush volume & files */
    VfatFlushVolume(DeviceExt, (PVFATFCB)FileObject->FsContext);

    /* Rebrowse the FCB in order to free them now */
    while (!IsListEmpty(&DeviceExt->FcbListHead))
    {
        NextEntry = RemoveHeadList(&DeviceExt->FcbListHead);
        Fcb = CONTAINING_RECORD(NextEntry, VFATFCB, FcbListEntry);
        vfatDestroyFCB(Fcb);
    }

    /* Mark we're being dismounted */
    DeviceExt->Flags |= VCB_DISMOUNT_PENDING;
#ifndef ENABLE_SWAPOUT
    IrpContext->DeviceObject->Vpb->Flags &= ~VPB_MOUNTED;
#endif

    ExReleaseResourceLite(&DeviceExt->FatResource);

    /* Release a few resources and quit, we're done */
    ExDeleteResourceLite(&DeviceExt->DirResource);
    ExDeleteResourceLite(&DeviceExt->FatResource);
    ObDereferenceObject(DeviceExt->FATFileObject);

    return STATUS_SUCCESS;
}
Exemplo n.º 9
0
exp bool CopyIn(const char* source, const char* dest) {
    DirectoryEntry* entry = 0;
    char* buffer = new char[bpb->bytesPerSector];

    // Open file we're copying in
    std::ifstream inHandle(source, std::ios::in | std::ios::binary | std::ios::ate);
    if (!inHandle.is_open()) {
        LastError("CopyIn", "Failed to open source file");
        return false;
    }

    // Get size of source file
    size_t inLength = (size_t)inHandle.tellg();
    inHandle.seekg(std::ios::beg);

    // Convert the filename into DOS8.3 format
    char* dosName = new char[12];
    ToDos83Name(dest, dosName);

    // Check if entry exists, if so, overwrite it
    entry = FindEntry(dosName, &directory);
    if (entry) {
        // Delete file
        Delete(dest);

        // Undelete entry
        entry->name[0] = dosName[0];
    }

    // Create the directory entry
    if (!entry) {
        // Didn't delete file, make it
        entry = MakeEntry(dosName, ATTRIB_ARCHIVE, inLength, &directory);
        if (!entry) {
            LastError("CopyIn", "Failed to create directory entry");
            delete[] dosName;
            delete[] buffer;
            return false;
        }
    }
    else {
        // Deleted file, find it
        entry = FindEntry(dosName, &directory);
        if (!entry) {
            LastError("CopyIn", "Somehow a file that was just undeleted can't be found...");
            delete[] dosName;
            delete[] buffer;
            return false;
        }

        UpdateEntry(entry, 0, inLength);
    }

    // Write entry to disk
    DirectoryWrite(&directory);

    // Update FAT and then load each cluster and write it while updating the FAT
    FatEntry fatEntry;
    fatEntry.buffer = new char[bpb->bytesPerSector];
    fatEntry.cluster = GetClusterFromEntry(entry);
    fatEntry.sector = GetFATSector(fatEntry.cluster);
    ReadSector(fatEntry.buffer, fatEntry.sector);

    UpdateFAT(&fatEntry, FindFreeCluster());

    // Write to disk
    for (size_t i = 0; i < inLength; i += bpb->bytesPerSector) {
        memset(buffer, 0, bpb->bytesPerSector);
        if (!(i % bpb->bytesPerSector))
            inHandle.read(buffer, bpb->bytesPerSector);
        else
            inHandle.read(buffer, i % bpb->bytesPerSector);

        WriteCluster(&fatEntry, buffer);
    }

    delete[] dosName;
    delete[] buffer;
    delete[] fatEntry.buffer;

    inHandle.close();

    return true;
}