GetProcAddress - не находит функцию в DLL, а она там есть!

Программирование на Visual Basic, главный форум. Обсуждение тем программирования на VB 1—6.
Даже если вы плохо разбираетесь в VB и программировании вообще — тут вам помогут. В разумных пределах, конечно.
Правила форума
Темы, в которых будет сначала написано «что нужно сделать», а затем просьба «помогите», будут закрыты.
Читайте требования к создаваемым темам.
jangle
Википедик
Википедик
Аватара пользователя
 
Сообщения: 3013
Зарегистрирован: 03.06.2005 (Пт) 12:02
Откуда: Нидерланды

GetProcAddress - не находит функцию в DLL, а она там есть!

Сообщение jangle » 04.09.2009 (Пт) 11:14

Есть задачка отсортировать Native DLL и ActiveX DLL, самый простой способ это искать функцию DllRegisterServer в экспорте, если она есть - имеем дело с COM DLL в противном случае Native DLL. Вот такая функция, работает нормально, но не во всех случаях.

Код: Выделить всё
Public Function TestDll(ByVal file As String) As Long

Dim hMod  As Long
Dim hLong As Long
    hMod = LoadLibrary(file)
    TestDll = GetProcAddress(hMod, "DllRegisterServer")
    Call FreeLibrary(hMod)
End Function


Например есть COM DLL с таким экспортом, но моя фунукция возвращает 0, хотя DllRegisterServer присуствует!
Не пойму в чем грабли? Подскажите :shock:


Код: Выделить всё
void boost::archive::detail::iserializer<class boost::archive::binary_iarchive,struct CriModelIO::Header>::load_object_data(class boost::archive::detail::basic_iarchive &,void *,unsigned int)
void boost::archive::detail::iserializer<class boost::archive::binary_iarchive,struct CriModelIO::Material>::load_object_data(class boost::archive::detail::basic_iarchive &,void *,unsigned int)
void boost::archive::detail::iserializer<class boost::archive::binary_iarchive,struct CriModelIO::Triangle>::load_object_data(class boost::archive::detail::basic_iarchive &,void *,unsigned int)
void boost::archive::detail::iserializer<class boost::archive::binary_iarchive,struct CriModelIO::Vec3>::load_object_data(class boost::archive::detail::basic_iarchive &,void *,unsigned int)
void boost::archive::detail::iserializer<class boost::archive::binary_iarchive,struct CriModelIO::Vec4>::load_object_data(class boost::archive::detail::basic_iarchive &,void *,unsigned int)
void boost::archive::detail::iserializer<class boost::archive::binary_iarchive,class std::vector<struct CriModelIO::Material,class std::allocator<struct CriModelIO::Material> > >::load_object_data(class boost::archive::detail::basic_iarchive &,void *,unsigned int)
void boost::archive::detail::iserializer<class boost::archive::binary_iarchive,class std::vector<struct CriModelIO::Triangle,class std::allocator<struct CriModelIO::Triangle> > >::load_object_data(class boost::archive::detail::basic_iarchive &,void *,unsigned int)
void boost::archive::detail::iserializer<class boost::archive::binary_iarchive,class std::vector<struct CriModelIO::Vec3,class std::allocator<struct CriModelIO::Vec3> > >::load_object_data(class boost::archive::detail::basic_iarchive &,void *,unsigned int)
void boost::archive::detail::iserializer<class boost::archive::binary_iarchive,class std::vector<class std::vector<struct CriModelIO::Vec3,class std::allocator<struct CriModelIO::Vec3> >,class std::allocator<class std::vector<struct CriModelIO::Vec3,class std::allocator<struct CriModelIO::Vec3> > > > >::load_object_data(class boost::archive::detail::basic_iarchive &,void *,unsigned int)
void boost::archive::detail::iserializer<class boost::archive::binary_iarchive,class CriModelIO>::load_object_data(class boost::archive::detail::basic_iarchive &,void *,unsigned int)
void boost::archive::detail::oserializer<class boost::archive::binary_oarchive,struct CriModelIO::Header>::save_object_data(class boost::archive::detail::basic_oarchive &,void const *)
void boost::archive::detail::oserializer<class boost::archive::binary_oarchive,struct CriModelIO::Material>::save_object_data(class boost::archive::detail::basic_oarchive &,void const *)
void boost::archive::detail::oserializer<class boost::archive::binary_oarchive,struct CriModelIO::Triangle>::save_object_data(class boost::archive::detail::basic_oarchive &,void const *)
void boost::archive::detail::oserializer<class boost::archive::binary_oarchive,struct CriModelIO::Vec3>::save_object_data(class boost::archive::detail::basic_oarchive &,void const *)
void boost::archive::detail::oserializer<class boost::archive::binary_oarchive,struct CriModelIO::Vec4>::save_object_data(class boost::archive::detail::basic_oarchive &,void const *)
void boost::archive::detail::oserializer<class boost::archive::binary_oarchive,class std::vector<struct CriModelIO::Material,class std::allocator<struct CriModelIO::Material> > >::save_object_data(class boost::archive::detail::basic_oarchive &,void const *)
void boost::archive::detail::oserializer<class boost::archive::binary_oarchive,class std::vector<struct CriModelIO::Triangle,class std::allocator<struct CriModelIO::Triangle> > >::save_object_data(class boost::archive::detail::basic_oarchive &,void const *)
void boost::archive::detail::oserializer<class boost::archive::binary_oarchive,class std::vector<struct CriModelIO::Vec3,class std::allocator<struct CriModelIO::Vec3> > >::save_object_data(class boost::archive::detail::basic_oarchive &,void const *)
void boost::archive::detail::oserializer<class boost::archive::binary_oarchive,class std::vector<class std::vector<struct CriModelIO::Vec3,class std::allocator<struct CriModelIO::Vec3> >,class std::allocator<class std::vector<struct CriModelIO::Vec3,class std::allocator<struct CriModelIO::Vec3> > > > >::save_object_data(class boost::archive::detail::basic_oarchive &,void const *)
void boost::archive::detail::oserializer<class boost::archive::binary_oarchive,class CriModelIO>::save_object_data(class boost::archive::detail::basic_oarchive &,void const *)
DllCanUnloadNow
DllGetClassObject
DllRegisterServer
DllUnregisterServer

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: GetProcAddress - не находит функцию в DLL, а она там есть!

