title: Error while reading disk
body: <p>I'm creating file deletion tool, so working with raw disk access. Have made some functions to read data.</p>
  
  <p>A bit sorry because posting so much code, but not sure where is the real problem.</p>
  
  <pre><code>struct Extent
  {
      LONGLONG ClustersCount; 
      LARGE_INTEGER Lcn;          //lcn - logical cluster number - the offset of a cluster from some arbitary point within volume
  
      Extent() : ClustersCount(), Lcn()
      {}
  
      Extent(LONGLONG clustersCount, LARGE_INTEGER lcn) : ClustersCount(clustersCount), Lcn(lcn)
      {}
  };
  
  typedef std::vector&lt;Extent&gt; ExtentsVector;
  
  bool GetFileExtentPoints(const std::wstring&amp; filePath, ExtentsVector&amp; output)
  {
      output.clear();
      DWORD err = ERROR_SUCCESS;
      HANDLE file = CreateFile(filePath.c_str(), FILE_READ_ATTRIBUTES, (FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE), NULL, OPEN_EXISTING, 0, 0);
      if (file != INVALID_HANDLE_VALUE)
      {
          STARTING_VCN_INPUT_BUFFER vcnStartBuffer = {};
          RETRIEVAL_POINTERS_BUFFER pointsBuffer = {};
          DWORD deviceIoControlDataritten = 0;
  
          do 
          {
              if (DeviceIoControl(file, FSCTL_GET_RETRIEVAL_POINTERS, &amp;vcnStartBuffer, sizeof(vcnStartBuffer), &amp;pointsBuffer, sizeof(pointsBuffer), &amp;deviceIoControlDataritten, NULL))
              {
                  Extent extent(pointsBuffer.Extents-&gt;NextVcn.QuadPart - pointsBuffer.StartingVcn.QuadPart, pointsBuffer.Extents[0].Lcn);
                  output.push_back(extent);
                  CloseHandle(file);
                  return true;
              }
              if (pointsBuffer.ExtentCount == 0)  //small files could be stroed in master file table, so this part shouldn't always return false
              {
                  CloseHandle(file);
                  return false;
              }
              Extent extent(pointsBuffer.Extents-&gt;NextVcn.QuadPart - pointsBuffer.StartingVcn.QuadPart, pointsBuffer.Extents[0].Lcn);
              output.push_back(extent);
              vcnStartBuffer.StartingVcn = pointsBuffer.Extents-&gt;NextVcn;
          }
          while (ERROR_MORE_DATA == GetLastError());
          CloseHandle(file);
      }
      return false;
  }
  
  bool PermanentDeleteFile/*for now just read...*/(const std::wstring&amp; filePath)
  {
      ExtentsVector extents;
      if (!GetFileExtentPoints(filePath, extents))
          return false;
  
      DWORD sectorsPerCluster = 0;
      DWORD bytesPerSector = 0;
      LARGE_INTEGER fileSize = {};
  
      HANDLE file = CreateFile(filePath.c_str(), FILE_READ_ATTRIBUTES, (FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE), NULL, OPEN_EXISTING, 0, 0);
      if (file != INVALID_HANDLE_VALUE)
      {
          TCHAR drive[] = L"?:\\"; 
          drive[0] = filePath[0];
  
          if (!GetDiskFreeSpace(drive, &amp;sectorsPerCluster, &amp;bytesPerSector, NULL, NULL))
          {
              CloseHandle(file);
              return false;
          }
          if (!GetFileSizeEx(file, &amp;fileSize))
          {
              CloseHandle(file);
              return false;
          }
          CloseHandle(file);
      }
      LONGLONG clusterSize = sectorsPerCluster * bytesPerSector;
      LONGLONG clustersCount = fileSize.QuadPart / clusterSize + ((fileSize.QuadPart % clusterSize == 0) ? 0 : 1);
  
      TCHAR rawDrive[] = L"\\\\.\\?:"; 
      rawDrive[4] = filePath[0];
  
      HANDLE driveHandle = CreateFile(rawDrive, /*GENERIC_WRITE*/GENERIC_READ/**/, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
  
      if (driveHandle != INVALID_HANDLE_VALUE)
      {
          for (ExtentsVector::iterator it = extents.begin(); it != extents.end(); ++it)
          {
              LARGE_INTEGER distance = {};
              distance.QuadPart = it-&gt;Lcn.QuadPart * clusterSize;
  
              BOOL b = SetFilePointerEx(driveHandle, distance, NULL, FILE_BEGIN);
              if (b)
              {
                  std::string buffer;
                  buffer.resize(clusterSize * it-&gt;ClustersCount);
                  DWORD read = 0;
                  BOOL B = ReadFile(driveHandle, &amp;buffer[0], clusterSize * it-&gt;ClustersCount, &amp;read, NULL);
                  B = FALSE;//here I have breakpoint and for FAT type drives buffer contains invalid data
              }
              else
              {
                  CloseHandle(driveHandle);
                  return false;
              }
  
          }
      }
      return false;
  }
  </code></pre>
  
  <p><code>GetFileExtentPoints</code> should collect clusters entries and cluster chain size for latter actions according to given file.</p>
  
  <p>The place where the problem is seen is in <code>PermanentDeleteFile</code> I have marked that place with comment. </p>
  
  <p>I have tried to read all my FAT32 drive and found that data I'm looking for is in drive but in other place so, as I understand FAT uses some kind of data offset. After that read <a href="http://en.wikipedia.org/wiki/File_Allocation_Table#Boot_Sector" rel="nofollow">this</a>. As I think the offset is described by first 3 bytes in drive, but don't understand how to use it. In my case it is <code>0xEB 0x58 0x90</code>. Want to ask, how to decode file system header into data offset.</p>
  
  <p>BTW. I'm coding with C++ and using WinAPI.</p>
  
  <p><strong>EDIT:</strong> I have change my line into <code>distance.QuadPart = it-&gt;Lcn.QuadPart * clusterSize + 0x01000000;</code>, this works for FAT, however I don't want to have hardcoded constants, so can someone tell, if it is always this value, or it is calculated some way.</p>