如何在Windows上使用C ++将包含多个分区的映像写入USB闪存驱动器

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

我已经阅读了关于安装一个filter驱动程序,最终将可移动媒体视为固定的,这将是很好的阅读,但我只想写这个图像与用户的电脑干扰less。 我可以从第一个扇区开始访问原始USB驱动器,只需写入MBR,然后是两个分区的数据?

如果您有足够的权限来执行此操作,则可以使用\\.\PhysicalDrive2等文件名,通过使用CreateFile打开一个句柄直接写入USB驱动器。

你需要弄清楚物理驱动器号码。 如果您有驱动器号,则可以使用文件名(如\\?\D:打开卷处理,然后使用IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS确定与该卷关联的物理驱动器号。

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

编辑:这里有一些我用于磁盘映像的代码,虽然我不记得是否曾经在USB盘上试过它。 公共领域,但没有保证,明示或暗示等(查看代码我注意到,我没有明确检查扇区的大小,以确保缓冲区和读/写操作正确对齐,在实际中这是一个问题,因为常用的最大扇区大小是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; } }