Сообщение Хакер » 04.09.2009 (Пт) 18:58

GetLastError?
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

jangle
Википедик
Википедик
Аватара пользователя
 
Сообщения: 3013
Зарегистрирован: 03.06.2005 (Пт) 12:02
Откуда: Нидерланды

Re: GetProcAddress - не находит функцию в DLL, а она там есть!

Сообщение jangle » 04.09.2009 (Пт) 20:02

Хакер писал(а):GetLastError?


GetLastError = 126, это "The specified module could not be found."

Что за фигня? Не может подхватить какой-то модуль связанный с загружаемой DLL? Но компонент работает нормально, значит всего ему хватает

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: GetProcAddress - не находит функцию в DLL, а она там есть!

Сообщение Хакер » 04.09.2009 (Пт) 20:07

Ты проверяешь hMod? Там не ноль?
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

jangle
Википедик
Википедик
Аватара пользователя
 
Сообщения: 3013
Зарегистрирован: 03.06.2005 (Пт) 12:02
Откуда: Нидерланды

Re: GetProcAddress - не находит функцию в DLL, а она там есть!

Сообщение jangle » 04.09.2009 (Пт) 20:12

Хакер писал(а):Ты проверяешь hMod? Там не ноль?


Проверил, hMod=0, значит LoadLibrary не срабатывает? Но почему, компонент рабочий. Нормально регистрируется утилитой REGSVR32, значит у нее получается загрузить этот компонент, а у меня нет

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: GetProcAddress - не находит функцию в DLL, а она там есть!

Сообщение Хакер » 04.09.2009 (Пт) 20:16

Ну, разве непонятно, что делать дальше? Проверять FileName, смотреть, как оно соотносится с перечнем мест, в которых производится поиск библиотеки.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

jangle
Википедик
Википедик
Аватара пользователя
 
Сообщения: 3013
Зарегистрирован: 03.06.2005 (Пт) 12:02
Откуда: Нидерланды

Re: GetProcAddress - не находит функцию в DLL, а она там есть!

Сообщение jangle » 04.09.2009 (Пт) 20:22

Хакер писал(а):Ну, разве непонятно, что делать дальше? Проверять FileName, смотреть, как оно соотносится с перечнем мест, в которых производится поиск библиотеки.


Так уже сто раз проверил, даже полный путь прописал в коде. Но все равно не грузится, LoadLibrary возвращает 0, ошибка 126.
Вроде как и нет по этому пути ничего... Мистика... :shock:

Код: Выделить всё
Option Explicit
Private Declare Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA" _
  (ByVal lpLibFileName As String) As Long

Private Declare Function GetProcAddress Lib "kernel32" (ByVal hModule As Long, _
    ByVal lpProcName As String) As Long
   
Private Declare Function FreeLibrary Lib "kernel32" (ByVal hLibModule As Long) As Long
   

Public Function TestDll(ByVal file As String) As Long
Dim hMod  As Long
    hMod = LoadLibrary(file)
    TestDll = GetProcAddress(hMod, "DllRegisterServer")
    Call FreeLibrary(hMod)
End Function


Private Sub Command1_Click()
    MsgBox TestDll("D:\Test\Viewer3D.ocx")
    MsgBox "Ошибка " & Err.LastDllError
End Sub

