Может ли GetModuleHandle(Ex) привести к вызову LoadLibrary?
От: ksd Россия  
Дата: 12.07.18 09:57
Оценка:
Коллега утверждает, что вызов GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_PIN, "ModuleName", &ModuleHandle) может привести к вызову LoadLibrary внутри при каких то условиях. Подтверждения в MSDN нет, но и явно опровержение не могу найти. Есть у кого-то точное знание? Заранее спасибо!
Re: Может ли GetModuleHandle(Ex) привести к вызову LoadLibrary?
От: Сергей Мухин Россия  
Дата: 12.07.18 10:14
Оценка:
Здравствуйте, ksd, Вы писали:

ksd>Коллега утверждает, что вызов GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_PIN, "ModuleName", &ModuleHandle) может привести к вызову LoadLibrary внутри при каких то условиях. Подтверждения в MSDN нет, но и явно опровержение не могу найти. Есть у кого-то точное знание? Заранее спасибо!


The module must have been loaded by the calling process.

этого не достаточно?
---
С уважением,
Сергей Мухин
Re: Может ли GetModuleHandle(Ex) привести к вызову LoadLibra
От: Maniacal Россия  
Дата: 12.07.18 10:28
Оценка:
Здравствуйте, ksd, Вы писали:

ksd>Коллега утверждает, что вызов GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_PIN, "ModuleName", &ModuleHandle) может привести к вызову LoadLibrary внутри при каких то условиях. Подтверждения в MSDN нет, но и явно опровержение не могу найти. Есть у кого-то точное знание? Заранее спасибо!


Если модуль уже загружен, то GetModuleHandle(Ex) никогда не вызовет LoadLibrary. Если исполняемый файл скомпанован с библиотеками в режиме deferred DLL load и до этого ни разу библиотека не использовалась, то LoadLibrary для библиотеки будет вызван, но... GetModuleHandle и GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, "ModuleName", &ModuleHandle) не увеличат счётчик загруженных DLL. Тут нужно быть аккуратнее.
Отредактировано 12.07.2018 10:30 Maniacal . Предыдущая версия .
Re[2]: Может ли GetModuleHandle(Ex) привести к вызову LoadLi
От: EreTIk EreTIk's Box
Дата: 12.07.18 11:08
Оценка: 9 (1)
M>Если исполняемый файл скомпанован с библиотеками в режиме deferred DLL load и до этого ни разу библиотека не использовалась, то LoadLibrary для библиотеки будет вызван, но...

Пример:
void __cdecl _tmain(int argc, TCHAR *argv[])
{
    HMODULE hModule{nullptr};
    ::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_PIN, L"user32.dll", &hModule);

    keybd_event(0,0,0,0);
}


Сборка:
>cl /Zi /MTd /EHsc test.cpp /link /RELEASE /OPT:REF /DELAYLOAD:user32.dll dloadhelper.lib


Отладчик:
test!wmain+0x16:
00007ff7`8a121036 4c8d442420      lea     r8,[rsp+20h]
0:000> lsa @$ip
    56: 
    57: void __cdecl _tmain(int argc, TCHAR *argv[])
    58: {
    59:     HMODULE hModule{nullptr};
>   60:     ::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_PIN, L"user32.dll", &hModule);
    61: 
    62:     keybd_event(0,0,0,0);
    63: }



Исполняем GetModuleHandleEx:
0:000> p
test!wmain+0x2d:
00007ff7`8a12104d 4533c9          xor     r9d,r9d
0:000> lsa @$ip
    58: {
    59:     HMODULE hModule{nullptr};
    60:     ::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_PIN, L"user32.dll", &hModule);
    61: 
>   62:     keybd_event(0,0,0,0);
    63: }


