La Web del Programador: Comunidad de Programadores
 
    Pregunta:  1928 - LEER/ESCRIBIR LOS SECTORES DE UN DISCO
Autor:  Cristhian Guzman Echeverria
Como puedo Leer/Escribir los sectores del disco duro mediante las API´s, lo que deseo es tener acceso a la parte fisica del disco duro, lo necesito para un programa que corra sobre windows, ya sea usando las API´s o un lenguaje ensamblador para windows

  Respuesta:  Paul Wolfe
' Para acceso R/W directamente a los sectores de un disco hay ciertas reglas.
'La longitud del buffer de lectura / escritura debe ser un múltiplo del tamaño de los sectores del disco, que generalmente es de 512 bytes.
'También el puntero de lectura / escritura debe estár posicionado al principio de un sector.
'Tanto el conteo de los sectores, como la posicion dentro de ellos empieza con 0. Por ejemplo si un disco tiene 1024 sectores, el primero será el sector 0, y el último el 1023. De igual manera un sector de 512 bytes comienza con la posición 0, y termina con 511.

'*******ESPERO TE SIRVA ESTO:**************

Option Explicit


Public Declare Function GetDiskFreeSpace Lib "Kernel32.dll" Alias "GetDiskFreeSpaceA" (ByVal lpRootPathName As String, lpSectorsPerCluster As Long, lpBytesPerSector As Long, lpNumberOfFreeClusters As Long, lpTotalNumberOfClusters As Long) As Long
Public Declare Function GetVolumeInformation Lib "Kernel32.dll" Alias "GetVolumeInformationA" (ByVal lpRootPathName As String, ByVal lpVolumeNameBuffer As String, ByVal nVolumeNameSize As Long, lpVolumeSerialNumber As Long, lpMaximumComponentLength As Long, lpFileSystemFlags As Long, ByVal lpFileSystemNameBuffer As String, ByVal nFileSystemNameSize As Long) As Long
Public Declare Function GetDriveType Lib "Kernel32.dll" Alias "GetDriveTypeA" (ByVal nDrive As String) As Long
Public Declare Function CreateFile Lib "Kernel32.dll" Alias "CreateFileA" (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, ByVal lpSecurityAttributes As Long, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long
Public Declare Function CloseHandle Lib "Kernel32.dll" (ByVal hObject As Long) As Long
Public Declare Function SetFilePointer Lib "Kernel32.dll" (ByVal hFile As Long, ByVal lDistanceToMove As Long, lpDistanceToMoveHigh As Long, ByVal dwMoveMethod As Long) As Long
Public Declare Function ReadFile Lib "Kernel32.dll" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToRead As Long, lpNumberOfBytesRead As Long, ByVal lpOverlapped As Long) As Long
Public Declare Function WriteFile Lib "Kernel32.dll" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToWrite As Long, lpNumberOfBytesWritten As Long, ByVal lpOverlapped As Long) As Long
Public Declare Function FlushFileBuffers Lib "Kernel32.dll" (ByVal hFile As Long) As Long
Public Declare Function DeviceIoControl Lib "Kernel32.dll" (ByVal hDevice As Long, ByVal dwIoControlCode As Long, ByRef lpInBuffer As Any, ByVal nInBufferSize As Long, ByRef lpOutBuffer As Any, ByVal nOutBufferSize As Long, ByRef lpBytesReturned As Long, ByVal lpOverlapped As Long) As Long
Public Declare Sub CopyMemory Lib "Kernel32.dll" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)


Public Const FILE_READ_ACCESS = &H1
Public Const FILE_WRITE_ACCESS = &H2
Public Const GENERIC_READ = &H80000000
Public Const GENERIC_WRITE = &H40000000
Public Const FILE_SHARE_READ = &H1
Public Const FILE_SHARE_WRITE = &H2
Public Const OPEN_EXISTING = 3
Public Const INVALID_HANDLE_VALUE = -1&
Public Const FILE_BEGIN = 0
Public Const FILE_CURRENT = 1
'Public Const lngMaxSectors As Long = 4194303
'Public Const FILE_END = 2
Public Const FSCTL_LOCK_VOLUME As Long = &H90018
Public Const FSCTL_UNLOCK_VOLUME As Long = &H9001C

