jjzjj

c++ - 如何使用 C++ 在 Windows 上将包含多个分区的图像写入 U 盘

coder 2023-11-12 原文

在 Windows 上,您只能看到可移动媒体上的第一个分区。我想编写一个 C++ 程序,可以将包含一个 MBR 和 2 个数据分区的图像写入 USB 闪存驱动器。我不需要第二个分区在 Windows 中可见 - 我只需要能够从 Windows/C++ 将此原始图像写入 USB 闪存驱动器,以便稍后在 Linux 上运行时可以看到这两个分区。

我读过有关安装过滤器驱动程序的信息,该驱动程序最终会将可移动媒体视为固定媒体,这对于阅读来说很不错,但我只想在写入此图像时尽量减少对用户 PC 的干扰。我可以从第一个扇区开始访问原始 USB 驱动器,然后只写入 MBR,然后写入两个数据分区吗?

最佳答案

如果您有足够的权限这样做,您可以使用 CreateFile 打开句柄以直接写入 USB 驱动器。文件名类似于 \\.\PhysicalDrive2

您需要计算出物理驱动器编号。如果您有驱动器盘符,则可以使用类似 \\?\D: 的文件名打开卷句柄,然后使用 IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS以确定与卷关联的物理驱动器编号。

您可能需要先卸载现有的卷(如果有的话)。我不确定最好的方法是什么,但您可以尝试使用 IOCTL_VOLUME_OFFLINE .

