Подключение х86 DLL к х64 проекту
От: Truper  
Дата: 20.05.10 06:26
Оценка:
Есть библиотека от стороннего разработчика х86
Есть необходимость подключить ее к проекту х64, а в идеале к MSSQL 2008 x64
Возможно ли такое и как это можно сделать? (даже через костыли)

20.05.10 16:27: Перенесено модератором из 'C/C++' — Кодт
Re: Подключение х86 DLL к х64 проекту
От: K13 http://akvis.com
Дата: 20.05.10 07:01
Оценка:
Здравствуйте, Truper, Вы писали:

T>Есть библиотека от стороннего разработчика х86

T>Есть необходимость подключить ее к проекту х64, а в идеале к MSSQL 2008 x64
T>Возможно ли такое и как это можно сделать? (даже через костыли)

сделать x64 переходник, который запускает x86 загрузчик (в тот процесс подгружается нужная x86 DLL).
Ну а дальше — все вызовы через IPC
Re[2]: Подключение х86 DLL к х64 проекту
От: Truper  
Дата: 20.05.10 07:32
Оценка:
Здравствуйте, K13, Вы писали:

K13>Здравствуйте, Truper, Вы писали:


T>>Есть библиотека от стороннего разработчика х86

T>>Есть необходимость подключить ее к проекту х64, а в идеале к MSSQL 2008 x64
T>>Возможно ли такое и как это можно сделать? (даже через костыли)

K13>сделать x64 переходник, который запускает x86 загрузчик (в тот процесс подгружается нужная x86 DLL).

K13>Ну а дальше — все вызовы через IPC

Как такие переходники делаются?
И что за IPC такое?
Re: Подключение х86 DLL к х64 проекту
От: _DAle_ Беларусь  
Дата: 20.05.10 07:50
Оценка: 5 (1)
Здравствуйте, Truper, Вы писали:

T>Есть библиотека от стороннего разработчика х86

T>Есть необходимость подключить ее к проекту х64, а в идеале к MSSQL 2008 x64
T>Возможно ли такое и как это можно сделать? (даже через костыли)

http://www.dnjonline.com/article.aspx?id=jun07_access3264
Re[3]: Подключение х86 DLL к х64 проекту
От: Мишень-сан  
Дата: 20.05.10 07:54
Оценка:
Здравствуйте, Truper, Вы писали:

T>Как такие переходники делаются?

T>И что за IPC такое?

<b>I</b>nter-<b>P</b>rocess <b>C</b>ommunication

По сути, делаешь маленькую x86 программку, которая подгружает нужную ДЛЛ и организует маршаллинг всех вызовов и возврат результатов.
Запускаешь программку из любого другого процесса и дёргаешь её, а она в свою очередь дёргает нужную библиотеку.
Re[2]: Подключение х86 DLL к х64 проекту
От: saf_e  
Дата: 20.05.10 08:26
Оценка: +1
Здравствуйте, K13, Вы писали:

K13>Здравствуйте, Truper, Вы писали:


T>>Есть библиотека от стороннего разработчика х86

T>>Есть необходимость подключить ее к проекту х64, а в идеале к MSSQL 2008 x64
T>>Возможно ли такое и как это можно сделать? (даже через костыли)

K13>сделать x64 переходник, который запускает x86 загрузчик (в тот процесс подгружается нужная x86 DLL).

K13>Ну а дальше — все вызовы через IPC

По-моему не-inproc COM проще...

Все как рассказывали, только делаешь COM-библиотеку обвертку, весь маршалинг за тебя делает СОМ.
Re: Подключение х86 DLL к х64 проекту
От: rg45 СССР  
Дата: 20.05.10 08:34
Оценка:
Здравствуйте, Truper, Вы писали:

T>Есть библиотека от стороннего разработчика х86

T>Есть необходимость подключить ее к проекту х64, а в идеале к MSSQL 2008 x64
T>Возможно ли такое и как это можно сделать? (даже через костыли)

