【问题标题】:SetFilePointerEx fails to read physical disk beyond size of LONGSetFilePointerEx 无法读取超出 LONG 大小的物理磁盘
【发布时间】:2011-01-17 22:34:27
【问题描述】:

花了几年时间,但我终于开始涉足 VC++。我需要能够读取物理设备(即硬盘)的 x 个扇区。我正在使用 CreateFile() 和 SetFilePointerEx() 以及 ReadFile() API。

  • 我在所有主要论坛上就该主题进行了大量在线阅读。我已经用尽了我的研究,现在我觉得是时候请专家们来权衡一下这个困境了。由于这是我关于这个主题的第一篇文章,请放轻松:)

  • 我还应该指出,这是一个 .DLL,我在一个简单的 C# 应用程序中使用它。管道一切正常。让我伤心的是 SetFilePointer(Ex)() API。

我可以让代码工作到大约 LONG (4,xxx,xxx) 的大小 - 我不记得确切的值。可以说我可以阅读所有内容,包括扇区#4,000,000,但不能阅读5,000,000或以上。问题在于 SetFilePointer() 和 SetFilePointerEx() API 的参数“大小”。我都试过了,到目前为止,SetFilePointerEx() 似乎是我在 64 位系统上工作时应该使用的。

SetFilePointer的第2个和第3个参数定义如下:

BOOL WINAPI SetFilePointerEx(
  __in       HANDLE hFile,
  __in       LARGE_INTEGER liDistanceToMove,
  __out_opt  PLARGE_INTEGER lpNewFilePointer,
  __in       DWORD dwMoveMethod
);

请注意,我尝试将 LowPart 和 HighPart 作为第二个和第三个参数传递,但没有成功,因为我得到一个 CANNOT CONVERT LARGE_INTEGER TO PLARGE_INTEGER(用于参数 3)。

这是我的代码。我使用 CODE-BREAK 来查看 buff[0] 等。我想了解 4,xxx,xxx 限制。显然我做错了什么。每次超过此限制的读取都会将我的文件指针重置为扇区 0。

#include "stdafx.h"
#include <windows.h>
#include <conio.h>   



extern "C" 
  __declspec(dllexport)  int ReadSectors(long startSector, long numSectors)
 {

  HANDLE hFile;

  const int SECTOR_SIZE = 512;
  const int BUFFER_SIZE = 512;

  LARGE_INTEGER liDistanceToMove;  
  PLARGE_INTEGER newFilePtr = NULL;   // not used in this context.
                // just reading from START to END


  liDistanceToMove.QuadPart = startSector * SECTOR_SIZE;


  DWORD  dwBytesRead, dwPos;

  LPCWSTR fname = L"\\\\.\\PHYSICALDRIVE0";

  char buff[BUFFER_SIZE];


  // Open the PHYSICALDEVICE as a file. 
  hFile = CreateFile(fname,            
     GENERIC_READ | GENERIC_WRITE,             
     FILE_SHARE_READ | FILE_SHARE_WRITE,                       
     NULL,                      
     OPEN_EXISTING,            
     FILE_ATTRIBUTE_NORMAL,     
     NULL);                   


  // Here's the API definition

  /*BOOL WINAPI SetFilePointerEx(
    __in       HANDLE hFile,
    __in       LARGE_INTEGER liDistanceToMove,
    __out_opt  PLARGE_INTEGER lpNewFilePointer,
    __in       DWORD dwMoveMethod
  );*/


  dwPos = SetFilePointerEx(hFile, liDistanceToMove, NULL, FILE_BEGIN);


  if(ReadFile(hFile, buff, BUFFER_SIZE, &dwBytesRead, NULL))
  {
   if(dwBytesRead > 5)
   {

    BYTE x1 = buff[0];
    BYTE x2 = buff[1];
    BYTE x3 = buff[2];
    BYTE x4 = buff[3];
    BYTE x5 = buff[4];
   }

  }


  // Close both files.
  CloseHandle(hFile);


  return 0;
 }

【问题讨论】:

    标签: winapi


    【解决方案1】:
     startSector * SECTOR_SIZE;
    

    startSector 是long(32 位),SECTOR_SIZE 是int(也是32 位),将这两个人相乘,中间结果会很长,会溢出,然后你把它塞进@ LARGE_INTEGER 的 987654324@,已经来不及了。你想在__int64s 上操作,比如

     liDistanceToMove.QuadPart = startSector;
     liDistanceToMove.QuadPart *= SECTOR_SIZE;
    

    例如。

    【讨论】:

    • 嗯......这很有趣,现在你指出它......它是有道理的。 LARGE_INTEGER 中的 struct 的想法(以某种方式在内部创建 LowPart 和 HighPart)对我来说有点新。我从来没有想过自己在 QuadPart 上工作。我期待着尝试一下。非常感谢!
    猜你喜欢
    • 2013-02-25
    • 2013-02-09
    • 1970-01-01
    • 2012-12-28
    • 1970-01-01
    • 2010-09-24
    • 1970-01-01
    • 2013-04-03
    • 2014-02-13
    相关资源
    最近更新 更多