Вы находитесь на странице: 1из 27

Тема: Работа с дисками, каталогами и файлами в Win32 API

Файловые системы

Файлы - наборы данных различных типов, размещаемые на внешнем


носителе

Для работы с файлами в ОС Windows используется несколько


файловых систем.

- FAT (File Allocation Table) – система, обеспечивающая создание и


хранение файлов на жестких и гибких дисках. Имеется две версии
этой системы:
а) FAT16 (устаревшая, используются короткие, до 8 символов, имена
файлов. Эта система использовалась еще в MS DOS и Windows 3.1;
б) FAT32 поддерживает имена длиной до 255 символов.

- CDFS (Compact Disc File System) - файловая система,


предназначенная для работы с компакт-дисками.

- NTFS (New Technology File System) – система, предназначенная для


организации данных на жестком диске.

- UDFS (Universal Disc File System) предназначена для работы с DVD


(Digital Video Disc) дисками.

- HPFS (High-Performance File System) - также организует данные на


жестком диске, разработана фирмой IBM для операционной системы
OS/2.

Получение информации о дисках на компьютере

1. Определение списка логических дисков, которые имеются в системе.

а) DWORD GetLogicalDrives( void );


Двойное слово, которое возвращает эта функция, является набором
битов, нулевой бит (самый младший) в котором соответствует диску А,
первый бит - диску В, второй - диску С и так далее.

Например:
if(GetLogicalDrives() & 0x8L)
printf("Логический диск D: присутствует\n");
else printf("Логический диск D: отсутствует\n");
б)
DWORD GetLogicalDrivesStrings(DWORD nBufferLength, LPTSTR lpBuffer);

nBufferLength задает длину строки, которая будет заполнена списком


корневых директорий дисков, установленных на компьютере; lpBuffer -
указатель на эту строку.
При успешном завершении функция возвращает количество символов,
скопированных в буфер.
Данные, записанные в буфер представляют собой несколько строк,
завершённых нулями. В конце списка стоит ещё один нуль. Например:
A:\<null>C:\<null>D:\<null><null>

2. Определение типов дисков:

UINT GetDriveType( LPTSTR lpszRootPathName );

В качестве параметра ей передается символьное имя корневого


каталога диска (например "С:\\"), а возвращаемое значение может
быть одно из следующих:
Идентификатор Значе- Описание
ние
DRIVE_UNKNOWN 0 Тип устройства
определить не удалось
DRIVE_NO_ROOT_DIR 1 Корневой директории не
существует
DRIVE_REMOVABLE 2 Дисковод со сменным
носителем - гибкий диск
DRIVE_FIXED 3 Дисковод с несменным
носителем - жёсткий диск
DRIVE_REMOTE 4 Удалённый дисковод -
сетевой диск
DRIVE_CDROM 5 Дисковод для компакт-
дисков
DRIVE_RAMDISK 6 Эмулируемый в опера-
тивной памяти диск - RAM-
диск
3. Для получения подробной информации о носителе используется
функция:
BOOL GetVolumeInformation(LPCTSTR lpRootPathName,
LPTSTR lpVolumeNameBuffer, DWORD nVolumeNameSize,
LPDWORD lpVolumeSerialNumber,
LPDWORD lpMaximumComponentLength,
LPDWORD lpFileSystemFlags,
LPTSTR lpFileSystemNameBuffer,
DWORD nFileSystemNameSize);
Назначение параметров функции:
- lpRootPathName (входной параметр) указывает на имя корневого
каталога диска, информацию о котором мы хотим получить. Если он
равен NULL, используется корневой каталог текущего диска;

- lpVolumeNameBuffer указывает на буфер, в который будет записано


имя диска;
- nVolumeNameSize определяет размер этого буфера в байтах;

- lpVolumeSerialNumber указывает на переменную, в которую функция


записывает серийный номер диска;

- lpMaximumComponentLength указывает на двойное слово, в которое


будет записана максимальная длина имени файла вместе с путём,
которая допускается в этой системе. Для FAT32 и NTFS это значение
будет равно 255;

- lpFileSystemFlags, указывает на двойное слово, в которое будут


записаны флаги, дающие дополнительную информацию о файловой
системе;

- lpFileSystemNameBuffer указывает на буфер, в который будет


записано название файловой системы, такое как FAT, HPFS или NTFS;
- nFileSystemNameSize определяет размер буфера, предназначенного
для имени файловой системы.
4. Получить информацию о размерах сектора и кластера, о наличии
свободных кластеров на диске можно с помощью следующих 2
функций:

