· Начало · Отвђтить · Статистика · Поиск · FAQ · Правила · Установки · Язык · Выход · WASM.RU · Noir.Ru ·

 WASM Phorum —› WASM.WIN32 —› Чтение с дисков.

Посл.отвђт Сообщенiе


Дата: Дек 3, 2002 18:42:29

Как из-под Windows 9x читать данные с дисков независимо от файловой системе, которая на них используется?


Дата: Дек 4, 2002 05:46:31

DeviceIoControl?


Дата: Дек 4, 2002 09:30:05

Абсолютно согласен с P2M.

Вот как я читал сектора:


.386
.model flat, stdcall
option casemap:none
; Эта константа взята с MSDN.
VWIN32_DIOC_DOS_DRIVEINFO EQU 6 ; Performs Interrupt 21h Function 730X commands.
; This value is supported in Windows 95 OEM Service Release 2 and later.
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\kernel32.lib
include \masm32\include\user32.inc
includelib \masm32\lib\user32.lib
; Структура, в которой обычно передаются значения регистров ф-ции DeviceIOControl(kernel32)
; А уж она их передает какой-нибудь VxD
DIOCRegs STRUC
reg_EBX DD 0
reg_EDX DD 0
reg_ECX DD 0
reg_EAX DD 0
reg_EDI DD 0
reg_ESI DD 0
reg_Flags DD 0
DIOCRegs ENDS
; Структура для передачи параметров о чтении дисковых секторов (прерыванию int 25h, cx=0FFFFh
; прерыванию int 21h, ф-ция ax=7305h, etc):
; (из Ральфа Брауна) Format of disk read packet:
; Offset Size Description (Table 1884)
; 00h DWORD sector number
; 04h WORD number of sectors to read
; 06h DWORD transfer address
DiskReadPacket STRUC
SectorNumber dd 00h ; DWORD sector number
SectorsToRead dw 00h ; WORD number of sectors to read
TransferAddress dd 00h ; DWORD transfer address
DiskReadPacket ENDS
.data
; Оказывется, чтобы получить хендл для доступа
; к дискам под 95 надо сделать так:
; hDevice = CreateFile("\\\\.\\vwin32",...
VxDFileName db '\\.\vwin32',0 ; Имя VxD
; Имена сообщений (для MessageBox)
AppName db "DeviceIoControl",0
Success db "The VxD is successfully loaded!",0
Failure db "The VxD is not loaded!",0
Unload db "The VxD is now unloaded!",0
; Переменные для чтения/записи секторов
; Объявляем группу переменных (как структуру DIOCRegs)
DeviceIOCallStructure DIOCRegs <>
CallParams DiskReadPacket <,,offset Buffer>
Buffer db 512 dup(0) ; read/write buffer for sector
CB dd 0 ; Unknown buffer for DeviceIOControl
; Отладочные сообщения, выводимые через MessageBox
MsgErrDeviceIO db "Error at DeviceIOControl execution ! ;)",0
MsgErrReadSector db "Raising Error ???????? at read sector ! ;)",0
MsgDeviceIOControl db "DeviceIOControl example: read disk sector",0
MsgOk db "Sector number ???????? at Drive ???????? contain: ???????? at begin and ???????? at the end.",0
.data?
; Хендл открытой VxD (vwin32)
hVxD dd ?
.code
start:
; Device IO Control
; Открываем "VxD"
invoke CreateFile,addr VxDFileName,0,0,0,0,FILE_FLAG_DELETE_ON_CLOSE,0
cmp eax,INVALID_HANDLE_VALUE
jz @@VxDNotOpen
; Сохраняем ID открытой VxD
mov hVxD,eax
; Выдаем сообщение о том, что она(VxD) открыта
invoke MessageBox,NULL,addr Success,addr AppName,MB_OK+MB_ICONINFORMATION
; Формируем пакет для чтения сектора
mov CallParams.SectorNumber,0 ; Номер сектора
mov CallParams.SectorsToRead,1 ; Число секторов
; Формируем структуру для вызова сервиса VxD через DeviceIOControl
mov DeviceIOCallStructure.reg_EAX,7305h ; DOS Abs_Disk_Read
mov DeviceIOCallStructure.reg_EBX,offset CallParams ; = (DWORD)&dio;
mov DeviceIOCallStructure.reg_ECX,-1 ; use DISKIO struct
mov DeviceIOCallStructure.reg_ESI,0 ; Read (for write - 1)
mov DeviceIOCallStructure.reg_EDX,0 ; Drive Number = 0=Default,1="A",2="B"...
; Вызываем DeviceIOControl
push NULL
push offset CB
push size DeviceIOCallStructure
push offset DeviceIOCallStructure
push size DeviceIOCallStructure
push offset DeviceIOCallStructure
push VWIN32_DIOC_DOS_DRIVEINFO
push hVxD
call DeviceIoControl
; Проверка на ошибку. Если ошибка, то eax = 0
test eax,eax
jnz @@NoDeviceIoControlError
; Ошибка при вызове DeviceIoControl
invoke MessageBox,NULL,addr MsgErrDeviceIO,NULL,MB_OK+MB_ICONERROR
jmp @@ResultDone
@@NoDeviceIoControlError:
; Надо проверить возращенное значение "регистра" флагов в структуре DeviceIOCallStructure
test DeviceIOCallStructure.reg_Flags,1h ; error if carry flag set
jz @@NoReadSectorError
; Ошибка выполнения ф-ции чтения сектора
mov eax,DeviceIOCallStructure.reg_EAX
mov edi,offset MsgErrReadSector+14
call HexChar
invoke MessageBox,NULL,addr MsgErrReadSector,NULL,MB_OK+MB_ICONERROR
jmp @@ResultDone
@@NoReadSectorError:
; Show 3 word for control
call OutResult ; Покажем р-ты чтения сектора
@@ResultDone:
invoke CloseHandle,hVxD
invoke MessageBox,NULL,addr Unload,addr AppName,MB_OK+MB_ICONINFORMATION
jmp @@DeviceIODone
@@VxDNotOpen:
invoke MessageBox,NULL,addr Failure,NULL,MB_OK+MB_ICONERROR
@@DeviceIODone:
jmp @@AllDone
@@AllDone:
invoke ExitProcess,NULL
OutResult proc
mov eax,CallParams.SectorNumber
mov edi,offset MsgOk+14
call HexChar
mov eax,DeviceIOCallStructure.reg_EDX
mov edi,offset MsgOk+32
call HexChar
mov eax,dword ptr Buffer[0]
mov edi,offset MsgOk+50
call HexChar
mov eax,dword ptr Buffer[512-4]
mov edi,offset MsgOk+72
call HexChar
invoke MessageBox,NULL,addr MsgOk,addr MsgDeviceIOControl,MB_OK+MB_ICONINFORMATION
ret
OutResult endp
HexChar proc
pushad
cld
mov ecx,8
mov ebx,offset TabHex
@GetHex:
rol eax,4
push eax
and al,0fh
xlat
stosb
pop eax
loop @GetHex
popad
ret
TabHex db '0123456789abcdef'
HexChar endp
end start


Дата: Дек 4, 2002 11:09:15

А можно ли так писать в сектора(Например в Boot sector)?


Дата: Дек 4, 2002 14:51:17

dragon
Воин дзена

Дата: Дек 4, 2002 11:09:15
А можно ли так писать в сектора(Например в Boot sector)?


Можно, хотя я не пробовал ;) Вроде вот это:

