Этот баннер — требование Роскомнадзора для исполнения 152 ФЗ.
«На сайте осуществляется обработка файлов cookie, необходимых для работы сайта, а также для анализа использования сайта и улучшения предоставляемых сервисов с использованием метрической программы Яндекс.Метрика. Продолжая использовать сайт, вы даёте согласие с использованием данных технологий».
Политика конфиденциальности
|
|
|
GetProcAddress и тайна мистического нуля.
|
|||
|---|---|---|---|
|
#18+
Вот есть у меня сторонняя dll. Динамически подгружаю её ( LoadLibrary ), получаю ненулевой хэндл. Затем пытаюсь получить точку входа по имени функции ( GetProcAddress ) - получаю 0. Для определённости: dll - mqic32.dll, подсунутая в 6.0 клиент от клиента 7.5. Да, с родной библиотекой 6.0 всё работает нормально. И да, от наглой подмены dll я ничего хорошего не жду, но уж GetProcAddress должна была отработать! ProcName - 'MQCONN'. ОС - Win7 64. Окэй, смотрю с помощью PE Explorer экспортируемый интерфейс библиотеки. Искомая функция в нём есть. Гугл намекает, что GetProcAddress может вернуть 0, если при загрузке dll не нашлись библиотеки, от которых та зависит. Открываю диаграмму зависимостей - и точно, vcredist80 светится красненьким - Path not found, пишет эксплорер. Окэй, не хватает мне VC redistributable 8.0, думаю я. Скачиваю, ставлю, появляется оно в списке программ. Раз ничего при установке не спросила, значит устанавливалась для всех сразу, и должна быть видна отовсюду. Обновляю диаграмму - ан, нет - опять vcredist80 красненький. Окэй, подсовываю прямо под ноги библиотеке все 3 msvc?80.dll. vcredist80 на диаграмме становится зелёненьким. Однако GetProcAddress не проведёшь - она снова возвращает 0. То же, если подложить 3 сии библиотечки под ноги программе. Окэй, мож дело в моём приложении. Пишу файл манифеста: vcr80.manifest Код: xml 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. Поняв, что нифига не Окэй, а фуфло натуральное, перехожу, собственно, к вопросам: 1) Почему при установленном VC redist 8.0 ни PE Explorer, ни (как я подозреваю) моё приложение не видят этот самый redist между LoadLibrary и GetProcAddress? 2) Если дело не в зависимостях - как в моём случае поступить, чтобы GetProcAddress вернул точку входа, а не 0? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.08.2014, 17:56 |
|
||
|
GetProcAddress и тайна мистического нуля.
|
|||
|---|---|---|---|
|
#18+
MrCatГугл намекает, что GetProcAddress может вернуть 0, если при загрузке dll не нашлись библиотеки, от которых та зависит. Гугль врёт. При этом процесс обломается ещё на LoadLibrary(). Posted via ActualForum NNTP Server 1.5 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.08.2014, 18:25 |
|
||
|
GetProcAddress и тайна мистического нуля.
|
|||
|---|---|---|---|
|
#18+
Dimitry Sibiryakov, Не факт - есть отложенная загрузка, т.е. облома не будет до тех пор, пока явно не попросили загрузить либу и получить у нее адрес входа для функции. 2ТС - никогда не показывай исходники. Тогда твоя ошибка будет всегда в 17 строке, что легко решается с помощью того же Гугла ;) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 14.08.2014, 03:18 |
|
||
|
GetProcAddress и тайна мистического нуля.
|
|||
|---|---|---|---|
|
#18+
Та было бы там на что смотреть - всё примитивнейше примитивно: осторожно, мёртвый язык! Код: pascal 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. Ещё раз скажу, что с аналогичной родной библиотекой всё работает гладко, аки часы с кукушем. А вот подкидная библиотека может что-то и не найти (vcredist80, как я подозреваю, т.к. у родной библиотеки vcredist71 под ногами лежит, подкидная его, скорее всего, тоже под ногами искать будет, однако подкладывание vcredist80 под ноги проблему не решает). В библиотеке есть и mangled-имена, их я тоже пробовал подсунуть в ProcName - не помогло. Кроме как от vcredist80, проблемная библиотека зависит только от системных библиотек - kernel, ntdll, api-ms-win-core-XXX, на них не грешу. Помимо свежего 8.0 x32, у меня есть и старая 8.0 x64, и 8.0 от Firebird Project. Из этого ада Dependency Walker находит х64 8.0. PE Explorer ничего не находит. Что при этом находит LoadLibrary - загадка. Загадка, так сказать, мистического нуля. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 14.08.2014, 15:15 |
|
||
|
GetProcAddress и тайна мистического нуля.
|
|||
|---|---|---|---|
|
#18+
MrCat, Гм.. В протыне мертвого языка у меня вызвало непонятку одно - почему на моих простынках: @FXXXX:=GetProcAddress(FHandle,'XXXX'); А у тебя просто : FXXXX:=GetProcAddress(...)? И вызываю я всегда как: if @FXXXX<>nil then FXXX(....); P.S. Внимательно не вчитывался, может чего и ступил. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 14.08.2014, 16:14 |
|
||
|
GetProcAddress и тайна мистического нуля.
|
|||
|---|---|---|---|
|
#18+
В проверке на nil собака на своём месте. Упрощать нельзя, ибо непонятно - с nil сравниваться должен результат функции, или её адрес. Хотя в if можно позвать Assigned(FXXXX) - без собаки, и будет проверяться адрес. Отсутствие собаки при присваивании - с позволения компилятора. При присваивании нет выбора адрес/результат, присвоить можно только адрес. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 14.08.2014, 16:52 |
|
||
|
GetProcAddress и тайна мистического нуля.
|
|||
|---|---|---|---|
|
#18+
MrCat, Есть еще одно предположение - а компилятор имя функции в DLL не корежит? Т.е. вместо "ABCD" нет ли преобразования в "@@ABCD"? И еще - если использовать статическое связывание - эффект тот же? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 14.08.2014, 18:07 |
|
||
|
GetProcAddress и тайна мистического нуля.
|
|||
|---|---|---|---|
|
#18+
MrCat[src Delphiif Result = nil then raise Exception.CreateFmt( SFuncNotFound, [FuncName, SLibCaption, FileName]);[/src] А должно быть RaiseLastOSError. Результат "tdump -w -ee <твоя библиотека>" - В СТУДИЮ!!! Posted via ActualForum NNTP Server 1.5 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 14.08.2014, 18:10 |
|
||
|
GetProcAddress и тайна мистического нуля.
|
|||
|---|---|---|---|
|
#18+
Со статическим связыванием та же ошибка. Правда в сообщении об ошибке к имени функции добавляется префикс - "MQIC.MQCONN". Насколько я понимаю, префикс указывает на имя модуля, т.е. видимо в исходниках библиотеки прописан namespace MQIC, или это имя назначается автоматически при компиляции библиотеки. Dependency Walker тоже показывает снабжённые префиксом имена в колонке EntryPoint. Как говорит справка - в этой колонке указывается точка входа с учётом имени модуля: справка Dependency WalkerThe entry point memory address for the function. This is usually a relative offset from the base address at which the module will load at by the operating system's loader. This base address is usually the base address listed in the Module List View for the particular module. If the function is forwarded to another module, then a forward string will be displayed instead of an address. The forward string is in the form of ModuleName.FunctionName. Для статической линковки пишу: Код: pascal 1. 2. , для name указываю различные вариации из '[MQIC.]MQCONN[std@16]'. Ничего не срабатывает. Насчёт декорированных имён - да, в самой библиотеке у некоторых функций есть пары (в частности есть MQCONN и MQCONNstd@16 ). Пара возникает, как мне кажется, при компиляции под различные условия использования - директивы вызова (std = stdcall?), как реакция на overloading, и т.п. После того, как библиотека скомпилирована, внешним приложениям должны быть доступны все варианты функций. Изменения ProcName со стороны WinAPI не жду, поиск в таблице экспорта должен идти по переданному мной аргументу. Хотя подмена здесь многое бы объяснила. Возможно, WinAPI по своим каким-то (неправильным) соображениям пытается "раздекорировать" мой аргумент (ProcName). В результате она будет, действительно, искать какое-нибудь "MQIC32@MQCONN@12@S@@12345" вместо явно указанного мной "MQCONN" или "MQCONNstd@12". ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 14.08.2014, 18:52 |
|
||
|
GetProcAddress и тайна мистического нуля.
|
|||
|---|---|---|---|
|
#18+
Dimitry Sibiryakov, Опцию -w в справке не нашёл, -ее даёт то же, что и оба просмотрщика: tdump -ee mqic32.dll.newTurbo Dump Version 5.0.16.6 Copyright (c) 1988, 1999 Inprise Corporation Display of File MQIC32.DLL.NEW EXPORT ord:0001='MQBACK' => 'MQIC.MQBACK' EXPORT ord:0002='MQBACKstd@12' => 'MQIC.MQBACKstd@12' EXPORT ord:0003='MQBEGIN' => 'MQIC.MQBEGIN' EXPORT ord:0004='MQBEGINstd@16' => 'MQIC.MQBEGINstd@16' EXPORT ord:0005='MQBUFMH' => 'MQIC.MQBUFMH' EXPORT ord:0006='MQCB' => 'MQIC.MQCB' EXPORT ord:0007='MQCLOSE' => 'MQIC.MQCLOSE' EXPORT ord:0008='MQCLOSEstd@20' => 'MQIC.MQCLOSEstd@20' EXPORT ord:0009='MQCMIT' => 'MQIC.MQCMIT' EXPORT ord:0010='MQCMITstd@12' => 'MQIC.MQCMITstd@12' EXPORT ord:0011='MQCONN' => 'MQIC.MQCONN' EXPORT ord:0012='MQCONNX' => 'MQIC.MQCONNX' EXPORT ord:0013='MQCONNXstd@20' => 'MQIC.MQCONNXstd@20' EXPORT ord:0014='MQCONNstd@16' => 'MQIC.MQCONNstd@16' EXPORT ord:0015='MQCRTMH' => 'MQIC.MQCRTMH' EXPORT ord:0016='MQCTL' => 'MQIC.MQCTL' EXPORT ord:0017='MQDISC' => 'MQIC.MQDISC' EXPORT ord:0018='MQDISCstd@12' => 'MQIC.MQDISCstd@12' EXPORT ord:0019='MQDLTMH' => 'MQIC.MQDLTMH' EXPORT ord:0020='MQDLTMP' => 'MQIC.MQDLTMP' EXPORT ord:0021='MQGET' => 'MQIC.MQGET' EXPORT ord:0022='MQGETstd@36' => 'MQIC.MQGETstd@36' EXPORT ord:0023='MQINQ' => 'MQIC.MQINQ' EXPORT ord:0024='MQINQMP' => 'MQIC.MQINQMP' EXPORT ord:0025='MQINQstd@40' => 'MQIC.MQINQstd@40' EXPORT ord:0026='MQMHBUF' => 'MQIC.MQMHBUF' EXPORT ord:0027='MQOPEN' => 'MQIC.MQOPEN' EXPORT ord:0028='MQOPENstd@24' => 'MQIC.MQOPENstd@24' EXPORT ord:0029='MQPUT' => 'MQIC.MQPUT' EXPORT ord:0030='MQPUT1' => 'MQIC.MQPUT1' EXPORT ord:0031='MQPUT1std@32' => 'MQIC.MQPUT1std@32' EXPORT ord:0032='MQPUTstd@32' => 'MQIC.MQPUTstd@32' EXPORT ord:0033='MQSET' => 'MQIC.MQSET' EXPORT ord:0034='MQSETMP' => 'MQIC.MQSETMP' EXPORT ord:0035='MQSETstd@40' => 'MQIC.MQSETstd@40' EXPORT ord:0036='MQSTAT' => 'MQIC.MQSTAT' EXPORT ord:0037='MQSUB' => 'MQIC.MQSUB' EXPORT ord:0038='MQSUBRQ' => 'MQIC.MQSUBRQ' EXPORT ord:0039='mqAddBag' => 'MQIC.mqAddBag' EXPORT ord:0040='mqAddBagstd@20' => 'MQIC.mqAddBagstd@20' EXPORT ord:0041='mqAddByteString' => 'MQIC.mqAddByteString' EXPORT ord:0042='mqAddByteStringFilter' => 'MQIC.mqAddByteStringFilter' EXPORT ord:0043='mqAddByteStringFilterstd@28' => 'MQIC.mqAddByteStringFilterstd@28' EXPORT ord:0044='mqAddByteStringstd@24' => 'MQIC.mqAddByteStringstd@24' EXPORT ord:0045='mqAddInquiry' => 'MQIC.mqAddInquiry' EXPORT ord:0046='mqAddInquirystd@16' => 'MQIC.mqAddInquirystd@16' EXPORT ord:0047='mqAddInteger' => 'MQIC.mqAddInteger' EXPORT ord:0048='mqAddInteger64' => 'MQIC.mqAddInteger64' EXPORT ord:0049='mqAddInteger64std@24' => 'MQIC.mqAddInteger64std@24' EXPORT ord:0050='mqAddIntegerFilter' => 'MQIC.mqAddIntegerFilter' EXPORT ord:0051='mqAddIntegerFilterstd@24' => 'MQIC.mqAddIntegerFilterstd@24' EXPORT ord:0052='mqAddIntegerstd@20' => 'MQIC.mqAddIntegerstd@20' EXPORT ord:0053='mqAddString' => 'MQIC.mqAddString' EXPORT ord:0054='mqAddStringFilter' => 'MQIC.mqAddStringFilter' EXPORT ord:0055='mqAddStringFilterstd@28' => 'MQIC.mqAddStringFilterstd@28' EXPORT ord:0056='mqAddStringstd@24' => 'MQIC.mqAddStringstd@24' EXPORT ord:0057='mqBagToBuffer' => 'MQIC.mqBagToBuffer' EXPORT ord:0058='mqBagToBufferstd@28' => 'MQIC.mqBagToBufferstd@28' EXPORT ord:0059='mqBufferToBag' => 'MQIC.mqBufferToBag' EXPORT ord:0060='mqBufferToBagstd@24' => 'MQIC.mqBufferToBagstd@24' EXPORT ord:0061='mqClearBag' => 'MQIC.mqClearBag' EXPORT ord:0062='mqClearBagstd@12' => 'MQIC.mqClearBagstd@12' EXPORT ord:0063='mqCountItems' => 'MQIC.mqCountItems' EXPORT ord:0064='mqCountItemsstd@20' => 'MQIC.mqCountItemsstd@20' EXPORT ord:0065='mqCreateBag' => 'MQIC.mqCreateBag' EXPORT ord:0066='mqCreateBagstd@16' => 'MQIC.mqCreateBagstd@16' EXPORT ord:0067='mqDeleteBag' => 'MQIC.mqDeleteBag' EXPORT ord:0068='mqDeleteBagstd@12' => 'MQIC.mqDeleteBagstd@12' EXPORT ord:0069='mqDeleteItem' => 'MQIC.mqDeleteItem' EXPORT ord:0070='mqDeleteItemstd@20' => 'MQIC.mqDeleteItemstd@20' EXPORT ord:0071='mqExecute' => 'MQIC.mqExecute' EXPORT ord:0072='mqExecutestd@36' => 'MQIC.mqExecutestd@36' EXPORT ord:0073='mqGetBag' => 'MQIC.mqGetBag' EXPORT ord:0074='mqGetBagstd@28' => 'MQIC.mqGetBagstd@28' EXPORT ord:0075='mqInquireBag' => 'MQIC.mqInquireBag' EXPORT ord:0076='mqInquireBagstd@24' => 'MQIC.mqInquireBagstd@24' EXPORT ord:0077='mqInquireByteString' => 'MQIC.mqInquireByteString' EXPORT ord:0078='mqInquireByteStringFilter' => 'MQIC.mqInquireByteStringFilter' EXPORT ord:0079='mqInquireByteStringFilterstd@36' => 'MQIC.mqInquireByteStringFilterstd@36' EXPORT ord:0080='mqInquireByteStringstd@32' => 'MQIC.mqInquireByteStringstd@32' EXPORT ord:0081='mqInquireInteger' => 'MQIC.mqInquireInteger' EXPORT ord:0082='mqInquireInteger64' => 'MQIC.mqInquireInteger64' EXPORT ord:0083='mqInquireInteger64std@24' => 'MQIC.mqInquireInteger64std@24' EXPORT ord:0084='mqInquireIntegerFilter' => 'MQIC.mqInquireIntegerFilter' EXPORT ord:0085='mqInquireIntegerFilterstd@28' => 'MQIC.mqInquireIntegerFilterstd@28' EXPORT ord:0086='mqInquireIntegerstd@24' => 'MQIC.mqInquireIntegerstd@24' EXPORT ord:0087='mqInquireItemInfo' => 'MQIC.mqInquireItemInfo' EXPORT ord:0088='mqInquireItemInfostd@28' => 'MQIC.mqInquireItemInfostd@28' EXPORT ord:0089='mqInquireString' => 'MQIC.mqInquireString' EXPORT ord:0090='mqInquireStringFilter' => 'MQIC.mqInquireStringFilter' EXPORT ord:0091='mqInquireStringFilterstd@40' => 'MQIC.mqInquireStringFilterstd@40' EXPORT ord:0092='mqInquireStringstd@36' => 'MQIC.mqInquireStringstd@36' EXPORT ord:0093='mqPad' => 'MQIC.mqPad' EXPORT ord:0094='mqPadstd@20' => 'MQIC.mqPadstd@20' EXPORT ord:0095='mqPutBag' => 'MQIC.mqPutBag' EXPORT ord:0096='mqPutBagstd@28' => 'MQIC.mqPutBagstd@28' EXPORT ord:0097='mqSetByteString' => 'MQIC.mqSetByteString' EXPORT ord:0098='mqSetByteStringFilter' => 'MQIC.mqSetByteStringFilter' EXPORT ord:0099='mqSetByteStringFilterstd@32' => 'MQIC.mqSetByteStringFilterstd@32' EXPORT ord:0100='mqSetByteStringstd@28' => 'MQIC.mqSetByteStringstd@28' EXPORT ord:0101='mqSetInteger' => 'MQIC.mqSetInteger' EXPORT ord:0102='mqSetInteger64' => 'MQIC.mqSetInteger64' EXPORT ord:0103='mqSetInteger64std@28' => 'MQIC.mqSetInteger64std@28' EXPORT ord:0104='mqSetIntegerFilter' => 'MQIC.mqSetIntegerFilter' EXPORT ord:0105='mqSetIntegerFilterstd@28' => 'MQIC.mqSetIntegerFilterstd@28' EXPORT ord:0106='mqSetIntegerstd@24' => 'MQIC.mqSetIntegerstd@24' EXPORT ord:0107='mqSetString' => 'MQIC.mqSetString' EXPORT ord:0108='mqSetStringFilter' => 'MQIC.mqSetStringFilter' EXPORT ord:0109='mqSetStringFilterstd@32' => 'MQIC.mqSetStringFilterstd@32' EXPORT ord:0110='mqSetStringstd@28' => 'MQIC.mqSetStringstd@28' EXPORT ord:0111='mqTrim' => 'MQIC.mqTrim' EXPORT ord:0112='mqTrimstd@20' => 'MQIC.mqTrimstd@20' EXPORT ord:0113='mqTruncateBag' => 'MQIC.mqTruncateBag' EXPORT ord:0114='mqTruncateBagstd@16' => 'MQIC.mqTruncateBagstd@16' EXPORT ord:0115='zrtMQCONN' => 'MQIC.zrtMQCONN' EXPORT ord:0116='zrtMQCONNX' => 'MQIC.zrtMQCONNX' EXPORT ord:0117='zstMQGET' => 'MQIC.zstMQGET' ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 14.08.2014, 19:03 |
|
||
|
GetProcAddress и тайна мистического нуля.
|
|||
|---|---|---|---|
|
#18+
MrCat-ее даёт то же, что и оба просмотрщика Не повезло тебе. Это не настоящая DLL, а только заглушка. Изучай полный вывод tdump и ищи в новом комплекте настоящую DLL. Posted via ActualForum NNTP Server 1.5 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 14.08.2014, 19:19 |
|
||
|
GetProcAddress и тайна мистического нуля.
|
|||
|---|---|---|---|
|
#18+
Dimitry Sibiryakov, чистую правду, мил человек, сказал, спасибо тебе от всей души! MQIC - никакое не пространство имён, а честное название соседней библиотеки. И надо-то было лишь поставить полного клиента 7.5 на виртуалку, да сравнить. Тайну мистического нуля на сём предлагаю считать разгаданной по самые помидоры. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 14.08.2014, 19:53 |
|
||
|
|

start [/forum/topic.php?fid=26&msg=38720716&tid=1494561]: |
0ms |
get settings: |
11ms |
get forum list: |
15ms |
check forum access: |
5ms |
check topic access: |
5ms |
track hit: |
53ms |
get topic data: |
12ms |
get forum data: |
3ms |
get page messages: |
47ms |
get tp. blocked users: |
2ms |
| others: | 16ms |
| total: | 169ms |

| 0 / 0 |
