![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
CreateFile - считывание дискеты в файл и обратная запись на нее [D7, WinXP]
kalexi © (2007-09-30 22:51:00)Сабж. Нужно сделать образ дискеты (вместе с ее загрузочной дорожкой), т.е. получить байтовый массив и сохранить его в файл. И наоборот.
Мучился с функцией [B]CreateFile [/B], но пока ничего не работает, есть у кого работающие примеры???
Dimaxx (2007-10-03 10:43:00) [1]
> Читаемый размер должен быть кратен размеру сектора
Забыл, в других случаях читаемый размер задаешь сам. Но в случае не буферизированного доступа размер читаемых данных обязательнодолжен быть кратен размеру сектора...
Dimaxx (2007-10-03 10:41:00) [2]Читаемый размер должен быть кратен размеру сектора в том случае, если используешь чтение в обход кэша (no buffering).
Кстати, в CreateFile очень сильно зависит правильность задания параметров. Я когда экспериментировал долго не мог добиться, чтобы работало так как мне надо. А мне нужно было читать дискеты, не содержащие файловой системы. При попытке чтения приложение сильно тормозило, долго читалась нулевая дорожка, несколько раз перепозиционировалась головка дисковода, но в итоге все читалось, но получался мусор, т.е. считанный образ не совпадал с содержимым дискеты.
Dimaxx (2007-10-03 10:35:00) [3]
> hDevice := CreateFile(pChar(Devname), GENERIC_READ, FILE_SHARE_READ
> or FILE_SHARE_WRITE, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
> 0);
Вместо FILE_ATTRIBUTE_NORMAL ставь 0.
Riply (2007-10-02 15:14:00) [4]> [17] kalexi (02.10.07 14:29)
>Так, стоп. А мне вообще нужно использовать то SetFilePointer?
>Мне в любом случае надо считывать всею дискету, а не сектор, поэтому
>прыгать на необходимый сектор мне нет необходимости.
Хозяин - барин :) Просто исходная функция была ReadSector
>На дискете в секторе 512 байт, 18 секторов на дорожке, 80 дорожек, 2 стороны.
>Т.е. 512*18*80*2=1 476 560 байт.
Ой не факт !
>Еще более простой сделал.
Это называется еще "хуже сделал".
Все что я говорила о возващаемом результате пошло в пустоту.
Как следствие такие фразы: "а после этого возникает ошибка. "
Что за ошибка ? Ни ты ни я не знаем, следовательно и как ее исправлять тоже.
> Теперь если ReadSize поставить кратным 512 - то nb (число прочитанных байтов)
> принимает значение равное ReadSize
Об этом подробно написано в Help`е.
kalexi (2007-10-02 14:38:00) [5]+ К предыдущему сообщению:
Еще более простой сделал.
function ReadSector(buffer : pointer):Boolean;
var
hDevice : THandle;
DevName : string;
nb : DWORD;
const
ReadSize = 1024;//Изменяемая
begin
DevName :='\\.\A:';
hDevice := CreateFile(pChar(Devname), GENERIC_READ, FILE_SHARE_READ
or FILE_SHARE_WRITE, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if (hDevice = INVALID_HANDLE_VALUE) then Exit;
ReadFile(hDevice, buffer, ReadSize, nb, nil);
ShowMessage(inttostr(nb));
CloseHandle(hDevice);
end;
Теперь если ReadSizeпоставить кратным 512 - то nb(число прочитанных байтов) принимает значение равное ReadSize, а после этого возникает ошибка. Если ставить иные значения nbпринимает 0.
kalexi (2007-10-02 14:29:00) [6]Так, стоп. А мне вообще нужно использовать то SetFilePointer?
Мне в любом случае надо считывать всею дискету, а не сектор, поэтому прыгать на необходимый сектор мне нет необходимости.
На дискете в секторе 512 байт, 18 секторов на дорожке, 80 дорожек, 2 стороны.
Т.е. 512*18*80*2=1 476 560 байт.
Синтаксис вызова ReadFile([файл], [указатель принимаемого буфера], [максимальное количество байт для чтения], [указатель на переменную которая получает число прочитанных байтов], nil).
Т.е. мне достаточно вызвать ReadFile(hDevice, buffer, 1476560, nb, nil)?
И не надо перемещать никуда указатель, так?
Jeer (2007-10-02 14:01:00) [7]
> Но если мы уж собрались что-то написать,
Продолжение следует ? :))
> kalexi (30.09.07 22:51)
Включи мозг, а ты хочешь чтобы тебе в "не включенку" залили полные баки.
Riply (2007-10-02 11:18:00) [8]> [14] Dimaxx © (02.10.07 10:55)
> В данном вопросе ему не нужно использовать (и запоминать) старое значение указателя.
Согласна: в данном случае не нужно.
Но если мы уж собрались что-то написать, то пусть это можно будет использовать
и в других случаях, а не только в этом. Imho.
> Поэтому чтобы не плодить себе проблем пусть использует ее как процедуру...
А вот с этим категорически не согласна: нам надо знать почему не сработало.
А вдруг ошибка еще на шаге SetFilePointer ?
Dimaxx (2007-10-02 10:55:00) [9]2 Riply: В данном вопросе ему не нужно использовать (и запоминать) старое значение указателя. Поэтому чтобы не плодить себе проблем пусть использует ее как процедуру...
Riply (2007-10-02 09:11:00) [10]>[12] Riply © (02.10.07 08:19)
P.S.
Я тут подумала, что так сходу тебе будет сложновато
разобраться с SetFilePointer и попробовала написать
маленькую функцию тебе в помощь:
const
INVALID_SET_FILE_POINTER = MAXDWORD;
function SetFilePointer64(const FHandle: THandle; const Distance64: Int64;
pNewPointer: PInt64; const MoveMethod: DWord): DWord;
var
Tmp: LARGE_INTEGER;
begin
with Tmp do
begin
QuadPart := Distance64;
LowPart := SetFilePointer(FHandle, LowPart, @HighPart, MoveMethod);
if LowPart = INVALID_SET_FILE_POINTER then
begin
Result := GetLastError;
if Result <> ERROR_SUCCESS then QuadPart := -1;
end
else Result := ERROR_SUCCESS;
end;
if pNewPointer <> nil then pNewPointer^ := Tmp.QuadPart;
end;
Мне самой больше нравиться SetFilePointerEx (из Kernel32),
но SetFilePointer64 более способствует пониманию :)
Попробуй ее использовать в нашей функции чтения.
Riply (2007-10-02 08:19:00) [11]> [11] kalexi (02.10.07 07:59)
Ну вот. Так уже будет получше. Приятно работать.
> Функция ничего не возвращает, процесс останавливается на середине.
> Кажется ошибка выполнения в момент вызова ReadFile.
С этими двумя пунктами можно попробоавть побороться:
При компиляции Delphi должна тебе выводить Warning
примерно такой: "Return value of function might be undefined".
(Не поленись залесть в словарь, если не переводится)
Исправь функцию так, чтобы он исчез.
При этом учитывай, что SetFilePointer тоже функция и возвращает результат.
Как его обработать есть пример в Help`е.
Когда же наша функция научится правильно выдавать ошибку,
то мы ее (ошибку) посмотрим с помощью SysErrorMessage и сразу поймем где собака зарыта :)
kalexi (2007-10-02 07:59:00) [12]Да, уже и сам увидел, что неправильно расставлены блок-операторы.
Функция ничего не возвращает, процесс останавливается на середине. Кажется ошибка выполнения в момент вызова ReadFile.
function ReadSector(Sector: Integer; buffer : pointer; Floppy: char):Integer;
var
hDevice : THandle;
DevName : string; nb : DWORD;
const
SectorSize = 512;
begin
DevName :='\\.\A:';
if Floppy in ['b', 'B'] then DevName[5] := Floppy;
hDevice := CreateFile(pChar(Devname), GENERIC_READ, FILE_SHARE_READ
or FILE_SHARE_WRITE, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if (hDevice = INVALID_HANDLE_VALUE) then
begin
Result := GetLastError;
Exit;
end;
SetFilePointer(hDevice, (Sector-1)*SectorSize, nil, FILE_BEGIN);
if not ReadFile(hDevice, buffer, SectorSize, nb, nil) and (nb=SectorSize) then Result := GetLastError;
CloseHandle(hDevice);
end;
Riply (2007-10-01 22:53:00) [13]>[9] kalexi (01.10.07 22:12)
>НО! Тогда единственная необходимая входная переменная это Sector ??
>Т.е. мне нужно будет ссылаться лишь на сектора?
Пока будем использовать только "сектор", чтобы не запутаться :)
>Убрал лишние переменные:
1. Уже лучше стало, сразу видны ошибки: Если ты удачно открыл файл (hDevice <> INVALID_HANDLE_VALUE),
то что ? Ничего делать не надо ? :)
2. А при каких условиях может выполниться код после Exit; ?
P.S.
И измени тип возвращаемого результата. Надо возвращать ошибку. См. [7] Riply
kalexi (2007-10-01 22:12:00) [14]Так, нет, это было мной оптимизирована функция под NT поэтому много лишних переменных. НО! Тогда единственная необходимая входная переменная это Sector?? Т.е. мне нужно будет ссылаться лишь на сектора?
Убрал лишние переменные:
function ReadSector(Sector: Integer; buffer : pointer; Floppy: char):Boolean;
var
hDevice : THandle;
DevName : string; nb : DWORD;
const
SectorSize = 512;
begin
DevName :='\\.\A:';
if Floppy in ['b', 'B'] then DevName[5] := Floppy;
hDevice := CreateFile(pChar(Devname), GENERIC_READ, FILE_SHARE_READ
or FILE_SHARE_WRITE, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if (hDevice = INVALID_HANDLE_VALUE) then
begin
Result := FALSE;
Exit;
SetFilePointer(hDevice, (Sector-1)*SectorSize, nil, FILE_BEGIN); // нумерация с 1
Result := ReadFile(hDevice, buffer, SectorSize, nb, nil) and (nb=SectorSize);
CloseHandle(hDevice);
end;
end;
kalexi (2007-10-01 22:02:00) [15]Функция не работает. Зато кажется работает эта.
function ReadSector(Head, Track, Sector: Integer; buffer : pointer;
Floppy: char):Boolean;
type
pDIOCRegs = ^TDIOCRegs;
TDIOCRegs = packed record
rEBX,rEDX,rECX,rEAX,rEDI, rESI, rFlags : DWORD;
end;
const
VWIN32_DIOC_DOS_IOCTL = 1;
VWIN32_DIOC_DOS_INT13 = 4; //Прерывание 13
SectorSize = 512;
var
hDevice : THandle;
Regs : TDIOCRegs;
DevName : string; nb : DWORD;
begin
DevName :='\\.\A:';
if Floppy in ['b', 'B'] then DevName[5] := Floppy;
hDevice := CreateFile(pChar(Devname), GENERIC_READ, FILE_SHARE_READ
or FILE_SHARE_WRITE, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if (hDevice = INVALID_HANDLE_VALUE) then
begin
Result := FALSE;
Exit;
SetFilePointer(hDevice, (Sector-1)*SectorSize, nil, FILE_BEGIN); // нумерация с 1
Result := ReadFile(hDevice, buffer, SectorSize, nb, nil) and (nb=SectorSize);
CloseHandle(hDevice);
end;
end;
Получается, что Head - это сторона, Track - дорожка, Sector - сектор. Так?
Riply (2007-10-01 21:52:00) [16]> [6] kalexi (01.10.07 21:33)
Что-то обозначения знакомы... C WASM.RU тянуто ?
Во-первых: приведи код в читабельный вид. А то понять невозможно. (лишние переменные и все такое)
Во-вторых: Если вместо выражений типа:
if hDevice = INVALID_HANDLE_VALUE then Result := FALSE;
попробуй так:
if hDevice = INVALID_HANDLE_VALUE then Result := GetLastError;
if not ReadFile(..) then Result := GetLastError ....
Может и вопросы типа: "почему не работает ?" сразу отпадут :)
>Как правильно ее вызвать?
См. "Во-первых"
>Предполагаю, что ее в цикл надо будет ставить?
Нет, разумеется. Цикл будет внутри ее. Или ты для чтения каждого кусочка
собираешся заново открывать и закрывать файл ?
kalexi (2007-10-01 21:33:00) [17]Хорошо.
function ReadSector(Head, Track, Sector: Integer; buffer : pointer; Floppy: char):Boolean;
type
pDIOCRegs = ^TDIOCRegs;
TDIOCRegs = packed record
rEBX,rEDX,rECX,rEAX,rEDI, rESI, rFlags : DWORD;
end;
var
hDevice : THandle;
Regs : TDIOCRegs;
DevName : string;
nb : DWORD;
const
SectorSize = 512;
begin
DevName :='\\.\A:';
if Floppy in ['b', 'B'] then DevName[5] := Floppy;
hDevice := CreateFile(pChar(Devname), GENERIC_READ, FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if (hDevice = INVALID_HANDLE_VALUE) then
begin
Result := FALSE;
Exit;
end;
SetFilePointer(hDevice, (Sector-1)*SectorSize, nil, FILE_BEGIN); // нумерация с 1
Result := ReadFile(hDevice, buffer^, SectorSize, nb, nil) and (nb=SectorSize);
CloseHandle(hDevice);
end;
Как правильно ее вызвать? Предполагаю, что ее в цикл надо будет ставить?
Riply (2007-10-01 11:32:00) [18]> [2] kalexi (01.10.07 08:44)
> А какие есть еще способы?
Разные. :)
Но давай сначала разберемся с самым простейшим.
Ты так и не написал, что именно "не получается".
Приведи свой код - попробуем разобраться.
>Желательно не на чистом асме.
Что значит "желательно" ?
Если подразумевается дать готовенькое, то "Дареному коню в зубы не смотрят" :)
SLoW.AlfaMoon.Com (2007-10-01 11:03:00) [19]код хоть покажите. Так то особых проблем не видится. CreateFile, определяем размер в байтах (дискеты, они разные бывают) и ReadFile
Сергей М. (2007-10-01 09:01:00) [20]
> Желательно не на чистом асме
Ты с WinAPI-то не смог разобраться, какой тебе "асм")...