Необходимо сразу отметить, что Win32 допускает два режима доступа к файлу — синхронный и асинхронный. Необходимость введения этих двух режимов в архитектуру Win32 вызвано тем, что файловый ввод-вывод относится к наиболее медленным операциям и способен значительно ухудшить впечатление от компьютера с хорошей центральной частью (процессором и материнской платой) и плохой дисковой подсистемой. Поэтому разработчики Win32 уделяют много внимания моделированию файловых операций с использованием памяти компьютера. Это и упомянутые выше временные файлы и гибкая система кэширования вводимых и выводимых данных, а также файлы, отображенные в память, работу с которыми мы рассмотрим в конце данного раздела. Наше дальнейшее изложение будет посвящено организации синхронного ввода-вывода. Для обычных несложных приложений Win32 его вполне достаточно.

Установка текущей файловой позиции

Доступ к содержимому файла может быть произвольным (прямым) и последовательным. Как обычно, функции ввода-вывода работают с файловым указателем. Но необходимо иметь в виду, что файловый указатель связан только с описателем файла. Его значение равно текущему номеру позиции в файле, с которой будет'производиться чтение-запись данных при очередном вызове функции ввода-вывода. В первый момент после открытия значение указателя равно 0, то есть он указывает на начало файла. Функции, производящие чтение-запись в файле, меняют значение файлового указателя на количество прочитанных или записанных байт. При необходимости, а при организаций прямого доступа к файлу без этого не обойтись, значение файлового указателя можно изменять с помощью функции SetFilePointer:

DWORD SetFilePointer( HANDLE hFile, LONG IDistanceToMove. PLONG lpDistanceToMoveHigh. DWORD dwMoveMethod );

Параметры этой функции имеют размер двойного слова и следующее назначение:

cmp eax.O
jz exit :если неуспех
eld
mov edi,p_start
mov esi.p_start
mov ecx.FileSize cycl: moval.Odh repne scasb
cmp byte ptr [edi].0ah
jne $-5
inc edi
dec ecx
jeexz exit :весь файл прочитан
mov eax.edi
sub eax.esi :в еах - длина строки для вывода на экран, а в esi - ее адрес ;вывести очередную строку
call WriteConsoleA
cmp eax,0
jz exit :если неуспех
add esi,eax
jmp cycl закрываем файлы exit: :выход из приложения
return: ¦

При небольшой модификации программы можно построчно выводить содержимое любого текстового файла. Для небольших файлов совсем необязательно отслеживать конец каждой строки — можно выводить из буфера сразу весь файл одним вызовом функции WriteConsoleA.

Получение и изменение атрибутов файла

Аналогично группе функций MS DOS для работы с файловой системой файловая подсистема Win32 содержит ряд функций, с помощью которых можно определить характеристики конкретного файла.
Начальные значения атрибутов файла назначаются при создании файла. Впоследствии их можно изменить вызовом функции SetFi I eAttributes.
BOOL SetFileAttributestLPCTSTR ipFileName. DWORD dwFi1eAttributes);
Параметры этой функции означают следующее:
ш ipFileName — указатель на ASCIIZ-строку, содержащую имя файла;
Ш dwFil eAttri butes — двойное слово, определяющее, какие атрибуты файла могут быть установлены.
Планируя использование этой функции, необходимо иметь в виду, что не все возможные атрибуты файлов могут быть установлены с ее помощью. Перечислим те атрибуты, комбинацию которых можно задавать для изменения атрибутов файла, специфицированного параметром lpFileName: FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTENORMAL,
FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_
SYSTEM, FILEATTRIBUTETEMPORARY.
При удачном завершении функция SetFi 1 eAttri butes возвращает ненулевое значение в регистре ЕАХ. В случае неудачи функция возвращает в регистре ЕАХ значение NULL.
Для получения атрибутов файла используется функция GetFil eAttri butes.
DWORD GetFileAttributes(LPCTSTR lpFileName):
Функция имеет один параметр lpFileName, который является указателем на ASCIIZ-строку, содержащую имя файла.
При удачном завершении функция GetFil eAttri butes возвращает значение в регистре ЕАХ, которое является комбинацией атрибутов файла, специфицированного параметром lpFileName. Выделить эти атрибуты можно, используя логические команды ассемблера или команды обработки битов. В случае неудачи функция возвращает в регистре ЕАХ значение NULL.
В приложениях очень часто требуется определить размер файла. Для этого Win32 содержит отдельную функцию GetFileSize. DWORD GetFileSize( HANDLE hFile, LPDWORD lpFileSizeHigh ): Параметры функции означают следующее:

  • hFile — дескриптор файла, размер которого требуется определить;
  • lpFileSizeHigh — адрес области памяти, куда помещаются старшие 32 бита значения размера файла, младшие 32 бита возвращаются функцией в регистре ЕАХ.

При удачном завершении функция GetFil eSize возвращает значение младших 32 бит размера файла в регистре ЕАХ. В случае неудачи функция возвращает в регистре ЕАХ значение Offffffffh.
Особого разговора заслуживают возможности получения информации о временных характеристиках файлов. По сравнению с аналогичными средствами MS DOS в Win32 этот вопрос проработан значительно глубже. Хотя если посмотреть номенклатуру и описание функций MS DOS для работы с длинными именами файлов, то видно, что у них уже есть общие идеи, реализованные рассматриваемыми ниже функциями Win32.
Как уже отмечалось выше, в Win32 с файлом связаны три значения времени: время создания, время последнего доступа и время последней модификации. Получить эти значения можно с помощью функции GetFileTime.

