Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2007.10.28;
Скачать: [xml.tar.bz2];

Вниз

CreateFile - считывание дискеты в файл и обратная запись на нее   Найти похожие ветки 

 
kalexi   (2007-09-30 22:51) [0]

Сабж. Нужно сделать образ дискеты (вместе с ее загрузочной дорожкой), т.е. получить байтовый массив и сохранить его в файл. И наоборот.

Мучился с функцией [B]CreateFile [/B], но пока ничего не работает, есть у кого работающие примеры???


 
Riply ©   (2007-10-01 06:31) [1]

> [0] kalexi   (30.09.07 22:51)
>есть у кого работающие примеры???

У меня и много (способы чтения разные :)

>Мучился с функцией [B]CreateFile [/B], но пока ничего не работает
Что именно "не работает" и как это выражается ?


 
kalexi   (2007-10-01 08:44) [2]

Ну нашел готовые функции работы с дисководом, а  он наже не пытается его прочитать.

А какие есть еще способы? Желательно не на чистом асме.


 
Сергей М. ©   (2007-10-01 09:01) [3]


> Желательно не на чистом асме


Ты с WinAPI-то не смог разобраться, какой тебе "асм")...


 
SLoW.AlfaMoon.Com   (2007-10-01 11:03) [4]

код хоть покажите. Так то особых проблем не видится. CreateFile, определяем размер в байтах (дискеты, они разные бывают) и ReadFile


 
Riply ©   (2007-10-01 11:32) [5]

> [2] kalexi   (01.10.07 08:44)
> А какие есть еще способы?
Разные. :)
Но давай сначала разберемся  с самым простейшим.
Ты так и не написал, что именно "не получается".
Приведи свой код - попробуем разобраться.

>Желательно не на чистом асме.
Что значит "желательно" ?
Если подразумевается дать готовенькое, то "Дареному коню в зубы не смотрят" :)


 
kalexi   (2007-10-01 21:33) [6]

Хорошо.

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 21:52) [7]

> [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 22:02) [8]

Функция не работает. Зато кажется работает эта.

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 - сектор. Так?


 
kalexi   (2007-10-01 22:12) [9]

Так, нет, это было мной оптимизирована функция под 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;


 
Riply ©   (2007-10-01 22:53) [10]

>[9] kalexi   (01.10.07 22:12)
>НО! Тогда единственная необходимая входная переменная это Sector ??
>Т.е. мне нужно будет ссылаться лишь на сектора?
Пока будем использовать только "сектор", чтобы не запутаться :)

>Убрал лишние переменные:
1. Уже лучше стало, сразу видны ошибки: Если ты удачно открыл файл (hDevice <> INVALID_HANDLE_VALUE),
то что ? Ничего делать не надо ? :)
2. А при каких условиях может выполниться код после Exit; ?

P.S.
И измени тип возвращаемого результата. Надо возвращать ошибку. См. [7] Riply


 
kalexi   (2007-10-02 07:59) [11]

Да, уже и сам увидел, что неправильно расставлены блок-операторы.
Функция ничего не возвращает, процесс останавливается на середине. Кажется ошибка выполнения в момент вызова 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-02 08:19) [12]

> [11] kalexi   (02.10.07 07:59)
Ну вот. Так уже будет получше. Приятно работать.

