HMODULE в DLL
От: Polosaty Беларусь  
Дата: 20.02.02 17:52
Оценка:
Подскажите, пожалуйста, как, находясь в DLL, получить HMODULE этой DLL? Проблема в том, что в этой DLL нужно пользовать custom ресурсы, а соответствующие вызовы API FindResource, LoadResource, SizeofResource требуют HMODULE. Если вместо HMODULE пользовать NULL или использовать GetModuleHandle(NULL), то возвращается HMODULE вызывающего DLL процесса, а не самой DLL. Вызывать
GetModuleHandle("Путь")

тоже нельзя, т.к. положение текущего каталога относительно каталога с DLL неизвестно. Абсолютный путь к DLL заранее тоже не известен.
Использовать HMODULE, который передается в DLLMain, в моем случае тоже не получается.
Так как же поиметь HMODULE DLL, находясь в самой DLL? Или как поиметь custom ресурс, который в этой же DLL?
Re: HMODULE в DLL
От: Владимир Гренадеров Россия  
Дата: 20.02.02 17:57
Оценка:
Здравствуйте Polosaty, Вы писали:

P>Подскажите, пожалуйста, как, находясь в DLL, получить HMODULE этой DLL? Проблема в том, что в этой DLL нужно пользовать custom ресурсы, а соответствующие вызовы API FindResource, LoadResource, SizeofResource требуют HMODULE. Если вместо HMODULE пользовать NULL или использовать GetModuleHandle(NULL), то возвращается HMODULE вызывающего DLL процесса, а не самой DLL. Вызывать

P>
P>GetModuleHandle("Путь")
P>

P>тоже нельзя, т.к. положение текущего каталога относительно каталога с DLL неизвестно. Абсолютный путь к DLL заранее тоже не известен.
P>Использовать HMODULE, который передается в DLLMain, в моем случае тоже не получается.
P>Так как же поиметь HMODULE DLL, находясь в самой DLL? Или как поиметь custom ресурс, который в этой же DLL?

Используй DllMain:

HINSTANCE hInst;
...
BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)
{ 
if (fdwReason == DLL_PROCESS_ATTACH)
  hInst = hinstDll;
}
...
use hInst in program
...
OK
Re: HMODULE в DLL
От: Alex Fedotov США  
Дата: 20.02.02 17:58
Оценка: 115 (10)
Здравствуйте Polosaty, Вы писали:

P>Подскажите, пожалуйста, как, находясь в DLL, получить HMODULE этой DLL? Проблема в том, что в этой DLL нужно пользовать custom ресурсы, а соответствующие вызовы API FindResource, LoadResource, SizeofResource требуют HMODULE. Если вместо HMODULE пользовать NULL или использовать GetModuleHandle(NULL), то возвращается HMODULE вызывающего DLL процесса, а не самой DLL. Вызывать

P>
P>GetModuleHandle("Путь")
P>

P>тоже нельзя, т.к. положение текущего каталога относительно каталога с DLL неизвестно. Абсолютный путь к DLL заранее тоже не известен.
P>Использовать HMODULE, который передается в DLLMain, в моем случае тоже не получается.
P>Так как же поиметь HMODULE DLL, находясь в самой DLL? Или как поиметь custom ресурс, который в этой же DLL?

Специально для таких случаев сделал функцию GetCurrentInstance (по аналогии с GetCurrentThread и GetCurrentProcess). Возвращает HINSTANCE модуля, из которого была вызвана эта функция.

HINSTANCE GetInstanceFromAddress(
    PVOID pEip
    )
{
    _ASSERTE(pEip != NULL);

    MEMORY_BASIC_INFORMATION mem;
    if (VirtualQuery(pEip, &mem, sizeof(mem)))
    {
        _ASSERTE(mem.Type == MEM_IMAGE);
        _ASSERTE(mem.AllocationBase != NULL);
        return (HINSTANCE)mem.AllocationBase;
    }
    return NULL;
}

__declspec(naked) 
HINSTANCE GetCurrentInstance()
{ __asm {
#ifdef _M_IX86
    mov   eax, [esp]
    push  eax
    jmp   GetInstanceFromAddress
#else
#   error This machine type is not supported.
#endif
} }
-- Alex Fedotov
Re[2]: HMODULE в DLL
От: Alex Fedotov США  
Дата: 20.02.02 18:02
Оценка: 9 (1)
Здравствуйте Alex Fedotov, Вы писали:

AF>Специально для таких случаев сделал функцию GetCurrentInstance (по аналогии с GetCurrentThread и GetCurrentProcess). Возвращает HINSTANCE модуля, из которого была вызвана эта функция.


AF>
AF>HINSTANCE GetInstanceFromAddress(
AF>    PVOID pEip
AF>    )
AF>{
AF>    _ASSERTE(pEip != NULL);

AF>    MEMORY_BASIC_INFORMATION mem;
AF>    if (VirtualQuery(pEip, &mem, sizeof(mem)))
AF>    {
AF>        _ASSERTE(mem.Type == MEM_IMAGE);
AF>        _ASSERTE(mem.AllocationBase != NULL);
AF>        return (HINSTANCE)mem.AllocationBase;
AF>    }
AF>    return NULL;
AF>}

AF>__declspec(naked) 
AF>HINSTANCE GetCurrentInstance()
AF>{ __asm {
AF>#ifdef _M_IX86
AF>    mov   eax, [esp]
AF>    push  eax
AF>    jmp   GetInstanceFromAddress
AF>#else
AF>#   error This machine type is not supported.
AF>#endif
AF>} }
AF>


Черт, в процессе публикации изчез __stdcall у обеих функций. Добавь, а то падать будет.
-- Alex Fedotov
Re[2]: HMODULE в DLL
От: Владимир Гренадеров Россия  
Дата: 20.02.02 18:07
Оценка:
Здравствуйте Alex Fedotov, Вы писали:

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


P>>Подскажите, пожалуйста, как, находясь в DLL, получить HMODULE этой DLL? Проблема в том, что в этой DLL нужно пользовать custom ресурсы, а соответствующие вызовы API FindResource, LoadResource, SizeofResource требуют HMODULE. Если вместо HMODULE пользовать NULL или использовать GetModuleHandle(NULL), то возвращается HMODULE вызывающего DLL процесса, а не самой DLL. Вызывать

P>>
P>>GetModuleHandle("Путь")
P>>

P>>тоже нельзя, т.к. положение текущего каталога относительно каталога с DLL неизвестно. Абсолютный путь к DLL заранее тоже не известен.
P>>Использовать HMODULE, который передается в DLLMain, в моем случае тоже не получается.
P>>Так как же поиметь HMODULE DLL, находясь в самой DLL? Или как поиметь custom ресурс, который в этой же DLL?

AF>Специально для таких случаев сделал функцию GetCurrentInstance (по аналогии с GetCurrentThread и GetCurrentProcess). Возвращает HINSTANCE модуля, из которого была вызвана эта функция.


AF>
AF>HINSTANCE GetInstanceFromAddress(
AF>    PVOID pEip
AF>    )
AF>{
AF>    _ASSERTE(pEip != NULL);

AF>    MEMORY_BASIC_INFORMATION mem;
AF>    if (VirtualQuery(pEip, &mem, sizeof(mem)))
AF>    {
AF>        _ASSERTE(mem.Type == MEM_IMAGE);
AF>        _ASSERTE(mem.AllocationBase != NULL);
AF>        return (HINSTANCE)mem.AllocationBase;
AF>    }
AF>    return NULL;
AF>}

AF>__declspec(naked) 
AF>HINSTANCE GetCurrentInstance()
AF>{ __asm {
AF>#ifdef _M_IX86
AF>    mov   eax, [esp]
AF>    push  eax
AF>    jmp   GetInstanceFromAddress
AF>#else
AF>#   error This machine type is not supported.
AF>#endif
AF>} }
AF>


Сильно !!!

А DllMain чем хуже? Или я не врубился?
OK
Re[3]: HMODULE в DLL
От: Alex Fedotov США  
Дата: 20.02.02 18:11
Оценка:
Здравствуйте Владимир Гренадеров, Вы писали:

ВГ>А DllMain чем хуже? Или я не врубился?


Ничем не хуже. Наоборот, даже лучше. Однако, иногда (в моей практике — однажды) бывают ситуации, когда на DllMain надеяться нельзя. Например, я делал статическую библиотеку, у которой уже был прописан интерфейс. То есть ни добраться до параметра DllMain, ни добавить параметр в свою функцию я не мог. Пришлось извратиться.
-- Alex Fedotov
Re[3]: HMODULE в DLL
От: Polosaty Беларусь  
Дата: 20.02.02 18:16
Оценка:
Здравствуйте Владимир Гренадеров, Вы писали:

ВГ>Здравствуйте Alex Fedotov, Вы писали:


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


P>>>Подскажите, пожалуйста, как, находясь в DLL, получить HMODULE этой DLL? Проблема в том, что в этой DLL нужно пользовать custom ресурсы, а соответствующие вызовы API FindResource, LoadResource, SizeofResource требуют HMODULE. Если вместо HMODULE пользовать NULL или использовать GetModuleHandle(NULL), то возвращается HMODULE вызывающего DLL процесса, а не самой DLL. Вызывать

P>>>
P>>>GetModuleHandle("Путь")
P>>>

P>>>тоже нельзя, т.к. положение текущего каталога относительно каталога с DLL неизвестно. Абсолютный путь к DLL заранее тоже не известен.
P>>>Использовать HMODULE, который передается в DLLMain, в моем случае тоже не получается.
P>>>Так как же поиметь HMODULE DLL, находясь в самой DLL? Или как поиметь custom ресурс, который в этой же DLL?

ВГ>Сильно !!!


Согласен

ВГ>А DllMain чем хуже? Или я не врубился?

Если посмотреть на 4 строки выше, то там есть одно предложение из самого первого письма с вопросом:
Использовать HMODULE, который передается в DLLMain, в моем случае тоже не получается.

Ну так получилось, что не могу я в моей ситуации поиметь HMODULE из DLLMain
Re[3]: HMODULE в DLL
От: Polosaty Беларусь  
Дата: 20.02.02 18:18
Оценка:
Здравствуйте Alex Fedotov, Вы писали:

AF>Здравствуйте Alex Fedotov, Вы писали:


AF>>Специально для таких случаев сделал функцию GetCurrentInstance (по аналогии с GetCurrentThread и GetCurrentProcess). Возвращает HINSTANCE модуля, из которого была вызвана эта функция.


AF>>
AF>>HINSTANCE GetInstanceFromAddress(
AF>>    PVOID pEip
AF>>    )
AF>>{
AF>>    _ASSERTE(pEip != NULL);

AF>>    MEMORY_BASIC_INFORMATION mem;
AF>>    if (VirtualQuery(pEip, &mem, sizeof(mem)))
AF>>    {
AF>>        _ASSERTE(mem.Type == MEM_IMAGE);
AF>>        _ASSERTE(mem.AllocationBase != NULL);
AF>>        return (HINSTANCE)mem.AllocationBase;
AF>>    }
AF>>    return NULL;
AF>>}

AF>>__declspec(naked) 
AF>>HINSTANCE GetCurrentInstance()
AF>>{ __asm {
AF>>#ifdef _M_IX86
AF>>    mov   eax, [esp]
AF>>    push  eax
AF>>    jmp   GetInstanceFromAddress
AF>>#else
AF>>#   error This machine type is not supported.
AF>>#endif
AF>>} }
AF>>


AF>Черт, в процессе публикации изчез __stdcall у обеих функций. Добавь, а то падать будет.


Огромное спасибо. Сейчас попробую.
Re[4]: HMODULE в DLL
От: Владимир Гренадеров Россия  
Дата: 20.02.02 18:25
Оценка:
Здравствуйте Polosaty, Вы писали:

ВГ>>А DllMain чем хуже? Или я не врубился?

P>Если посмотреть на 4 строки выше, то там есть одно предложение из самого первого письма с вопросом:
P>
P>Использовать HMODULE, который передается в DLLMain, в моем случае тоже не получается.
P>

P>Ну так получилось, что не могу я в моей ситуации поиметь HMODULE из DLLMain

А-а... Ступил что-то я...

P.S. А все-таки, почему DllMain не пашет (вдруг и уменя такое произойдет?), или ты
LoadLibraryEx юзаешь ?
OK
Re[5]: HMODULE в DLL
От: Polosaty Беларусь  
Дата: 20.02.02 18:37
Оценка:
Здравствуйте Владимир Гренадеров, Вы писали:

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


ВГ>>>А DllMain чем хуже? Или я не врубился?

P>>Если посмотреть на 4 строки выше, то там есть одно предложение из самого первого письма с вопросом:
P>>
P>>Использовать HMODULE, который передается в DLLMain, в моем случае тоже не получается.
P>>

P>>Ну так получилось, что не могу я в моей ситуации поиметь HMODULE из DLLMain

ВГ>А-а... Ступил что-то я...


ВГ>P.S. А все-таки, почему DllMain не пашет (вдруг и уменя такое произойдет?), или ты

ВГ>LoadLibraryEx юзаешь ?

DllMain пашет. Все гораздо хуже. У меня ее нет
Это один из случаев, когда HMODULE получить в DllMain нельзя. Можно было, конечно, определить DllMain, но... "нормальные герои всегда идут в обход" .
Второй случай, который привел Alex Fedotov — это когда Вы делаете статическую библиотеку, которая будет прилинкована неизвестно к чему, да еще и интерфейсы определены заранее и передача HMODULE ни в один из вызовов этой библиотеки не предусмотрена.
В общем, DllMain работает, только вот до HMODULE иногда не удается добраться.
Re: HMODULE в DLL
От: Kaa Украина http://blog.meta.ua/users/kaa/
Дата: 21.02.02 17:32
Оценка:
Здравствуйте Polosaty, Вы писали:

P>Подскажите, пожалуйста, как, находясь в DLL, получить HMODULE этой DLL? Проблема в том, что в этой DLL нужно пользовать custom ресурсы, а соответствующие вызовы API FindResource, LoadResource, SizeofResource требуют HMODULE. Если вместо HMODULE пользовать NULL или использовать GetModuleHandle(NULL), то возвращается HMODULE вызывающего DLL процесса, а не самой DLL. Вызывать

P>
P>GetModuleHandle("Путь")
P>

P>тоже нельзя, т.к. положение текущего каталога относительно каталога с DLL неизвестно. Абсолютный путь к DLL заранее тоже не известен.
P>Так как же поиметь HMODULE DLL, находясь в самой DLL?
А почему нельзя? Ведь про каталог ничего не сказано в описании данной функции. Она case independently определяет, загружена ли библиотека с таким именем, без учета пути. По-моему (мне так кажется, и у Рихтера о том вроде написано, хотя не нашел сейчас), что чтоб узнать адрес либы внутри исполняемого модуля, надо знать только имя библиотеки, и не нужно путь к ней. А потом, по HMODULE получается полный путь, откуда она загружена (GetModuleFileName).

Я ошибаюсь?
Алексей Кирдин
Re[2]: HMODULE в DLL
От: Polosaty Беларусь  
Дата: 21.02.02 17:43
Оценка:
Здравствуйте Kaa, Вы писали:

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


P>>Подскажите, пожалуйста, как, находясь в DLL, получить HMODULE этой DLL? Проблема в том, что в этой DLL нужно пользовать custom ресурсы, а соответствующие вызовы API FindResource, LoadResource, SizeofResource требуют HMODULE. Если вместо HMODULE пользовать NULL или использовать GetModuleHandle(NULL), то возвращается HMODULE вызывающего DLL процесса, а не самой DLL. Вызывать

P>>
P>>GetModuleHandle("Путь")
P>>

P>>тоже нельзя, т.к. положение текущего каталога относительно каталога с DLL неизвестно. Абсолютный путь к DLL заранее тоже не известен.
P>>Так как же поиметь HMODULE DLL, находясь в самой DLL?
Kaa>А почему нельзя? Ведь про каталог ничего не сказано в описании данной функции. Она case independently определяет, загружена ли библиотека с таким именем, без учета пути. По-моему (мне так кажется, и у Рихтера о том вроде написано, хотя не нашел сейчас), что чтоб узнать адрес либы внутри исполняемого модуля, надо знать только имя библиотеки, и не нужно путь к ней. А потом, по HMODULE получается полный путь, откуда она загружена (GetModuleFileName).

Kaa>Я ошибаюсь?


Наверняка сказать, что Вы ошибаетесь, не могу, не знаю точно. Но логика у меня такая.
Представьте себе, что 2 разных приложения запускаются из разных каталогов. Совершенно случайно в составе обоих приложений оказались DLL с одним и тем же именем, и лежат эти DLL каждая в каталоге со своим EXE, т.е. каждая в своем. Если бы ОС было "наплевать" на путь к DLL, то что бы Вам вернул GetModuleHandle, когда обе DLL загружены?
Re[3]: HMODULE в DLL
От: Polosaty Беларусь  
Дата: 21.02.02 18:02
Оценка:
Здравствуйте Polosaty, Вы писали:

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


Kaa>>А почему нельзя? Ведь про каталог ничего не сказано в описании данной функции. Она case independently определяет, загружена ли библиотека с таким именем, без учета пути. По-моему (мне так кажется, и у Рихтера о том вроде написано, хотя не нашел сейчас), что чтоб узнать адрес либы внутри исполняемого модуля, надо знать только имя библиотеки, и не нужно путь к ней. А потом, по HMODULE получается полный путь, откуда она загружена (GetModuleFileName).


Kaa>>Я ошибаюсь?


P>Наверняка сказать, что Вы ошибаетесь, не могу, не знаю точно. Но логика у меня такая.

P>Представьте себе, что 2 разных приложения запускаются из разных каталогов. Совершенно случайно в составе обоих приложений оказались DLL с одним и тем же именем, и лежат эти DLL каждая в каталоге со своим EXE, т.е. каждая в своем. Если бы ОС было "наплевать" на путь к DLL, то что бы Вам вернул GetModuleHandle, когда обе DLL загружены?

Вот написал такое и сам засомневался и полез в Рихтера. А там на стр. 54 IV издания сказано, что GetModuleHandle проверяет адресное пространство только того процесса, который ее вызвал. Тогда вопрос формулируется по-другому: если приложение загружает несколько разных DLL, которые имеют одинаковое имя, но лежат в разных каталогах, то что вернет GetModuleHandle?
Вообще-то обходиться без имени просто надежнее. Вдруг вздумается когда-нибудь переобозвать DLL, а аргумент функции GetModuleHandle при пересборке поменять забудете... Хотя это, конечно, за уши притянуто.
Кроме того, в Рихтере есть еще такое замечание: "если же файл системой не найден, функция возвращает NULL." Непонятно, что стоит за словами "файл системой не найден".
А метод, предложенный Alex Fedotov, работает всегда. И не только для DLL. И, как я понял, не только для исполняемого модуля (впрочем, как и GetModuleHandle). Но что еще выгодно отличает его от GetModuleHandle (если, конечно, я правильно врубился) — можно даже имени файла, спроецированного на адресное пространство процесса, не знать, а его HMODULE Вы получите.
Re[3]: HMODULE в DLL
От: Kaa Украина http://blog.meta.ua/users/kaa/
Дата: 21.02.02 18:03
Оценка:
Здравствуйте Polosaty, Вы писали:

P>Наверняка сказать, что Вы ошибаетесь, не могу, не знаю точно. Но логика у меня такая.

P>Представьте себе, что 2 разных приложения запускаются из разных каталогов. Совершенно случайно в составе обоих приложений оказались DLL с одним и тем же именем, и лежат эти DLL каждая в каталоге со своим EXE, т.е. каждая в своем. Если бы ОС было "наплевать" на путь к DLL, то что бы Вам вернул GetModuleHandle, когда обе DLL загружены?

Ну, ОС такое допускает. Вернут будет первый из найденных "инстансов". Адреса загрузки DLL начинаются с 0x10000000. Будет выдан адрес первой найденной DLL. Если уж думать о том, что их может быть более одной, то все плохо. Тогда надо этого либо не допускать, либо проверять на наличие нескольких экземпляров. Но наличие нескольких экземпляров — не пресекается.

Прогони в отладчике такой пример (имена либ измени на свой манер, но чтоб пути разные были )
# include <windows.h>

int main()
{
  HMODULE hSecond = LoadLibrary( "d:\\ProjectRoot\\bin\\somelib.dll" );
  HMODULE hFirst  = LoadLibrary( "d:\\ProjectRoot\\SE\\bin\\somelib.dll" );

  HMODULE hFound = GetModuleHandle( "metazlib" );
  char szPath[0x1000];

  GetModuleFileName( hFound, szPath, sizeof(szPath) );
  printf( "%s\n", szPath );
  GetModuleFileName( hFirst, szPath, sizeof(szPath) );
  printf( "%s\n", szPath );

  return 0;
}


Как видишь, все четко определяется, но находится первая библиотека, и находится она только по имени, без учета каталога. Так что, в этом случае какраз ОС "наплевать"

С уважением
Алексей Кирдин
Re[4]: HMODULE в DLL
От: Polosaty Беларусь  
Дата: 21.02.02 18:08
Оценка:
Kaa>Как видишь, все четко определяется, но находится первая библиотека, и находится она только по имени, без учета каталога. Так что, в этом случае какраз ОС "наплевать"

Да, похоже, что ты прав . Но после твоего примера становится понятно, что метод от Alex Fedotov надежнее .
Re[4]: HMODULE в DLL
От: Kaa Украина http://blog.meta.ua/users/kaa/
Дата: 21.02.02 18:11
Оценка:
Здравствуйте Polosaty, Вы писали:

P>Вообще-то обходиться без имени просто надежнее. Вдруг вздумается когда-нибудь переобозвать DLL, а аргумент функции GetModuleHandle при пересборке поменять забудете... Хотя это, конечно, за уши притянуто.

Это точно. Большинство приложений линкуются со своими библиотеками статически, поэтому случаев на общем фоне не так много. Хотя предположить такое можно, и есть задачи, которые к этому иногда приводят.

P>Кроме того, в Рихтере есть еще такое замечание: "если же файл системой не найден, функция возвращает NULL." Непонятно, что стоит за словами "файл системой не найден".

Это значит, что в адресное пространство процесса файл с таким именем не "замапплен".

P>А метод, предложенный Alex Fedotov, работает всегда. И не только для DLL. И, как я понял, не только для исполняемого модуля (впрочем, как и GetModuleHandle).


Никто не ставит под сомнение метод мэтра. Просто есть стандартное средство проверить, что загружено в адресное пространство процесса, причем совершенно все равно, ккого типа это файл. При умолчании расширения .dll подразумевается, но там может быть все что угодно: от .exe до .txt

С уважением
Алексей Кирдин
Re[2]: HMODULE в DLL
От: VladD2 Российская Империя www.nemerle.org
Дата: 21.02.02 21:04
Оценка:
Здравствуйте Alex Fedotov, Вы писали:

Таки надо FAQ написать по этому делу.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: HMODULE в DLL
От: Alex Fedotov США  
Дата: 21.02.02 21:07
Оценка:
Здравствуйте VladD2, Вы писали:

VD>Таки надо FAQ написать по этому делу.