Совсем недавно такой костыль пришлось сооружать. Идею, в принципе, правильно описал K13. Более детально: реализуется 64-разрядная проксирующая dll, идентичная по списку экспорта целевой 32-разрядной dll. Эта 64-разрядная dll-ка в DllMain по кодам DLL_PROCESS_ATTACH и DLL_THREAD_ATTACH поднимает дочерние 32-разрядные процессы, которые в свою очередь подгружают целевую 32-разрядную dll. Т.о. получается, что на каждый поток 64-разрядного родительского процесса будет приходиться отдельный 32-разрядный дочерний поток. Для хранения даннных, связывающих, потоки родительского процесса с дочерними процессами удобно использовать Thread Local Storage (TLS), для этих целей можно использовать модификатор __declspec(thread). Соответственно по кодам DLL_PROCESS_DETACH и DLL_THREAD_DETACH в DllMain необходимо выполнить действия, которые прямо или косвенно обеспечат завершение дочерних процессов. Вот для примера фрагмент моей реализации:
namespace {

using my_namespace::MyClient;

std::string home_directory(HMODULE);
void init_output(const std::string& homeDirectory);
MyClient* create_client(const std::string& homeDirectory);
destroy_client(MyClient*);

__declspec(thread) MyClient* _tls_client = 0;

} //namespace 


int WINAPI DllMain(HMODULE module, unsigned long reason, void*)
{
  switch(reason)
  {
  case DLL_PROCESS_ATTACH:
    init_output(home_directory(module));
  case DLL_THREAD_ATTACH:
    _tls_client = create_client(home_directory(module));
    break;

  case DLL_PROCESS_DETACH:
  case DLL_THREAD_DETACH:
    {
      MyClient* client = _tls_client;
      _tls_client = 0;
      destroy_client(client);
    }
    break;
  }
  return 1;
}


Способ передачи данных между родительским и дочерними процессами — отдельная тема. Теоретически, подойдет любой способ межпроцессного взаимодействия. На мой взгляд наиболее удачным в данном случае является использование анонимных каналов (Anonimous Pipes). Для каждого из дочерних процессов родительский процесс создает тройку однонаправленных каналов и передает их хендлы дочерним процессам. Два канала используются в качестве управляющих: в одну сторону по одному каналу передаются параметры вызова, по другому, в обратную сторону передаются результаты. Третий канал используется как STDOUT дочернего процесса.

Наиболее естественным условием завершения дочернего процесса при этом является закрытие со стороны родительского процесса конца канала, по которому передаются параметры вызова функций. При такой схеме обеспечивается гарантированное завершение дочерних процессов в самых различных сценариях — от штатного завершения потока в родительском процессе до банального падения родительского процесса.

Существует одна засада, связанная с тем, что В 32-разрядной может присутствовать собственный вывод в STDOUT. Ситуация усугубляется, если этот вывод выполняется на этапе инициализации переменных со статическим временем жизни, которые живут внутри этой dll-ки. Вы скажете: "руки отбивать за такое". Полностью согласен. Но мы же разбираем случай построения обертки вокруг "чужой" dll-ки, о качестве реализации которой нам ничего не известно, поэтому нужно быть готовым к худшему. Именно с этой проблемой я столкнулся на практике. Я опробовал несколько разных способов борьбы с этим явлением и, в конце концов, остановился на том, что для передачи управляющего потока создаю двунаправленный именованный канал (Named Pipe) — отдельный для каждого дочернего процесса. Имя для этого канала задаю в таком формате: \\.\pipe\mypipe_[process ID]_[thread ID], но это уже варианты.
--
Справедливость выше закона. А человечность выше справедливости.
Re[2]: Подключение х86 DLL к х64 проекту
От: ononim  
Дата: 20.05.10 08:43
Оценка: +1 -1
R> Эта 64-разрядная dll-ка в DllMain по кодам DLL_PROCESS_ATTACH и DLL_THREAD_ATTACH поднимает дочерние 32-разрядные процессы,
Ужасно. Нельзя из DllMain такое делать.
Как много веселых ребят, и все делают велосипед...
Re[3]: Подключение х86 DLL к х64 проекту
От: rg45 СССР  
Дата: 20.05.10 08:52
Оценка:
Здравствуйте, ononim, Вы писали:

