ilyachalov (ilyachalov) wrote,
ilyachalov
ilyachalov

Categories:

Порядок поиска DLL

Начало тут:
1. динамически подключаемые библиотеки;
2. о динамически подключаемых библиотеках подробнее;
3. преимущества динамического связывания;
4. создание динамически подключаемой библиотеки;
5. функция точки входа DLL;
6. динамическое связывание во время запуска;
7. динамическое связывание во время выполнения.

Перевод с английского статьи от 31.05.2018 г. «Dynamic-Link Library Search Order»:
https://docs.microsoft.com/ru-ru/windows/win32/dlls/dynamic-link-library-search-order
(На данный момент на этом сайте нет перевода этой статьи на русский, есть только версия на английском.)

[Операционная] система может содержать множество версий одной и той же динамически подключаемой библиотеки (DLL). Приложения могут контролировать местоположение, из которого DLL загружается, путем определения полного пути [к файлу DLL] или с помощью другого механизма, такого как манифест [файл на языке XML с информацией о приложении, в том числе может содержать информацию о необходимых приложению DLL]. Если эти методы не используются, система ищет DLL во время запуска программы так, как описано в этой статье.

Так как статья довольно длинная [и в ней много повторов, поэтому она довольно нудная], то вот ее содержание со ссылками на ее разделы (все они находятся на этой же странице):

Факторы, влияющие на процесс поиска

Следующие факторы влияют на то, будет ли система искать DLL:
  • если DLL с тем же самым именем модуля уже загружена в память, система проверит только [следует ли выполнить] перенаправление [перенаправление включается наличием в папке с исполняемым файлом приложения пустого файла с таким же именем, как у приложения, и расширением .local и указывает системе начать поиск DLL с папки, в которой находится этот файл .local] и манифест [на наличие указаний о местонахождении нужной DLL] и [при отсутствии перенаправления и манифеста] будет считать результатом поиска загруженную DLL, при этом не будет иметь значения, в каком каталоге эта загруженная DLL находится. Система не станет выполнять других действий по поиску DLL;

  • если DLL есть в списке библиотек DLL, известных той версии операционной системы Windows, в которой запущено приложение, система использует свою копию известной DLL (и свои копии библиотек DLL, от которых эта известная DLL зависит, если таковые имеются) вместо того, чтобы искать эту DLL. Увидеть список известных текущей системе DLL можно, обратившись к следующему ключу реестра: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs;

  • если DLL имеет зависимости [от других DLL], система будет искать библиотеки DLL, от которых зависит исходная, так, как если бы эти библиотеки загружались с указанием только имен их модулей. Это правило остается верным, даже если исходная DLL загружалась с указанием полного пути к ней.

Порядок поиска DLL для приложений «Windows Store»

Когда приложение «Windows Store» загружает упакованный модуль [DLL] посредством вызова функции LoadPackagedLibrary, DLL должна находиться в графе зависимостей пакета для процесса. Подробнее об этом читайте в описании функции LoadPackagedLibrary. Когда приложение «Windows Store» загружает модуль [DLL] другими средствами и не указывает полный путь к нему, система ищет DLL и ее зависимости [модули, от которых эта DLL зависит] во время запуска программы так, как описано в этом разделе.

Замечание для пользователей предыдущих по отношению к свежим на дату написания статьи версиям операционных систем Windows (Windows 7 (вики: с 22.10.2009 г.), Windows Server 2008 R2 (вики: с 22.10.2009 г.), Windows Vista (вики: с 30.11.2006 г.), Windows Server 2008 (вики: с 12.12.2008 г.), Windows Server 2003 (вики: с 24.04.2003 г.) и Windows XP (вики: с 24.08.2001 г.)): приложения «Windows Store» поддерживаются, начиная с операционных систем «Windows 8» (вики: с 26.10.2012 г.) и «Windows Server 2012» (вики: с 04.09.2012 г.).