> Функция ничего не возвращает, процесс останавливается на середине.
> Кажется ошибка выполнения в момент вызова ReadFile.
С этими двумя пунктами можно попробоавть побороться:
При компиляции Delphi должна тебе выводить Warning
примерно такой: "Return value of function might be undefined".
(Не поленись залесть в словарь, если не переводится)
Исправь функцию так, чтобы он исчез.
При этом учитывай, что SetFilePointer тоже функция и возвращает результат.
Как его обработать есть пример в Help`е.

Когда же наша функция научится правильно выдавать ошибку,
то мы ее (ошибку) посмотрим с помощью SysErrorMessage и сразу поймем где собака зарыта :)


 
Riply ©   (2007-10-02 09:11) [13]

>[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 более способствует пониманию :)
Попробуй ее использовать в нашей функции чтения.


 
Dimaxx ©   (2007-10-02 10:55) [14]

2 Riply: В данном вопросе ему не нужно использовать (и запоминать) старое значение указателя. Поэтому чтобы не плодить себе проблем пусть использует ее как процедуру...


 
Riply ©   (2007-10-02 11:18) [15]

> [14] Dimaxx ©   (02.10.07 10:55)
> В данном вопросе ему не нужно использовать (и запоминать) старое значение указателя.

Согласна: в данном случае не нужно.
Но если мы уж собрались что-то написать, то пусть это можно будет использовать
и в других случаях, а не только в этом. Imho.

> Поэтому чтобы не плодить себе проблем пусть использует ее как процедуру...
А вот с этим категорически не согласна: нам надо знать почему не сработало.
А вдруг ошибка еще на шаге SetFilePointer ?


 
Jeer ©   (2007-10-02 14:01) [16]


> Но если мы уж собрались что-то написать,


Продолжение следует ? :))


> kalexi   (30.09.07 22:51)


Включи мозг, а ты хочешь чтобы тебе в "не включенку" залили полные баки.


 
kalexi   (2007-10-02 14:29) [17]

Так, стоп. А мне вообще нужно использовать то SetFilePointer?
Мне в любом случае надо считывать всею дискету, а не сектор, поэтому прыгать на необходимый сектор мне нет необходимости.

На дискете в секторе 512 байт, 18 секторов на дорожке, 80 дорожек, 2 стороны.
Т.е. 512*18*80*2=1 476 560 байт.

Синтаксис вызова ReadFile([файл], [указатель принимаемого буфера], [максимальное количество байт для чтения], [указатель на переменную которая получает число прочитанных байтов], nil).

Т.е. мне достаточно вызвать ReadFile(hDevice, buffer, 1476560, nb, nil)?
И не надо перемещать никуда указатель, так?


 
kalexi   (2007-10-02 14:38) [18]

+ К предыдущему сообщению:

Еще более простой сделал.

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.


 
Riply ©   (2007-10-02 15:14) [19]

> [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`е.


 
Dimaxx ©   (2007-10-03 10:35) [20]


> hDevice := CreateFile(pChar(Devname), GENERIC_READ, FILE_SHARE_READ
> or FILE_SHARE_WRITE, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
>  0);

Вместо FILE_ATTRIBUTE_NORMAL ставь 0.


 
Dimaxx ©   (2007-10-03 10:41) [21]

Читаемый размер должен быть кратен размеру сектора в том случае, если используешь чтение в обход кэша (no buffering).

Кстати, в CreateFile очень сильно зависит правильность задания параметров. Я когда экспериментировал долго не мог добиться, чтобы работало так как мне надо. А мне нужно было читать дискеты, не содержащие файловой системы. При попытке чтения приложение сильно тормозило, долго читалась нулевая дорожка, несколько раз перепозиционировалась головка дисковода, но в итоге все читалось, но получался мусор, т.е. считанный образ не совпадал с содержимым дискеты.


 
Dimaxx ©   (2007-10-03 10:43) [22]


> Читаемый размер должен быть кратен размеру сектора

Забыл, в других случаях читаемый размер задаешь сам. Но в случае не буферизированного доступа размер читаемых данных обязательно должен быть кратен размеру сектора...



Страницы: 1 вся ветка

Форум: "Начинающим";
Текущий архив: 2007.10.28;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.52 MB
Время: 0.047 c
1-1186721899
Ануфрий
2007-08-10 08:58
2007.10.28
Обновление программы динамически через интернет


1-1187006465
Dio
2007-08-13 16:01
2007.10.28
Эмулировать прокрутку колеса мыши


15-1190873947
F@T@L_Err0r
2007-09-27 10:19
2007.10.28
Ctrl+Alt+Del


6-1172579067
SergGuk
2007-02-27 15:24
2007.10.28
DDE + сеть


2-1191593097
Vitek2
2007-10-05 18:04
2007.10.28
"Сохранить" и "Сохранить как..".





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский