option explicit
'/////////////////////////////////////////
'// 對磁盤的物理扇區數據讀/寫操作
'// last update: 2004-8-7
'// kwanhong young
'/////////////////////////////////////////
'//file system
private declare function createfile lib "kernel32" alias "createfilea" (byval lpfilename as string, byval dwdesiredaccess as long, byval dwsharemode as long, lpsecurityattributes as long, byval dwcreationdisposition as long, byval dwflagsandattributes as long, byval htemplatefile as long) as long
private declare function closehandle lib "kernel32" (byval hobject as long) as long
private declare function readfile lib "kernel32" (byval hfile as long, lpbuffer as any, byval nnumberofbytestoread as long, lpnumberofbytesread as long, byval lpoverlapped as long) as long '//declare has changed
private declare function writefile lib "kernel32" (byval hfile as long, lpbuffer as any, byval nnumberofbytestowrite as long, lpnumberofbyteswritten as long, byval lpoverlapped as long) as long '//declare has changed
private declare function setfilepointer lib "kernel32" (byval hfile as long, byval ldistancetomove as long, lpdistancetomovehigh as long, byval dwmovemethod as long) as long
private const generic_read = &h80000000
private const generic_write = &h40000000
private const file_share_read = &h1
private const file_share_write = &h2
private const open_existing = 3
private const invalid_handle_value = -1
'//file seek
private const file_begin = 0
private const file_current = 1
private const file_end = 2
private const error_success = 0&
'//device io control
private declare function deviceiocontrol lib "kernel32" (byval hdevice as long, byval dwiocontrolcode as long, lpinbuffer as any, byval ninbuffersize as long, lpoutbuffer as any, byval noutbuffersize as long, lpbytesreturned as long, byval lpoverlapped as long) as long
private const ioctl_disk_get_drive_geometry as long = &h70000 '458752
private const ioctl_storage_get_media_types_ex as long = &h2d0c04
private const ioctl_disk_format_tracks as long = &h7c018
private const fsctl_lock_volume as long = &h90018
private const fsctl_unlock_volume as long = &h9001c
private const fsctl_dismount_volume as long = &h90020
private const fsctl_get_volume_bitmap = &h9006f
'//type
private type large_integer
 lowpart as long
 highpart as long
end type
private enum media_type
 unknown
 f5_1pt2_512
 f3_1pt44_512
 f3_2pt88_512
 f3_20pt8_512
 f3_720_512
 f5_360_512
 f5_320_512
 f5_320_1024
 f5_180_512
 f5_160_512
 removablemedia
 fixedmedia
end enum
private type disk_geometry
 cylinders as large_integer
 mediatype as media_type
 trackspercylinder as long
 sectorspertrack as long
 bytespersector as long
end type
'//private vars
private hdisk as long 'disk handle
private lpgeometry as disk_geometry 'disk info
private lbuffersize as long 'the buffer size of read/write
public function opendisk(byval filename as string) as boolean
'// 打開磁盤
 hdisk = createfile(filename, _
 generic_read or generic_write, _
 file_share_read or file_share_write, _
 byval 0&, _
 open_existing, _
 0, _
 0)
 opendisk = not (hdisk = invalid_handle_value)
end function
public function closedisk() as boolean
'//關閉磁盤
 closedisk = closehandle(hdisk)
end function
public function getdiskgeometry() as boolean
'//獲取磁盤參數
 dim dwoutbytes as long
 dim bresult as boolean
 
 bresult = deviceiocontrol(hdisk, _
 ioctl_disk_get_drive_geometry, _
 byval 0&, 0, _
 lpgeometry, len(lpgeometry), _
 dwoutbytes, _
 byval 0&)
 
 if bresult then lbuffersize = lpgeometry.bytespersector * lpgeometry.sectorspertrack
 getdiskgeometry = bresult
end function
public sub getdiskinfo(mediatype as long, _
 cylinders as long, _
 trackspercylinder as long, _
 sectorspertrack as long, _
 bytespersector as long)
'//返回磁盤的參數
 mediatype = lpgeometry.mediatype
 cylinders = lpgeometry.cylinders.lowpart
 trackspercylinder = lpgeometry.trackspercylinder
 sectorspertrack = lpgeometry.sectorspertrack
 bytespersector = lpgeometry.bytespersector
end sub
public property get buffersize() as long
'//返回每次讀/寫的緩沖大小
 buffersize = lbuffersize
end property
public function lockvolume() as boolean
'// 將卷鎖定
 dim dwoutbytes as long
 dim bresult as boolean
 
 bresult = deviceiocontrol(hdisk, _
 fsctl_lock_volume, _
 byval 0&, 0, _
 byval 0&, 0, _
 dwoutbytes, _
 byval 0&)
 lockvolume = bresult
end function
public function unlockvolume() as boolean
'// 將卷解鎖
 dim dwoutbytes as long
 dim bresult as boolean
 
 bresult = deviceiocontrol(hdisk, _
 fsctl_unlock_volume, _
 byval 0&, 0, _
 byval 0&, 0, _
 dwoutbytes, _
 byval 0&)
 unlockvolume = bresult
end function
public function dismountvolume() as boolean
'// 將卷卸下,使系統重新辨識磁盤,等效于重新插盤
 dim dwoutbytes as long
 dim bresult as boolean
 
 bresult = deviceiocontrol(hdisk, _
 fsctl_dismount_volume, _
 byval 0&, 0, _
 byval 0&, 0, _
 dwoutbytes, _
 byval 0&)
 dismountvolume = bresult
end function
public function readdisk(byval cylinders as long, _
 byval tracks as long, _
 db() as byte) as boolean
'//按柱面和磁道來讀取磁盤數據
 dim ipos as long
 dim lread as long
 
 ipos = cylinders * tracks * lbuffersize
 
 if seekabsolute(0, ipos) then
 readdisk = readbytes(lbuffersize, db(), lread)
 end if
end function
public function writedisk(byval cylinders as long, _
 byval tracks as long, _
 db() as byte) as boolean
'//按柱面和磁道來寫磁盤數據
 dim ipos as long
 dim lread as long
 
 ipos = cylinders * tracks * lbuffersize
 
 if seekabsolute(0, ipos) then
 writedisk = writebytes(lbuffersize, db())
 end if
end function
'/////////////////////////////////////////////////////////////////////////////////////
'//file system
private function seekabsolute(byval highpos as long, byval lowpos as long) as boolean
'//seek file
 '//notice: when you set lowpos=5, the read/write will begin with the 6th(lowpos+1) byte
 lowpos = setfilepointer(hdisk, lowpos, highpos, file_begin)
 if lowpos = -1 then
 seekabsolute = (err.lastdllerror = error_success)
 else
 seekabsolute = true
 end if
 
end function
private function readbytes(byval bytecount as long, byref databytes() as byte, byref actuallyreadbyte as long) as boolean
'//read data to array
 dim retval as long
 retval = readfile(hdisk, databytes(0), bytecount, actuallyreadbyte, 0)
 'actuallyreadbyte =>> if the bytesread=0 mean eof
 readbytes = not (retval = 0)
 
end function
private function writebytes(byval bytecount as long, byref databytes() as byte) as boolean
'//write data from array
 dim retval as long
 dim bytestowrite as long
 dim byteswritten as long
 
 retval = writefile(hdisk, databytes(0), bytecount, byteswritten, 0)
 
 writebytes = not (retval = 0)
end function