суббота, 23 мая 2020 г.

Дело о SHGetFolderPath(CSIDL_COMMON_DOCUMENTS), возвращающей ERROR_PATH_NOT_FOUND

Это перевод The case of the SHGetFolderPath(CSIDL_COMMON_DOCUMENTS) that returned ERROR_PATH_NOT_FOUND. Автор: Реймонд Чен.

У клиента возникла проблема с функцией SHGetFolderPath. В частности, у них была программа, которая вызывала функцию так:
SHGetFolderPath(0, CSIDL_COMMON_DOCUMENTS, 0, SHGFP_TYPE_CURRENT, PChar(pathBuffer));
но вызов функции возвращал ошибку $80070003 - это HRESULT-версия для ERROR_PATH_NOT_FOUND. Ошибка возникает только при запуске из Jenkins pipeline. Если же программа запускается автономно, то функция завершается успешно и возвращает ожидаемый результат.

Трассировка от procmon показала, что приложение пыталось получить доступ к папке C:\Windows\SysWOW64\autobuild\Documents и потерпело неудачу с ошибкой NAME_NOT_FOUND. Это и была подсказка к тому, почему всё сломалось.

По умолчанию папка Common Documents имеет значение %PUBLIC%\Documents. Обычное значение переменной среды PUBLIC - это C:\Users\Public, но когда программа запускается как часть Jenkins pipeline, для переменной среды по какой-то причине задается значение autobuild.

Это означает, что когда программа вызывает SHGetFolderPath и запрашивает CSIDL_COMMON_DOCUMENTS - система ищет папку autobuild\Documents, которая не существует, поэтому возникает ошибка $80070003: "Система не может найти указанный путь".

Есть ряд переменных среды, которые имеют особое значение, и вы меняете их на свой страх и риск. Вы, вероятно, знаете о таких переменных, как windir, ProgramFiles и TEMP, но существует множество других специальных переменных среды - и PUBLIC является одной из них.

Вооружившись этой информацией, клиент начал искать, кто портит переменную среды PUBLIC, и попытаться его остановить.

Комментариев нет:

Отправка комментария

Можно использовать некоторые HTML-теги, например:

<b>Жирный</b>
<i>Курсив</i>
<a href="http://www.example.com/">Ссылка</a>

Вам необязательно регистрироваться для комментирования - для этого просто выберите из списка "Анонимный" (для анонимного комментария) или "Имя/URL" (для указания вашего имени и ссылки на сайт). Все прочие варианты потребуют от вас входа в вашу учётку.

Пожалуйста, по возможности используйте "Имя/URL" вместо "Анонимный". URL можно просто не указывать.

Ваше сообщение может быть помечено как спам спам-фильтром - не волнуйтесь, оно появится после проверки администратором.