BOOL GetFileTime( HANDLE hFile, LPFILETIME ipCreationTime. LPFILETIME ipLastAccessTime,
LPFILETIME ipLastWhteTime);

Перед вызовом данной функции, необходимо открыть файл, о значениях времени которого мы хотим получить информацию. Функции GetFileTime передается дескриптор этого файла и указатели на три экземпляра структуры FILETIME, в которые будут записаны время создания (IpCreationTime), время последнего доступа (lpLastAccessTime) и время последней записи (lpLastWriteTime).
Аналогично функции MS DOS 71a7h Win32 предоставляет две функции для взаимного преобразования DOS-времени файла в 64-битное представление времени:

BOOL FileTimeToDosDateTime(CONST FILETIME *lpFileTime, LPWORD lpFatDate.
LPWORD ipFatTime): BOOL DosDateTimeToFileTimetWORD wFatDate.
WORD wFatTime. LPFILETIME ipFiieTime);

Функция FileTimeToDosDateTime в качестве входного параметра принимает указатель *lpFi1eTime на экземпляр структуры FILETIME. Этот указатель содержит представление времени в виде 64-битного значения. На выходе данная функция формирует два значения в переменных размером в слово, адреса которых указаны параметрами lpFatDate и lpFatTime. Формат этих слов совпадает с форматом соответствующих параметров, которыми манипулирует функция 71a7h.
Функция DosDateTimeToFileTime, наоборот, преобразует время в формате DOS представленное в виде двух слов wFatDate, wFatTime (для времени и даты соответственно), в 64-битное значение 1 pFi I eTime.
Установить время создания, последнего доступа или модификации файлов можно с помощью функции SetFileTime.

BOOL SetFileTime( HANDLE hFile. const FILETIME *lpCreationTime.
const FILETIME *lpLastAccessTime, const FILETIME *lpLastWriteTime ):

В качестве входных параметров функция SetFil eTime принимает указатели на три экземпляра структуры FILETIME и дескриптор файла. Экземпляры структур уже заполнены необходимыми значениями времени. Если какое-либо из значений устанавливать не нужно, то вместо указателя на соответствующую структуру передается NULL. В случае успешного завершения функция возвращает ненулевое значение в регистре ЕАХ.
Из вышеизложенного видно, что для получения различных характеристик файла используются множество различных функций. Работа с ними может утомить кого угодно. Нельзя ли чего-нибудь попроще? Можно. Win32 предоставляет функцию GetFi I elnformationByHandl e:

BOOL GetFileInformationByHandle( HANDLE hFile.
LPBY_HANDLE_FILE_INFORMATION lpFilelnformation );

На вход данной функции передается дескриптор файла, о котором необходимо получить Информацию, и указатель на экземпляр структуры BYHANDLEFI LE_ INFORMATION, который заполняется этой функцией. Как видно из названия полей (см. код ниже), в этой структуре сосредоточена вся информация о файле. Ниже приведен пример кода, использующего данную структуру.

;prg07_32.asm - Win32-nporpaMMa консольного приложения для
Win32 для исследования работы
функции GetFilelnformationByHandle API Win32.
;описание структур
FILETIME struc
DwLowDateTime dd ? ;младшие 32 бита значения времени
DwHighDateTime dd ? :старшие 32 бита значения времени
FILETIME ends
BY_HANDLE_FILE_INFORMATION struc
DwFileAttributes dd 0 атрибуты файла
struc
FtCreationTime_DwLowDateTime dd ? ;младшие 32 бита
значения времени создания файла FtCreationTime_
DwHighDateTiirie dd ? :старшие 32 бита значения времени создания файла
ends
struc
FtLastAccessTime_DwLowDateTime dd ? ;младшие 32 бита значения времени поел,
доступа FtLastAccessTime_DwHighDateTime dd ? :старшие 32 бита значения времени поел, доступа
ends
struc
^¦LastWriteTime_DwLowOateTime dd ? :младшие 32 бита значения времени поел, записи
^¦LastWnteTimeJDwHighDateTime dd ? :старшие 32 бита значения времени поел, записи ends
. .".-rialNumber dd С ;серийный номер тома, на котором находится файл
| nfTleSizeHigh d
d 0 :старшие 32 бита размера файла ¦nFiieSizeLow dd 0
:младшие 32 бита размера файла I nNumberOftinks dd 0 ;
число ссылок на файл | nFilelndexHigh dd 0 ;старшие 32 бита идентификатора файла nFilelndexLow dd 0 ; младшие 32 бита идентификатора файла
ends .data
t info BY_HANDLE_FILE_INFORMATION <> TitleText db 'Получение информации о файле в
Win32',О lpBuf db "p",0 I hFile dd 0 .code
¦-------------------------------------CreateFi 1 e
Нгкрываем файл
push О
push 0 -.атрибуты (они игнорируются)
push OPEN_EXISTING :открыть существующий файл, если его нет - ошибка
push 0 : защита файла не требуется
push FILE_SHARE_READ разрешено совместное использование файла (по чтению)
push GENERIC_READ разрешено чтение из файла
push offset lpBuf
call CreateFileA
emp eax.Offffffffh
je exit :если неуспех
mov hFile.eax :дескриптор файла №
GetFilelnformationByHandle
push offset info
push hFile
call GetFilelnformationByHandle
emp eax.O
jz exit :выход в случае неудачи ¦"^
результат смотрим в отладчике TD32.exe

Результат работы данной программы можно посмотреть и проанализировать в отладчике.