R>> Эта 64-разрядная dll-ка в DllMain по кодам DLL_PROCESS_ATTACH и DLL_THREAD_ATTACH поднимает дочерние 32-разрядные процессы,

O>Ужасно. Нельзя из DllMain такое делать.

А можно получить какое-нибудь обоснование? Я знаю, что далеко не все можно делать внутри DllMain, но что касается поднятия дочерних процессов, прямых противопоказаний этому я не нашел. И на практике — тестировалось на разных операционках, проблем не обнаружено.
--
Справедливость выше закона. А человечность выше справедливости.
Re[4]: Подключение х86 DLL к х64 проекту
От: ononim  
Дата: 20.05.10 10:13
Оценка: 11 (2)
Здравствуйте, rg45, Вы писали:

R>Здравствуйте, ononim, Вы писали:


R>>> Эта 64-разрядная dll-ка в DllMain по кодам DLL_PROCESS_ATTACH и DLL_THREAD_ATTACH поднимает дочерние 32-разрядные процессы,

O>>Ужасно. Нельзя из DllMain такое делать.

R>А можно получить какое-нибудь обоснование? Я знаю, что далеко не все можно делать внутри DllMain, но что касается поднятия дочерних процессов, прямых противопоказаний этому я не нашел. И на практике — тестировалось на разных операционках, проблем не обнаружено.

Это потому что на чистой системе в вашем процессе не запускаются дополнительные потоки при запуске процесса.
Но это не значит что не найдется какого нить 3rd party софта который к примеру перехватывает запуски процессов через AppCertDlls, валидирует можно ли их запускать через wintrust/cryptoapi, и в такой системе стоит еще какой нить криптопровайдер который для своих внутренних задач подымает и ждет дополнительный поток который благополучно зависнет потому что вся эта байда пытается взлететь из под PEB loader lock'а. И виноваты в этой ситуации будете вы, потому что из DllMain можно "The entry-point function should perform only simple initialization or termination tasks. " (c) MSDN
А если мы еще откроем там же хелп по CreateProcess: http://msdn.microsoft.com/en-us/library/ms885182.aspx и не поленимся прочитать его дальше первого экрана, то там есть любопытная строчка "Do not call CreateProcess from a DllMain function. This causes the application to stop responding."
Как много веселых ребят, и все делают велосипед...
Re[5]: Подключение х86 DLL к х64 проекту
От: rg45 СССР  
Дата: 20.05.10 10:52
Оценка:
Здравствуйте, ononim, Вы писали:


R>>>> Эта 64-разрядная dll-ка в DllMain по кодам DLL_PROCESS_ATTACH и DLL_THREAD_ATTACH поднимает дочерние 32-разрядные процессы,

O>>>Ужасно. Нельзя из DllMain такое делать.

O>А если мы еще откроем там же хелп по CreateProcess: http://msdn.microsoft.com/en-us/library/ms885182.aspx и не поленимся прочитать его дальше первого экрана, то там есть любопытная строчка "Do not call CreateProcess from a DllMain function. This causes the application to stop responding."


Мда, действительно. Дурацкая привычка не дочитывать документацию. Придется реализовать отложенное поднятие дочерних процессов, благо, это не сложно.
--
Справедливость выше закона. А человечность выше справедливости.
Re[6]: Подключение х86 DLL к х64 проекту
От: ononim  
Дата: 20.05.10 10:56
Оценка: 5 (1)
R>Мда, действительно. Дурацкая привычка не дочитывать документацию. Придется реализовать отложенное поднятие дочерних процессов, благо, это не сложно.
еще пот пример из гугла: http://www.google.com/search?hl=en&amp;q=dllmain+createprocess&amp;aq=f&amp;aqi=&amp;aql=&amp;oq=&amp;gs_rfai= -> http://www.experts-exchange.com/Programming/System/Windows__Programming/Q_11892738.html
Как много веселых ребят, и все делают велосипед...
Re[5]: Подключение х86 DLL к х64 проекту
От: gear nuke  
Дата: 20.05.10 15:40
Оценка: 10 (1) :)
Здравствуйте, ononim, Вы писали:

