Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

CreateFile - считывание дискеты в файл и обратная запись на нее [D7, WinXP]


Страницы:   1 2

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-то не смог разобраться, какой тебе "асм")...


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо