Автор работы: Пользователь скрыл имя, 25 Марта 2014 в 14:49, лекция
Конспект лекций содержит описание технологии системного программирования под Windows с использованием функций Win32 API. В первой части конспекта лекций рассмотрены особенности архитектуры ОС Windows, специфика интерфейса прикладного программирования Win32, структура приложений для Windows. Подробно рассмотрены API функции и основные структуры данных для работы с дисками, каталогами, файлами. Отдельная глава посвящена структурной обработке исключений SEH.
Win32 не поддерживает ссылок на файлы (file linking), благодаря которым два имени файла могут указывать на один и тот же файл.
Ярлыки поддерживаются оболочками Windows, которые по содержимому файла ярлыка определяют местонахождение самого файла, но не поддерживаются в Win32. Ярлыки могут играть роль ссылок на файлы, но только для пользователей оболочки.
При перемещениии файл реально перемещается только тогда, когда он перемещается с одного диска на другой. Иначе просто изменяется ссылка на файл в таблице размещения файлов
Создание или удаление каталога выполняется двумя простыми функциями.
BOOL CreateDirectory (LPCTSTR lpszPath,
LPSECURITY_ATTRIBUTES lpsa)
и
BOOL RemoveDirectory (LPCTSTR lpszPath)
lpszPath указывает на строку с завершающим нулем, содержащую имя каталога, который должен быть создан или удален. Второй параметр - атрибуты безопасности – позволяет назначить особые привилегии для каталога. Если в этом нет необходимости, то этот параметр должен быть равен NULL. При успешном завершении функция CreateDirectory создает каталог и возвращает значение TRUE. В случае возникновения какой-либо ошибки функция возвращает FALSE.
Удалить можно только пустой каталог.
Каждый процесс имеет текущий, или рабочий, каталог. Программист может и узнать текущий каталог, и установить его. Устанавливает каталог функция:
BOOL SetCurrentDirectory (LPCTSTR lpszCurDir)
lpszCurDir – путь к новому текущему каталогу. Это может быть относительный путь или полностью уточненный путь, начинающийся либо с буквы диска и двоеточия, например D:, либо с имени UNC (например, \\ACCNG_SERVER\PUBLIC).
Если путь к каталогу – просто обозначение привода (например, А: или С:), текущим становится рабочий каталог указанного диска. Например, если рабочие каталоги установлены в последовательности
C:\MSDEV
INCLUDE
A:\MEMOS\TODO
C:
то в результате текущий каталог будет C:\MSDEV\INCLUDE.
Следующая функция возвращает в буфер, заданный программистом, полностью уточненный путь.
DWORD GetCurrentDirectory (DWORD cchCurDir,
LPTSTR lpszCurDir)
Возвращаемое значение: длина строки возвращенного пути или требуемый размер буфера, если он недостаточно велик; нуль при неудаче.
Параметры этой функции:
Заметьте, что, если буфер слишком мал для пути, возвращаемое значение сообщает его необходимую величину. Поэтому при проверке на неудачное выполнение функции должен проверяться как нулевой результат функции, так и результат, превышающий значение параметра cchCurDir.
Этот метод возвращения строки и ее длины обычен в Win32; работать с ним следует осторожно.
В этой программе мы сделаем следующее:
1. Создадим на диске С две директории с именами
«Demo_Directory_For_Book_1» и «Demo_Directory_For_Book_2».
2. В каждой из этих директорий создадим файлы с именами
«File_1.dem»
3. Постараемся
скопировать файл из первой
директории во вторую и
4. Переименуем файл в первой директории в «File_2.dem».
5. Скопируем файл из первой директории во вторую.
6. Удалим файлы и директории.
#include "stdafx.h"
#include <windows.h>
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
const int szBuffer=200;
char cBuffer[256];
char cBufferForCurrentDirectory[
HANDLE hFile;
// Сохраняем имя текущего каталога
int LenCurDir=GetCurrentDirectory(
if (LenCurDir==0)
{MessageBox(NULL, "Не удается определить текущий каталог",
"Ошибка", MB_OK);
return 0;}
if (LenCurDir>szBuffer)
{MessageBox(NULL, "Имя
текущего каталога слишком
return 0;}
strcpy(cBuffer, "c:\\Demo_Directory_For_Book_
// Создаём первый каталог
if(CreateDirectory(cBuffer, NULL)) MessageBox(NULL,
"Директория c:\\Demo_Directory_For_Book_1 создана!",
"Info", MB_OK);
else { MessageBox(NULL,
"He могу создать
директорию c:\\Demo_Directory_For_Book_1"
"Error", MB_OK);
return 0; }
//Делаем только что созданный каталог текущим.
SetCurrentDirectory(cBuffer);
// Создаём в текущем каталоге файл с именем "File_1.dem"
if(INVALID_HANDLE_VALUE == (hFile =
CreateFile("File_1.dem", GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,CREATE_NEW,
FILE_ATTRIBUTE_NORMAL, 0)) )
{MessageBox(NULL,
"He могу создать файл в
директории c:\\Demo_Directory_For_Book_1"
"Error", MB_OK);
return 0;}
else
//закрываем файл, иначе будем получать сообщения об ошибке доступа к файлу.
CloseHandle(hFile);
strcpy(cBuffer, "c:\\Demo_Directory_For_Book_
//создаем второй каталог
if (CreateDirectory(cBuffer, NULL))
MessageBox(NULL,
"Директория c:\\Demo_Directory_For_Book_2 создана!", "Info", MB_OK);
else
{ MessageBox(NULL,
"He могу создать
директорию c:\\Demo_Directory_For_Book_2"
"Error", MB_OK);
return 0;}
//делаем только что созданный каталог текущим
SetCurrentDirectory(cBuffer);
// Создаём в текущем каталоге файл с именем "File_1.dem"
if(INVALID_HANDLE_VALUE == (hFile =
CreateFile("File_1.dem", GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,CREATE_NEW,
FILE_ATTRIBUTE_NORMAL, 0)) )
{MessageBox(NULL,
"He могу создать файл в
директории c:\\Demo_Directory_For_Book_2"
"Error", MB_OK);
return 0;}
else
//закрываем файл, иначе будем получать сообщения
//об ошибке доступа к файлу.
CloseHandle(hFile);
//Делаем попытку скопировать файл. Файл с таким именем
//уже существует, поэтому получаем сообщение об ошибке.
if(!CopyFile("c:\\Demo_
"c:\\Demo_Directory_For_Book_
MessageBox(NULL, "He могу скопировать файл File_1.dem!", "Error", MB_OK);
// Переименовываем файл.
if(!MoveFile("c:\\Demo_
"c:\\Demo_Directory_For_Book_
{ MessageBox(NULL, "He могу переименовать файл", "Error", MB_OK);
return 0;}
//Делаем вторую попытку скопировать файл.
// Файла с таким именем уже не существует,
// поэтому копирование происходит успешно.
if(!CopyFile("c:\\Demo_
"c:\\Demo_Directory_For_Book_
{ MessageBox(NULL, "He могу скопировать файл из1 в 2!", "Error", MB_OK);
return 0;
} else
MessageBox(NULL, "Файл скопирован успешно", "Info", MB_OK);
// Делаем попытку удалить каталог, в котором ещё есть файлы,
// поэтому получаем сообщение об ошибке
if(!RemoveDirectory("с\\Demo_
MessageBox(NULL,
"He могу удалить каталог\nВозможно, в нем ещё есть файлы",
"Error", MB_OK);
// Удаляем файлы из второго каталога.
DeleteFile("c:\\Demo_
DeleteFile("c:\\Demo_
// Удаляем файл из первого каталога.
DeleteFile("c:\\Demo_
// Удаляем первый каталог.
RemoveDirectory("c:\\Demo_
// Делаем попытку удалить текущий каталог
if(!RemoveDirectory("с \\Demo_Directory_For_Book_2"))
MessageBox(NULL,
"He могу удалить каталог\
"Error", MB_OK);
// Делаем текущим тот каталог, который был текущим
// перед началом работы программы.
SetCurrentDirectory(
// Удаляем второй каталог
RemoveDirectory("c:\\Demo_
return 1;
}
Иногда программе необходимо узнать, какая директория является системной, то есть в каком каталоге хранятся основные файлы, обеспечивающие работоспособность системы. К таким файлам относятся основные динамические библиотеки, драйверы, шрифты и т.п. Имя этой директории можно получить с помощью функции
UINT GetSystemDirectory(
LPTSTR lpBuffer, // указатель на буфер, хранящий имя сист. каталога
UINT uSize // размер этого буфера );
В случае успешного завершения функция заполняет буфер и возвращает число байтов, записанных в буфер. В случае ошибки система возвращает 0.
Аналогичным образом можно узнать и имя основной директории Windows :
UINT GetWindowsDirectory(
LPTSTR lpBuffer,
UINT uSize );
Простейшей функцией, определяющей, какие логические диски присутствуют в системе, является функция
DWORD GetLogicalDrives(VOID);
Эта функция без параметров. Значение, которое она возвращает , фактически является логической шкалой. Нулевой (самый младший) бит этой шкалы соответствует диску А, первый бит – диску В, второй – диску –С и так далее.
Эта функция достаточно проста и понятна, но чтобы извлечь из нее информацию, приходится писать еще одну функцию. Поэтому более удобной в использовании можно считать функцию:
DWORD GetLogicalDriveStrings (DWORD nBufferLenght,
LPSTR lpBuffer);
Первый аргумент этой функции – длина буфера, который будет заполнен списком корневых каталогов дисков, установленных на компьютере. Второй аргумент – указатель на этот буфер. При успешном завершении функция возвращает количество символов, скопированных в этот буфер. Если возвращаемое значение больше длины буфера, следует увеличить его размер. Если при выполнении функции произошла ошибка, функция возвращает 0.
Данные записываются в буфер в виде строк с завершающими нулями. В конце списка стоит еще один нуль.
Для определения типа дисков используется функция:
UINT GetDriveType (LPCSTR lpRootPathName);
В качестве единственного аргумента функции необходимо передать наименование корневого каталога диска, тип которого следует определить. Перечень возможных значений, возвращаемых функцией, приведен в табл. 4.1.
Таблица 4.1
Идентификатор |
Значение |
Назначение |
DRIVE_UNKNOWN |
0 |
Тип определить не удалось |
DRIVE_NO_ROOT_DIR |
1 |
Корневой директории не существует |
DRIVE_REMOVABLE |
2 |
Дисковод со сменным носителем (гибкий диск FDD) |
DRIVE_FIXED |
3 |
Дисковод с несменным носителем (жесткий диск НDD) |
DRIVE_REMOTE |
4 |
Удаленный дисковод – сетевой диск |
DRIVE_CDROM |
5 |
Дисковод для компакт-дисков |
DRIVE_RAMDISK |
6 |
Эмулируемый в оперативной памяти диск – RAM-диск |
Для получения более полной информации о дисках предусмотрена функция :
BOOL GetVolumeInformation (
LPCTSTR lpRootPathName,
LPTSTR lpVolumeNameBuffer,
DWORD nVolumeNameSize,
LPDWORD lpVolumeSerialNumber,
LPDWORD lpMaximumComponentLength,
LPDWORD lpFileSystemFlags,
LPTSTR lpFileSystemNameBuffer,
DWORD nFileSystemNameSize );
Первый аргумент этой функции, lpRootPathName, указывает на наименование корневой директории того диска, информацию о котором мы хотим получить. Если этот параметр равен NULL, используется корневая директория текущего диска.
Второй и третий аргументы функции работают в связке. Второй аргумент, lpVolumeNameBuffer, должен указывать на буфер, в который будет записано имя диска, а третий, nVolumeNameSize, определяет размер этого буфера в байтах.
В переменную, на которую указывает четвёртый аргумент, lpVolumeSerialNumber, функция записывает серийный номер диска. Если, однако, при вызове функции эта переменная будет равна NULL, то система определит, что информация о серийном номере вам не нужна и не станет возвращать её.
Пятый аргумент, lpMaximumComponentLength, указывает на двойное слово, в которое будет записана информация о том, какая максимальная длина имени файла вместе с путём, естественно, допускается в этой системе. Например, в FAT и NTFS это значение будет равно 255.
Шестой параметр, lpFileSystemFlags, указывает на двойное слово, в которое будут записаны флаги, дающие дополнительную информацию о файловой системе. Их перечень приведен в табл. 4.2 .
Таблица 4.2
Значение |
Назначение |
FS_CASE_IS_PRESERVED |
Если этот флаг установлен, то при записи на диск сохраняется регистр букв в имени файла |
FS_CASE_SENSITIVE |
Если этот флаг установлен, то файловая система поддерживает поиск файлов с учётом регистра букв в именах |
FS_UNICODE_STORED_ON_DISK |
Если этот флаг установлен, то файловая система поддерживает хранение на диске имён файлов в Unicode |
FS_PERSISTENT_ACLS |
Если этот флаг установлен, то файловая система способна оперировать со списками контроля доступа (ACL) (доступно только в NTFS) |
FS_VOL_IS_COMPRESSED |
Если этот флаг установлен, то том, информация о котором запрашивается, был подвергнут сжатию (например, DoubleSpace) |
FS_FILE_COMPRESSION |
Если этот флаг установлен, то файловая система поддерживает сжатие файлов |
Седьмой параметр, lpFileSystemNameBuffer, указывает на буфер, в который будет записано название файловой системы, такое как FAT, HPFS или NTFS. Если этот параметр при вызове функции равен NULL, то операционная система не будет возвращать имя файловой системы.
Последний, восьмой параметр, nFileSystemNameSize, определяет размер буфера, предназначенного для имени файловой системы. Если предыдущий аргумент равен NULL, то этот аргумент игнорируется.
Информация о работе Системное программирование в среде Win32