а)
BOOL GetDiskFreeSpace(LPCTSTR lpRootPathName,
LPDWORD lpSectorsPerCluster, LPDWORD lpBytesPerSector,
LPDWORD lpNumberOfFreeClusters,
LPDWORD lpTotalNumberOfClusters);
Параметры функции:
- lpRootPathName (входной параметр) указывает на строку с именем
корневого каталога диска, информацию о котором мы хотим получить.
Если он равен NULL, используется корневой каталог текущего диска;
- lpSectorsPerCluster указывает на двойное слово, в которое функция
запишет количество секторов в одном кластере;
- lpBytesPerSector является указателем на двойное слово, в которое
будет записано количество байтов в одном секторе.
- lpNumberOfFreeClusters содержит указатель на двойное слово,
предназначенное для записи в него количества свободных кластеров
на диске.
- lpTotalNumberOfClusters указывает на двойное слово, в которое будет
записано общее число кластеров на диске.

б) функция GetDiskFreeSpaceEx(), которая имеет вид:


BOOL GetDiskFreeSpaceEx(LPCTSTR lpDirectoryName,
PULARGE_INTEGER lpFreeBytesAvailable,
PULARGE_INTEGER lpTotalNumberOfBytes,
PULARGE_INTEGER lpTotalNumberOfFreeBytes
);
Параметры функции:
- lpDirectoryName (входной параметр) указывает на строку с корневым
каталогом интересующего нас диска. Если этот параметр равен NULL,
используется корневой каталог текущего диска;
- lpFreeBytesAvailable указывает на переменную типа ULARGE_INTEGER
(беззнаковую длиной 64 бита), в которую будет записано число
свободных байтов на диске, доступных данному пользователю;
- lpTotalNumberOfBytes указывает на переменную типа
ULARGE_INTEGER, в которую будет записано общее число байтов на
диске, доступных данному пользователю;
- lpTotalNumberOfFreeBytes указывает на переменную типа
ULARGE_INTEGER, в которую будет записано общее число свободных
байтов на диске.
Пример определения и отображения параметров диска С:\

char cBuffer[1024], cVolumeNameBuffer[128],


cFileSystemNameBuffer[128];

DWORD dwVolumeNameSize, dwVolumeSerialNumber,


dwMaximumComponentLength, dwFileSystemFlags,
dwFileSystemNameSize;

if( GetVolumelnformation("С:\\", cVolumeNameBuffer, 128,


&dwVolumeSerialNumber, &dwMaximumComponentLength,
&dwFileSystemFlags, cFileSystemNameBuffer, 128))
{
sprintf(cBuffer, "Drive - %03s\nVolume name - %s\n
Volume serial number - %08x\n Maximum component
length - %08x\n File system flags - %08x\n File
system name - %s", "С:\\", cVolumeNameBuffer,
dwVolumeSerialNumber,
dwMaximumComponentLength, dwFileSystemFlags,
cFileSystemNameBuffer, dwSectorsPerCluster,
dwBytesPerSector, dwNumberOfFreeClusters,
dwTotalNumberOfClusters);
MessageBox(NULL, cBuffer, "Drive info", MB_OK);
}
else
MessageBox(NULL,"Error in drive info","Error", MB_OK);

Работа с каталогами
Для работы с каталогами в Win32 API имеется следующий набор
функций:
Функция Выполняемое действие
GetCurrentDirectory Получение текущего
каталога
SetCurrentDirectory Смена текущего каталога
GetSystemDirectory Получение системного
каталога
GetWindowsDirectory Получение основного
каталога системы
CreateDirectory Создание каталога
RemoveDirectory Удаление каталога
1. Функция получения текущего каталога
DWORD GetCurrentDirectory(DWORD nBufferLength,
LPTSTR lpBuffer);

2. Функция смены текущего каталога


BOOL SetCurrentDirectory(LPCTSTR lpPathName);

3. Функция получения системного каталога, в котором хранятся


основные файлы, обеспечивающие работоспособность системы. К
таким файлам можно отнести основные динамические библиотеки,
драйверы, шрифты и прочее.
UINT GetSystemDirectory(LPTSTR lpBuffer, UINT uSize);

4. Функция получения основного каталога, где расположена ОС


Windows:
UINT GetWindowsDirectory(LPTSTR lpBuffer, UINT uSize);

5. Функция для создания каталога


BOOL CreateDirectory(LPCTSTR lpPathName,
LPSECURITY_ATTRIBUTES lpSecurityAttributes);

6. Функция для удаления каталога


BOOL RemoveDirectory(LPCTSTR lpPathName);

Получение информации об ошибках

DWORD GetLastError(void);
Функция возвращает код возникшей ошибки. Комментарии к кодам
ошибок находятся в заголовочном файле error.h.

Пример получения информации о каталогах


char cBuffer[1280], cBufferForCurrentDirectory[256],
cBufferForWindowsDirectory[256],
cBufferForSystemDirectory[256];
GetCurrentDirectory(256, cBufferForCurrentDirectory);
GetWindowsDirectory(cBufferForWindowsDirectory, 256);
GetSystemDirectory(cBufferForSystemDirectory, 256);
sprintf(cBuffer, "Текущий каталог - %s\n Каталог Windows - %s\n
Системный каталог - %s", cBufferForCurrentDirectory,
cBufferForWindowsDirector, cBufferForSystemDirectory);
MessageBox(hWnd, cBuffer, "Directories", MB_OK);
Манипулирование файлами
Для манипулирования файлами в Win32 API имеется следующий набор
функций:
Функция Выполняемое действие
CopyFile Копирование файла
DeleteFile Удаление файла
MoveFile Перемещение или
MoveFileEx переименование файла