Перед тем, как система запустит поиск DLL, она проверит следующее:
  • если DLL с таким же именем модуля уже загружена в память, система будет использовать загруженную DLL, при этом не будет иметь значения, в каком каталоге эта загруженная DLL находится. Система не станет выполнять других действий по поиску DLL;

  • если DLL есть в списке библиотек DLL, известных той версии операционной системы Windows, в которой запущено приложение, система использует свою копию известной DLL (и свои копии библиотек DLL, от которых эта известная DLL зависит, если таковые имеются) вместо того, чтобы искать эту DLL. Увидеть список известных текущей системе DLL можно, обратившись к следующему ключу реестра: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs.

Если система должна выполнить поиск модуля или его зависимостей [других модулей, от которых зависит работа исходного модуля], система всегда будет использовать порядок поиска, предназначенный для приложений «Windows Store», даже если искомая зависимость представляет из себя не код приложения «Windows Store».

Стандартный порядок поиска DLL для приложений «Windows Store»

Если модуль DLL еще не загружен или не находится в списке известных системе DLL, то система начинает поиск в следующих местах в указанном ниже порядке:
  1. Граф зависимостей пакета для процесса. Местом поиска является пакет приложения плюс любые зависимости, отмеченные как <PackageDependency> в разделе <Dependencies> манифеста пакета приложения. Зависимости ищутся системой в том порядке, в котором они появляются в манифесте;

  2. Каталог, из которого был загружен вызывающий DLL процесс;

  3. Системный каталог (%SystemRoot%\system32).

Если DLL имеет зависимости [от других DLL], система будет искать библиотеки DLL, от которых зависит исходная, так, как если бы эти библиотеки загружались с указанием только имен их модулей. Это правило остается верным, даже если исходная DLL загружалась с указанием полного пути к ней.

Альтернативный порядок поиска DLL для приложений «Windows Store»

Если модуль меняет стандартный порядок поиска DLL посредством вызова функции LoadLibraryEx с флагом LOAD_WITH_ALTERED_SEARCH_PATH, система ищет в каталоге, из которого указанный [в параметре функции LoadLibraryEx] модуль был загружен, вместо каталога вызывающего процесса. Система выполняет поиск в следующих местах в указанном ниже порядке:
  1. Граф зависимостей пакета для процесса. Местом поиска является пакет приложения плюс любые зависимости, отмеченные как <PackageDependency> в разделе <Dependencies> манифеста пакета приложения. Зависимости ищутся системой в том порядке, в котором они появляются в манифесте;

  2. Каталог, из которого указанный [в параметре функции LoadLibraryEx] модуль был загружен;

  3. Системный каталог (%SystemRoot%\system32).

Порядок поиска DLL для приложений настольного компьютера

Приложения настольного компьютера [desktop applications] могут указывать место, из которого будет загружена DLL, посредством указания полного пути к DLL, могут использовать перенаправление поиска DLL, либо могут использовать манифест. Если ни один из этих методов не используется, система ищет DLL во время загрузки программы так, как описано в этом разделе.

Перед тем, как система запустит поиск DLL, она проверит следующее:
  • если DLL с таким же именем модуля уже загружена в память, система будет использовать загруженную DLL, при этом не будет иметь значения, в каком каталоге эта загруженная DLL находится. Система не станет выполнять других действий по поиску DLL;

  • если DLL есть в списке библиотек DLL, известных той версии операционной системы Windows, в которой запущено приложение, система использует свою копию известной DLL (и свои копии библиотек DLL, от которых эта известная DLL зависит, если таковые имеются) вместо того, чтобы искать эту DLL. Увидеть список известных текущей системе DLL можно, обратившись к следующему ключу реестра: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs.

Если DLL имеет зависимости [от других DLL], система будет искать библиотеки DLL, от которых зависит исходная, так, как если бы эти библиотеки загружались с указанием только имен их модулей. Это правило остается верным, даже если исходная DLL загружалась с указанием полного пути к ней.

Важное замечание. Если злоумышленник получит доступ к одному из каталогов, в которых выполняется поиск DLL, он может поместить в этот каталог вредоносную копию искомой DLL. Чтобы узнать способы предотвращения таких атак, читайте статью «Безопасность DLL».