O>стоит еще какой нить криптопровайдер который для своих внутренних задач подымает и ждет дополнительный поток который благополучно зависнет потому что вся эта байда пытается взлететь из под PEB loader lock'а.


Какой лок в другом АП?

O>А если мы еще откроем там же хелп по CreateProcess: http://msdn.microsoft.com/en-us/library/ms885182.aspx и не поленимся прочитать его дальше первого экрана, то там есть любопытная строчка "Do not call CreateProcess from a DllMain function. This causes the application to stop responding."


А если еще и будем читать внимательно, то увидим что Platform Builder for Microsoft Windows CE 5.0 не имеет отношения к WinAPI.
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Re[7]: Подключение х86 DLL к х64 проекту
От: gear nuke  
Дата: 20.05.10 15:40
Оценка:
Здравствуйте, ononim, Вы писали:

O>еще пот пример из гугла: http://www.google.com/search?hl=en&amp;q=dllmain+createprocess&amp;aq=f&amp;aqi=&amp;aql=&amp;oq=&amp;gs_rfai= -> http://www.experts-exchange.com/Programming/System/Windows__Programming/Q_11892738.html


All comments and solutions are available to Premium Service Members only. Sign-up to view the solution to this question.

People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Re[6]: Подключение х86 DLL к х64 проекту
От: ononim  
Дата: 20.05.10 16:38
Оценка: +1
O>>стоит еще какой нить криптопровайдер который для своих внутренних задач подымает и ждет дополнительный поток который благополучно зависнет потому что вся эта байда пытается взлететь из под PEB loader lock'а.
GN>Какой лок в другом АП?
В каком другом АП? AppCertDlls исполняется в контексте процесса, вызывающего CreateProcess, до того как собственно тот процесс будет запущен.
Как много веселых ребят, и все делают велосипед...
Re[7]: Подключение х86 DLL к х64 проекту
От: gear nuke  
Дата: 20.05.10 18:20
Оценка: +1
Здравствуйте, ononim, Вы писали:

O>В каком другом АП?


Прошу прощения, сбило создание тредов в дочернем процессе выше.

O>AppCertDlls исполняется в контексте процесса, вызывающего CreateProcess, до того как собственно тот процесс будет запущен.


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

Вот что сказано про точку входа длл прямо, и что можно притянуть к AppCertDlls

The entry-point function should perform only simple initialization or termination tasks. It must not call the LoadLibrary or LoadLibraryEx function (or a function that calls these functions), because this may create dependency loops in the DLL load order.

People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Re[8]: Подключение х86 DLL к х64 проекту
От: ononim  
Дата: 20.05.10 21:46
Оценка: 13 (2)
GN>Вот что сказано про точку входа длл прямо, и что можно притянуть к AppCertDlls
GN>

The entry-point function should perform only simple initialization or termination tasks. It must not call the LoadLibrary or LoadLibraryEx function (or a function that calls these functions), because this may create dependency loops in the DLL load order.

а еще

Calling functions that require DLLs other than Kernel32.dll may result in problems that are difficult to diagnose. For example, calling User, Shell, and COM functions can cause access violation errors, because some functions load other system components. Conversely, calling functions such as these during termination can cause access violation errors because the corresponding component may already have been unloaded or uninitialized.

и еще

Because Kernel32.dll is guaranteed to be loaded in the process address space when the entry-point function is called, calling functions in Kernel32.dll does not result in the DLL being used before its initialization code has been executed. Therefore, the entry-point function can call functions in Kernel32.dll that do not load other DLLs. For example, DllMain can create synchronization objects such as critical sections and mutexes, and use TLS. Unfortunately, there is not a comprehensive list of safe functions in Kernel32.dll.


И еще ожидание потоков упомянуто:

Because DLL notifications are serialized, entry-point functions should not attempt to communicate with other threads or processes. Deadlocks may occur as a result.