Ну путь кто-нибудь еще для Alpha и IA64 напишет, тогда можно и FAQ.
-- Alex Fedotov
Re[4]: HMODULE в DLL
От: VladD2 Российская Империя www.nemerle.org
Дата: 21.02.02 21:10
Оценка:
Здравствуйте Alex Fedotov, Вы писали:

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


VD>>Таки надо FAQ написать по этому делу.


AF>Ну путь кто-нибудь еще для Alpha и IA64 напишет, тогда можно и FAQ.


Ну, для IA64 ты наверное и сам сможешь, а для Alpha-ы уже поздновато.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: HMODULE в DLL
От: Аноним  
Дата: 24.02.02 17:14
Оценка:
Здравствуйте Alex Fedotov, Вы писали:

AF>Специально для таких случаев сделал функцию GetCurrentInstance (по аналогии с GetCurrentThread и GetCurrentProcess). Возвращает HINSTANCE модуля, из которого была вызвана эта функция.


AF>
AF>HINSTANCE GetInstanceFromAddress(
AF>    PVOID pEip
AF>    )
AF>{
AF>    _ASSERTE(pEip != NULL);

AF>    MEMORY_BASIC_INFORMATION mem;
AF>    if (VirtualQuery(pEip, &mem, sizeof(mem)))
AF>    {
AF>        _ASSERTE(mem.Type == MEM_IMAGE);
AF>        _ASSERTE(mem.AllocationBase != NULL);
AF>        return (HINSTANCE)mem.AllocationBase;
AF>    }
AF>    return NULL;
AF>}

AF>__declspec(naked) 
AF>HINSTANCE GetCurrentInstance()
AF>{ __asm {
AF>#ifdef _M_IX86
AF>    mov   eax, [esp]
AF>    push  eax
AF>    jmp   GetInstanceFromAddress
AF>#else
AF>#   error This machine type is not supported.
AF>#endif
AF>} }
AF>


Мне кажется, что во второй функции лучше использовать GetThreadContext. Получится переносимее.
Re[3]: HMODULE в DLL
От: SergH Россия  
Дата: 24.02.02 17:16
Оценка:
Здравствуйте Аноним, Вы писали:

Блин. Опять забыл подписаться.
Делай что должно, и будь что будет
Re[3]: HMODULE в DLL
От: Alex Fedotov США  
Дата: 24.02.02 17:22
Оценка:
Здравствуйте Аноним, Вы писали:

AF>>Специально для таких случаев сделал функцию GetCurrentInstance (по аналогии с GetCurrentThread и GetCurrentProcess). Возвращает HINSTANCE модуля, из которого была вызвана эта функция.


А>Мне кажется, что во второй функции лучше использовать GetThreadContext. Получится переносимее.


Во-первых, в таком случае она перестанет решать поставленную задачу, а именно возвращает HINSTANCE модуля, из которого была вызвана эта функция. Вместо этого она будет возвращать HINSTANCE модуля в котором она сама находится, что тоже неплохо.

Во-вторых, структура CONTEXT сама по себе зависит от платформы, так что выигрыш в переносимости не очень большой.
-- Alex Fedotov
Re[4]: HMODULE в DLL
От: SergH Россия  
Дата: 24.02.02 17:41
Оценка:
Здравствуйте Alex Fedotov, Вы писали:

AF>Во-первых, в таком случае она перестанет решать поставленную задачу, а именно возвращает HINSTANCE модуля, из которого была вызвана эта функция. Вместо этого она будет возвращать HINSTANCE модуля в котором она сама находится, что тоже неплохо.


Да, про это я не подумал.

AF>Во-вторых, структура CONTEXT сама по себе зависит от платформы, так что выигрыш в переносимости не очень большой.
Делай что должно, и будь что будет
Re[5]: HMODULE в DLL
От: Alex Fedotov США  
Дата: 24.02.02 22:04
Оценка: 87 (10)
Здравствуйте SergH, Вы писали:

AF>>Во-первых, в таком случае она перестанет решать поставленную задачу, а именно возвращает HINSTANCE модуля, из которого была вызвана эта функция. Вместо этого она будет возвращать HINSTANCE модуля в котором она сама находится, что тоже неплохо.


SH>Да, про это я не подумал.


Кстати, о переносимости. Только что узнал, причем читая книгу Рихтера про .Net.

Оказывается, VC 7.0 поддерживат intrinsic-функцию с именем _ReturnAddress, которая возвращает адрес возврата из текущей функции. С ее помощью можно обойтись и без ассемблера.

Но самое интересное в том, что на VC 6.0 она тоже поддерживается (уж не знаю, начиная с какого SP), так что вот этот код без проблем компилируется и работает на моем VC 6.0 SP5 + Processor Pack.

extern "C" void * _ReturnAddress();
#pragma intrinsic(_ReturnAddress)