Public Type typeVolumeInformation
byteTipoUnidad As Byte ' Removible=2, Fijo=3, etc..
byteEtiqueta() As Byte
byteSistemaArchivos() As Byte
lngSerialVolumen As Long
lngBytesPorSector As Long
lngSectoresPorCluster As Long
lngBytesPorCluster As Long
lngTotalDeSectores As Long
lngSectoresLibres As Long
lngTotalDeClusters As Long
lngClustersLibres As Long
End Type

Public Function ObtenerInfoVolumen(ByVal byteDrv As Byte, typeRetVolInfo As typeVolumeInformation) As Long
On Error Resume Next

If byteDrv <= 0 Or byteDrv > 26 Then Exit Function ' Unidad incorrecta, sale...

Const lStrLen = 256
Dim sUnidad As String: sUnidad = ""
Dim lRet As Long: lRet = 0
Dim l As Long: l = 0

Dim sVolLabel As String: sVolLabel = String(lStrLen, 0)
Dim sVolFileSys As String: sVolFileSys = String(lStrLen, 0)
Dim lTmpTotalClusters As Long: lTmpTotalClusters = 0
Dim lTmpBytesSec As Long: lTmpBytesSec = 0

sUnidad = Chr$(byteDrv + 64) & ":\"
typeRetVolInfo.byteTipoUnidad = CByte(GetDriveType(sUnidad))
If typeRetVolInfo.byteTipoUnidad <> 2 And typeRetVolInfo.byteTipoUnidad <> 3 And typeRetVolInfo.byteTipoUnidad <> 5 And typeRetVolInfo.byteTipoUnidad <> 6 Then Exit Function

lRet = GetDiskFreeSpace(sUnidad, typeRetVolInfo.lngSectoresPorCluster, lTmpBytesSec, l, lTmpTotalClusters)
If lTmpBytesSec > 0 Then
typeRetVolInfo.lngBytesPorSector = lTmpBytesSec
Else
typeRetVolInfo.lngBytesPorSector = 512
End If
typeRetVolInfo.lngTotalDeSectores = typeRetVolInfo.lngSectoresPorCluster * lTmpTotalClusters
typeRetVolInfo.lngBytesPorCluster = typeRetVolInfo.lngSectoresPorCluster * typeRetVolInfo.lngBytesPorSector
Call GetVolumeInformation(sUnidad, sVolLabel, lStrLen, typeRetVolInfo.lngSerialVolumen, &H0, &H0, sVolFileSys, lStrLen)
sVolLabel = Replace(sVolLabel, Chr(0), "")
sVolFileSys = Replace(sVolFileSys, Chr(0), "")
If sVolLabel <> vbNullString Then ' Convertir a array de bytes:...
For l = 1 To Len(sVolLabel)
ReDim Preserve typeRetVolInfo.byteEtiqueta(l - 1)
typeRetVolInfo.byteEtiqueta(l - 1) = CByte(Asc(Mid$(sVolLabel, l, 1)))
Next l
Else
ReDim typeRetVolInfo.byteEtiqueta(0)
typeRetVolInfo.byteEtiqueta(0) = 0
End If
If sVolFileSys <> vbNullString Then ' Convertir a array de bytes:...
For l = 1 To Len(sVolFileSys)
ReDim Preserve typeRetVolInfo.byteSistemaArchivos(l - 1)
typeRetVolInfo.byteSistemaArchivos(l - 1) = CByte(Asc(Mid$(sVolFileSys, l, 1)))
Next l
Else
ReDim typeRetVolInfo.byteSistemaArchivos(0)
typeRetVolInfo.byteSistemaArchivos(0) = 0
End If

FsOk:
If Err = 0 Then ObtenerInfoVolumen = 1
On Error GoTo 0
End Function



Public Function LeerDisco(ByVal byteDrv As Byte, ByVal lngSectorInicial As Long, ByVal lngPosicion As Long, ByRef byteRetArray() As Byte, ByVal lngCntBytes As Long) As Long
On Error Resume Next