1. Функция копирования файла


BOOL CopyFile(LPCTSTR lpExistingFileName,
LPCTSTR lpNewFileName, BOOL bFailIfExists);
Параметры функции:
- lpExistingFileName указывает на буфер, в котором записано имя
файла, подлежащего копированию;
- lpNewFileName указывает на буфер, в котором хранится имя нового
файла;
- bFailIfExists определяет, что должна делать функция в том случае,
если файл с именем, указанным во втором аргументе, уже существует.
Если он равен TRUE и файл уже существует, то функция вернёт
значение FALSE. Если этот аргумент равен FALSE и файл уже
существует, то функция удалит старый файл и создаст новый.

2. Функция удаления файла


BOOL DeleteFile(LPCTSTR lpFileName);
где lpFileName является указателем на буфер, в котором хранится имя
удаляемого файла.

3. Функции перемещения (переименования) файла


BOOL MoveFile(LPCTSTR lpExistingFileName,
LPCTSTR lpNewFileName);
и
BOOL MoveFileEx(LPCTSTR lpExistingFileName,
LPCTSTR lpNewFileName, DWORD dwFlags);
Аргументы этих функций:
- lpExistingFileName указывает на буфер, в котором записано имя
перемещаемого файла;
- lpNewFileName указывает на другой буфер, в котором записан другой
путь с именем файла. Если задать его равным NULL, то произойдёт
удаление, а не перемещение файла;
- dwFlags представляет собой набор битовых флагов, определяющих
поведение функции MoveFileEx
Пример. На диске С:\ создать каталог "Demo directory", в него из
текущего каталога скопировать файл File_1.txt. Затем этот файл
переименовать в File_2.txt. Удалить этот файл и созданный каталог.
char cBuffer[256], cBufferForCurrentDirectory[256];
// Сохраняем текущий каталог
GetCurrentDirectory(256, cBufferForCurrentDirectory);
strcpy(cBuffer, "c:\\Demo Directory");
// Создаём новый каталог
if(CreateDirectory(cBuffer, NULL))
MessageBox(NULL, "Каталог c:\\Demo Directory
создан!", "Info", MB_OK);
else
{ MessageBox(NULL, "He могу создать каталог
c:\\Demo Directory", "Error", MB_OK); return 0;
}
// Формируем путь файла File_1.txt в
// текущем каталоге
strcpy(cBuffer, cBufferForCurrentDirectory);
strcat(cBuffer, "\\File_1.txt ");
// Делаем попытку скопировать файл
if(!CopyFile(cBuffer, "c:\\Demo Directory\\File_1 .txt", FALSE))
MessageBox(NULL, "He могу скопировать файл!",
"Error", MB_OK);
// Переименовываем файл
if(!MoveFile("c:\\Demo Directory\\File_1 .txt", "c:\\Demo Directory\\File_2
.txt"))
{
MessageBox(NULL, "He могу переименовать файл",
"Error", MB_OK); return 0;
}
// Делаем попытку удалить каталог, в котором ещё
// есть файлы, поэтому получаем сообщение об
// ошибке.
if(!RemoveDirectory("c:\\Demo Directory"))
MessageBox(NULL, "He могу удалить каталог\n
Возможно в нем ещё есть файлы!", "Error", MB_OK);
// Удаляем файл из нового каталога
DeleteFile("c:\\Demo Directory\\File_2. txt");
// Удаляем новый каталог
RemoveDirectory("c:\\Demo Directory");
Операции с файлами в Win32 API

Функция Выполняемое действие


CreateFile Создание нового или открытие
существующего файла
CloseHandle Закрытие файла
ReadFile Чтение данных из файла
WriteFile Запись данных в файл
SetFilePointer Позиционирование указателя
SetEndOfFile Изменение размера файла
FlushFileBuffers Принудительная запись буферов
кэширования на диск
LockFile Блокировка части файла от записи
LockFileEx другими потоками
UnlockFile Разблокировка ранее заблокированной
UnlockFileEx части файла

1. Функция для создания нового или открытия существующего файла


HANDLE CreateFile(LPCTSTR lpFileName,
DWORD dwDesiredAccess, DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDisposition,
DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile);
Параметры функции:
- lpFileName это указатель на имя файла (вместе с путём), который
необходимо создать или открыть;
- dwDesiredAccess определяет, какие действия можно производить с
содержимым файла. Он может принимать следующие значения:

Значение Описание
0 Не разрешены ни чтение, ни запись.
Используется, когда необходимо
получить инф. о файле
GENERIC_READ Разрешается чтение из файла
GENERIC_WRITE Разрешена запись в файл
GENERIC_READ | Разрешено чтение из файла и
GENERIC_WRITE запись в файл
- dwShareMode определяет права по совместному доступу разных
процессов к файлу. Параметр может принимать следующие значения:
Значение Описание
0 Исключительный доступ к файлу,
сторонние пользователи открыть
файл не могут
FILE_SHARE_READ Разрешено чтение из файла
сторонним пользователям
FILE_SHARE_WRITE Разрешена запись в файл сторонним
пользователям
FILE_SHARE_READ| Разрешены чтение из файла и
FILE_SHARE_WRITE запись в файл сторонними
пользователями

- lpSecurityAttributes представляет собой указатель на структуру типа


SECURITY_ATTRIBUTES;

- dwCreationDisposition определяет, какие действия необходимо


произвести в тех случаях, когда файл уже существует и когда файл
ещё не существует. Этот параметр может принимать одно из
следующих значений:
Значение Описание
CREATE_NEW Создаётся новый файл. Если файл с
указанным именем уже существует,
функция завершает работу с
ошибкой.
CREATE_ALWAYS Создаётся новый файл. Если файл
с указанным именем уже
существует, то он стирается.
OPEN_EXISTING Открывается существующий файл.
Если файла с указанным именем не
существует, то функция завершает
работу с ошибкой.
OPEN_ALWAYS Если файл с указанным именем
существует, то он открывается.
Если такой файл не существует, то
он создаётся.
TRUNCATE_EXISTING Открывается существующий файл
и сразу усекается до нулевой дли-
ны. Если файл с указанным именем
не существует, то функция
завершает работу с ошибкой.
- dwFlagsAndAttributes указывает атрибуты и флаги для файла.
Некоторые значения атрибутов и флагов приведены ниже в таблице:
Значение Описание
FILE_ATTRIBUTE Файл открывается только для
_READONLY чтения.
FILE_ATTRIBUTE Скрытый файл, в обычных условиях
_HIDDEN в списке файлов не появляется.
FILE_ATTRIBUTE Файл является частью опе-
_SYSTEM рационной системы или
используется только операционной
системой.
FILE_ATTRIBUTE Создаётся временный файл, система
_TEMPORARY пытается не записывать его на
диск, а держать в памяти, что
ускоряет доступ к файлу.
FILE_FLAG_DELETE Файл после закрытия удаляется.
_ON_CLOSE Обычно этот флаг используется для
временных файлов.
FILE_FLAG Режим кэширования файла
_SEQUENTIAL_SCAN оптимизируется для после-
довательного доступа к файлу.
FILE_FLAG_RANDOM Режим кэширования файла
_ACCESS оптимизируется для произвольного
доступа к файлу.
FILE_FLAG Устанавливается асинхронный
_OVERLAPPED доступ к файлу (в Windows 95/98 не
реализован).

- hTemplateFile указывает либо дескриптор временного файла, либо


равен NULL. В первом случае значение параметра dwFlagsAndAttributes
игнорируется и функция использует флаги и атрибуты файла, на
который указывает hTemplateFile.

Если функция отработала нормально, то она возвращает дескриптор


открытого файла, в случае неуспешного завершения - значение
INVALID_HANDLE_VALUE.

2. Функция закрытия файла


BOOL CloseHandle(HANDLE hFile);
где hFile является дескриптором того файла, который необходимо
закрыть.
3. Функция чтения данных из файла
BOOL ReadFile(HANDLE hFile, LPVOID lpBuffer,
DWORD nNumberOfBytesToRead,
LPDWORD lpNumberOfBytesRead,
LPOVERLAPPED lpOverlapped);
Параметры функции:
- hFile является дескриптором файла, из которого будет производиться
чтение данных. Файл должен быть открыт с флагом GENERIC_READ;
- lpBuffer указывает на буфер, в который будет производиться чтение
данных;
- nNumberOfBytesToRead определяет число байтов, которые
необходимо прочесть из файла;
- lpNumberOfBytesRead указывает на переменную, в которую будет
записано число реально прочитанных из файла байтов;
- lpOverlapped является указателем на структуру типа OVERLAPPED,
которая используется только для асинхронного ввода-вывода.

Чтение данных производится с текущей позиции указателя файла.

Установить указатель в нужную позицию можно с помощью функции


SetFilePointer().

4. Функция записи данных в файл


BOOL WriteFile(HANDLE hFile, LPCVOID lpBuffer,
DWORD nNumberOfBytesToWrite,
LPDWORD lpNumberOfBytesWritten,
LPOVERLAPPED lpOverlapped);
Параметры функции:
- hFile является дескриптором файла, в который будет производиться
запись данных. Файл должен быть открыт с флагом GENERIC_WRITE;
- lpBuffer указывает на буфер, из которого будет производиться запись
данных;
- nNumberOfBytesToWrite указывает число байтов, которые
необходимо записать в файл;
- lpNumberOfBytesWritten указывает на переменную, в которую будет
записано число реально записанных в файл байтов;
- lpOverlapped является указателем на структуру типа OVERLAPPED,
которая используется только для асинхронного ввода-вывода.

Запись данных начинается с текущей позиции указателя файла. После


каждой операции записи указатель файла смещается на величину,
равную количеству записанных байтов.
5. Функция изменения размеров файла
BOOL SetEndOfFile(HANDLE hFile);
Эта функция используется, когда необходимо увеличить или
уменьшить размер файла. Она устанавливает конец файла hFile в том
месте, где находится в данный момент его указатель. После того, как
будет установлен конец файла, необходимо закрыть файл. (Конец
файла – маркер EOF.)

Например, необходимо изменить длину файла и сделать её равной


65535 байтов. Для этого потребуется выполнить следующие действия:
HFILE hFile = CreateFile(...);
SetFilePointer(hFile, 65535, NULL, FILE_BEGIN);
SetEndOfFile(hFile);
CloseHandle(hFile);
Пример. Текст из нескольких строк из буфера записывается в файл,
буфер очищается, в него из файла считываются данные и
отображаются.
char cBuffer[1024], cDirectoryBuffer[256];
char cTextBuffer[] = {"Текстовая строка 1 …\n",
"Текстовая строка 2 …\n",
"Текстовая строка 3 …\n"};
HANDLE hFile;
DWORD dwBytes; int i;

// Определяем текущую директорию и запоминаем


// её в массиве cDirectoryBuffer.
GetCurrentDirectory(256, cDirectoryBuffer);

// Создаём директорию, в которой будем


// производить все манипуляции.
CreateDirectory("c:\\Demo_Directory", NULL);

// Делаем вновь созданную директорию текущей.


SetCurrentDirectory("c:\\Demo_Directory");

// Создаём файл, в который запишем данные.


if(INVALID_HANDLE_VALUE == (hFile =
CreateFile("TestFile.txt", GENERIC_WRITE, FILE_SHARE_READ,
NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL)))
{ MessageBox(NULL,"Can't create file","Error", MB_OK); return 0; }

// Записываем данные в файл.


WriteFile(hFile, cTextBuffer, sizeof(cTextBuffer), &dwBytes, NULL);

// Закрываем файл.
CloseHandle(hFile);

// Очищаем текстовый буфер.


for(i=0;i<sizeof(cTextBuffer);*(cTextBuffer+i)=0,i++);

// Выводим содержимое буфера на экран.


MessageBox(NULL, cTextBuffer, "Clear buffer", MB_OK); // Открываем
файл для чтения.
if(INVALID_HANDLE VALUE == (hFile =
CreateFile("TestFile.txt",
GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL)))
{ MessageBox(NULL, "Can't open file", "Error", MB_OK); return 0; }

// Читаем из файла.
ReadFile(hFile, cTextBuffer, sizeof(cTextBuffer), &dwBytes, NULL);

// Выдаём содержимое буфера на экран.


MessageBox(NULL,cTextBuffer,"Fulled buffer", MB_OK);

// Закрываем файл.
CloseHandle(hFile);

// Удаляем созданный файл.


DeleteFile("TestFile.txt");

// Делаем текущей ту же директорию, которая была


// текущей до начала работы программы.
SetCurrentDirectory(cDirectoryBuffer);

// Удаляем созданную директорию.


RemoveDirectory("c:\\Demo_Directory");
Получение и установка характеристик файла
Функция Выполняемое действие
GetFileAttributes Получение атрибутов файла
SetFileAttributes Установка атрибутов файла
GetFileSize Получение размера файла
GetFileTime Получение информации о временах
создания, последнего обращения и
последней записи в файл
FileTimeToSystemTime Преобразование времени из формата
FileTime в формат SystemTime
SystemTimeToFileTime Преобразование времени из формата
SystemTime в формат FileTime
SetFileTime Изменение меток времени, связанных
с файлом
GetFileInformation- Получение комплексной информации о
ByHandle файле (атрибуты, размер, времена и
др.)

1. Функция получения атрибутов файла


DWORD GetFileAttributes(LPCTSTR lpFileName);
где lpFileName – строка с именем файла с путем.
Функция возвращает двойное слово, биты которого соответствуют
атрибутам и флагам файла, которые рассматривались при изучении
функции CreateFile(). Каждый из атрибутов и флагов, кроме
символического обозначения имеет и числовое значение. Например:
FILE_ATTRIBUTE_READONLY - 0x00000001
FILE_ATTRIBUTE_NORMAL - 0x00000080
FILE_FLAG_DELETE_ON_CLOSE - 0x04000000
FILE_FLAG_SEQUENTIAL_SCAN - 0x08000000 и т.д.

Получить значение требуемого атрибута или флага можно с помощью


побитовой логической операции &. Например:
DWORD dwFlagsAndAttributes = GetFileAttributes( "C:\\TestFile.txt");
if(dwFlagsAndAttributes & FILE_ATTRIBUTE_NORMAL)
или if(dwFlagsAndAttributes & 0x00000080)
// Формирование сообщения, что файл имеет
// соответствующий атрибут
2. Функция получения размера файла
DWORD GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh);
где hFile является дескриптором файла, размер которого необходимо
получить. Этот файл должен быть предварительно открыт.
Возвращаемое функцией значение содержит младшие тридцать два
разряда размера файла. Старшие тридцать два разряда размера
файла функция помещает в двойное слово, указатель на которое
передан ей в качестве второго аргумента lpFileSizeHigh. Если старшая
часть размера файла не нужна, то в качестве второго аргумента
указывается NULL.

3. Функция получения информации о метках времени файла


BOOL GetFileTime(HANDLE hFile, LPFILETIME lpCreationTime,
LPFILETIME lpLastAccessTime, LPFILETIME lpLastWriteTime);
Аргументы функции:
- hFile является дескриптором файла, информацию для которого
необходимо получить. Этот файл должен быть предварительно открыт;
- lpCreationTime, lpLastAccessTime, lpLastWriteTime являются
указателями на структуру типа FILETIME. По этим адресам будут
записаны соответственно время создания файла, время последнего
обращения к файлу и время последней записи в файл. Если какая-то
из этих меток не нужна, то в качестве указателя на соответствующую
структуру нужно передать NULL.

Структура FILETIME является 64-битным значением, равным числу


100-наносекундных интервалов, прошедших с 1 января 1601 г. и
выглядит следующим образом:
typedef struct _FILETIME {
DWORD dwLowDateTime;
DWORD dwHighDateTime;
} FILETIME, *PFILETIME, *LPFILETIME;

4. Функция преобразования времени из формата FILETIME в формат


SYSTEMTIME
BOOL FileTimeToSystemTime(const LPFILETIME lpFileTime,
LPSYSTEMTIME lpSystemTime);
где lpFileTime является указателем на структуру типа FILETIME, а
lpSystemTime - указателем на структуру типа SYSTEMTIME.

Эта структура имеет следующий вид:


typedef struct _SYSTEMTIME {
WORD wYear;
WORD wMonth;
WORD wDayOfWeek;
WORD wDay;
WORD wHour;
WORD wMinute;
WORD wSecond;
WORD wMilliseconds;
} SYSTEMTIME, *PSYSTEMTIME, *LPSYSTEMTIME;
Поля этой структуры:
- wYear – год, должен быть больше или равен 1601;
- wDayOfWeek – день недели, Воскресенье (Sunday) = 0, Понедельник
(Monday) = 1, и т.д.

5. Функция получения комплексной информации о файле


BOOL GetFileInformationByHandle(HANDLE hFile,
LPBY_HANDLE_FILE_INFORMATION lpFileInformation);
где hFile - дескриптор файла, информацию о котором необходимо
получить; lpFileInformation является указателем на структуру типа
BY_HANDLE_FILE_INFORMATION, которая заполняется функцией.

typedef struct _BY_HANDLE_FILE_INFORMATION {


DWORD dwFileAttributes; // атрибуты файла
FILETIME ftCreationTime; // время создания файла
FILETIME ftLastAccessTime; // время последнего
// доступа к файлу
FILETIME ftLastWriteTime; // время последней записи
// в файл
DWORD dwVolumeSerialNumber; // серийный номер
// тома, на котором находится файл
DWORD nFileSizeHigh; // старшие тридцать два
// разряда размера файла
DWORD nFileSizeLow; // младшие тридцать два
// разряда размера файла
DWORD nNumberOfLinks; // число ссылок на файл
DWORD nFileIndexHigh; // старшие тридцать два
// разряда идентификатора файла
DWORD nFileIndexLow; // младшие тридцать два
// разряда идентификатора файла
} BY_HANDLE_FILE_INFORMATION, *PBY_HANDLE_FILE_INFORMATION;
Пример. Получение некоторых характеристик файла.
HANDLE hFile;
char cBuffer[1024];
OPENFILENAME OpenFileName;
... // Заполнение полей структуры OPENFILENAME

// Выбор файла и получение его имени


if(!GetOpenFileName(&OpenFileName))
{ MessageBox(hWnd, "Не могу открыть файл", "Ошибка открытия
файла", MB_OK); return 0; }

else
// Открытие выбранного файла
if(INVALID_HANDLE_VALUE == (hFile =
CreateFile(OpenFileName.lpstrFile,
GENERIC_READ | GENERIC_WRITE, 0, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)))
{ MessageBox(hWnd, "Не могу открыть файл", "Ошибка открытия
файла", MB_OK); return 0; }

else
{
// Заполнение cBuffer инф. об атрибутах и флагах
strcpy(cBuffer,"");
DWORD dwFileAttributes =
GetFileAttributes(OpenFileName.lpstrFile);

if(dwFileAttributes & FILE_ATTRIBUTE_READONLY)


strcat(cBuffer, "FILE_ATTRIBUTE_READONLY"); if(dwFileAttributes &
FILE_ATTRIBUTE_HIDDEN)
strcat(cBuffer," | FILE_ATTRIBUTE_HIDDEN");

... // Проверка других атрибутов файла


if(dwFileAttributes & FILE_FLAG_DELETE ON_CLOSE)
strcat(cBuffer,"| FILE_FLAG_DELETE_ON_CLOSE");
... // Проверка других флагов файла

// Вывод информации об атрибутах и флагах


MessageBox(hWnd, cBuffer, "Атрибуты и флаги файла", MB_OK);

// Определение размера файла


DWORD dwFileSize = GetFileSize(hFile, NULL);
sprintf(cBuffer, "Размер файла %ld bytes", dwFileSize);
MessageBox(hWnd, cBuffer, "Размер файла", MB_OK);

// Определение временных меток файла


FILETIME ftCreationTime, ftLastAccessTime,
ftLastWriteTime;
SYSTEMTIME stCreationTime, stLastAccessTime,
stLastWriteTime;
GetFileTime(hFile, &ftCreationTime, &ftLastAccessTime,
&ftLastWriteTime);
FileTimeToSystemTime(&ftCreationTime, &stCreationTime);
FileTimeToSystemTime(&ftLastAccessTime, &stLastAccessTime);
FileTimeToSystemTime(&ftLastWriteTime, &stLastWriteTime);
// Вывод данных о временных метках файла
sprintf(cBuffer, "Время создания: %d.%d.%d г. %d.%d\nВремя
последнего доступа: ... ", stCreationTime.wDay, stCreationTime.wMonth,
stCreationTime.wYear, stCreationTime.wHour, stCreationTime.wMinute,
...);
MessageBox(hWnd, cBuffer, " Информация о файле ", MB_OK);
Тема: Проецируемые в память файлы

Позволяют зарезервировать адресное пространство и скопировать в


него данные из файла на диске, после чего работать с этим участком
памяти как с файлом напрямую.

Проецируемые файлы применяются для:

- загрузки и выполнения ЕХЕ- и DLL-файлов;

- доступа к файлу данных, размещенному на диске;

- разделения общих данных между несколькими процессами,


выполняемыми на одном компьютере.

Для работы с этим видом файлов используются следующие Win32 API


функции:
Функция Выполняемое действие
CreateFile Создание нового или открытие
существующего файла
CreateFileMapping Создание объекта «проецируемый
файл»
MapViewOfFile Проецирование данных файла на
адресное пространство процесса
UnmapViewOfFile Отмена отображения файла на
адресное пространство процесса
CloseHandle Закрытие файла. Закрытие объекта
«проецируемый файл»

Последовательность операций с проецируемыми в память файлами


соответствует порядку расположения функций в таблице.

1. Функция создания объекта «проецируемый файл», сообщает ОС


какой файл будет проецируемым, его размер и способ доступа к нему
HANDLE CreateFileMapping(HANDLE hFile,
LPSECURITY_ATTRIBUTES lpAttributes,
DWORD flProtect, DWORD dwMaximumSizeHigh,
DWORD dwMaximumSizeLow, LPCTSTR lpName);
Аргументы функции:
- hFile является дескриптором файла, который необходимо спрое-
цировать в память и который был возвращён при вызове функции
CreateFile();
- lpAttributes представляет собой указатель на структуру типа
SECURITY_ATTRIBUTES;
- flProtect определяет, какой атрибут защиты будет присвоен
странице физической памяти, на которую проецируется файл.
Обычно используются следующие атрибуты:
Атрибут Описание
PAGE_READONLY После проецирования из файла можно
считывать данные. При открытии
файла необходимо использовать флаг
GENERIC_READ
PAGE_READWRITE После проецирования можно
считывать данные из файла и
записывать данные в файл. При
открытии файла необходимо
использовать флаги GENERIC_READ |
GENERIC_WRITE.
PAGE_WRITECOPY После проецирования можно
считывать данные из файла и
записывать данные в файл. Запись
приводит к созданию копии страницы.
При открытии файла необходимо
использовать флаги GENERIC READ
или GENERIC READ | GENERIC WRITE.
Кроме того, в этом аргументе могут указываться дополнительные
атрибуты защиты страницы памяти, которые объединяются с
предыдущими атрибутами побитовой логической операцией | (ИЛИ):
Атрибут Описание
SEC_COMMIT Обеспечивается физическое сохранение
в памяти или в страничном файле на
диске для всех страниц секции. Это
значение, устанавливаемое по
умолчанию.
SEC_NOCACHE Данные из файла, спроецированного в
память, кэшировать не нужно.
SEC_RESERVE Резервируются все страницы секции без
выделения физической памяти.

- dwMaximumSizeHigh, dwMaximumSizeLow являются старшими и


младшими 32 битами максимального размера проецируемого файла в
байтах. Если необходимо спроецировать файл в память таким, чтобы
размер спроецированного файла совпадал с размером файла на диске,
нам необходимо передать в этих параметрах нули;
- lpName указывается имя объекта «проецируемый файл». Это
необходимо для того, чтобы к нему могли получить доступ и другие
процессы. Если этого не нужно, то через данный аргумент передают
значение NULL.
При нормальном завершении этой функции система возвращает
дескриптор объекта «спроецированный файл». Если же создание
объекта завершилось с какой-то ошибкой, то функция возвращает
NULL.

2. Функция проецирования данных файла на адресное пространство


процесса резервирует адресное пространство в памяти под данные
файла
LPVOID MapViewOfFile(HANDLE hFileMappingObject,
DWORD dwDesiredAccess, DWORD dwFileOffsetHigh,
DWORD dwFileOffsetLow,
SIZE_T dwNumberOfBytesToMap);
Аргументы функции:
- hFileMappingObject представляет собой дескриптор отображённого в
память на предыдущем этапе файла;
- dwDesiredAccess определяет права доступа к проекции файла:
Атрибут Описание
FILE_MAP_WRITE Данные файла доступны как по
чтению, так и по записи. Объект
«проецируемый файл» должен быть
создан с атрибутом PAGE_READWRITE
FILE_MAP_READ Данные файла доступны только для
чтения. Объект «проецируемый файл»
должен быть создан с атрибутом
PAGE_ READONLY, PAGE_READWRITE
или PAGE_WRITECOPY.
FILE_MAP_ALL To же, что и FILE_MAP_WRITE
_ACCESS
FILE_MAP_COPY Данные файла доступны только для
чтения. При записи создаётся
закрытая копия страницы. Объект
«проецируемый файл» должен быть
создан с атрибутом PAGE_ READONLY,
PAGE_READWRITE или
PAGE_WRITECOPY.
- dwFileOffsetHigh, dwFileOffsetLow являются старшими и младшими 32
битами смещения, которое указывет системе, какой байт файла
необходимо считать первым;
- dwNumberOfBytesToMap указывает размер отображаемой части
файла. Если этот аргумент равен нулю, то система будет отображать
весь файл.
Функция в случае нормального завершения возвращает указатель на
начало области отображения файла. Если же функция завершает свою
работу с ошибкой, то она возвращает NULL.

3. Функция отмены отображения файла на адресное пространство


процесса
BOOL UnmapViewOfFile(LPCVOID lpBaseAddress);
где lpBaseAddress - указатель на начало области отображения файла,
возвращенный функцией MapViewOfFile().

Примечание. Открытие файла, закрытие его и объекта «проецируемый


файл» производится соответственно функциями CreateFile и
CloseHandle, которые рассматривались ранее.
Пример. Фрагмент программы, которая в текстовом файле все пробелы
заменяет символом '#'. Для просмотра измененного содержимого
файла вызывается редактор Notepad.

OPENFILENAME OpenFileName;
... // Заполнение полей структуры OPENFILENAME
// Выбор файла и получение его имени
if(!GetOpenFileName(&OpenFileName))
{ MessageBox(hWnd, "Не могу открыть файл",
"Ошибка открытия файла", MB_OK); return 0; }
else
// Открытие выбранного файла для чтения-записи
HANDLE hFile = CreateFile(OpenFileName.lpstrFile,
GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);
if(INVALID_HANDLE_VALUE == hFile)
{ MessageBox(hWnd, "Не могу открыть файл",
"Ошибка открытия файла", MB_OK); return 0; }

// Получение размера файла


DWORD dwFileSize = GetFileSize(hFile, NULL);

// Создаем объект "проецируемый файл"


HANDLE hFileMap = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0,
0, NULL);
if (hFileMap == NULL)
{ MessageBox(hWnd,"Не могу создать проекцию файла", "Ошибка
создания проекции файла", MB_OK); return 0; }

// Получение адреса, по которому проецируется


// в память первый байт файла
PVOID lpMapViewFile = MapViewOfFile(hFileMap, FILE_MAP_WRITE, 0,
0, 0);
if (lpMapViewFile == NULL)
{ MessageBox(hWnd,"Не могу получить адрес проекции файла",
"Ошибка проекцирования файла", MB_OK); return 0; }

// Изменение содержимого файла в памяти


for (long i=0; i < dwFileSize; i++)
if(*(lpMapViewFile+i) == ' ')
*(lpMapViewFile+i) = '#'; // Замена пробела на #
// Отмена отображения файла на адресное
// пространство процесса
UnmapViewOfFile((LPVOID) lpMapViewFile);

// Закрытие объекта "проекция файла"


CloseHandle(hFileMap);

// Закрытие файла
CloseHandle(hFile);

// Просмотр измененного содержимого файла


STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory( &si, sizeof(si)); // Очистка si нулями
si.cb = sizeof( si );

// Формирование строки с именем запускаемого


// процесса и передаваемого ему файла
TCHAR szPath[256];
strcpy(szPath, "Notepad ");
strcat(szPath, OpenFileName.lpstrFile);
CreateProcess( NULL, szPath, NULL, NULL, FALSE, 0,NULL, NULL, &si, &pi
);
...