Мы пытаемся понять некоторые более тонкие детали определения символа во время выполнения. Я уже рассмотрелДжеффри Рихтера, главы 19 (Основы DLL) и 20 (DLL Advanced). Рихтер немного более всеобъемлющий и более сплоченный, чем MSDN.Связывание неявных библиотек и GetModuleHandle/GetProcAdress
Мы пытаемся объединить неявное соединение библиотек с динамическим расположением символов. Мы хотим избежать звонков на LoadLibrary
из-за некоторых потенциальных угроз безопасности. Мы также пытаемся избежать проблем с блокировкой загрузчика , если пользователь делает слишком много работы в функции DllMain
.
#include <windows.h>
#pragma comment(lib, "kernel32")
extern "C" {
typedef BOOL (WINAPI * PFN_GOR)(HANDLE, LPOVERLAPPED, LPDWORD, BOOL);
typedef BOOL (WINAPI * PFN_GORX)(HANDLE, LPOVERLAPPED, LPDWORD, DWORD, BOOL);
}
int main(int argc, char* argv[])
{
HINSTANCE hInst = GetModuleHandle("kernel32");
PFN_GOR pfn1 = hInst ? (PFN_GOR)GetProcAddress(hInst, "GetOverlappedResult") : NULL;
PFN_GORX pfn2 = hInst ? (PFN_GORX)GetProcAddress(hInst, "GetOverlappedResultEx") : NULL;
std::cout << "kernel32: " << std::hex << (void*)hInst << std::endl;
std::cout << "GetOverlappedResult: " << std::hex << (void*)pfn1 << std::endl;
std::cout << "GetOverlappedResultEx: " << std::hex << (void*)pfn2 << std::endl;
return 0;
}
Мы отчасти повезло с GetOverlappedResult
и GetOverlappedResultEx
, потому что kernel32.dll
обеспечивает им обоим независимо от платформы. kernel32.dll
имеет еще одно приятное свойство, потому что каждое приложение Windows ссылается на него, и нет способа его вывести из строя.
Случайные числа с платформы выглядят немного более хлопотными. В Windows 7 и ниже мы имеем CryptGenRandom
от advapi32.dll
; в то время как Windows 10 и выше использует BCryptGenRandom
от bcrypt.dll
. Windows 8 - это серая область, потому что некоторые версии, такие как Windows Phone 8, ничего не предлагают. Мы считаем, что мы можем защитить включение библиотеки на основе WINVER
или _WINNT_VER
.
Я чувствую, что образец неявной связи библиотек в сочетании с GetModuleHandle
и GetProcAdress
необычен, но он соответствует нашим требованиям. Его необычный, потому что он использует неявное связывание и GetModuleHandle
, а не LoadLibrary
. Я также не могу найти текст, который запрещает неявное связывание и GetModuleHandle
.
Он отвечает нашим требованиям, потому что мы не несем ответственности за небезопасную загрузку библиотеки из-за бинарной посадки и других трюков перенаправления DLL. Мы также избежим DoS'ов от случайного неправильного использования, сделав слишком много в DLLmain
.
Мой вопрос в том, является ли код юридической комбинацией или узором. Если это дефектный шаблон, то в чем дефект?
Мы поддерживаем Windows XP и Visual Studio .Net через Windows, 10/10 Телефон/Магазин 10 с помощью Visual Studio 2015
В Windows XP код дает следующий результат:
>cl.exe /TP /EHsc test.cxx /Fetest.exe
...
>.\test.exe
kernel32: 7D4C0000
GetOverlappedResult: 7D52E12C
GetOverlappedResultEx: 00000000
в Windows 7 код дает следующий результат:
>cl.exe /TP /EHsc test.cxx /Fetest.exe
...
>.\test.exe
kernel32: 772A0000
GetOverlappedResult: 772CCC69
GetOverlappedResultEx: 00000000
в Windows 8, код выдает следующий результат (Windows 10 аналогична):
>cl.exe /TP /EHsc test.cxx /Fetest.exe
...
>.\test.exe
kernel32: 74FD0000
GetOverlappedResult: 74FEF8C0
GetOverlappedResultEx: 7675C4D0
В Windows 8 и 10 мы можем проверить только кросс-компилировать и компоновать с подсказкой ARM Developer.Мы тестируем компиляции для рабочего стола, телефона и магазина с помощью следующих дополнительных CXXFLAGS
:
- Чтобы проверить приложение рабочего стола, добавьте следующие
CXXFLAGS
:/DWINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APP
- Для тестирования приложения Windows Store, добавить следующие
CXXFLAGS
:/DWINAPI_FAMILY=WINAPI_FAMILY_APP
- Чтобы проверить Windows Phone, добавьте следующие
CXXFLAGS
:/DWINAPI_FAMILY=WINAPI_FAMILY_PHONE_APP
- Чтобы проверить Surface RT (ARM таблетки), добавьте следующие
CXXFLAGS
:/D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1 /DWINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APP
Я нахожу много хитов, как Implicit vs. Explicit linking to a DLL, но я не смог найти тот, который рассматривает некоторые из вопросов безопасности, которые LoadLibrary
может наложить, и как избежать LoadLibrary
вообще.
Для тех, кому это интересно, вот комментарий к вопросу, который мы оцениваем и пытаемся: [комментарий 233405697] (http://github.com/weidai11/cryptopp/issues/178#issuecomment-233405697). – jww
После прочтения ссылки github, похоже, вы пытаетесь получить свой минимум. и целевые платформы должным образом реализованы. Я бы предложил другое решение этой проблемы в целом: используйте [Поддержка компоновщика для DLL с задержкой] (https://msdn.microsoft.com/en-us/library/151kt790.aspx), укажите целевую версию через символы препроцессора , и изящно обрабатывать недоступные функции, предоставляя пользовательские функции задержки загрузки [вспомогательные функции] (https://msdn.microsoft.com/en-us/library/09t6x5ds.aspx). – IInspectable
Я полагаю, вы уже знаете об этом, но для того, чтобы рассказать об этом для будущих читателей, этот подход не будет работать для Windows Phone, и я не думаю, что он будет работать и для UWP. Если вы их поддерживаете, вам придется использовать условную компиляцию, но это не будет означать '_WIN32_WINNT', который, похоже, вас раздражает. –