Linux下面直接dd在windows下要绕几个坑。。
先上做法
- 在target device上新建一个分区,占满整个disk
- 假设分区代号
\\.\W:
,整盘代号\\.\PhysicalDrive99
,下面开始打开vs写程序(需要windows.h等等) 看磁盘代号打开Powershell 然后
`wmic DISKDRIVE
// 1. get volume HANDLE hVolume = CreateFile("\\\\.\\W:", GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); // 2. lock volume (we cannot lock the whole disk but we can do that) DeviceIoControl(hVolume, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &bytesreturned, NULL); // 3. unmountVolume (we cannot lock the whole disk but we can do that) DeviceIoControl(hVolume, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0, &junk, NULL); // 4. get device HANDLE hDev = CreateFile("\\.\PhysicalDrive99", GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); // 5. write WriteFile(......) // 6. close & unlock ......
首先windows不支持lock整个disk,所以我们只能lock volume。
所以会有下面几个坑
坑:没写上面1,2,3步,直接打开device直接写,写时候报lasterror = 2, 32, 87, 5等等??
而且在不知道什么时候比如22% 38% 0.7%...
在写的时候刷新了磁盘分区表,然后系统发现哇,分区变了,并且第一个区如果可读的话,系统会兴高采烈地挂载它。
此时我们丧失了对整个DEVICE的full control权力,即使在上述步骤第四步,fileshare参数设为NULL也不行,因为这不是文件,挂载分区是“驱动程序”做的事情,而不是操作系统。
而我们控制文件独占,是“操作系统”的事情,上述路径是整个驱动器的代号,所以LOCK驱动器行不通啦。。
但是我就不写1,2,3步能行吗?就直接CreateFile后开搞
也是可以的!
先看这个:https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea#physical-disks-and-volumes
虽然明确说了"Direct access to the disk or to a volume is restricted. ",但我非要这么做。
那就是:写失败了以后,保留分区表里面的分区位置信息,删掉分配的盘符,并把分区1跳1的删掉(主要删系统认识的分区) or 格式化成系统不认得的格。
1跳1的删掉为了在更新分区表插入分区时,不触发系统抢占整个磁盘。
写失败的时候一般来说分区表是写完了的!(看下面例子)
举例:磁盘从前向后写入,写入分区表->写入第一个分区(fat32)->写入第二个(ext4)
当写完分区表和fat32分区时候,系统哇,发现一个分区,我认识,快给安上!
然后就抢占了,我们的程序就失去了控制权。。
这也说明了如果运气好,写小img可以一次成型,在系统没发现时候就已经写好了!
而上述土办法呢,打这系统一个措手不及,啊你这分区表没变啊,那没有新的,不动了!
Note
下述windd64代码稍作更改 然后
windd64.exe /if:F:\xxx.img /of:\\.\PHYSICALDRIVE2
Refs:
- Win32DiskImager-1.0.0-src.zip
- Github: windd64