А если не поленимся сходить по ссылке: http://www.microsoft.com/whdc/driver/kernel/DLL_bestprac.mspx
и скачать оттуда мелкий док, в котором четко написано:

You should never perform the following tasks from within DllMain:
...
Call CreateProces. Creating a process can load another DLL.
...

и прошу заметить на CE тут намеков нету

То есть будем полагать что установленная каким нить секурити сьютом юзера в каком нить мухосранске AppCertDll не будет делать вышеперечисленные вещи? Так ведь если обломаемся, то будем виноваты мы, ибо см выше.
Как много веселых ребят, и все делают велосипед...
Re[9]: Подключение х86 DLL к х64 проекту
От: gear nuke  
Дата: 21.05.10 01:52
Оценка:
Здравствуйте, ononim, Вы писали:

O>а еще

O>

O>Calling functions that require DLLs other than Kernel32.dll may result in problems that are difficult to diagnose. For example, calling User, Shell, and COM functions can cause access violation errors, because some functions load other system components. Conversely, calling functions such as these during termination can cause access violation errors because the corresponding component may already have been unloaded or uninitialized.


Это "because this may create dependency loops in the DLL load order"

O>и еще

O>

O>Because Kernel32.dll is guaranteed to be loaded in the process address space when the entry-point function is called, calling functions in Kernel32.dll does not result in the DLL being used before its initialization code has been executed. Therefore, the entry-point function can call functions in Kernel32.dll that do not load other DLLs. For example, DllMain can create synchronization objects such as critical sections and mutexes, and use TLS. Unfortunately, there is not a comprehensive list of safe functions in Kernel32.dll.


Про dll причина опять же выше. А последнее предложение так трактовать: то, что безопасно работает сегодня, сломается завтра? Уважительная причина.

O>И еще ожидание потоков упомянуто:

O>

O>Because DLL notifications are serialized, entry-point functions should not attempt to communicate with other threads or processes. Deadlocks may occur as a result.


Да впринципе дедлоки могут случиться и при простом использовании других объектов синхронизации, не обязательно CRITICAL_SECTION и именем Peb.LdrLock Для безопасного использования важно понимать, что происходит.

O>А если не поленимся сходить по ссылке: http://www.microsoft.com/whdc/driver/kernel/DLL_bestprac.mspx

O>и скачать оттуда мелкий док, в котором четко написано:
O>

You should never perform the following tasks from within DllMain:
O>...
O> Call CreateProces. Creating a process can load another DLL.
O>...

O>и прошу заметить на CE тут намеков нету

Да, поэтому "Do not call" заменено на "You should never perform".

O>То есть будем полагать что установленная каким нить секурити сьютом юзера в каком нить мухосранске AppCertDll не будет делать вышеперечисленные вещи?


Ведь это не рекомендуется, и секурити сьют (хотя я сильно сомневаюсь, что такой софт должен использовать AppCertDlls, в силу сомнительной полезности) расчитывает на совместимость с бесконечным количеством софта, поэтому так делать не будет, по закону больших чисел ошибка обязательно случится.

O>Так ведь если обломаемся, то будем виноваты мы, ибо см выше.


Ты точно не будешь виноват, ибо предупредил, разве что я

Погугли на тему AppCertDlls. Всё, что нашел я, это оригинальная публикации Андрея Воробьева на RSDN и позже в блоге о том зачем оно надо, а так же ссылки на малвару; блог x64 не считаю — дело КК живёт ("но тут я не поручусь, проверять надо, оставим это вам на домашнее задание").

I wonder, if 18 Jan 2007 Google gave by the request "AppCertDlls" exactly zero links, but now (6 Jan 2008) it gives 173 links on the English and additionally more than 20 pages, on non-English...

People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Re[9]: Подключение х86 DLL к х64 проекту
От: rg45 СССР  
Дата: 21.05.10 04:27
Оценка:
Здравствуйте, ononim, Вы писали:


O>А если не поленимся сходить по ссылке: http://www.microsoft.com/whdc/driver/kernel/DLL_bestprac.mspx

O>...

За ссылку спасибо.
--
Справедливость выше закона. А человечность выше справедливости.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.