User32 не появился:
0:000> ?? hModule
struct HINSTANCE__ * 0x00000000`00000000
0:000> lm
start             end                 module name
00007ff7`8a120000 00007ff7`8a172000   test       (private pdb symbols)  test.pdb
00007ff8`00090000 00007ff8`00303000   KERNELBASE   (deferred)             
00007ff8`031b0000 00007ff8`03262000   KERNEL32   (deferred)             
00007ff8`032c0000 00007ff8`034a1000   ntdll      (pdb symbols)          ~\symbols\ntdll.pdb\E7A53714619369B2356D6363BA34ACA31\ntdll.pdb


Трассируем первое использование:
0:000> p
ModLoad: 00007ff8`01990000 00007ff8`01b20000   C:\WINDOWS\System32\USER32.dll
ModLoad: 00007fff`ff720000 00007fff`ff740000   C:\WINDOWS\System32\win32u.dll
ModLoad: 00007ff8`00d10000 00007ff8`00d38000   C:\WINDOWS\System32\GDI32.dll
ModLoad: 00007fff`ff740000 00007fff`ff8d2000   C:\WINDOWS\System32\gdi32full.dll
ModLoad: 00007ff8`006b0000 00007ff8`0074f000   C:\WINDOWS\System32\msvcp_win.dll
ModLoad: 00007ff8`005b0000 00007ff8`006aa000   C:\WINDOWS\System32\ucrtbase.dll
ModLoad: 00007ff8`016b0000 00007ff8`016dd000   C:\WINDOWS\System32\IMM32.DLL
test!wmain+0x3d:
00007ff7`8a12105d 33c0            xor     eax,eax
0:000> lm
start             end                 module name
00007ff7`8a120000 00007ff7`8a172000   test       (private pdb symbols)  test.pdb
00007ff8`00090000 00007ff8`00303000   KERNELBASE   (deferred)             
00007ff8`005b0000 00007ff8`006aa000   ucrtbase   (deferred)             
00007ff8`006b0000 00007ff8`0074f000   msvcp_win   (deferred)             
00007ff8`00d10000 00007ff8`00d38000   GDI32      (deferred)             
00007ff8`016b0000 00007ff8`016dd000   IMM32      (deferred)             
00007ff8`01990000 00007ff8`01b20000   USER32     (deferred)             
00007ff8`031b0000 00007ff8`03262000   KERNEL32   (deferred)             
00007ff8`032c0000 00007ff8`034a1000   ntdll      (pdb symbols)          ~\symbols\ntdll.pdb\E7A53714619369B2356D6363BA34ACA31\ntdll.pdb
00007fff`ff720000 00007fff`ff740000   win32u     (deferred)             
00007fff`ff740000 00007fff`ff8d2000   gdi32full   (deferred)             
0:000> lsa @$ip
    59:     HMODULE hModule{nullptr};
    60:     ::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_PIN, L"user32.dll", &hModule);
    61: 
    62:     keybd_event(0,0,0,0);
>   63: }


Что я делаю не так?

UPD:
Отредактировано 12.07.2018 12:10 EreTIk . Предыдущая версия . Еще …
Отредактировано 12.07.2018 11:27 EreTIk . Предыдущая версия .
Отредактировано 12.07.2018 11:22 EreTIk . Предыдущая версия .
Re[2]: нет не достаточно
От: ksd Россия  
Дата: 12.07.18 11:27
Оценка:
Здравствуйте, Сергей Мухин, Вы писали:

СМ>Здравствуйте, ksd, Вы писали:


ksd>>Коллега утверждает, что вызов GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_PIN, "ModuleName", &ModuleHandle) может привести к вызову LoadLibrary внутри при каких то условиях. Подтверждения в MSDN нет, но и явно опровержение не могу найти. Есть у кого-то точное знание? Заранее спасибо!


СМ>The module must have been loaded by the calling process.


СМ>этого не достаточно?

Да, это я и сам видел, конечно, но это требование к пользователю WINAPI, а не к реализации. Хорошо бы, чтобы было явно указано то, что реализация ни в одной версии винды не станет звать LoadLibrary, если пользователь не выполнил указанное условие.
Re[3]: Может ли GetModuleHandle(Ex) привести к вызову LoadLi
От: Maniacal Россия  
Дата: 12.07.18 13:38
Оценка:
Здравствуйте, EreTIk, Вы писали:

В общем, так я и не нашёл, где я сегодня нашёл, что при отложенной загрузке библиотек, GetModuleHandle может вызвать загрузку библиотеки... Слишком бегло читал, видимо, совсем наискосок. Везде пишут, что при нулевом RefCount для библиотеки функция GetModuleHandle(ex) никогда не отработает.

Да и сами Microsoft пишут, что

...A workaround is to explicitly handle the data import yourself using LoadLibrary (or GetModuleHandle after you know the delay-load helper has loaded the DLL) and GetProcAddress.

 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.