mov DeviceIOCallStructure.reg_ESI,0 ; Read (for write - 1)

А вот в mbr так не запишшешь ;)


Дата: Дек 4, 2002 15:33:08

Я пробывал читать с обычной дискеты нулевой сектор, параметр CB всё время получается 28, а в буфере сплошные нули. Тот же результат при чтении других секторов и при чиении с жесткого диска. Может в Windows Me программа не работает?

Да, а что такое mbr?


Дата: Дек 4, 2002 17:01:47

Я пробывал читать с обычной дискеты нулевой сектор

Я не уверен, что она применима для чтения секторов дискеты. Для дискет я пользовался чем-то другим.

параметр CB всё время получается 28, а в буфере сплошные нули. Тот же результат при чтении других секторов и при чиении с жесткого диска. Может в Windows Me программа не работает?


Задай как у меня:

mov CallParams.SectorNumber,0 ; Номер сектора

Это будет означать чтение бут-сектора того раздела, на котором у тебя винда. У меня на 98-х (несколько компов все работало). Примерно так:

(Messaege Box):
SecNumber: 00000 at Drive 000000 contain 4d9058ed at begin and aa550000 at the end.

Здесь видно типичное содержимое boot-сектора: короткий jmp в начале и маркер бута (aa55) в конце.

