Ошибка CreateFile в Delphi: некорректный дескриптор файла и глобальные настройки коротких имен
При работе с функциями операционной системы Windows разработчики на языке Delphi могут столкнуться с различными ошибками. Одной из таких проблем является некорректный дескриптор файла, возвращаемый функцией CreateFile. В данной статье мы рассмотрим, как может возникнуть такая ошибка и как её можно устранить, рассмотрев пример, связанный с редактированием сырых томов.
Описание проблемы
Разработчик столкнулся с проблемой при работе со своим классом TDiskStream, наследуемым от THandleStream, который используется для редактирования сырого объема. При вызове функции CreateFile для открытия диска, вместо возврата корректного дескриптора файла, функция возвращает странный код ошибки. В режиме отладки это значение ошибки обозначается как 348, а во время выполнения — как 304. При этом, несмотря на то что дескриптор не выглядит валидным, сама ошибка не генерируется. Значение дескриптора соответствует коду ошибки __ERROR_INCOMPATIBLE_WITH_GLOBAL_SHORT_NAME_REGISTRY_SETTING__, который описывается на MSDN, но встречается довольно редко. Параметр aDrive класса TDiskStream устанавливается корректно, в формате \\.\x:, где x — буква диска.
Пример кода
Constructor TDiskStream.Create(const aDrive: String);
var
Hdl: Cardinal;
A, B: Int64;
begin
Hdl := CreateFile(PChar(aDrive),
GENERIC_WRITE,
FILE_SHARE_READ or FILE_SHARE_WRITE,
0, OPEN_EXISTING, 0, 0);
Inherited Create(Hdl);
GetDiskFreeSpaceEx(PChar(RightStr(aDrive, 2) + '\'), A, FSize, @B);
end;
Подтвержденный ответ
Прежде всего, стоит отметить, что CreateFile не возвращает коды ошибок напрямую. В случае неудачи функция возвращает INVALID_HANDLE_VALUE. Для получения информации об ошибке следует использовать функцию GetLastError. В примере кода, предоставленном разработчиком, отсутствует проверка дескриптора файла, что и приводит к ошибке. Чтобы исправить ситуацию, необходимо добавить проверку на INVALID_HANDLE_VALUE и, в случае необходимости, сгенерировать исключение с помощью RaiseLastOSError.
Исправленный код
Constructor TDiskStream.Create(const aDrive: String);
var
Hdl: THandle;
begin
Hdl := CreateFile(PChar(aDrive), GENERIC_READ or GENERIC_WRITE,
FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0);
if Hdl = INVALID_HANDLE_VALUE then
raise Exception.CreateFmt('Не удалось открыть диск: %d', [GetLastError]);
try
Inherited Create(Hdl);
// Дополнительный код
finally
if Hdl <> INVALID_HANDLE_VALUE then
CloseHandle(Hdl);
end;
end;
Альтернативный ответ
Возможно, значения, возвращаемые CreateFile, на самом деле являются валидными дескрипторами файлов. Однако, если функция CreateFile не удается открыть файл, она возвращает INVALID_HANDLE_VALUE, а информацию об ошибке можно получить с помощью GetLastError. Важно проверять возвращаемое значение дескриптора и, при необходимости, обрабатывать возможные ошибки корректно.
Заключение
При работе с функциями операционной системы Windows важно тщательно обрабатывать возвращаемые значения и коды ошибок. В данном случае, проверка дескриптора файла и обработка возможных ошибок поможет избежать недоразумений, связанных с глобальными настройками коротких имен в реестре и другими потенциальными проблемами.
Разработчик на Delphi столкнулся с ошибкой `CreateFile`, связанной с некорректным дескриптором файла и проблемами глобальных настроек коротких имен в Windows.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.