程序里有自动重启 Windows 系统的功能,当有多个 Windows 共存的时候 C: 根目录下的 boot.ini 文件包含类似下面的内容:
[boot loader]
timeout=30
default=multi(0)disk(0)rdisk(0)partition(1)/WINNT
[operating systems]
multi(0)disk(0)rdisk(0)partition(1)/WINNT="Windows 2000 Professional"
multi(0)disk(0)rdisk(0)partition(2)/WINDOWS="Windows XP Professional" /fastdetect
我们会判断当前系统所在的驱动器,然后改写 boot.ini 中的 default 值,以使得程序重启系统后进入当前启动的操作系统。例如在拥有以上 boot.ini 的系统上,用户手工从操作系统列表选择了启动处于 partition(2) 上的 Windows XP ,如果我们不作任何修改的重启系统,那么重启以后将进入当前的缺省操作系统 Windows 2000 而不是先前启动的 Windows XP。 GetSystemDirectory() 可以获得当前操作系统所在目录。
开始我们想当然的将盘符和分区作了以下映射
C: -> partition(1)
D: -> partition(2)
E: -> partition(3)
.......
后来这里被 Report 了一个 Bug, 在 Dell 600m 笔记本电脑上, 单一操作系统, 我们的程序无法正常重启系统。检查后发现这个型号的笔记本电脑有一个隐藏分区,而 C: 则是 partition(2)。我们必须寻找一个途径将驱动器号转换成分区号。
查阅 MSDN 后得知标准 Win32 API 的解决方法, 简单范例:
#include <stdlib.h> #include <stdio.h> #include <windows.h> #include <Winioctl.h> #include <iostream.h>
// Required to ensure correct PhysicalDrive IOCTL structure setup #pragma pack(1)
int main(int argc, char** argv) { HANDLE hDrv = CreateFile(".//C:", GENERIC_READ, // Read only to the drive FILE_SHARE_READ | // share mode FILE_SHARE_WRITE, NULL, // default security attributes OPEN_EXISTING, // disposition 0, // file attributes NULL);
if(!hDrv) { cout << "Error Can not open the Driver " << GetLastError(); return 0; }
PARTITION_INFORMATION pinfo; DWORD lpBytesReturned;
BOOL bSuccess = DeviceIoControl( (HANDLE) hDrv, // handle to a partition IOCTL_DISK_GET_PARTITION_INFO, // dwIoControlCode NULL, // lpInBuffer 0, // nInBufferSize (LPVOID) &pinfo, // output buffer (DWORD) sizeof(pinfo), // size of output buffer (LPDWORD) &lpBytesReturned, // number of bytes returned (LPOVERLAPPED) NULL // OVERLAPPED structure );
CloseHandle(hDrv);
if(!bSuccess) { cout << "ERROR " << GetLastError(); return 0; } cout << pinfo.PartitionNumber;
return 1; }
|