Вопрос, с которым сталкиваются разработчики в Delphi, заключается в возникновении ошибки доступа при работе с функциями Windows API, которые не были правильно объявлены. В частности, рассмотрим проблему, связанную с функцией SHParseDisplayName, которая используется для получения PIDL (Permanent Identifier List) из пути к файлу.
Описание проблемы
Разработчик столкнулся с ошибкой доступа при попытке получить PIDL из пути к файлу в среде разработки Delphi. Функция SHParseDisplayName, используемая для этой цели, возвращала nil в качестве результата. Код, представленный разработчиком, выглядел следующим образом:
type
TParseDisplayName = function(pszPath: PWideChar; pbc: IBindCtx; var pidl: PItemIDList; sfgaoIn: ULong; var psfgaoOut: ULong): HResult;
var
SHParseDisplayName: TParseDisplayName;
SHELL32DLLHandle: THandle;
procedure test();
var
ws: WideString;
tmpLongWord: ULong;
lpItemID: PItemIDList;
begin
CoInitialize(nil);
// Путь к файлу для тестирования
ws := 'C:\inetsdk\Nouveau Document WordPad.doc';
if (SHParseDisplayName(PWideChar(ws), nil, lpItemID, 0, tmpLongWord) = S_OK) then
if not Assigned(lpItemID) then
s := SysErrorMessage(GetLastError);
CoUnInitialize();
end;
initialization
SHELL32DLLHandle := LoadLibraryW('shell32.dll');
@SHParseDisplayName := GetProcAddress(SHELL32DLLHandle, 'SHParseDisplayName');
Подтвержденный ответ
Проблема заключалась в том, что объявление функции TParseDisplayName не включало указание соглашения о вызовах. Необходимо было добавить stdcall, которое является стандартным соглашением о вызовах для большинства функций Windows API. Исправленное объявление функции выглядит следующим образом:
TParseDisplayName = function(pszPath: PWideChar; pbc: IBindCtx; var pidl: PItemIDList; sfgaoIn: ULong; var psfgaoOut: ULong): HResult; stdcall;
Если соглашение о вызовах не указано явно, используется стандартное соглашение, которое называется register. Это отличается от stdcall по семантике передачи параметров и очистки, что и приводит к возникновению ошибок во время выполнения программы.
Альтернативный ответ
В предоставленном контексте альтернативные ответы не рассматриваются, так как проблема уже имеет подробное описание и подтвержденное решение.
Рекомендации по исправлению
Убедитесь, что объявление функции Windows API включает указание stdcall.
Проверьте корректность пути к файлу, который передается в функцию SHParseDisplayName.
Перед использованием функций COM, таких как CoInitialize, убедитесь, что вы понимаете их поведение и порядок вызова.
Заключение
Исправление ошибки доступа в Delphi заключается в правильном объявлении функций Windows API с указанием соглашения о вызовах stdcall. Это позволит избежать несоответствия в передаче параметров и обработке стека, что часто является причиной ошибок типа доступа в программах, использующих динамическое связывание функций из библиотек Windows.
Разработчик в Delphi столкнулся с ошибкой доступа при неправильном объявлении функции Windows API `SHParseDisplayName`.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.