Показать полную графическую версию : Функция ReadFile
DillerInc
17-07-2005, 01:01
Здраствуйте!
Проблема заключается в том,что указанная функция походу возвращает False,и я не могу разобраться,почему так происходит.
Итак имеется следующая ситуация:
var
hExe : HWND = 0;
{ Дескриптор получен с помощью CreateFileA с установкой флага GENERIC_READ и без каких-либо FILE_FLAG_NO_BUFFERING }
MemPtr : Pointer = NIL;
{ Указатель получен с помощью VirtualAlloc }
FileSize : DWORD;
{ Этот параметр получен от GetFileSize(hExe, NIL) }
BytesRead : DWORD;
begin
ReadFile(hExe, MemPtr, FileSize, BytesRead, NIL);
...
В итоге,как я уже говорил,функция возвращает False, по указателю MemPtr не наблюдается никаких считанных данных и переменная BytesRead не содержит кол-ва этих считанных байт.
Собственно,господа,какие будут соображения замечания по данному поводу ?
А мона кода побольше? Вот эти самые CreateFile() (без А), VirtualAlloc()... Кстати, что возвращает GetLastError() после ReadFile()? hEXE на всякий сделай типа HANDLE.
DillerInc
17-07-2005, 02:04
Savant
А мона кода побольше?
CreateFile(OpenDlgBox.lpstrFile, GENERIC_READ, 0, NIL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
...кстати,почему без "А" - меняется ли от этого что-нибудь?
VirtualAlloc(NIL, MemSize, MEM_COMMIT, PAGE_READWRITE);
Параметр MemSize типа DWORD получен какими-то непонятными ухищрениями от значания параметра FileSize:
asm
mov eax, [FileSize] // Этот
add eax, 00010000 // код
and eax, 3FFF0000 // не я придумал =]
mov [MemSize], eax
end;
GetLastError в следующей конструкции:
if ReadFile(тра-ля-ля) = False then
GetLastError;
...вроде бы возвращает значение 03Е6h = 998 = ERROR_NOACCESS (смотрел в отладчике), что возможно означает,что проблема в функции VirtualAlloc.
hEXE на всякий сделай типа HANDLE
...дык, Delphi начинает орать,что не знает такого идентификатора...
DillerInc
...кстати,почему без "А" - меняется ли от этого что-нибудь?
Все системы семейства вындос начиная с в2к работают только с уникодом, точнее они работают и с анси строками но с начала они их переведут в уникод сделают нужное преоброзование а затем результат вернут в анси, так что А это для работы с анси а W с уникодом -> с юникодом программа будет быстрее работать
Есть 2 функции CreateFile - это CreateFileA и CreateFileW разница между ними что А работает с анси кодировкой а W с уникодом, когда ты просто пишешь CreateFile компилятор сам определит с чем ты работаешь, вот кусок определеня критфайл из winbase.h
WINBASEAPI HANDLE WINAPI CreateFileA(IN LPCSTR lpFileName,
IN DWORD dwDesiredAccess,
IN DWORD dwShareMode,
IN LPSECURITY_ATTRIBUTES lpSecurityAttributes,
IN DWORD dwCreationDisposition,
IN DWORD dwFlagsAndAttributes,
IN HANDLE hTemplateFile );
WINBASEAPI HANDLE WINAPI CreateFileW(IN LPCWSTR lpFileName,
IN DWORD dwDesiredAccess,
IN DWORD dwShareMode,
IN LPSECURITY_ATTRIBUTES lpSecurityAttributes,
IN DWORD dwCreationDisposition,
IN DWORD dwFlagsAndAttributes,
IN HANDLE hTemplateFile );
#ifdef UNICODE
#define CreateFile CreateFileW
#else
#define CreateFile CreateFileA
#endif // !UNICODE
Такая схема у всех функций которые работают с файлами и со строками.
DillerInc
а файл вообще открылся???
DillerInc
17-07-2005, 16:43
lehha
CreateFile - это CreateFileA и CreateFileW
...значит выгоднее работать с функцией CreateFile ?
а файл вообще открылся???
...да,дескриптор файла возвратился нормальный,на его основе также нормально отработала функция GetFileSize,вернув размер открытого файла в байтах.
Мне кажется,что косяк кроется в работе функции VirtualAlloc,которая,если я правильно понял,должна инициализировать резервируемое пространство нулями.В моём случае,значение возвращаемое ею выглядит в отладчике как:
EAX=01490000
...если же посмотреть,что находится по этому смещению,то наблюдаешь одни знаки вопроса вместо нулей...разве так должно быть ?
Сейчас отлаживал в режиме ручной трассировки - наблюдал следующее:
;Значит зайдя внутрь функции ReadFile
;и очутившись в библиотеке Kernel32...
...
; в стек заносятся необходимые параметры и далее...
call [_imp_NtReadFile]
cmp eax, 00000103 ; а в EAX значение C0000005
jnz ... ; тут мы естественно прыгаем к чертям
Вот так вот,в EAX находится "любимое" значение C0000005 - STATUS_ACCESS_VIOLATION :( .
Как же быть тогда с этой VirtualAlloc - ведь получается,из-за неё тогда выходит такой бедлам ?
DillerInc
Хех, как все просто...... =) А сначала вообще в ступор я впал =) Даже весь код написать пришлось.
program rf;
{$APPTYPE CONSOLE}
uses
Windows;
var
hExe: Cardinal = 0;
MemPtr: Pointer = nil;
FileSize, BytesRead, MemSize: Cardinal;
begin
hExe := CreateFile('c:\temp\test.txt', GENERIC_READ, 0, NIL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if hExe = INVALID_HANDLE_VALUE then WriteLn('CreateFile failed with code: ', GetLastError()) else WriteLn('CreateFile succeeded');
FileSize := GetFileSize(hExe, nil);
if FileSize = INVALID_FILE_SIZE then WriteLn('GetSize failed with code: ', GetLastError()) else WriteLn('GetSize succeeded, FileSize = ', FileSize);
asm
mov eax, [FileSize] // FileSize -> eax
add eax, $00010000 // +65536
and eax, $3FFF0000 // выравнивание + ограничение по размеру
mov [MemSize], eax // eax -> MemSize
end;
MemPtr := VirtualAlloc(nil, MemSize, MEM_COMMIT, PAGE_READWRITE);
if MemPtr = nil then WriteLn('VA failed with code: ', GetLastError()) else WriteLn('VA succeeded');
if not ReadFile(hExe, MemPtr^, FileSize, BytesRead, NIL) then
WriteLn('RF failed with code: ', GetLastError(), '. FileSize = ', FileSize, ', BytesRead = ', BytesRead, '.')
else
WriteLn('RF succeeded. FileSize = ', FileSize, ', BytesRead = ', BytesRead, '.');
ReadLn;
VirtualFree(MemPtr, 0, MEM_RELEASE);
CloseHandle(hExe);
end.
Видно, что изменилось? ;)
DillerInc
17-07-2005, 23:57
Savant
Видно, что изменилось?
...кто бы мог подумать,что одна перевёрнутая галка,разыменовывающая указатель,может спасти "гиганта мысли"...
Ну,это называется - что я буду без тебя делать в своих инфотехнологических поползновениях :grin: .
Кстати,вот всё-таки хотелось бы подробнее узнать,чего мы добиваемся с помощью описанной ассемблерной вставки,в чём её суть ?
DillerInc
>>Кстати,вот всё-таки хотелось бы подробнее узнать,чего мы добиваемся с помощью описанной ассемблерной вставки,в чём её суть ?
Ну если я правильно понимаю, то:
asm
// кладем значение FileSize в регистр eax процессора
mov eax, [FileSize]
// добавляем к значению FileSize (которое в регистре) число 10000h (65536)
add eax, $00010000
// выравниваем это значение на границу 10000h (т.е. делаем число кратным 10000h)
// и ограничиваем размерчик загребаемой памяти числом 3FFF0000h (1073676288 байт ~ 1 Гб)
and eax, $3FFF0000
// кладем полученное значение в MemSize
mov [MemSize], eax
end;
© OSzone.net 2001-2012
vBulletin v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.