Вообще, скомпили мой пример без модификации и запусти. Должно работать.

Да, а что такое mbr?

Мастер Бут Рекорд. Код, который первым получает управление при загрузке компа с винта.


Дата: Дек 4, 2002 21:04:22

Я не могу скомпилить пример без модификации, переписываю его на TASM.(Вроде от этого ничего не меняется), или на C++. Всё то же самое - CB всё время 28, в буфер ничего не записывается ни при чтении с дискеты ни с жесткого диска. Может есть какой-нибудь другой способ чтения из Ring3? Из Ring0 можно работать с дисками, используя Vxd, но как читать оттуда, я не знаю(В опциях прерывания 13h буфер чтения указывается, смещение относительно CS, поэтому трудно указать правильный адрес буфера, а как работать через порты, вообще не понятно.) Да и не найти документации, как вызвать функцию Vxd из простого приложения.


Дата: Дек 5, 2002 04:06:05 · Поправил: P2M

dragon
переписываю его на TASM
Если есть возможность попробовать C/C++, то BUG: Int 21 Read/Write Track on Logical Drive Fails on OSR2 and Later

Может есть какой-нибудь другой способ чтения
Попробуйте PRB: DeviceIoControl Int 13h Does Not Support Hard Disks


Дата: Дек 14, 2002 04:33:39

1) VXD-туториал в руки.
2) Вот такая шняга должна сработать:
; Выполнить код в режме v86
Push_Client_State
VMMCall Begin_Nest_V86_Exec
assume ebp:ptr Client_word_reg_struc
mov edx,edi ;EDI[0-1] - смещение, EDI[2-3] - сегмент
mov [ebp].Client_ax,201h ;}
mov [ebp].Client_bx,dx ; }

mov bx,CYLNUMBER
mov cx,SECNUMBER

; 0-5 биты AX <- 0-5 биты CX
; 6-7 биты AX <- 8-9 биты BX
; 8-15 биты AX <- 0-7 биты BX

;1)
mov al,bh ;} поместить 8-9 биты BX в 6-7 биты AX
shl al,6 ;}
;2)
and cl,00111111b ;обнулить 6-7 биты CX
or al,cl ; поместить 0-5 биты CX в 0-5 биты AX
;3)
mov ah,bl ;поместить 0-7 биты BX в 8-15 биты AX

mov [ebp].Client_cx,ax ; } Заполнить Client_word_reg_struc для

mov ah,HEADNUMBER
mov al,80h
mov [ebp].Client_dx,ax ; } чтения 0-го сектора

shr edx,16 ; }
mov [ebp].Client_es,dx ;}
mov eax,13h
VMMCall Exec_Int
VMMCall End_Nest_Exec
Pop_Client_State


Дата: Янв 7, 2003 21:13:07

На С++ код по чтению и записи секторов с 13 прерыванием работает.

#define VWIN32_DIOC_DOS_DRIVEINFO 6 //Performs Interrupt 21h Function 730X commands. This value is supported in Windows 95 OEM Service Release 2 and later.
#define VWIN32_DIOC_DOS_INT13 4 //Performs Interrupt 13h commands
#define VWIN32_DIOC_DOS_INT25 2 //Performs the Absolute Disk Read command (Interrupt 25h)
#define VWIN32_DIOC_DOS_INT26 3 //Performs the Absolute Disk Write command (Interrupt 26h)
#define VWIN32_DIOC_DOS_IOCTL 1 //Performs the specified MS-DOS device I/O control function (Interrupt 21h Function 4400h through 4411h)

#define FUNC_DISK_FORMAT 5
#define FUNC_DISK_READ 2
#define FUNC_DISK_WRITE 3
#define FUNC_DISK_RESET 0
#define FUNC_DISK_STATUS 1
#define FUNC_DISK_VERIFY 4


#define SECTOR_SIZE 512 // Size, in bytes, of a disk sector
#define CARRY_FLAG 0x0001

BOOL SimulateInt13(PDEVIOCTL_REGISTERS preg)
{
HANDLE hDevice;
BOOL fResult;
DWORD cb;

hDevice = CreateFile("\\\\.\\vwin32",
GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
(LPSECURITY_ATTRIBUTES) NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, (HANDLE) NULL);

if (hDevice == (HANDLE) INVALID_HANDLE_VALUE)
return FALSE;

preg->reg_Flags = CARRY_FLAG; // assume error (carry flag is set)

fResult = DeviceIoControl(hDevice,
VWIN32_DIOC_DOS_INT13,
preg, sizeof(DEVIOCTL_REGISTERS),
preg, sizeof(DEVIOCTL_REGISTERS),
&cb, 0);

CloseHandle(hDevice);

if (!fResult || (preg->reg_Flags & CARRY_FLAG)) // error if carry flag set
return FALSE;

return TRUE;
}

