winntsimplefilesystem.c

来自「Next BIOS Source code : Extensible Firmw」· C语言 代码 · 共 1,315 行 · 第 1/3 页

C
1,315
字号
	  Status = gBS->AllocatePool(
                    EfiBootServicesData,
									  EfiStrSize(PrivateFile->FilePath) + EfiStrSize(L"\\*"),
                    &SearchPath
                    );
    if (EFI_ERROR (Status)) {
      return Status;
    }

    EfiStrCpy(SearchPath, PrivateFile->FilePath);
    EfiStrCat(SearchPath,L"\\*");
    PrivateFile->LHandle = PrivateFile->WinNtThunk->FindFirstFile (
                                                      SearchPath,
                                                      &FBuf
                                                      );

    gBS->FreePool(SearchPath);
    
    Status = PrivateFile->LHandle == INVALID_HANDLE_VALUE ? EFI_DEVICE_ERROR : EFI_SUCCESS;

  } else {

    PositionHigh = 0;
    *Position = PrivateFile->WinNtThunk->SetFilePointer(
                                           PrivateFile->LHandle, 
                                           0, 
                                           &PositionHigh, 
                                           FILE_CURRENT
                                           );

    Status = *Position == 0xffffffff ? EFI_DEVICE_ERROR : EFI_SUCCESS;
    if ( EFI_ERROR(Status) ) {
      goto Done;
    }
    PosHigh64 = PositionHigh;
    *Position += DriverLibLShiftU64(PosHigh64,32);
  }

Done:
  return Status;
}

static
EFI_STATUS
WinNtSimpleFileSystemFileInfo (
  IN     WIN_NT_EFI_FILE_PRIVATE  *PrivateFile,
  IN OUT UINTN                    *BufferSize, 
  OUT    VOID                     *Buffer    
  )
/*++

Routine Description:

Arguments:

Returns:

  None

--*/
{
  EFI_STATUS                 Status;
  UINTN                      Size;
  UINTN                      NameSize;
  UINTN                      ResultSize;
  EFI_FILE_INFO              *Info;
  BY_HANDLE_FILE_INFORMATION FileInfo;
  SYSTEMTIME                 SystemTime;

  Size = SIZE_OF_EFI_FILE_INFO;
  NameSize = EfiStrSize (PrivateFile->FileName);
  ResultSize = Size + NameSize;

  Status = EFI_BUFFER_TOO_SMALL;
  if (*BufferSize >= ResultSize) {
    Status = EFI_SUCCESS;

    Info = Buffer;
    EfiZeroMem (Info, ResultSize);

    Info->Size = ResultSize;
    PrivateFile->WinNtThunk->GetFileInformationByHandle(PrivateFile->LHandle, &FileInfo);
    Info->FileSize = FileInfo.nFileSizeLow;
    Info->PhysicalSize = Info->FileSize;

    PrivateFile->WinNtThunk->FileTimeToSystemTime(&FileInfo.ftCreationTime, &SystemTime);
    Info->CreateTime.Year    = SystemTime.wYear;
    Info->CreateTime.Month   = (UINT8)SystemTime.wMonth;
    Info->CreateTime.Day     = (UINT8)SystemTime.wDay;
    Info->CreateTime.Hour    = (UINT8)SystemTime.wHour;
    Info->CreateTime.Minute  = (UINT8)SystemTime.wMinute;
    Info->CreateTime.Second  = (UINT8)SystemTime.wSecond;

    PrivateFile->WinNtThunk->FileTimeToSystemTime(&FileInfo.ftLastAccessTime, &SystemTime);
    Info->LastAccessTime.Year    = SystemTime.wYear;
    Info->LastAccessTime.Month   = (UINT8)SystemTime.wMonth;
    Info->LastAccessTime.Day     = (UINT8)SystemTime.wDay;
    Info->LastAccessTime.Hour    = (UINT8)SystemTime.wHour;
    Info->LastAccessTime.Minute  = (UINT8)SystemTime.wMinute;
    Info->LastAccessTime.Second  = (UINT8)SystemTime.wSecond;

    PrivateFile->WinNtThunk->FileTimeToSystemTime(&FileInfo.ftLastWriteTime, &SystemTime);
    Info->ModificationTime.Year    = SystemTime.wYear;
    Info->ModificationTime.Month   = (UINT8)SystemTime.wMonth;
    Info->ModificationTime.Day     = (UINT8)SystemTime.wDay;
    Info->ModificationTime.Hour    = (UINT8)SystemTime.wHour;
    Info->ModificationTime.Minute  = (UINT8)SystemTime.wMinute;
    Info->ModificationTime.Second  = (UINT8)SystemTime.wSecond;

    if (FileInfo.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) {
      Info->Attribute |= EFI_FILE_ARCHIVE;
    }
    if (FileInfo.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) {
      Info->Attribute |= EFI_FILE_HIDDEN;
    }
    if (FileInfo.dwFileAttributes & FILE_ATTRIBUTE_READONLY) {
      Info->Attribute |= EFI_FILE_READ_ONLY;
    }
    if (FileInfo.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) {
      Info->Attribute |= EFI_FILE_SYSTEM;
    }
    if (FileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
      Info->Attribute |= EFI_FILE_DIRECTORY;
    }

    if (PrivateFile->IsDirectoryPath) {
      Info->Attribute |= EFI_FILE_DIRECTORY;
    }

    EfiCopyMem ((CHAR8 *) Buffer + Size, PrivateFile->FileName, NameSize);
  }

  *BufferSize = ResultSize;
  return Status;
}