编辑:这是我用于磁盘镜像的一些代码,尽管我不记得是否曾在 USB 磁盘上尝试过。公共(public)领域,但没有明示或暗示的保证等。(查看代码我注意到我没有明确检查扇区大小以确保缓冲区和读/写操作正确对齐。这不应该'在实践中这不是问题,因为通常使用的最大扇区大小是 4K,这也是 Windows 上的内存页面大小。但是,在生产代码中,您应该始终明确确定相关设备的扇区大小并确保正确对齐相应地。)

#define _WIN32_WINNT 0x0501

#include <windows.h>

#include <stdio.h>

#define dump_buffersize_megs 16
#define dump_buffersize (dump_buffersize_megs * 1024 * 1024)
#define dump_workingsetsize ((dump_buffersize_megs + 1) * 1024 * 1024)

DWORD save(const wchar_t * source_device_name, const wchar_t * filename) {

  DWORD err;

  HANDLE hdevice, houtput;

  DWORD bytes_to_transfer, byte_count;

  GET_LENGTH_INFORMATION source_disklength;

  DISK_GEOMETRY source_diskgeometry;

  LARGE_INTEGER offset;

  OVERLAPPED overlapped;

  BYTE * buffer;

  if (!SetProcessWorkingSetSize(GetCurrentProcess(), dump_workingsetsize, dump_workingsetsize)) 
  {
    err = GetLastError();
    printf("Error %u trying to expand working set.\n", err);
    return err;
  }

  buffer = VirtualAlloc(NULL, dump_buffersize, MEM_COMMIT, PAGE_READWRITE);

  if (buffer == NULL)
  {
    err = GetLastError();
    printf("Error %u trying to allocate buffer.\n", err);
    return err;
  }

  if (!VirtualLock(buffer, dump_buffersize))
  {
    err = GetLastError();
    printf("Error %u trying to lock buffer.\n", err);
    return err;
  }

  hdevice = CreateFile
    (
    source_device_name,
    GENERIC_READ,
    0,
    NULL,
    OPEN_EXISTING,
    FILE_FLAG_NO_BUFFERING,
    NULL
    );

  if (hdevice == INVALID_HANDLE_VALUE) {
    err = GetLastError();
    fprintf(stderr, "Error %u opening input device.\n", err);
    return err;
  }

  if (!DeviceIoControl
    (
    hdevice,
    FSCTL_LOCK_VOLUME,
    NULL,
    0,
    NULL,
    0,
    &byte_count,
    NULL
    ))
  {
    err = GetLastError();
    fprintf(stderr, "Error %u locking input volume.\n", err);
    return err;
  }

  if (!DeviceIoControl
    (
    hdevice,
    IOCTL_DISK_GET_DRIVE_GEOMETRY,
    NULL,
    0,
    &source_diskgeometry,
    sizeof(source_diskgeometry),
    &byte_count,
    NULL
    ))
  {
    err = GetLastError();
    fprintf(stderr, "Error %u getting device geometry.\n", err);
    return err;
  }

  switch (source_diskgeometry.MediaType)
  {
  case Unknown:
  case RemovableMedia:
  case FixedMedia:

    if (!DeviceIoControl
      (
      hdevice,
      IOCTL_DISK_GET_LENGTH_INFO,
      NULL,
      0,
      &source_disklength,
      sizeof(source_disklength),
      &byte_count,
      NULL
      ))
    {
      err = GetLastError();
      fprintf(stderr, "Error %u getting input device length.\n", err);
      return err;
    }

    fprintf(stderr, "\nInput disk has %I64i bytes.\n\n", source_disklength.Length.QuadPart);
    break;

  default:

    source_disklength.Length.QuadPart = 
      source_diskgeometry.Cylinders.QuadPart *
      source_diskgeometry.TracksPerCylinder *
      source_diskgeometry.SectorsPerTrack *
      source_diskgeometry.BytesPerSector;

    fprintf(stderr, 
      "\n"
      "Input device appears to be a floppy disk.  WARNING: if this is not a\n"
      "floppy disk the calculated size will probably be incorrect, resulting\n"
      "in an incomplete copy.\n"
      "\n"
      "Input disk has %I64i bytes.\n"
      "\n", 
      source_disklength.Length.QuadPart);

    break;
  }

  houtput = CreateFile
    (
    filename,
    GENERIC_WRITE,
    0,
    NULL,
    CREATE_ALWAYS,
    FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED,
    NULL
    );

  if (houtput == INVALID_HANDLE_VALUE)
  {
    err = GetLastError();
    fprintf(stderr, "Error %u creating output file.\n", err);
    return err;
  }

  offset.QuadPart = 0;
  overlapped.hEvent = 0;

  for (;;) 
  {
    overlapped.Offset = offset.LowPart;
    overlapped.OffsetHigh = offset.HighPart;

    if (source_disklength.Length.QuadPart - offset.QuadPart < dump_buffersize) 
    {
      bytes_to_transfer = (DWORD)(source_disklength.Length.QuadPart - offset.QuadPart);
      if (bytes_to_transfer == 0) break;
    }
    else
    {
      bytes_to_transfer = dump_buffersize;
    }

    if (!ReadFile(hdevice, buffer, bytes_to_transfer, NULL, &overlapped)) 
    {
      err = GetLastError();
      printf("Error %u initiating read from input disk.\n", err);
      return err;
    }

    if (!GetOverlappedResult(hdevice, &overlapped, &byte_count, TRUE)) 
    {
      err = GetLastError();
      printf("Error %u reading from input disk.\n", err);
      return err;
    }

    if (byte_count != bytes_to_transfer)
    {
      err = GetLastError();
      printf("Internal error - partial read.  Last error code %u.\n", err);
      printf("bytes_to_transfer = %u; byte_count = %u.\n", bytes_to_transfer, byte_count);
      if (byte_count == 0) return ERROR_INVALID_FUNCTION;
      bytes_to_transfer = byte_count;
    }

    if (!WriteFile(houtput, buffer, bytes_to_transfer, NULL, &overlapped)) 
    {
      err = GetLastError();
      if (err != ERROR_IO_PENDING)
      {
        printf("Error %u initiating write to output file.\n", err);
        return err;
      }
    }

    if (!GetOverlappedResult(houtput, &overlapped, &byte_count, TRUE)) 
    {
      err = GetLastError();
      printf("Error %u writing to output file.\n", err);
      return err;
    }

    if (byte_count != bytes_to_transfer)
    {
      printf("Internal error - partial write.\n");
      printf("bytes_to_transfer = %u; byte_count = %u.\n", bytes_to_transfer, byte_count);
      return ERROR_INVALID_FUNCTION;
    }

    offset.QuadPart += bytes_to_transfer;
  }

  overlapped.Offset = offset.LowPart;
  overlapped.OffsetHigh = offset.HighPart;

  if (!ReadFile(hdevice, buffer, source_diskgeometry.BytesPerSector, NULL, &overlapped)) 
  {
    err = GetLastError();
    if (err == ERROR_HANDLE_EOF)
    {
      printf("Save successfully completed.\n");      
      return 0;
    }
    printf("Error %u initiating read from input disk past end of file.\n", err);
    return err;
  }

  if (!GetOverlappedResult(hdevice, &overlapped, &byte_count, TRUE)) 
  {
    err = GetLastError();
    if (err == ERROR_HANDLE_EOF)
    {
      printf("Save successfully completed.\n");      
      return 0;
    }
    printf("Error %u reading from input disk past end of file.\n", err);
    return err;
  }

  if (byte_count == 0)
  {
    printf("Save successfully completed.\n"); 
    return 0;
  }

  printf("WARNING: the expected amount of data was successfully copied,\n"
         "but end of file not detected on input disk.  The copy might\n"
         "not be complete.");

  return ERROR_MORE_DATA;

}

DWORD write(const wchar_t * filename, const wchar_t * target_device_name) {

  DWORD err;

  HANDLE hinput, houtput;

  WIN32_FILE_ATTRIBUTE_DATA fad;

  DWORD bytes_to_transfer, byte_count;

  LARGE_INTEGER filelength;

  GET_LENGTH_INFORMATION target_disklength;

  DISK_GEOMETRY target_diskgeometry;

  LARGE_INTEGER transfer_length;

  LARGE_INTEGER offset;

  OVERLAPPED overlapped;

  BYTE * buffer;

  if (!SetProcessWorkingSetSize(GetCurrentProcess(), dump_workingsetsize, dump_workingsetsize)) 
  {
    err = GetLastError();
    printf("Error %u trying to expand working set.\n", err);
    return err;
  }

  buffer = VirtualAlloc(NULL, dump_buffersize, MEM_COMMIT, PAGE_READWRITE);

  if (buffer == NULL)
  {
    err = GetLastError();
    printf("Error %u trying to allocate buffer.\n", err);
    return err;
  }

  if (!VirtualLock(buffer, dump_buffersize))
  {
    err = GetLastError();
    printf("Error %u trying to lock buffer.\n", err);
    return err;
  }

  if (!GetFileAttributesEx(filename, GetFileExInfoStandard, &fad)) 
  {
    err = GetLastError();
    fprintf(stderr, "Error %u reading input file attributes.\n", err);
    return err;
  }

  filelength.HighPart = fad.nFileSizeHigh;
  filelength.LowPart = fad.nFileSizeLow;

  fprintf(stderr, "\nInput file has %I64i bytes.\n", filelength.QuadPart);

  hinput = CreateFile
    (
    filename,
    GENERIC_READ,
    0,
    NULL,
    OPEN_EXISTING,
    FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED,
    NULL
    );

  if (hinput == INVALID_HANDLE_VALUE)
  {
    err = GetLastError();
    fprintf(stderr, "Error %u opening input file.\n", err);
    return err;
  }

  houtput = CreateFile
    (
    target_device_name,
    GENERIC_READ | GENERIC_WRITE,
    0,
    NULL,
    OPEN_EXISTING,
    FILE_FLAG_NO_BUFFERING,
    NULL
    );

  if (houtput == INVALID_HANDLE_VALUE) {
    err = GetLastError();
    fprintf(stderr, "Error %u opening output device.\n", err);
    return err;
  }

  if (!DeviceIoControl
    (
    houtput,
    FSCTL_LOCK_VOLUME,
    NULL,
    0,
    NULL,
    0,
    &byte_count,
    NULL
    ))
  {
    err = GetLastError();
    fprintf(stderr, "Error %u locking volume.\n", err);
    return err;
  }

  if (!DeviceIoControl
    (
    houtput,
    IOCTL_DISK_GET_DRIVE_GEOMETRY,
    NULL,
    0,
    &target_diskgeometry,
    sizeof(target_diskgeometry),
    &byte_count,
    NULL
    ))
  {
    err = GetLastError();
    fprintf(stderr, "Error %u getting output device geometry.\n", err);
    return err;
  }

  switch (target_diskgeometry.MediaType)
  {
  case Unknown:
  case RemovableMedia:
  case FixedMedia:

    if (!DeviceIoControl
      (
      houtput,
      IOCTL_DISK_GET_LENGTH_INFO,
      NULL,
      0,
      &target_disklength,
      sizeof(target_disklength),
      &byte_count,
      NULL
      ))
    {
      err = GetLastError();
      fprintf(stderr, "Error %u getting output device length.\n", err);
      return err;
    }

    fprintf(stderr, "Output disk has %I64i bytes.\n\n", target_disklength.Length.QuadPart);
    break;

  default:

    target_disklength.Length.QuadPart = 
      target_diskgeometry.Cylinders.QuadPart *
      target_diskgeometry.TracksPerCylinder *
      target_diskgeometry.SectorsPerTrack *
      target_diskgeometry.BytesPerSector;

    fprintf(stderr, 
      "\n"
      "Output device appears to be a floppy disk.  WARNING: if this is not a\n"
      "floppy disk the calculated output device size is probably incorrect,\n"
      "which might result in an incomplete copy.\n"
      "\n"
      "Output disk has %I64i bytes.\n"
      "\n", 
      target_disklength.Length.QuadPart);

    break;
  }

  if (filelength.QuadPart == target_disklength.Length.QuadPart)
  {
    transfer_length.QuadPart = filelength.QuadPart;
  }
  else if (filelength.QuadPart < target_disklength.Length.QuadPart)
  {
    fprintf(stderr, "Image is smaller than target.  Part of the target will not be written to.\n\n");
    transfer_length.QuadPart = filelength.QuadPart;
  }
  else
  {
    fprintf(stderr, "Image is larger than target.  Part of the image will not be copied.\n\n");
    transfer_length.QuadPart = target_disklength.Length.QuadPart;
  }

  offset.QuadPart = 0;
  overlapped.hEvent = 0;

  for (;;) 
  {
    overlapped.Offset = offset.LowPart;
    overlapped.OffsetHigh = offset.HighPart;

    if (transfer_length.QuadPart - offset.QuadPart < dump_buffersize) 
    {
      bytes_to_transfer = (DWORD)(transfer_length.QuadPart - offset.QuadPart);
      if (bytes_to_transfer == 0) break;
    }
    else
    {
      bytes_to_transfer = dump_buffersize;
    }

    if (!ReadFile(hinput, buffer, bytes_to_transfer, NULL, &overlapped)) 
    {
      err = GetLastError();
      if (err != ERROR_IO_PENDING)
      {
        printf("Error %u initiating read from input file.\n", err);
        return err;
      }
    }

    if (!GetOverlappedResult(hinput, &overlapped, &byte_count, TRUE)) 
    {
      err = GetLastError();
      printf("Error %u reading from input file.\n", err);
      return err;
    }

    if (byte_count != bytes_to_transfer)
    {
      err = GetLastError();
      printf("Internal error - partial read.  Last error code %u.\n", err);
      printf("bytes_to_transfer = %u; byte_count = %u.\n", bytes_to_transfer, byte_count);
      if (byte_count == 0) return ERROR_INVALID_FUNCTION;
      bytes_to_transfer = byte_count;
    }

    if (!WriteFile(houtput, buffer, bytes_to_transfer, NULL, &overlapped)) 
    {
      err = GetLastError();
      if (err != ERROR_IO_PENDING)
      {
        printf("Error %u initiating write to output disk.\n", err);
        return err;
      }
    }

    if (!GetOverlappedResult(houtput, &overlapped, &byte_count, TRUE)) 
    {
      err = GetLastError();
      printf("Error %u writing to output disk.\n", err);
      return err;
    }

    if (byte_count != bytes_to_transfer)
    {
      printf("Internal error - partial write.\n");
      printf("bytes_to_transfer = %u; byte_count = %u.\n", bytes_to_transfer, byte_count);
      return ERROR_INVALID_FUNCTION;
    }

    offset.QuadPart += bytes_to_transfer;
  }

  printf("Write successfully completed.\n");
  return 0;
}

DWORD clone(const wchar_t * source_device_name, const wchar_t * target_device_name) {

  DWORD err;

  HANDLE hinput, houtput;

  DWORD bytes_to_transfer, byte_count;

  GET_LENGTH_INFORMATION source_disklength;

  DISK_GEOMETRY source_diskgeometry;

  GET_LENGTH_INFORMATION target_disklength;

  DISK_GEOMETRY target_diskgeometry;

  LARGE_INTEGER transfer_length;

  LARGE_INTEGER offset;

  OVERLAPPED overlapped;

  BYTE * buffer;

  DWORD result;

  if (!SetProcessWorkingSetSize(GetCurrentProcess(), dump_workingsetsize, dump_workingsetsize)) 
  {
    err = GetLastError();
    printf("Error %u trying to expand working set.\n", err);
    return err;
  }

  buffer = VirtualAlloc(NULL, dump_buffersize, MEM_COMMIT, PAGE_READWRITE);

  if (buffer == NULL)
  {
    err = GetLastError();
    printf("Error %u trying to allocate buffer.\n", err);
    return err;
  }

  if (!VirtualLock(buffer, dump_buffersize))
  {
    err = GetLastError();
    printf("Error %u trying to lock buffer.\n", err);
    return err;
  }

  hinput = CreateFile
    (
    source_device_name,
    GENERIC_READ,
    0,
    NULL,
    OPEN_EXISTING,
    FILE_FLAG_NO_BUFFERING,
    NULL
    );

  if (hinput == INVALID_HANDLE_VALUE) {
    err = GetLastError();
    fprintf(stderr, "Error %u opening input device.\n", err);
    return err;
  }

  if (!DeviceIoControl
    (
    hinput,
    FSCTL_LOCK_VOLUME,
    NULL,
    0,
    NULL,
    0,
    &byte_count,
    NULL
    ))
  {
    err = GetLastError();
    fprintf(stderr, "Error %u locking input volume.\n", err);
    return err;
  }

  if (!DeviceIoControl
    (
    hinput,
    IOCTL_DISK_GET_DRIVE_GEOMETRY,
    NULL,
    0,
    &source_diskgeometry,
    sizeof(source_diskgeometry),
    &byte_count,
    NULL
    ))
  {
    err = GetLastError();
    fprintf(stderr, "Error %u getting device geometry.\n", err);
    return err;
  }

  switch (source_diskgeometry.MediaType)
  {
  case Unknown:
  case RemovableMedia:
  case FixedMedia:

    if (!DeviceIoControl
      (
      hinput,
      IOCTL_DISK_GET_LENGTH_INFO,
      NULL,
      0,
      &source_disklength,
      sizeof(source_disklength),
      &byte_count,
      NULL
      ))
    {
      err = GetLastError();
      fprintf(stderr, "Error %u getting input device length.\n", err);
      return err;
    }

    fprintf(stderr, "\nInput disk has %I64i bytes.\n", source_disklength.Length.QuadPart);
    break;

  default:

    source_disklength.Length.QuadPart = 
      source_diskgeometry.Cylinders.QuadPart *
      source_diskgeometry.TracksPerCylinder *
      source_diskgeometry.SectorsPerTrack *
      source_diskgeometry.BytesPerSector;

    fprintf(stderr, 
      "\n"
      "Input device appears to be a floppy disk.  WARNING: if this is not a\n"
      "floppy disk the calculated disk size is probably incorrect, resulting\n"
      "in an incomplete copy.\n"
      "\n"
      "Input disk has %I64i bytes.\n",
      source_disklength.Length.QuadPart);

    break;
  }

  houtput = CreateFile
    (
    target_device_name,
    GENERIC_READ | GENERIC_WRITE,
    0,
    NULL,
    OPEN_EXISTING,
    FILE_FLAG_NO_BUFFERING,
    NULL
    );

  if (houtput == INVALID_HANDLE_VALUE) {
    err = GetLastError();
    fprintf(stderr, "Error %u opening output device.\n", err);
    return err;
  }

  if (!DeviceIoControl
    (
    houtput,
    FSCTL_LOCK_VOLUME,
    NULL,
    0,
    NULL,
    0,
    &byte_count,
    NULL
    ))
  {
    err = GetLastError();
    fprintf(stderr, "Error %u locking output volume.\n", err);
    return err;
  }

  if (!DeviceIoControl
    (
    houtput,
    IOCTL_DISK_GET_DRIVE_GEOMETRY,
    NULL,
    0,
    &target_diskgeometry,
    sizeof(target_diskgeometry),
    &byte_count,
    NULL
    ))
  {
    err = GetLastError();
    fprintf(stderr, "Error %u getting output device geometry.\n", err);
    return err;
  }

  switch (target_diskgeometry.MediaType)
  {
  case Unknown:
  case RemovableMedia:
  case FixedMedia:

    if (!DeviceIoControl
      (
      houtput,
      IOCTL_DISK_GET_LENGTH_INFO,
      NULL,
      0,
      &target_disklength,
      sizeof(target_disklength),
      &byte_count,
      NULL
      ))
    {
      err = GetLastError();
      fprintf(stderr, "Error %u getting output device length.\n", err);
      return err;
    }

    fprintf(stderr, "Output disk has %I64i bytes.\n\n", target_disklength.Length.QuadPart);
    break;

  default:

    target_disklength.Length.QuadPart = 
      target_diskgeometry.Cylinders.QuadPart *
      target_diskgeometry.TracksPerCylinder *
      target_diskgeometry.SectorsPerTrack *
      target_diskgeometry.BytesPerSector;

    fprintf(stderr, 
      "\n"
      "Output device appears to be a floppy disk.  WARNING: if this is not a\n"
      "floppy disk the calculated output device size is probably incorrect,\n"
      "which might result in an incomplete copy.\n"
      "\n"
      "Output disk has %I64i bytes.\n"
      "\n", 
      target_disklength.Length.QuadPart);

    break;
  }

  if (source_disklength.Length.QuadPart == target_disklength.Length.QuadPart)
  {
    transfer_length.QuadPart = source_disklength.Length.QuadPart;
  }
  else if (source_disklength.Length.QuadPart < target_disklength.Length.QuadPart)
  {
    printf("Input shorter than output.  Part of the output disk will not be written to.\n\n");
    transfer_length.QuadPart = source_disklength.Length.QuadPart;
  }
  else
  {
    printf("Output shorter than input.  Copy will be truncated to output length.\n\n");
    transfer_length.QuadPart = target_disklength.Length.QuadPart;
  }

  offset.QuadPart = 0;
  overlapped.hEvent = 0;

  for (;;) 
  {
    overlapped.Offset = offset.LowPart;
    overlapped.OffsetHigh = offset.HighPart;

    if (transfer_length.QuadPart - offset.QuadPart < dump_buffersize) 
    {
      bytes_to_transfer = (DWORD)(transfer_length.QuadPart - offset.QuadPart);
      if (bytes_to_transfer == 0) break;
    }
    else
    {
      bytes_to_transfer = dump_buffersize;
    }

    if (!ReadFile(hinput, buffer, bytes_to_transfer, NULL, &overlapped)) 
    {
      err = GetLastError();
      printf("Error %u initiating read from input file.\n", err);
      return err;
    }

    if (!GetOverlappedResult(hinput, &overlapped, &byte_count, TRUE)) 
    {
      err = GetLastError();
      printf("Error %u reading from input file.\n", err);
      return err;
    }

    if (byte_count != bytes_to_transfer)
    {
      err = GetLastError();
      printf("Internal error - partial read.  Last error code %u.\n", err);
      printf("bytes_to_transfer = %u; byte_count = %u.\n", bytes_to_transfer, byte_count);
      if (byte_count == 0) return ERROR_INVALID_FUNCTION;
      bytes_to_transfer = byte_count;
    }

    if (!WriteFile(houtput, buffer, bytes_to_transfer, NULL, &overlapped)) 
    {
      err = GetLastError();
      if (err != ERROR_IO_PENDING)
      {
        printf("Error %u initiating write to output disk.\n", err);
        return err;
      }
    }

    if (!GetOverlappedResult(houtput, &overlapped, &byte_count, TRUE)) 
    {
      err = GetLastError();
      printf("Error %u writing to output disk.\n", err);
      return err;
    }

    if (byte_count != bytes_to_transfer)
    {
      printf("Internal error - partial write.\n");
      printf("bytes_to_transfer = %u; byte_count = %u.\n", bytes_to_transfer, byte_count);
      return ERROR_INVALID_FUNCTION;
    }

    offset.QuadPart += bytes_to_transfer;
  }

  if (transfer_length.QuadPart == source_disklength.Length.QuadPart)
  {
    overlapped.Offset = offset.LowPart;
    overlapped.OffsetHigh = offset.HighPart;

    if (!ReadFile(hinput, buffer, source_diskgeometry.BytesPerSector, NULL, &overlapped)) 
    {
      err = GetLastError();
      if (err == ERROR_HANDLE_EOF)
      {
        printf("Copy successfully completed.\n");      
        return 0;
      }
      printf("Error %u initiating read from input disk past end of file.\n", err);
      return err;
    }

    if (!GetOverlappedResult(hinput, &overlapped, &byte_count, TRUE)) 
    {
      err = GetLastError();
      if (err == ERROR_HANDLE_EOF)
      {
        printf("Copy successfully completed.\n");
        return 0;
      }
      printf("Error %u reading from input disk past end of file.\n", err);
      return err;
    }

    if (byte_count == 0)
    {
      printf("Copy successfully completed.\n"); 
      return 0;
    }

    printf("WARNING: the expected amount of data was successfully copied,\n"
           "but end of file not detected on input disk.  The copy might\n"
           "not be complete.");

    result = ERROR_MORE_DATA;
    return 0;
  }

  printf("Copy successfully completed.\n");
  return 0;
}

int wmain(int argc, wchar_t ** argv)
{
  if (argc < 4)
  {
    printf("Syntax: \n"
      "To save an image of a physical drive:\n"
      "diskimage /save \\\\.\\PhysicalDrive0 file.img\n"
      "diskimage /save \\\\.\\A: file.img\n"
      "To write from an image file to a physical drive:\n"
      "diskimage /write file.img \\\\.\\PhysicalDrive0\n"
      "diskimage /write file.img \\\\.\\A:\n"
      "To clone input drive 0 to output drive 1:\n"
      "diskimage /clone \\\\.\\PhysicalDrive0 \\\\.\\PhysicalDrive1\n"
      );
    return 1;
  }
  if (_wcsicmp(argv[1], L"/save") == 0)
  {
    return save(argv[2], argv[3]);
  }
  else if (_wcsicmp(argv[1], L"/write") == 0)
  {
    return write(argv[2], argv[3]);
  }
  else if (_wcsicmp(argv[1], L"/clone") == 0)
  {
    return clone(argv[2], argv[3]);
  }
  else
  {
    printf("Invalid argument.  Use /? for syntax help.\n");
    return 1;
  }
}

关于c++ - 如何使用 C++ 在 Windows 上将包含多个分区的图像写入 U 盘,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15004984/

有关c++ - 如何使用 C++ 在 Windows 上将包含多个分区的图像写入 U 盘的更多相关文章

  1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

    我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

  2. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  3. ruby - 使用 RubyZip 生成 ZIP 文件时设置压缩级别 - 2

    我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看ruby​​zip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d

  4. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  5. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

    很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

  6. ruby - 在 Ruby 中使用匿名模块 - 2

    假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于

  7. ruby - 使用 ruby​​ 和 savon 的 SOAP 服务 - 2

    我正在尝试使用ruby​​和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我

  8. ruby - 在 Ruby 程序执行时阻止 Windows 7 PC 进入休眠状态 - 2

    我需要在客户计算机上运行Ruby应用程序。通常需要几天才能完成(复制大备份文件)。问题是如果启用sleep,它会中断应用程序。否则,计算机将持续运行数周,直到我下次访问为止。有什么方法可以防止执行期间休眠并让Windows在执行后休眠吗?欢迎任何疯狂的想法;-) 最佳答案 Here建议使用SetThreadExecutionStateWinAPI函数,使应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入休眠状态或关闭显示。像这样的东西:require'Win32API'ES_AWAYMODE_REQUIRED=0x0

  9. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  10. ruby-on-rails - Rails 3 中的多个路由文件 - 2

    Rails2.3可以选择随时使用RouteSet#add_configuration_file添加更多路由。是否可以在Rails3项目中做同样的事情? 最佳答案 在config/application.rb中:config.paths.config.routes在Rails3.2(也可能是Rails3.1)中,使用:config.paths["config/routes"] 关于ruby-on-rails-Rails3中的多个路由文件,我们在StackOverflow上找到一个类似的问题

随机推荐