Newsgroup: it.comp.lang.visual-basic
Titolo: Lettura disco

Salve a tutti.
Dovrei sviluppare un'applicazione che possa leggere in punti particolari di
un disco richiamabili o come traccia-settore o come numero sequenziale.
Ho controllato su API-Guide, ma non c'è nessuna API che faccia questo
lavoro.
Una volta, con quick basic, c'erano gli interrupt per poter richiamare
queste funzioni sua come traccia-settore che come numero sequenziale, ma
ora, con vb6, non ho trovato nulla.
Chi può darmi una dritta?
Grazie
Sergio

ora, con vb6, non ho trovato nulla.
Ti sei preso una bella gatta da pelare ;-)
Devi rivolgerti all' API di Windows, distinguendo tra i 9x e gli NT,
La chiave di ricerca e' DeviceIOControl.
Per i 9x ho recuperato questo vecchio articolo di msdn, che riporto qui
prima che sparisca (ricordo che c'era anche per NT, ma non lo trovo piu'.
<codice per 9x>
In Windows 95 per accedere ai settori di un disco e` necessario invocare un
particolare virtual device driver, chiamato VWIN32.VXD. Esso fornisce le
funzionalita` degli interrupt del DOS. Nel caso specifico sara` necessario
richiedere l'esecuzione delle funzionalita` dell'INT 25h per la lettura di
un settore di disco e dell'INT 26h per la scrittura.
Il passaggio di parametri avviene con una struttura i cui membri
rappresentano i registri del processore nel momento della chiamata
all'interrupt desiderato. La semantica dei parametri e` la stessa dei
corrispondenti interrupt del DOS.
ESEMPIO
=======
L'applicazione listata nel seguito apre il device A: e legge i primi 512
bytes ovvero il primo settore e lo mostra opportunamente formattato in una
TextBox.
Seguono le istruzione per ricostruire l'applicazione.
1. Creare un nuovo progetto Visual Basic
2. Dimensionare opportunamente Form1 che e` stato creato per default,
esso dovra` accogliere un output di dati binari nel seguente formato:
.........
1C0 64 20 74 68 65 6E 20 70 72 65 73 73 20 61 6E 79 d then press any
1D0 20 6B 65 79 0D 0A 00 00 49 4F 20 20 20 20 20 20 key....IO
.........
3. Porre sul form un TextBox che per default si chiamera` Text1.
4. Dimensionare il TextBox in modo che occupi quasi tutta l'area
disponibile nel form
5. Porre sul form un bottone che per default si chiamera` Command1
6. Associare il codice che segue a Form1.
============ codice di form1 ==================
Option Explicit
Const g_Drive = "A:"
Const SECTOR_SIZE = 512
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 VWIN32_DIOC_DOS_INT25 = 2& 'Read Command
Private Const VWIN32_DIOC_DOS_INT26 = 3& 'Write Command
Private Type DIOC_REGISTER
reg_EBX As Long
reg_EDX As Long
reg_ECX As Long
reg_EAX As Long
reg_EDI As Long
reg_ESI As Long
reg_Flags As Long
End Type
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 CloseHandle Lib "kernel32" ( _
ByVal hObject As Long _
) As Long
Private Declare Function DeviceIoControl Lib "kernel32" ( _
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
Dim buf(0 To SECTOR_SIZE - 1) As Byte
Private Sub DisplaySector()
Dim i As Long, j As Long
Dim s As String
Dim dsply As String
Text1.FontSize = 8
Text1.FontName = "Courier"
For i = 0 To SECTOR_SIZE - 1 Step 16
'index
s = Hex(i)
If Len(s) = 1 Then dsply = dsply & "00"
If Len(s) = 2 Then dsply = dsply & "0"
dsply = dsply & s & " "
'Numbers
For j = 0 To 15
s = Hex(buf(i + j))
If Len(s) = 1 Then dsply = dsply & "0"
dsply = dsply & s & " "
Next j
dsply = dsply & " "
'chars
For j = 0 To 15
s = Chr(buf(i + j))
If Asc(s) < 32 Then
s = "."
End If
dsply = dsply & s
Next j
dsply = dsply & vbNewLine
Next i
Text1.Text = dsply
End Sub
Private Sub Command1_Click()
Dim hDrive As Long
Dim r As Long
Dim nRead As Long
Dim inP As DIOC_REGISTER
Dim outP As DIOC_REGISTER
AutoRedraw = True
hDrive = CreateFile( _
"\\.\VWIN32", _
GENERIC_READ, _
FILE_SHARE_READ Or FILE_SHARE_WRITE, _
0&, OPEN_EXISTING, 0&, 0& _
)
If hDrive = INVALID_HANDLE_VALUE Then
MsgBox "Errore nell'apertura del vwin32 vxd"
Else
' Apertura device OK
inP.reg_EAX = Asc(g_Drive) - Asc("A")
inP.reg_ECX = 1 'one sector
inP.reg_EDX = 0 'sector number
inP.reg_EBX = VarPtr(buf(0))
r = DeviceIoControl(hDrive, VWIN32_DIOC_DOS_INT25, _
inP, Len(inP), _
outP, Len(outP), _
nRead, 0& _
)
CloseHandle hDrive
If r <> 0 Then DisplaySector
End If
End Sub
========== fine codice di form1 ===============
NOTE
====
La numerazione dei settori per i floppy e gli hard disk usuali avviene
numerando sequenzialmente partendo da track=0, head=0, sector=1. Sector
deve essere incrementato prima di head, head prima di track.
E' da notare che e` possibile accedere anche ai settori di uno hard disk.
</codice per 9x>
Per gli NT puoi provare una cosa del genere (prova prima con i floppy!)
<codice per NT>
' PARAMETRI:
'      drive_letter: lettera del drive da leggere;
'      head, sector, track: testina, settore e traccia da cui inizia la lettura;
'      numsec: numero di settori da leggere;
'      sectors_per track: numero di settori per traccia;
'      num_of_heads: numero di testine;
'      bytes_per _sector: bytes per settore (512 se provi con un floppy)
'      ret_Sectors(): array dei byte che sono stati letti;
'
' RITORNO: il numero di bytes letti;
'
Public Function GetSectors(ByVal drive_letter As String, _
                        ByVal head As Long, ByVal sector As Long, _
                        ByVal track As Long, ByVal numsec As Long, _
                        ByVal sectors_per_track As Long, _
                        ByVal num_of_heads As Long, _
                        ByVal bytes_per_sector As Long, _
                        ByRef retSectors() As Byte _
		) As Long
Dim LogicalSector   As Long     '// settore logico corrispondente a H/T/S
Dim hDevice         As Long     '// handle al disco
Dim bytesRead       As Long
'// cerchiamo di ottenere l' handle al disco
hDevice = CreateFile("\\.\" & drive_letter & ":", _
                GENERIC_READ, FILE_SHARE_READ Or FILE_SHARE_WRITE, _
                ByVal 0&, OPEN_EXISTING, ByVal 0&, ByVal 0&)
 
If (0 = hDevice) Then Exit Function     '// abbiamo sbagliato qualcosa
'// calcoliamo il settore logico
LogicalSector = (sector - 1) + (head * sectors_per_track) + _
                        (track * sectors_per_track * num_of_heads)
'// dimensioniamo il buffer che ospitera' il contenuto dei settori da leggere
ReDim retSectors(0 To bytes_per_sector * numsec)
'// puntiamo all' inizio del settore da leggere
Call SetFilePointer(hDevice, _
                 (LogicalSector * bytes_per_sector), _
                 ByVal 0&, _
                 FILE_BEGIN)
'// finalmente leggiamo i settori
If (ReadFile(hDevice, retSectors(0), bytes_per_sector * numsec, bytesRead, ByVal 0&)) Then
    '// restituiamo il numero di byte letti
    GetSectors = bytesRead
End If
CloseHandle (hDevice)
End Function    '// GetSectors
</codice per NT>
Importante:
1. NON ho eseguito questa funzione, quindi non provarla subito sulla
    partizione di sistema, ma collaudala sui floppy;
2. NON ho messo nessun controllo sulla qualita' dei valori ricevuti
    come parametro;
3. I valori da passare come parametro relativi alla geometria del disco
    sono da cercare a parte ;-)
3.  Trovi le dichiarazioni delle chiamate all' API sull' API viewer fornito con VB.
Se funziona o, piu' probabile, se trovi di meglio, facci sapere.
In bocca a Lupo :-P
-- 
hth, hal

 Sergio Tardioli ha scritto:
CUT
grande hal(finito un lavoro martedì o mercoledì la voglio provare sotto il
mio XP....mi ci vorrà la vers di nt
....) sempre che si possa fare!
Da un po fastidio l'idea che si possa maneggiare oggetti di così basso
livello!...
con i vecchi amiga mi ricordo che una protezione era quella di formattare
qualche settore del floppy in maniera "strana"....chissà se si può fare
anche sotto Windows...mmm ora ho troppo da fare....da Mercoledì ci si pensa
un po...
a...dimenticavo....
Ciauz!
:-)
p.s.
Da qui traspare tutta la mia ignoranza......se maneggi oggetti così
"delicati"....tramite le API...sei sempre soggetto (da winNT in poi eh!)alle
restrizioni dei permessi?...ossia(nello specifico di questo thread) il debug
dei settori di un disco è appannaggio di tutti o si può restringere solo
all'Administrator??...scusa il dubbio amletico!

 all'Administrator??...scusa il dubbio amletico!
Dubbio atletico accolto ;-)
Lo user normale si attacca al tram :-P
-- 
ciao, hal
-- 
Posted via Mailgate.ORG Server - 
http://www.Mailgate.ORG

Grazie hal, sei sempre il migliore...
Ho provato il tuo suggerimento per 98 e funziona benissimo.
Il problema è che non riesco a trovare il parametri per il GetSectors
Public Function GetSectors(ByVal drive_letter As String, _
                        ByVal head As Long, ByVal sector As Long, _
                        ByVal track As Long, ByVal numsec As Long, _
                        ByVal sectors_per_track As Long, _
                        ByVal num_of_heads As Long, _
                        ByVal bytes_per_sector As Long, _
                        ByRef retSectors() As Byte _
) As Long
Il mio problema è che dovrei fare un'applicazione che legge da un magneto
ottico scritto con sistema Unix per estrarre dati, e vorrei implementarlo
anche per 2000.
Ho letto sul post che lo hai trovato su msdn!!
Grazie comunque