EFI_STATUS
WinNtSimpleFileSystemGetInfo (
  IN     EFI_FILE  *This,
  IN     EFI_GUID  *InformationType,
  IN OUT UINTN     *BufferSize,
  OUT    VOID      *Buffer
  )
/*++

Routine Description:

Arguments:

Returns:

  None

--*/
{
  EFI_STATUS               Status;
  WIN_NT_EFI_FILE_PRIVATE  *PrivateFile;
  EFI_FILE_SYSTEM_INFO     *FileSystemInfoBuffer;
  UINT32                   SectorsPerCluster;
  UINT32                   BytesPerSector;
  UINT32                   FreeClusters;
  UINT32                   TotalClusters;
  UINT32                   BytesPerCluster;
  CHAR16                   *DriveName;
  BOOLEAN                  DriveNameFound;
  BOOL                     NtStatus;
  UINTN                    Index;
  
  PrivateFile =  WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);

  Status = EFI_UNSUPPORTED;
  if (EfiCompareGuid (InformationType, &gEfiFileInfoGuid)) {
    Status = WinNtSimpleFileSystemFileInfo (PrivateFile, BufferSize, Buffer);
  }
  if (EfiCompareGuid (InformationType, &gEfiFileInfoIdGuid)) {
    if (*BufferSize < SIZE_OF_EFI_FILE_SYSTEM_INFO + sizeof(L"EFI_EMULATED")) {
      return EFI_BUFFER_TOO_SMALL;
    }
    FileSystemInfoBuffer = (EFI_FILE_SYSTEM_INFO *)Buffer;
    FileSystemInfoBuffer->Size        = SIZE_OF_EFI_FILE_SYSTEM_INFO + sizeof("EFI_EMULATED");
    FileSystemInfoBuffer->ReadOnly    = FALSE;
    
    //
    // Try to get the drive name
    //

    DriveName = NULL;
    DriveNameFound = FALSE;
    Status = gBS->AllocatePool(
                    EfiBootServicesData,
  									EfiStrSize(PrivateFile->FilePath) + 1,
                    &DriveName
                    );
    if (EFI_ERROR (Status)) {
      return Status;
    }  
    EfiStrCpy (DriveName, PrivateFile->FilePath);    
    for (Index = 0; DriveName[Index] != 0 && DriveName[Index] != ':'; Index ++) {
      ;
    }    
    if (DriveName [Index] == ':') {
      DriveName[Index + 1] = '\\';
      DriveName[Index + 2] = 0;      
      DriveNameFound = TRUE;
    } else if (DriveName[0] == '\\' && DriveName[1] == '\\') {
      for (Index = 2; DriveName[Index] != 0 && DriveName[Index] != '\\'; Index ++) {
        ;
      }
      if (DriveName[Index] == '\\') {
        DriveNameFound = TRUE;
        for (Index++; DriveName[Index] != 0 && DriveName[Index] != '\\'; Index ++) {
          ;
        }
        DriveName[Index] = '\\';
        DriveName[Index + 1] = 0;
      }              
    }    
    
    //
    // Try GetDiskFreeSpace first
    //

    NtStatus = PrivateFile->WinNtThunk->GetDiskFreeSpace (
                               DriveNameFound ? DriveName : NULL,                               
                               &SectorsPerCluster,
                               &BytesPerSector,
                               &FreeClusters,
                               &TotalClusters
                               );
    if (DriveName) {
      gBS->FreePool (DriveName);
    }
    
    if (NtStatus) {
      
      //
      // Succeeded
      //

      BytesPerCluster = BytesPerSector * SectorsPerCluster;
      FileSystemInfoBuffer->VolumeSize  = DriverLibMultU64x32 (TotalClusters, BytesPerCluster);
      FileSystemInfoBuffer->FreeSpace   = DriverLibMultU64x32 (FreeClusters, BytesPerCluster);
      FileSystemInfoBuffer->BlockSize   = BytesPerCluster;

    } else {
  
    
      //
      // try GetDiskFreeSpaceEx then
      //
      
      FileSystemInfoBuffer->BlockSize = 0;
      NtStatus = PrivateFile->WinNtThunk->GetDiskFreeSpaceEx (
                                            PrivateFile->FilePath,
                                            (PULARGE_INTEGER)(&FileSystemInfoBuffer->FreeSpace),
                                            (PULARGE_INTEGER)(&FileSystemInfoBuffer->VolumeSize),
                                            NULL
                                            );
      if (!NtStatus)  {
        return EFI_DEVICE_ERROR;
      }
    }
  
    EfiStrCpy((CHAR16 *)FileSystemInfoBuffer->VolumeLabel,L"EFI_EMULATED");
    *BufferSize = SIZE_OF_EFI_FILE_SYSTEM_INFO + sizeof(L"EFI_EMULATED");
    Status = EFI_SUCCESS;
  }
  if (EfiCompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid)) {
    if (*BufferSize < sizeof(L"EFI_EMULATED")) {
      return EFI_BUFFER_TOO_SMALL;
    }
    EfiStrCpy((CHAR16 *)Buffer,L"EFI_EMULATED");
    *BufferSize = sizeof(L"EFI_EMULATED");
    Status = EFI_SUCCESS;
  }

  return Status;
}