jangle
Википедик
Википедик
Аватара пользователя
 
Сообщения: 3013
Зарегистрирован: 03.06.2005 (Пт) 12:02
Откуда: Нидерланды

Re: GetProcAddress - не находит функцию в DLL, а она там есть!

Сообщение jangle » 04.09.2009 (Пт) 20:47

Вобщем что-то тут странное, REGSVR32 может загрузить DLL, а я нет. Ведь REGSVR32 это просто обертка над вызовом DllRegisterServer.
ИМХО REGSVR32 грузит библу все-таки по другому.
Cейчас запустил эту утилиту под API монитором программы Dependency Walker, вот кусок лога.
Ясно видно загрузку VIEWER3D.OCX функцией LoadLibraryExW, т.е. нужен UNICODE вариант LoadLibrary?


---------------------------------------------------------------------------------------------------------------------
Starting profile on 04.09.2009 at 21:28:48

Operating System: Microsoft Windows XP Professional (32-bit), version 5.01.2600 Service Pack 3
Program Executable: d:\windows\system32\REGSVR32.EXE
Program Arguments: "D:\Test\Viewer3D.ocx"
Starting Directory: D:\WINDOWS\system32\
Search Path: D:\WINDOWS\system32;D:\WINDOWS;D:\WINDOWS\System32\Wbem;d:\Program Files\Microsoft SQL Server\90\Tools\binn\;D:\Program Files\QuickTime\QTSystem\;C:\PBWin90\BIN

Options Selected:
Simulate ShellExecute by inserting any App Paths directories into the PATH environment variable.
Log DllMain calls for process attach and process detach messages.
Log DllMain calls for all other messages, including thread attach and thread detach.
Hook the process to gather more detailed dependency information.
Log LoadLibrary function calls.
Log GetProcAddress function calls.
Log thread information.
Use simple thread numbers instead of actual thread IDs.
Log first chance exceptions.
Log debug output messages.
Use full paths when logging file names.
Log a time stamp with each line of log.
Automatically open and profile child processes.
--------------------------------------------------------------------------------


00:00:01.172: DllMain(0x00920000, DLL_PROCESS_ATTACH, 0x00000000) in "d:\Test\VIEWER3D.OCX" called by thread 1.
00:00:01.203: GetProcAddress(0x7E360000 [d:\windows\system32\USER32.DLL], "NotifyWinEvent") called from "d:\windows\winsxs\x86_microsoft.vc80.mfc_1fc8b3b9a1e18e3b_8.0.50727.762_x-ww_3bf8fa05\MFC80.DLL" at address 0x78239813 and returned 0x7E3799CB by thread 1.
00:00:01.203: DllMain(0x00920000, DLL_PROCESS_ATTACH, 0x00000000) in "d:\Test\VIEWER3D.OCX" returned 1 (0x1) by thread 1.
00:00:01.203: LoadLibraryExW("D:\Test\Viewer3D.ocx", 0x00000000, LOAD_WITH_ALTERED_SEARCH_PATH) returned 0x00920000 by thread 1.00:00:01.250: GetProcAddress(0x00920000 [d:\Test\VIEWER3D.OCX], "DllRegisterServer") called from "d:\windows\system32\REGSVR32.EXE" at address 0x01001EA0 and returned 0x009ED990 by thread 1.
00:00:01.250: LoadLibraryA("OLEAUT32.dll") called from "d:\windows\winsxs\x86_microsoft.vc80.mfc_1fc8b3b9a1e18e3b_8.0.50727.762_x-ww_3bf8fa05\MFC80.DLL" at address 0x782972C1 by thread 1.

------------------------------------------------------------------------------

jangle
Википедик
Википедик
Аватара пользователя
 
Сообщения: 3013
Зарегистрирован: 03.06.2005 (Пт) 12:02
Откуда: Нидерланды

Re: GetProcAddress - не находит функцию в DLL, а она там есть!

Сообщение jangle » 05.09.2009 (Сб) 12:36

Удалось выяснить в чем баг, оказывается если у проверяемой DLL есть ссылка в импорте на неявно загружаемую другую DLL
LoadLibrary не сможет ее загрузить, будет возвращаться ошибка 126. Нужно использовать функцию LoadLibraryEx с параметром DONT_RESOLVE_DLL_REFERENCES. Ниже написан полностью рабочий код.

Код: Выделить всё
Public Function TestDll(ByVal file As String) As Long
    Dim hMod  As Long
    hMod = LoadLibraryEx(file, ByVal 0, DONT_RESOLVE_DLL_REFERENCES)
    TestDll = GetProcAddress(hMod, "DllRegisterServer")
    Call FreeLibrary(hMod)
End Function


Вернуться в Visual Basic 1–6

Кто сейчас на конференции

Сейчас этот форум просматривают: AhrefsBot и гости: 2

    TopList