BOOL BiosDisk(BYTE bFunc, PDISK_INFO pDiskInfo)
{
DEVIOCTL_REGISTERS reg;
BOOL fResult;

reg.reg_EAX = MAKEWORD(pDiskInfo->nsectors, bFunc); // BIOS func, Sectors count #
reg.reg_ECX = MAKEWORD(pDiskInfo->sector, pDiskInfo->track); // Cylinder #, Sector #
reg.reg_EDX = MAKEWORD(pDiskInfo->drive, pDiskInfo->head); // Head #, Drive #
reg.reg_EBX = (DWORD)pDiskInfo->buffer; // Offset of sector buffer

fResult = SimulateInt13(&reg);
if (fResult == TRUE)
{
pDiskInfo->sector = LOBYTE(reg.reg_ECX);
pDiskInfo->track = HIBYTE(reg.reg_ECX);
pDiskInfo->drive = LOBYTE(reg.reg_EDX);
pDiskInfo->head = HIBYTE(reg.reg_EDX);
}

return fResult;
}

Можно использовать прерывание 21h 440D commands 41 function - write, 42 - format ....
смотри MSDN там все написано.

Или использоавть прерывание 25h, 26h.
Или использоавть прерывание 21h, 730X commands

Кто бы обьяснил чем эти методы отличаются?


Дата: Янв 11, 2003 18:25:19 · Поправил: OxMDN

А не подскажете как считать гибкий диск нестандартного
формата (256 байт) под досом... только не отсылайте к докам плз
... я их уже порядком начитался :(( Не помогает
А так же как отформатить под тот же дос тот же диск на тот же формат
Почему то моя прога не помогает:

cseg segment 'code'
assume cs:cseg,ds:dseg
include macro.mac
main proc
mov ax,dseg
mov ds,ax
; reset controller
mov ah,00h
int 13h
; set media for formating
mov ah,18h
mov ch,tpd ; track per side
mov cl,spt ; sector per track
mov dl,0 ; disk num
int 13h
; set buffer data for formating
xor cx,cx
mov cl,spt
mov bx,0 ; offset of element in 4-th byte structure
mov sci,1 ; struct element index
mov dx,4
nextel: mov ah,trind
mov finf[bx],ah ; track number
mov ah,hind
mov finf[bx+1],ah ; head number
mov ah,sci
mov finf[bx+2],ah ; sector index
mov ah,bps
mov finf[bx+3],ah ; code of sector length
mov bx,dx
add dx,4
inc sci ; inc sector index
loop nextel
wrblock finf 32 ; display array
wrstr new_str
;format track
xor cx,cx
mov ch,trind ; track number
mov dh,hind ; head number
mov dl,0 ; disk number
mov ax,ds
mov es,ax
mov bx,offset finf
mov ah,05h
int 13h
; exit program
ou_p: mov ax,4c00h
int 21h
main endp
cseg ends
dseg segment
; vars for filling finf buffer
bps db 2 ; byte per sector
spt db 8 ; sector per track
tpd db 40 ; track per side
trind db 0 ; tr index
hind db 0 ; head index
sci db 0 ; sector index
finf db 32 dup ('*')
new_str db 10,13,24h
dseg ends
end main



Заранее плз.


Дата: Янв 12, 2003 21:15:31

По адресу 0000:007A находится байт, который отвечает за код размера сектора, попробуй поставить его в 1, и запусти процедуру чтения(ah=2). Если флаг переноса будет установлен, то значит сектор не 256 байт или диск повреждён.

Но вообще я сомневаюсь, что Bios будет читать нестандартную дискету. Поэтому надо читать через порты. Алгоритм такой: Определяешь размер сектора функцией 01001010, и читаешь посекторно. Функцию определения размера сектора лучше вызывать для каждой дорожки, т.к. на каждой дорожке может быть свой размер сектора.


Дата: Янв 13, 2003 15:41:55

а код РАБОЧИЙ прислать не можешь ??
Плззз malyshev_d@mail.ru


Powered by miniBB 1.6 © 2001-2002
Время загрузки страницы (сек.): 0.061