EFI_STATUS
WinNtSimpleFileSystemSetInfo (
  IN EFI_FILE  *This,
  IN EFI_GUID         *InformationType,
  IN UINTN            BufferSize,
  IN VOID             *Buffer
  )
/*++

Routine Description:

Arguments:

Returns:

  None

--*/
{
  EFI_STATUS               Status;
  WIN_NT_EFI_FILE_PRIVATE  *PrivateFile;
  EFI_FILE_INFO            *Info;
  UINT64                   CurPos;
  WCHAR                    OriginalFileName[256];
  WCHAR                    NewFileName[256];
  BOOL                     NtStatus;
  UINTN                    Index;

  PrivateFile = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);

  //
  //  We only support GenericFileInfo.FileSize for regular files on NT for now
  //

  Status = EFI_UNSUPPORTED;
  if (PrivateFile->IsDirectoryPath) {
    goto Done;
  }
  
  if ( EfiCompareGuid( InformationType, &gEfiFileInfoGuid ) ) {

      Info = Buffer;

      for (Index = 1; Info->FileName[Index]; Index++) {
        if (Info->FileName[Index] == '\\') {
          goto Done;
        }
      }

      Status = EFI_SUCCESS;
      //
      // Set the New File Name
      //
      
      PrivateFile->WinNtThunk->CloseHandle (PrivateFile->LHandle);
      
      EfiStrCpy (OriginalFileName, PrivateFile->FilePath);
      EfiStrCat (OriginalFileName, L"\\");
      EfiStrCat (OriginalFileName, PrivateFile->FileName);

      EfiStrCpy (NewFileName, PrivateFile->FilePath);
      EfiStrCat (NewFileName, L"\\");
      if (Info->FileName[0] == '\\') {
        EfiStrCat (NewFileName, &(Info->FileName[1]));
      } else {
        EfiStrCat (NewFileName, Info->FileName);
      }

      NtStatus = PrivateFile->WinNtThunk->MoveFile (OriginalFileName, NewFileName);
      if (!NtStatus) {
        Status = EFI_ACCESS_DENIED;
        goto Done;
      }     
      
      gBS->FreePool (PrivateFile->FileName);

      Status = gBS->AllocatePool(
                      EfiBootServicesData,
									    EfiStrSize(Info->FileName),
                      &PrivateFile->FileName
                      );
      if (EFI_ERROR (Status)) {
        goto Done;
      }
      EfiStrCpy (PrivateFile->FileName, Info->FileName);

      PrivateFile->LHandle = PrivateFile->WinNtThunk->CreateFile (
                                                          NewFileName,
                                                          GENERIC_READ | GENERIC_WRITE,
                                                          FILE_SHARE_READ | FILE_SHARE_WRITE,
                                                          NULL,
                                                          OPEN_EXISTING,
                                                          0,
                                                          NULL
                                                          );

      if (PrivateFile->LHandle == INVALID_HANDLE_VALUE) {
        Status = EFI_DEVICE_ERROR;
        goto Done;
      }

      //
      //  Flush buffers just in case
      //
      if ( PrivateFile->WinNtThunk->FlushFileBuffers( PrivateFile->LHandle ) == 0 ) {
        Status = EFI_DEVICE_ERROR;
        goto Done;
      }

      //
      //  Set the file size
      //
      Status = This->GetPosition( This, &CurPos );
      if ( EFI_ERROR(Status) ) {
        goto Done;
      }

      Status = This->SetPosition( This, Info->FileSize );
      if ( EFI_ERROR(Status) ) {
        goto Done;
      }

      if ( PrivateFile->WinNtThunk->SetEndOfFile( PrivateFile->LHandle ) == 0 ) {
        Status = EFI_DEVICE_ERROR;
        goto Done;
      }

      Status = This->SetPosition( This, CurPos );
      if ( EFI_ERROR(Status) ) {
        goto Done;
      }
  }
  
Done:
  return Status;
}

EFI_STATUS
WinNtSimpleFileSystemFlush (
  IN EFI_FILE  *This
  )
/*++

Routine Description:

Arguments:

Returns:

  None

--*/
{
  return EFI_SUCCESS;
}


⌨️ 快捷键说明

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