HINSTANCE GetCurrentInstance()
{
    MEMORY_BASIC_INFORMATION mem;
    if (VirtualQuery(_ReturnAddress(), &mem, sizeof(mem)))
    {
        _ASSERTE(mem.Type == MEM_IMAGE);
        _ASSERTE(mem.AllocationBase != NULL);
        return (HINSTANCE)mem.AllocationBase;
    }
    return NULL;
}


Так что переносимость в пределах поддерживаемых MS платформ обеспечена (а для других задача не имеет смысла).
-- Alex Fedotov
Re[3]: HMODULE в DLL
От: Kaa Украина http://blog.meta.ua/users/kaa/
Дата: 25.02.02 15:31
Оценка:
Здравствуйте Alex Fedotov, Вы писали:

AF>>Специально для таких случаев сделал функцию GetCurrentInstance (по аналогии с GetCurrentThread и GetCurrentProcess). Возвращает HINSTANCE модуля, из которого была вызвана эта функция.


А почему нельзя написать просто так:
HINSTANCE GetInstance()
{
  MEMORY_BASIC_INFORMATION mbi;
  if ( VirtualQuery( &GetInstance, &mbi, sizeof(mbi) ) )
  {
    _ASSERTE(mem.Type == MEM_IMAGE);
    _ASSERTE(mem.AllocationBase != NULL);
    return (HMODULE)mbi.AllocationBase;
  } 
  return NULL;
};
? Ведь GetInstance сам является указателем внутри модуля (code pointer), правильно? Тогда и платформная независимость появляется.

В чем соль той ассемблерной вставки? В каких случаях мой вариант не будет работать? Я прогнал его на одной конкретной машине под Win2k. Пашет.

С уважением
Алексей Кирдин
Re[4]: Вопрос снимается
От: Kaa Украина http://blog.meta.ua/users/kaa/
Дата: 25.02.02 15:51
Оценка: +1
Здравствуйте Kaa, Вы писали:

Kaa>В каких случаях мой вариант не будет работать?


Вопрос снимается. Функция при загрузке dll в другой адрес имеет адрес относительно адреса, указанного при сборке dll, а не относительно того, в который dll была загружена. (Как мутно выразился )

С уважением
Алексей Кирдин
Re[6]: HMODULE в DLL
От: Polosaty Беларусь  
Дата: 26.02.02 12:26
Оценка:
Здравствуйте Alex Fedotov, Вы писали:

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


AF>>>Во-первых, в таком случае она перестанет решать поставленную задачу, а именно возвращает HINSTANCE модуля, из которого была вызвана эта функция. Вместо этого она будет возвращать HINSTANCE модуля в котором она сама находится, что тоже неплохо.


SH>>Да, про это я не подумал.


AF>Кстати, о переносимости. Только что узнал, причем читая книгу Рихтера про .Net.


AF>Оказывается, VC 7.0 поддерживат intrinsic-функцию с именем _ReturnAddress, которая возвращает адрес возврата из текущей функции. С ее помощью можно обойтись и без ассемблера.


AF>Но самое интересное в том, что на VC 6.0 она тоже поддерживается (уж не знаю, начиная с какого SP), так что вот этот код без проблем компилируется и работает на моем VC 6.0 SP5 + Processor Pack.


AF>
AF>extern "C" void * _ReturnAddress();
AF>#pragma intrinsic(_ReturnAddress)

AF>HINSTANCE GetCurrentInstance()
AF>{
AF>    MEMORY_BASIC_INFORMATION mem;
AF>    if (VirtualQuery(_ReturnAddress(), &mem, sizeof(mem)))
AF>    {
AF>        _ASSERTE(mem.Type == MEM_IMAGE);
AF>        _ASSERTE(mem.AllocationBase != NULL);
AF>        return (HINSTANCE)mem.AllocationBase;
AF>    }
AF>    return NULL;
AF>}
AF>


AF>Так что переносимость в пределах поддерживаемых MS платформ обеспечена (а для других задача не имеет смысла).


Мне понравилось. Попробовал. У меня на VC6 SP5 без Processor Pack скомпилялось без проблем. На моей W2K работает тоже без проблем. А вот на W98SE срабатывает _ASSERTE(mem.Type == MEM_IMAGE);. Можно ли это победить?
Re[7]: HMODULE в DLL
От: Alex Fedotov США  
Дата: 26.02.02 18:29
Оценка:
Здравствуйте Polosaty, Вы писали:

AF>>
AF>>extern "C" void * _ReturnAddress();
AF>>#pragma intrinsic(_ReturnAddress)

AF>>HINSTANCE GetCurrentInstance()
AF>>{
AF>>    MEMORY_BASIC_INFORMATION mem;
AF>>    if (VirtualQuery(_ReturnAddress(), &mem, sizeof(mem)))
AF>>    {
AF>>        _ASSERTE(mem.Type == MEM_IMAGE);
AF>>        _ASSERTE(mem.AllocationBase != NULL);
AF>>        return (HINSTANCE)mem.AllocationBase;
AF>>    }
AF>>    return NULL;
AF>>}
AF>>