Стандартный порядок поиска DLL для приложений настольного компьютера

Стандартный порядок поиска DLL, используемый системой, зависит от того, включен или выключен безопасный режим поиска DLL. Безопасный режим поиска DLL помещает текущий каталог пользователя позже в очередности хода поиска.

Безопасный режим поиска DLL по умолчанию включен. Чтобы его выключить, следует создать в реестре параметр HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\SafeDllSearchMode и установить его значение в 0 (ноль). Вызов функции SetDllDirectory при ее успешном завершении отключает параметр реестра SafeDllSearchMode, в то время как указанный [в параметре функции SetDllDirectory] каталог находится в поисковом списке каталогов и изменяет порядок поиска так, как описано [далее] в этой статье.

Замечание для пользователей операционной системы Windows XP (вики: с 24.08.2001 г.; поддержка этой системы прекращена корпорацией «Microsoft» c 08.04.2014 г.): безопасный режим поиска DLL по умолчанию выключен. Чтобы включить его, следует создать параметр реестра SafeDllSearchMode и установить его значение в 1. Безопасный режим поиска DLL включен по умолчанию, начиная с «Windows XP» с установленным пакетом обновления SP2.

Если параметр реестра SafeDllSearchMode включен, порядок поиска DLL будет следующим:
  1. Каталог, из которого загружено приложение;

  2. Системный каталог [обычно это каталог ..\Windows\System32\, но не всегда]. Используйте функцию GetSystemDirectory, чтобы получить путь к этому каталогу;

  3. Системный каталог для 16-разрядных библиотек DLL [обычно это каталог ..\Windows\System\, но не всегда]. Не существует функции [из набора Windows API], которая получала бы путь к этому каталогу, но поиск в этом каталоге всё равно выполняется;

  4. Каталог операционной системы Windows [обычно это каталог ..\Windows\, но не всегда]. Используйте функцию GetWindowsDirectory, чтобы получить путь к этому каталогу;

  5. Текущий каталог;

  6. Каталоги, перечисленные в переменной среды PATH. Заметим, что эта переменная не включает путь, определенный в разрезе каждого приложения ключом реестра App Paths [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths]. Ключ реестра App Paths не используется при поиске DLL.

Если параметр реестра SafeDllSearchMode выключен, порядок поиска DLL будет следующим:
  1. Каталог, из которого загружено приложение;

  2. Текущий каталог;

  3. Системный каталог [обычно это каталог ..\Windows\System32\, но не всегда]. Используйте функцию GetSystemDirectory, чтобы получить путь к этому каталогу;

  4. Системный каталог для 16-разрядных библиотек DLL [обычно это каталог ..\Windows\System\, но не всегда]. Не существует функции [из набора Windows API], которая получала бы путь к этому каталогу, но поиск в этом каталоге всё равно выполняется;

  5. Каталог операционной системы Windows [обычно это каталог ..\Windows\, но не всегда]. Используйте функцию GetWindowsDirectory, чтобы получить путь к этому каталогу;

  6. Каталоги, перечисленные в переменной среды PATH. Заметим, что эта переменная не включает путь, определенный в разрезе каждого приложения ключом реестра App Paths [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths]. Ключ реестра App Paths не используется при поиске DLL.

Альтернативный порядок поиска DLL для приложений настольного компьютера

Стандартный порядок поиска DLL, используемый системой, может быть изменен с помощью вызова функции LoadLibraryEx с флагом LOAD_WITH_ALTERED_SEARCH_PATH. Стандартный порядок поиска DLL также может быть изменен с помощью вызова функции SetDllDirectory.

Замечание: стандартный порядок поиска DLL для процесса попадет под влияние вызова функции SetDllDirectory в родительском процессе, если этот вызов был выполнен до запуска текущего процесса.

Замечание для пользователей операционной системы Windows XP (вики: с 24.08.2001 г.; поддержка этой системы прекращена корпорацией «Microsoft» c 08.04.2014 г.): изменение стандартного порядка поиска DLL с помощью вызова функции SetDllDirectory не поддерживалось до «Windows XP» с установленным пакетом обновления SP1.

