-
Oct 29th, 2009, 06:07 PM
#1
Thread Starter
New Member
physical disk raw access
Hello,
I need to access the physical disk (removable SD card) in raw mode and write data to the sectors. I am currently doing this with HxD http://mh-nexus.de/en/ but I need to do it from within my visual basic program.
An example would be helpfull.
I am using VB6.
Thanks.
-
Dec 1st, 2009, 04:00 AM
#2
New Member
Re: physical disk raw access
Hello,
I have the same problem with access to a sd card of 512Mo, i have used a few programs that i have found on the net, but no of this program can use raw or physical access ?
I have found a VB6 program wich can access curiously in logical access and read the 955 thirst binary sectors and read error on the 956 ?
Have you found today a solution to your problem ?
Thank you
Jo
-
Dec 6th, 2009, 01:05 AM
#3
Addicted Member
Re: physical disk raw access
Vista and Windows 7 block write access to a mounted volume unless it's locked first: http://msdn.microsoft.com/en-us/library/cc835968.aspx
As that article states, you can either unmount it first or lock it during the write operation and unlock it when finished. This example uses the lock method:
Code:
Option Explicit
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Private Declare Function SetFilePointer Lib "kernel32" (ByVal hFile As Long, ByVal lDistanceToMove As Long, lpDistanceToMoveHigh As Long, ByVal dwMoveMethod 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
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
Private Declare Function CreateFile Lib "kernel32" 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
Private Declare Function FlushFileBuffers Lib "kernel32" (ByVal hFile As Long) As Long
Private Declare Function LockFile Lib "kernel32" (ByVal hFile As Long, ByVal dwFileOffsetLow As Long, ByVal dwFileOffsetHigh As Long, ByVal nNumberOfBytesToLockLow As Long, ByVal nNumberOfBytesToLockHigh As Long) As Long
Private Declare Function UnlockFile Lib "kernel32" (ByVal hFile As Long, ByVal dwFileOffsetLow As Long, ByVal dwFileOffsetHigh As Long, ByVal nNumberOfBytesToUnlockLow As Long, ByVal nNumberOfBytesToUnlockHigh As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject 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&
Private Const BytesPerSector = 512
Private Const FILE_BEGIN = 0
Private Function DirectWriteDriveNT(ByVal sDrive As String, ByVal iStartSec As Long, ByVal iOffset As Long, ByVal sWrite As String) As Boolean
Dim hDevice As Long
Dim abBuff() As Byte
Dim nSectors As Long
Dim nRead As Long
Dim ab() As Byte
nSectors = Int((iOffset + Len(sWrite) - 1) / BytesPerSector) + 1
hDevice = CreateFile(sDrive, GENERIC_READ Or GENERIC_WRITE, FILE_SHARE_READ Or FILE_SHARE_WRITE, 0&, OPEN_EXISTING, 0&, 0&)
If hDevice = INVALID_HANDLE_VALUE Then Exit Function
abBuff = DirectReadDriveNT(sDrive, iStartSec, 0, nSectors * BytesPerSector)
ab = StrConv(sWrite, vbFromUnicode)
CopyMemory abBuff(iOffset), ab(0), Len(sWrite)
Call SetFilePointer(hDevice, iStartSec * BytesPerSector, 0, FILE_BEGIN)
Call LockFile(hDevice, LoWord(iStartSec * BytesPerSector), HiWord(iStartSec * BytesPerSector), LoWord(nSectors * BytesPerSector), HiWord(nSectors * BytesPerSector))
DirectWriteDriveNT = WriteFile(hDevice, abBuff(0), UBound(abBuff) + 1, nRead, 0&)
Call FlushFileBuffers(hDevice)
Call UnlockFile(hDevice, LoWord(iStartSec * BytesPerSector), HiWord(iStartSec * BytesPerSector), LoWord(nSectors * BytesPerSector), HiWord(nSectors * BytesPerSector))
CloseHandle hDevice
End Function
Private Function DirectReadDriveNT(ByVal sDrive As String, ByVal iStartSec As Long, ByVal iOffset As Long, ByVal cBytes As Long) As Variant
Dim hDevice As Long
Dim nSectors As Long
Dim nRead As Long
Dim abResult() As Byte
nSectors = Int((iOffset + cBytes - 1) / BytesPerSector) + 1
hDevice = CreateFile(sDrive, GENERIC_READ Or GENERIC_WRITE, FILE_SHARE_READ Or FILE_SHARE_WRITE, 0&, OPEN_EXISTING, 0&, 0&)
If hDevice = INVALID_HANDLE_VALUE Then Exit Function
Call SetFilePointer(hDevice, iStartSec * BytesPerSector, 0, FILE_BEGIN)
ReDim abResult(cBytes - 1)
ReDim abBuff(nSectors * BytesPerSector - 1)
Call ReadFile(hDevice, abBuff(0), UBound(abBuff) + 1, nRead, 0&)
CloseHandle hDevice
CopyMemory abResult(0), abBuff(iOffset), cBytes
DirectReadDriveNT = abResult '(0)
End Function
Private Function LoWord(ByVal dw As Long) As Integer
If dw And &H8000& Then
LoWord = dw Or &HFFFF0000
Else
LoWord = dw And &HFFFF&
End If
End Function
Private Function HiWord(ByVal dw As Long) As Integer
HiWord = (dw And &HFFFF0000) \ 65536
End Function
Private Function hex2ascii(ByVal hextext As String) As String
Dim y As Integer
Dim num
Dim Value
For y = 1 To Len(hextext)
num = Mid(hextext, y, 2)
Value = Value & Chr(Val("&h" & num))
y = y + 1
Next y
hex2ascii = Value
End Function
Call it like this:
Code:
Private Sub Command1_Click()
' Write hex "EB" to the first byte of the MBR on PhysicalDrive2
DirectWriteDriveNT "\\?\PhysicalDrive2", 0, 0, hex2ascii("eb")
End Sub
OR:
Code:
Private Sub Command1_Click()
' Write hex "EB" to the first byte of the first partition boot sector of PhysicalDrive2:
DirectWriteDriveNT "\\?\PhysicalDrive2", 63, 0, hex2ascii("eb")
End Sub
Assuming that H: is the first partition on PhysicalDrive2, this does the same thing as the previous example:
Code:
Private Sub Command1_Click()
' Write hex "EB" to the first byte of the partition boot sector of volume H:
DirectWriteDriveNT "\\?\H:", 0, 0, hex2ascii("eb")
End Sub
Code:
Private Sub Command1_Click()
' Write hex "EB" to the last byte of the partition boot sector of volume H:
DirectWriteDriveNT "\\?\H:", 0, 511, hex2ascii("eb")
End Sub
Code:
Private Sub Command1_Click()
' Write hex "EB" to the last byte of the MBR of PhysicalDrive2
DirectWriteDriveNT "\\?\PhysicalDrive2", 0, 511, hex2ascii("eb")
End Sub
Change "PhysicalDrive2" and "H:" to match your drive layout.
-
Dec 6th, 2009, 03:07 AM
#4
New Member
Re: physical disk raw access
Thank you pcuser
all is right now, i can read and write my sd card
this is a good work !!!
thanks for all
Jo
-
Mar 1st, 2010, 05:32 PM
#5
Thread Starter
New Member
Re: physical disk raw access
I works! but very slow transfer. can I do anything here?
Last edited by georpo; Mar 1st, 2010 at 05:58 PM.
-
Mar 3rd, 2010, 01:40 AM
#6
Addicted Member
Re: physical disk raw access
I works! but very slow transfer. can I do anything here?
Just because it's "possible" to do something like this with VB doesn't always mean that it "should" be done with VB.
Have you ever heard of Thunder VB?
ThunderVB is an add-in for VB6. ThunderVB let's you embed Asm and C instructions directly in you VB source programs.
Let's take the above DirectReadDriveNT function for example:
Code:
Private Function DirectReadDriveNT(ByVal sDrive As String, ByVal iStartSec As Long, ByVal iOffset As Long, ByVal cBytes As Long) As Variant
Dim hDevice As Long
Dim nSectors As Long
Dim nRead As Long
Dim abResult() As Byte
nSectors = Int((iOffset + cBytes - 1) / BytesPerSector) + 1
hDevice = CreateFile(sDrive, GENERIC_READ Or GENERIC_WRITE, FILE_SHARE_READ Or FILE_SHARE_WRITE, 0&, OPEN_EXISTING, 0&, 0&)
If hDevice = INVALID_HANDLE_VALUE Then Exit Function
Call SetFilePointer(hDevice, iStartSec * BytesPerSector, 0, FILE_BEGIN)
ReDim abResult(cBytes - 1)
ReDim abBuff(nSectors * BytesPerSector - 1)
Call ReadFile(hDevice, abBuff(0), UBound(abBuff) + 1, nRead, 0&)
CloseHandle hDevice
CopyMemory abResult(0), abBuff(iOffset), cBytes
DirectReadDriveNT = abResult '(0)
End Function
That's alot of overhead to read a single byte. Here's an example in C that does the same thing:
Code:
#include <io.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
int fd;
int result;
unsigned char buf[512];
fd = open("\\\\.\\PhysicalDrive1",0);
if (fd == -1)
{
printf("%d Open \n", fd);
return -2;
}
result = read(fd, buf, 512);
printf ("%d Read \n", buf[511]);
return buf[511];
}
Here's how to do it from VB using inline C with Thunder VB:
Code:
Public Function ReadDrive(ByVal MyByte As Integer) As Long
'#c'
'#c'lib="C:\Program Files\Microsoft Visual Studio\VC98\lib\msvcrt.lib"
'#c'lib="C:\Program Files\Microsoft Visual Studio\VC98\\lib\oldnames.lib"
'#c'#include "C:\Program Files\Microsoft Visual Studio\VC98\include\io.h"
'#c'
'#c'int ReadDrive(int MyByte)
'#c'{
'#c' int fd;
'#c' int result;
'#c' unsigned char buf[512];
'#c'
'#c' fd = open("\\\\.\\PhysicalDrive1", 0);
'#c'
'#c' if (fd == -1)
'#c' {
'#c' return -2;
'#c' }
'#c'
'#c' result = read(fd, buf, 512);
'#c'
'#c' close(fd);
'#c'
'#c' return buf[MyByte];
'#c'}
End Function
Here's how to call that C function from VB and return the last byte of the MBR:
Code:
Private Sub Command1_Click()
MsgBox Hex(ReadDrive(511))
End Sub
The original code that was posted can most likely be optimized (to an extent) for your specific needs but we don't know what that is. Inline C or ASM with Thunder VB will probabally be much better though.
-
Sep 25th, 2011, 11:25 PM
#7
Frenzied Member
Re: physical disk raw access
Originally Posted by pcuser
Vista and Windows 7 block write access to a mounted volume unless it's locked first: http://msdn.microsoft.com/en-us/library/cc835968.aspx
As that article states, you can either unmount it first or lock it during the write operation and unlock it when finished. This example uses the lock method:
Code:
Option Explicit
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Private Declare Function SetFilePointer Lib "kernel32" (ByVal hFile As Long, ByVal lDistanceToMove As Long, lpDistanceToMoveHigh As Long, ByVal dwMoveMethod 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
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
Private Declare Function CreateFile Lib "kernel32" 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
Private Declare Function FlushFileBuffers Lib "kernel32" (ByVal hFile As Long) As Long
Private Declare Function LockFile Lib "kernel32" (ByVal hFile As Long, ByVal dwFileOffsetLow As Long, ByVal dwFileOffsetHigh As Long, ByVal nNumberOfBytesToLockLow As Long, ByVal nNumberOfBytesToLockHigh As Long) As Long
Private Declare Function UnlockFile Lib "kernel32" (ByVal hFile As Long, ByVal dwFileOffsetLow As Long, ByVal dwFileOffsetHigh As Long, ByVal nNumberOfBytesToUnlockLow As Long, ByVal nNumberOfBytesToUnlockHigh As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject 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&
Private Const BytesPerSector = 512
Private Const FILE_BEGIN = 0
Private Function DirectWriteDriveNT(ByVal sDrive As String, ByVal iStartSec As Long, ByVal iOffset As Long, ByVal sWrite As String) As Boolean
Dim hDevice As Long
Dim abBuff() As Byte
Dim nSectors As Long
Dim nRead As Long
Dim ab() As Byte
nSectors = Int((iOffset + Len(sWrite) - 1) / BytesPerSector) + 1
hDevice = CreateFile(sDrive, GENERIC_READ Or GENERIC_WRITE, FILE_SHARE_READ Or FILE_SHARE_WRITE, 0&, OPEN_EXISTING, 0&, 0&)
If hDevice = INVALID_HANDLE_VALUE Then Exit Function
abBuff = DirectReadDriveNT(sDrive, iStartSec, 0, nSectors * BytesPerSector)
ab = StrConv(sWrite, vbFromUnicode)
CopyMemory abBuff(iOffset), ab(0), Len(sWrite)
Call SetFilePointer(hDevice, iStartSec * BytesPerSector, 0, FILE_BEGIN)
Call LockFile(hDevice, LoWord(iStartSec * BytesPerSector), HiWord(iStartSec * BytesPerSector), LoWord(nSectors * BytesPerSector), HiWord(nSectors * BytesPerSector))
DirectWriteDriveNT = WriteFile(hDevice, abBuff(0), UBound(abBuff) + 1, nRead, 0&)
Call FlushFileBuffers(hDevice)
Call UnlockFile(hDevice, LoWord(iStartSec * BytesPerSector), HiWord(iStartSec * BytesPerSector), LoWord(nSectors * BytesPerSector), HiWord(nSectors * BytesPerSector))
CloseHandle hDevice
End Function
Private Function DirectReadDriveNT(ByVal sDrive As String, ByVal iStartSec As Long, ByVal iOffset As Long, ByVal cBytes As Long) As Variant
Dim hDevice As Long
Dim nSectors As Long
Dim nRead As Long
Dim abResult() As Byte
nSectors = Int((iOffset + cBytes - 1) / BytesPerSector) + 1
hDevice = CreateFile(sDrive, GENERIC_READ Or GENERIC_WRITE, FILE_SHARE_READ Or FILE_SHARE_WRITE, 0&, OPEN_EXISTING, 0&, 0&)
If hDevice = INVALID_HANDLE_VALUE Then Exit Function
Call SetFilePointer(hDevice, iStartSec * BytesPerSector, 0, FILE_BEGIN)
ReDim abResult(cBytes - 1)
ReDim abBuff(nSectors * BytesPerSector - 1)
Call ReadFile(hDevice, abBuff(0), UBound(abBuff) + 1, nRead, 0&)
CloseHandle hDevice
CopyMemory abResult(0), abBuff(iOffset), cBytes
DirectReadDriveNT = abResult '(0)
End Function
Private Function LoWord(ByVal dw As Long) As Integer
If dw And &H8000& Then
LoWord = dw Or &HFFFF0000
Else
LoWord = dw And &HFFFF&
End If
End Function
Private Function HiWord(ByVal dw As Long) As Integer
HiWord = (dw And &HFFFF0000) \ 65536
End Function
Private Function hex2ascii(ByVal hextext As String) As String
Dim y As Integer
Dim num
Dim Value
For y = 1 To Len(hextext)
num = Mid(hextext, y, 2)
Value = Value & Chr(Val("&h" & num))
y = y + 1
Next y
hex2ascii = Value
End Function
Call it like this:
Code:
Private Sub Command1_Click()
' Write hex "EB" to the first byte of the MBR on PhysicalDrive2
DirectWriteDriveNT "\\?\PhysicalDrive2", 0, 0, hex2ascii("eb")
End Sub
OR:
Code:
Private Sub Command1_Click()
' Write hex "EB" to the first byte of the first partition boot sector of PhysicalDrive2:
DirectWriteDriveNT "\\?\PhysicalDrive2", 63, 0, hex2ascii("eb")
End Sub
Assuming that H: is the first partition on PhysicalDrive2, this does the same thing as the previous example:
Code:
Private Sub Command1_Click()
' Write hex "EB" to the first byte of the partition boot sector of volume H:
DirectWriteDriveNT "\\?\H:", 0, 0, hex2ascii("eb")
End Sub
Code:
Private Sub Command1_Click()
' Write hex "EB" to the last byte of the partition boot sector of volume H:
DirectWriteDriveNT "\\?\H:", 0, 511, hex2ascii("eb")
End Sub
Code:
Private Sub Command1_Click()
' Write hex "EB" to the last byte of the MBR of PhysicalDrive2
DirectWriteDriveNT "\\?\PhysicalDrive2", 0, 511, hex2ascii("eb")
End Sub
Change "PhysicalDrive2" and "H:" to match your drive layout.
AWESOME CODE!
Now how do I address drives without funny names like "//?/physicaldrive2", and instead directly use volume numbers such as the numerical value 2 to mean "volume 2". I see how the code works. It takes a String value for the drive identifier. I'd prefer if it took a Byte or Integer value for the drive identifier, to represent the volume number.
This would be MUCH easier, because when I program I think about the drive's number, not some overcomplicated string name.
How could I change your code to make it work that way?
-
Sep 26th, 2011, 02:08 PM
#8
Addicted Member
Re: physical disk raw access
Where does the volume number come from and how is it determined?
-
Sep 26th, 2011, 10:07 PM
#9
Frenzied Member
Re: physical disk raw access
Originally Posted by pcuser
Where does the volume number come from and how is it determined?
I believe it's automatically assigned to a given drive at a low level by the CPU when a new drive is added, as DOS software always referred to drives by volume number.
On another note this program glitches like crazy. When I said how good it was, I had at that point only tried to read and/or write data to one sector (usually the first sector). I've found now that performing operations on a sector other than the first on a disk, and ESPECIALLY when I use a FOR...NEXT loop to read or write to multiple sectors sequentially, it really crashes and gives the standard Windows error of such and such a program has crashed and asks me to send the "error report" to Microsoft.
Please debug your code and re-release it. This code in its current state SUCKS BAD.
-
Sep 26th, 2011, 11:12 PM
#10
Addicted Member
Re: physical disk raw access
Please debug your code and re-release it. This code in its current state SUCKS BAD.
Maybe YOUR code in it's current state SUCKS BAD?
Last edited by pcuser; Sep 26th, 2011 at 11:45 PM.
-
Sep 27th, 2011, 11:55 PM
#11
Addicted Member
Re: physical disk raw access
I believe it's automatically assigned to a given drive at a low level by the CPU when a new drive is added
The CPU doesn't assign volume numbers.
as DOS software always referred to drives by volume number.
You may have posted in the wrong section of the forum. This is the Windows API section, not the DOS section.
On another note this program glitches like crazy.
I didn't post a finished program and therefore am guessing that you're referring to your own program. What exactly are you trying to do and how exactly are you trying to do it?
I've found now that performing operations on a sector other than the first on a disk, and ESPECIALLY when I use a FOR...NEXT loop to read or write to multiple sectors sequentially, it really crashes and gives the standard Windows error of such and such a program has crashed and asks me to send the "error report" to Microsoft.
Now I really want to know what you're trying to accomplish and would like to see the code that you're using.
-
Jan 11th, 2013, 02:21 AM
#12
Frenzied Member
Re: physical disk raw access
Still doesn't work in Windows 7.
My program is written in VB6. If I try to raw-write to any sector on my USB Jumpdrive that is other than sector-0, it refuses to do so. This means if the sector offset is 1 or more, or if the data I'm saving to sector-0 is more than 512 bytes so that it has to move on to sector-1, it refuses to perform the write. The API is NOT LETTING ME WRITE to my own drive, just to "protect" me from damaging it, and you say I can get around that with your code that uses the locking method, but IT DOESN'T WORK!
Yet the freeware hex editor program HxD, seems to have ABSOLUTELY NO PROBLEM letting me write ABSOLUTELY ANYWHERE on the drive with ANY LENGTH of data I might want, just as if the whole drive was ONE LARGE FILE.
Now why can't I get VB6 and Windows API to do that?
By the way, I'm using Windows 7 Home Premium, 64bit version. And I believe it also has SP1 on it.
-
Sep 16th, 2013, 02:15 PM
#13
Fanatic Member
Re: physical disk raw access
I also had problems with Windows 7 (Excel would hang/quit) but seem to have found a fix. I noticed that abBuff was not declared in DirectReadDriveNT. I added the statement Dim abBuff() as Byte and everything now works fine.
-
May 1st, 2014, 08:16 AM
#14
Frenzied Member
Re: physical disk raw access
Why do you use "\\?\PhysicalDrive2" with the question mark like that? It's supposed to have a period like "\\.\PhysicalDrive2".
-
May 2nd, 2014, 02:44 PM
#15
Re: physical disk raw access
I think that you should look at the documentation for the CreateFile, SetFilePointer and LockFile APIs. All 3 return values indicating success or failure. By using those values you should be able to identify where the problem(s) lie.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|