AF>>Так что переносимость в пределах поддерживаемых MS платформ обеспечена (а для других задача не имеет смысла).


P>Мне понравилось. Попробовал. У меня на VC6 SP5 без Processor Pack скомпилялось без проблем. На моей W2K работает тоже без проблем. А вот на W98SE срабатывает _ASSERTE(mem.Type == MEM_IMAGE);. Можно ли это победить?


А что там в поле Type оказалось?
-- Alex Fedotov
Re[8]: HMODULE в DLL
От: Polosaty Беларусь  
Дата: 26.02.02 18:55
Оценка:
Здравствуйте Alex Fedotov, Вы писали:

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


AF>>>
AF>>>extern "C" void * _ReturnAddress();
AF>>>#pragma intrinsic(_ReturnAddress)

AF>>>HINSTANCE GetCurrentInstance()
AF>>>{
AF>>>    MEMORY_BASIC_INFORMATION mem;
AF>>>    if (VirtualQuery(_ReturnAddress(), &mem, sizeof(mem)))
AF>>>    {
AF>>>        _ASSERTE(mem.Type == MEM_IMAGE);
AF>>>        _ASSERTE(mem.AllocationBase != NULL);
AF>>>        return (HINSTANCE)mem.AllocationBase;
AF>>>    }
AF>>>    return NULL;
AF>>>}
AF>>>


AF>>>Так что переносимость в пределах поддерживаемых MS платформ обеспечена (а для других задача не имеет смысла).


P>>Мне понравилось. Попробовал. У меня на VC6 SP5 без Processor Pack скомпилялось без проблем. На моей W2K работает тоже без проблем. А вот на W98SE срабатывает _ASSERTE(mem.Type == MEM_IMAGE);. Можно ли это победить?


AF>А что там в поле Type оказалось?


MEM_PRIVATE
Re[9]: HMODULE в DLL
От: Alex Fedotov США  
Дата: 26.02.02 19:20
Оценка:
Здравствуйте Polosaty, Вы писали:

AF>>А что там в поле Type оказалось?


P>MEM_PRIVATE


Э... Ну если адрес правильный возвращается, просто убери этот ASSERT и все.
-- Alex Fedotov
Re[10]: HMODULE в DLL
От: Polosaty Беларусь  
Дата: 26.02.02 19:29
Оценка:
Здравствуйте Alex Fedotov, Вы писали:

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


AF>>>А что там в поле Type оказалось?


P>>MEM_PRIVATE


AF>Э... Ну если адрес правильный возвращается, просто убери этот ASSERT и все.


Я совсем убирать не стал, в релизе сам уберется. Сделал на всякий случай
_ASSERTE(mem.Type == MEM_IMAGE || mem.Type == MEM_PRIVATE);

Работает. По крайней мере, по получаемому Instance до ресурса в DLL добирается.
Спасибо.
Re: HMODULE в DLL
От: Polosaty Беларусь  
Дата: 24.11.03 00:01
Оценка:
Недавно встретил еще один любопытный подход. Выглядит он примерно так: есть некая dll, назовем ее lib1.dll. Для того, чтобы добраться до HINSTANCE, присутствует такая конструкция:

HINSTANCE hRes=LoadLibrary("Lib1.dll");


т.е. делается LoadLibrary самой себя. Как я понимаю, dll не может быть повторно загружена в адресное пространство процесса, т.е. данный вызов только возвращает HINSTANCE. Есть ли недостатки у такого подхода (не считая экзотики типа одноименных библиотек, загруженных из разных каталогов).
Re[2]: HMODULE в DLL
От: SergeMukhin Россия  
Дата: 24.11.03 05:52
Оценка:
Здравствуйте, Polosaty, Вы писали:

P>Недавно встретил еще один любопытный подход. Выглядит он примерно так: есть некая dll, назовем ее lib1.dll. Для того, чтобы добраться до HINSTANCE, присутствует такая конструкция:


P>
P>HINSTANCE hRes=LoadLibrary("Lib1.dll");
P>


P>т.е. делается LoadLibrary самой себя. Как я понимаю, dll не может быть повторно загружена в адресное пространство процесса, т.е. данный вызов только возвращает HINSTANCE. Есть ли недостатки у такого подхода (не считая экзотики типа одноименных библиотек, загруженных из разных каталогов).


а DllMain будет отрабатывать второй раз? если так, то лучше LoadLibraryEx c LOAD_LIBRARY_AS_DATAFILE
... << RSDN@Home 1.1.0 stable >>
---
С уважением,
Сергей Мухин
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.