Если вы включили стратегию альтернативного порядка поиска DLL, она будет продолжать своё действие до того момента, пока все соответствующие исполняемые модули не будут найдены. После того, как система запустит в работу подпрограммы инициализации DLL, она вернется к стратегии стандартного порядка поиска DLL.

Функция LoadLibraryEx поддерживает альтернативный порядок поиска DLL, если она вызывается с флагом LOAD_WITH_ALTERED_SEARCH_PATH и в ее параметре lpFileName указан абсолютный путь.

Заметим, что стратегия стандартного порядка поиска DLL и стратегия альтернативного порядка поиска DLL, установленная функцией LoadLibraryEx с флагом LOAD_WITH_ALTERED_SEARCH_PATH, различаются только в одном: стандартный порядок поиска DLL начинается с каталога вызывающего приложения, а альтернативный порядок поиска DLL начинается с каталога исполняемого модуля, загружаемого функцией LoadLibraryEx.

Если параметр реестра SafeDllSearchMode включен, альтернативный порядок поиска DLL будет следующим:
  1. Каталог, определенный параметром lpFileName функции LoadLibraryEx;

  2. Системный каталог [обычно это каталог ..\Windows\System32\, но не всегда]. Используйте функцию GetSystemDirectory, чтобы получить путь к этому каталогу;

  3. Системный каталог для 16-разрядных библиотек DLL [обычно это каталог ..\Windows\System\, но не всегда]. Не существует функции [из набора Windows API], которая получала бы путь к этому каталогу, но поиск в этом каталоге всё равно выполняется;

  4. Каталог операционной системы Windows [обычно это каталог ..\Windows\, но не всегда]. Используйте функцию GetWindowsDirectory, чтобы получить путь к этому каталогу;

  5. Текущий каталог;

  6. Каталоги, перечисленные в переменной среды PATH. Заметим, что эта переменная не включает путь, определенный в разрезе каждого приложения ключом реестра App Paths [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths]. Ключ реестра App Paths не используется при поиске DLL.

Если параметр реестра SafeDllSearchMode выключен, альтернативный порядок поиска DLL будет следующим:
  1. Каталог, определенный параметром lpFileName функции LoadLibraryEx;

  2. Текущий каталог;

  3. Системный каталог [обычно это каталог ..\Windows\System32\, но не всегда]. Используйте функцию GetSystemDirectory, чтобы получить путь к этому каталогу;

  4. Системный каталог для 16-разрядных библиотек DLL [обычно это каталог ..\Windows\System\, но не всегда]. Не существует функции [из набора Windows API], которая получала бы путь к этому каталогу, но поиск в этом каталоге всё равно выполняется;

  5. Каталог операционной системы Windows [обычно это каталог ..\Windows\, но не всегда]. Используйте функцию GetWindowsDirectory, чтобы получить путь к этому каталогу;

  6. Каталоги, перечисленные в переменной среды PATH. Заметим, что эта переменная не включает путь, определенный в разрезе каждого приложения ключом реестра App Paths [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths]. Ключ реестра App Paths не используется при поиске DLL.

Функция SetDllDirectory поддерживает альтернативный порядок поиска DLL, если в ее параметре lpPathName указан путь. В этом случае альтернативный порядок поиска DLL будет следующим:
  1. Каталог, из которого загружено приложение;

  2. Каталог, указанный в параметре lpPathName функции SetDllDirectory;

  3. Системный каталог [обычно это каталог ..\Windows\System32\, но не всегда]. Используйте функцию GetSystemDirectory, чтобы получить путь к этому каталогу;

  4. Системный каталог для 16-разрядных библиотек DLL [обычно это каталог ..\Windows\System\, но не всегда]. Не существует функции [из набора Windows API], которая получала бы путь к этому каталогу, но поиск в этом каталоге всё равно выполняется;

  5. Каталог операционной системы Windows [обычно это каталог ..\Windows\, но не всегда]. Используйте функцию GetWindowsDirectory, чтобы получить путь к этому каталогу;

  6. Каталоги, перечисленные в переменной среды PATH. Заметим, что эта переменная не включает путь, определенный в разрезе каждого приложения ключом реестра App Paths [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths]. Ключ реестра App Paths не используется при поиске DLL.

