问题描述
我正在尝试从原始磁盘读取字节. (Windows 7和VS 2010.)
I'm trying to read bytes from a raw disk. (Windows 7, VS 2010.)
对于hDisk,我得到的值为-1(我认为这是一个错误).
I get a value of -1 for hDisk (which I assume is an error).
如何获取真实数据?
#include "stdafx.h"
#include <windows.h>
#include <WinIoCtl.h>
#include <stdio.h>
#include <iostream>
int _tmain(int argc, _TCHAR* argv[])
{
printf("hello world\n");
DWORD nRead;
char buf[512];
HANDLE hDisk = CreateFile(L"\\\\.\\PhysicalDrive0",
GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, 0, NULL);
printf("hDisk %i\n", hDisk);
SetFilePointer(hDisk, 0xA00, 0, FILE_BEGIN);
ReadFile(hDisk, buf, 512, &nRead, NULL);
for (int currentpos=0;currentpos < 512;currentpos++) {
std::cout << buf[currentpos];
}
CloseHandle(hDisk);
std::cin.get();
return 0;
}
推荐答案
您的代码(在以提升的特权运行时)应该可以工作,除了:
Your code should I think work (when run with elevated privileges) except that:
-
buf[]
没有正确对齐.
物理驱动器0可能是系统驱动器,因此正在使用中.
Physical Drive 0 is likely to be the system drive, and hence in use.
这是我用于磁盘映像的一些代码. (以前在这里发布.)公共领域,但不作任何明示或暗示的担保.(查看我注意到的代码我没有明确检查扇区大小以确保缓冲区和读/写操作正确对齐,这在实际中应该不是问题,因为通常使用的最大扇区大小为4K,这也是Windows上的内存页面大小.但是,在生产代码中,您应始终明确确定所讨论设备的扇区大小,并确保相应地正确对齐.)
Here's some code I use for disk imaging. (Previously posted here.) Public domain, but no warranty, express or implied, etc. (Looking over the code I note that I haven't explicitly checked the sector size in order to make sure that the buffer and read/write operations are properly aligned. This shouldn't be a problem in practice because the largest sector size in common use is 4K and this is also the memory page size on Windows. However, in production code, you should always explicitly determine the sector size of the device in question and ensure proper alignment accordingly.)
#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;
}
}
这篇关于Windows,打开原始磁盘的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!