'Dim sDrive As String: sDrive = Chr$(byteDrv + 64) & ":"
Dim tDatosVol As typeVolumeInformation
Dim lRet As Long: lRet = ObtenerInfoVolumen(byteDrv, tDatosVol)
If lRet = 0 Then Exit Function
lRet = 0

Dim lCVolumen As Long: lCVolumen = 0
Dim iSectores As Integer: iSectores = 0
Dim lngLow As Long: lngLow = 0
Dim lCntMAXes As Long: lCntMAXes = 0
Dim lngTmpSSec As Long: lngTmpSSec = lngSectorInicial
Dim boolFlagF As Boolean: boolFlagF = False
Dim lTmpBL As Long: lTmpBL = 0

iSectores = Int((lngPosicion + lngCntBytes - 1) / tDatosVol.lngBytesPorSector) + 1
If (lngSectorInicial + iSectores - 1) > (tDatosVol.lngTotalDeSectores - 1) Then Exit Function
lCVolumen = CreateFile("\\.\" & Chr$(byteDrv + 64) & ":", GENERIC_READ Or GENERIC_WRITE, FILE_SHARE_READ Or FILE_SHARE_WRITE, 0&, OPEN_EXISTING, 0&, 0&)
If lCVolumen = INVALID_HANDLE_VALUE Then Exit Function ' Or GENERIC_WRITE

'*********************************************************************************

ReDim abBuff(iSectores * tDatosVol.lngBytesPorSector - 1) As Byte
Call SetPos(lCVolumen, lngSectorInicial, tDatosVol.lngBytesPorSector)
lRet = ReadFile(lCVolumen, abBuff(0), UBound(abBuff) + 1, lTmpBL, 0&)
CloseHandle lCVolumen
ReDim byteRetArray(lngCntBytes - 1)
CopyMemory byteRetArray(0), abBuff(lngPosicion), lngCntBytes
Erase abBuff()
LeerDisco = lngCntBytes 'lTmpBL
On Error GoTo 0
End Function


Public Function SetPos(ByVal lVolHand As Long, ByVal lSecIni As Long, ByVal lBxSec As Long) As Boolean
On Error Resume Next

Const lngMaxValLong As Long = 2147483647
Dim lngMaxSectors As Long: lngMaxSectors = CLng(Fix(lngMaxValLong / lBxSec))
Dim lngTmpSSec As Long: lngTmpSSec = lSecIni
Dim lFileMovePos As Long: lFileMovePos = 0

While lngTmpSSec > lngMaxSectors
Call SetFilePointer(lVolHand, CLng(lngMaxSectors * lBxSec), 0, lFileMovePos)
lngTmpSSec = lngTmpSSec - lngMaxSectors
If lFileMovePos = 0 Then lFileMovePos = 1
Wend
Call SetFilePointer(lVolHand, CLng(lngTmpSSec * lBxSec), 0, lFileMovePos)
If Err = 0 Then SetPos = True
On Error GoTo 0
End Function

  Respuesta:  René Berra
puede que esto te sirva:
Function CopyFile(Src As String, Dst As String) As Single
Static buf$
Dim BTest!, FSize! ´declare the needed variables
Dim Chunk%, F1%, F2%
Const BUFSIZE = 1024 ´set the buffer size
If Len(Dir(Dst)) Then ´check to see if the destination file already exists
Kill Dst ´delete the already found file, and carryon with the code
End If
On Error GoTo FileCopyError ´incase of error goto this label
F1 = FreeFile ´returns file number available
Open Src For Binary As F1 ´open the source file
F2 = FreeFile ´returns file number available
Open Dst For Binary As F2 ´open the destination file
FSize = LOF(F1)
BTest = FSize - LOF(F2)
Do
If BTest < BUFSIZE Then Chunk = BTest Else Chunk = BUFSIZE
buf = String(Chunk, " ")
Get F1, , buf
Put F2, , buf
BTest = FSize - LOF(F2)
Loop Until BTest = 0
Close F1 ´closes the source file
Close F2 ´closes the destination file
CopyFile = FSize
Exit Function ´exit the procedure
FileCopyError: ´file copy error label
CopyFile = 0
Close F1 ´closes the source file
Close F2 ´closes the destination file
Exit Function ´exit the procedure
End Function