Если в параметр lpPathName функции SetDllDirectory передана пустая строка, эта функция удаляет текущий каталог из поискового списка каталогов.

Функция SetDllDirectory в случае своей успешной отработки выключает безопасный режим поиска DLL, а указанный в ее параметре каталог включается в поисковый список каталогов. Чтобы восстановить безопасный режим поиска DLL, основанный на параметре реестра SafeDllSearchMode, и вернуть текущий каталог в поисковый список каталогов, следует вызвать функцию SetDllDirectory с ее параметром lpPathName, установленным в значение NULL.

Порядок поиска DLL с использованием флагов LOAD_LIBRARY_SEARCH

Приложение может определить порядок поиска DLL, используя один или более флагов LOAD_LIBRARY_SEARCH функции LoadLibraryEx. Приложение также может использовать флаги LOAD_LIBRARY_SEARCH в качестве параметра функции SetDefaultDllDirectories, чтобы настроить порядок поиска DLL для процесса. Приложение может задать дополнительные каталоги для настройки порядка поиска DLL, нужных процессу, с помощью функций AddDllDirectory или SetDllDirectory.

Замечание для пользователей предыдущих по отношению к свежим на дату написания статьи версиям операционных систем Windows (Windows 7 (вики: с 22.10.2009 г.), Windows Server 2008 R2 (вики: с 22.10.2009 г.), Windows Vista (вики: с 30.11.2006 г.), Windows Server 2008 (вики: с 12.12.2008 г.)): флаги LOAD_LIBRARY_SEARCH доступны на этих системах, если установлено обновление KB2533623.

Замечание для пользователей операционных систем Windows Server 2003 (вики: с 24.04.2003 г.) и Windows XP (вики: с 24.08.2001 г.): флаги LOAD_LIBRARY_SEARCH в этих системах не поддерживаются.

В каких именно каталогах происходит поиск DLL, зависит от флагов, указанных при вызове функций SetDefaultDllDirectories или LoadLibraryEx. Если используется более, чем один флаг, соответствующие каталоги обыскиваются в следующем порядке:
  1. Каталог, содержащий DLL (флаг LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR). В этом каталоге ищутся только DLL, от которых зависит загружаемая DLL;

  2. Каталог приложения (флаг LOAD_LIBRARY_SEARCH_APPLICATION_DIR);

  3. Пути, явно добавленные с помощью функции AddDllDirectory (флаг LOAD_LIBRARY_SEARCH_USER_DIRS) или функции SetDllDirectory. Если был добавлен больше, чем один путь, порядок, в котором эти пути обыскиваются, является неопределенным;

  4. Системный каталог (флаг LOAD_LIBRARY_SEARCH_SYSTEM32).

Если приложение не производит вызова функции LoadLibraryEx с любым из флагов LOAD_LIBRARY_SEARCH, чтобы настроить порядок поиска DLL для процесса, система ищет библиотеки DLL либо с помощью стандартного порядка поиска, либо с помощью альтернативного порядка поиска.
Tags: Английский язык, Образование, Программирование
Subscribe

  • Сценарий фильма, который никогда не снимут

    Залпом прочитал набросок сценария художественного фильма, который в 2015-2016 годах написал в своем ЖЖ Григорий Циденков в десяти постах: 1.…

  • Непрощенный, 1992, кино

    Фильм очень понравился. Первый раз смотрел в 90-х, почти ничего не запомнил. Недавно пересмотрел дважды. После «долларовой трилогии» запустил на…

  • Вероятности в сериале «Менталист»

    В первой серии второго сезона сериала «Менталист» (серия называется «Искупление») сотрудники КБР обыскивают помещение, в котором полиция нашла убитую…

  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your IP address will be recorded 

  • 0 comments