Управление каталогами
Создание и удаление каталогов осуществляется при помощи двух простых функций.
BOOL CreateDirectory(LPCTSTR lpPathName, LPSECURITY_ATTRIBUTES lpSecurityAttributes)
BOOL RemoveDirectory(LPCTSTR lpPathName)
lpPathName является указателем на завершающуюся нулевым символом строку, которая содержит путь к создаваемому или удаляемому каталогу. Как и в случае других функций, на данном этапе атрибуты защиты файла должны полагаться равными NULL; вопросы безопасности файлов и объектов рассматриваются в главе 15. Удалить можно только пустой каталог.
Как и в UNIX, у каждого процесса имеется текущий, или рабочий, каталог. Кроме того, для каждого диска поддерживается свой рабочий каталог. Программист может как устанавливать рабочий каталог, так и получать информацию о том, какой каталог в данный момент является текущим. Первая функция предназначена для установки каталогов.
BOOL SetCurrentDirectory(LPCTSTR lpPathName)
lpPathName определяет путь к новому текущему каталогу. Это может быть относительный путь или абсолютный полный путь, в начале которого указаны либо буква диска и двоеточие (например, D:), либо имя UNC (например, \\ACCTG_SERVER\PUBLIC).
Если в качестве пути к каталогу указывается только имя диска (например, А: или С:), то рабочим каталогом становится рабочий каталог данного диска. Например, если рабочие каталоги устанавливались в последовательности:
C:\MSDEV
INCLUDE
A:\MEMOS\TODO
С:
то результирующим рабочим каталогом будет:
C:\MSDEV\INCLUDE
Следующая функция возвращает абсолютный полный путь к текущему каталогу, помещая его в буфер, предоставляемый программистом:
DWORD GetCurrentDirectory(DWORD cchCurDir, LPTSTR lpCurDir)
Возвращаемое значение: длина строки, содержащей путь доступа к текущему каталогу, или требуемый размер буфера, если буфер не достаточно велик; в случае ошибки — нуль.
cchCurDir — размер буфера, содержащего имя каталога, который определяется количеством символов (а не байт). Размер буфера должен рассчитываться с учетом завершающего нулевого символа строки. lpCurDir является указателем на буфер, предназначенный для получения строки, содержащей путь.
Заметьте, что в случае если размер буфера оказался недостаточным для того, чтобы в нем уместилась вся строка пути, функция возвратит значение, указывающее на требуемый размер буфера. Поэтому при тестировании успешности выполнения функции следует проверять два условия: равно ли возвращаемое значение нулю и не превышает ли оно значение, заданное аргументом cchCurDir.
Подобный метод возврата строк и их длины широко распространен в Windows и требует внимательной обработки результатов. Программа 2.6 иллюстрирует типичный фрагмент кода, реализующего эту логику. Аналогичная логика реализуется и в других примерах. Вместе с тем, указанный метод применяется не всегда. Некоторые функции возвращают булевские значения, а параметр размера в них используется дважды: перед вызовом функции его значение устанавливается равным размеру буфера, а затем изменяется функцией. В качестве одного из многих возможных примеров можно привести функцию LookupAccountName, с которой вы встретитесь в главе 15.
Альтернативный подход, демонстрируемый в программе 15.4 функцией GetFileSecurity, заключается в выделении буферной памяти в промежутке между двумя вызовами функций. Первый вызов обеспечивает получение длины строки, на основании чего и выделяется память, тогда как второй — получение самой строки. Самым простым подходом в данном случае является выделение памяти для строки, насчитывающей МАХ_РАТН символов.
Пример: печать текущего каталога
Программа 2.6 реализует очередную версию команды UNIX pwd. Размер буфера определяется значением параметра МАХ_РАТН, однако проверка ошибок все равно предусмотрена, чтобы проиллюстрировать работу функции GetCurrent-Directory.
Программа 2.6. pwd: печать текущего каталога
/* Глава 2. pwd – вывод на печать содержимого рабочего каталога. */
#include "EvryThng.h"
#define DIRNAME_LEN MAX_PATH + 2
int _tmain(int argc, LPTSTR argv[]) {
TCHAR pwdBuffer [DIRNAME_LEN];
DWORD LenCurDir;
LenCurDir = GetCurrentDirectory(DIRNAME_LEN, pwdBuffer);
if (LenCurDir == 0) ReportError(_T("He удается получить путь."), 1, TRUE);
if (LenCurDir > DIRNAME_LEN) ReportError(_T("Слишком длинный путь."), 2, FALSE);
PrintMsg(GetStdHandle(STD_OUTPUT_HANDLE), pwdBuffer);
return 0;
}
Резюме
Наряду с функциями, предназначенными для обработки символов, в Windows поддерживается полный набор функций, обеспечивающих управление файлами и каталогами. Кроме того, вы можете создавать переносимые, обобщенные приложения, которые могут быть рассчитаны на работу как с символами ASCII, так и с символами Unicode.
Функции Windows во многом напоминают их аналоги в UNIX и библиотеке С, хотя различия между ними также очевидны. В приложении Б представлена таблица, в которой сведены функции Windows, UNIX и библиотеки С и показано, в чем они соответствуют друг другу, а в чем заметно отличаются.