2009-02-17 43 views
31

Tôi có một thư viện tĩnh có thể được liên kết với một trong số .exe hoặc .dll. Khi chạy, tôi muốn ony của các hàm thư viện của mình nhận được HMODULE cho bất kỳ điều gì mà mã thư viện tĩnh đã được liên kết.Làm cách nào để lấy mã HMODULE cho mã hiện đang thực thi?

Tôi hiện đang sử dụng các thủ thuật sau đây (lấy cảm hứng từ this forum):

const HMODULE GetCurrentModule() 
{ 
    MEMORY_BASIC_INFORMATION mbi = {0}; 
    ::VirtualQuery(GetCurrentModule, &mbi, sizeof(mbi)); 

    return reinterpret_cast<HMODULE>(mbi.AllocationBase); 
} 

Có cách nào tốt hơn để làm điều này mà không trông rất hacky?

(Lưu ý: Mục đích của việc này là để tải một số tài nguyên Win32 mà tôi biết người dùng của tôi sẽ được liên kết trong cùng lúc như thư viện tĩnh của tôi.)

+0

liên quan: http://stackoverflow.com/q/119706/946850 – krlmlr

Trả lời

42
HMODULE GetCurrentModule() 
{ // NB: XP+ solution! 
    HMODULE hModule = NULL; 
    GetModuleHandleEx(
    GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, 
    (LPCTSTR)GetCurrentModule, 
    &hModule); 

    return hModule; 
} 
+0

Tuyệt. Tôi nhớ bây giờ khi tôi đã viết hàm GetCurrentModule(), chúng tôi đã hỗ trợ Windows 2000. Đó là lý do tại sao tôi đã sử dụng VirtualQuery() hack thay vì GetModuleHandleEx(). – pauldoo

+0

Rất vui được trợ giúp. Ngoài sự tò mò, tại sao bạn lại thích giải pháp của tôi hơn giải pháp __ImageBase? –

+1

Có lẽ do không hiểu cách Windows sửa địa chỉ biểu tượng. – MSN

3

Tôi muốn nhìn vào GetModuleHandleEx() sử dụng cờ GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS. Có vẻ như bạn có thể thay đổi số GetCurrentModule() để gọi thường lệ này thay vì VirtualQuery() và chuyển địa chỉ của số GetCurrentModule() làm đối số lpModuleName.

ETA:

const HMODULE GetCurrentModule() 
{ 
    DWORD flags = GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS; 
    HMODULE hm = 0; 
    ::GetModuleHandleEx(flags, reinterpret_cast<LPCTSTR>(GetCurrentModule), &hm); 
    return hm; 
} 

Tôi không thử nó, nhưng tôi nghĩ rằng tôi sẽ làm những gì bạn muốn.

-4

HMODULE là HINSTANCE là địa chỉ cơ sở của mô-đun. Vì vậy, tôi muốn xem nó hoạt động như thế nào. Nhưng nếu tất cả những gì bạn muốn là HMODULE của file thực thi, thì tại sao không liệt kê tất cả HMODULE trong quá trình (EnumProcessModules). Một trong số họ sẽ có .lib của bạn được liên kết.

Giới hạn mà tôi thấy là bạn không biết DLL hoặc EXE của bạn .lib đến từ đâu. Bạn có thể muốn so sánh các HMODULE (các địa chỉ cơ sở) với _ReturnAddress bạn nhận được từ .lib của bạn. lib của bạn sẽ thuộc về HMODLUE cao nhất nhỏ hơn _ReturnAddress bạn

+0

Tiến hành thống kê một danh sách các mô-đun là rất không hiệu quả, và không gần như gọn gàng như gọi GetModuleHandleEx. Hãy xem; nhận được câu trả lời tôi cần với một cuộc gọi API nhanh, đơn lẻ hoặc lặp qua hàng tá mô-đun có khả năng, thực hiện so sánh chuỗi (RẤT đắt tiền!) khi tôi thực hiện. Tôi nghĩ tôi sẽ đi theo lối tắt. –

25

__ImageBase là một mối liên kết tạo ra biểu tượng đó là tiêu đề DOS của module (MSVC chỉ). Từ đó, bạn có thể truyền địa chỉ của nó tới số HINSTANCE hoặc HMODULE. Vì vậy, nó thuận tiện hơn là đi qua một API.

Vì vậy, bạn chỉ cần làm điều này:

EXTERN_C IMAGE_DOS_HEADER __ImageBase; 
#define HINST_THISCOMPONENT ((HINSTANCE)&__ImageBase) 

Từ http://blogs.msdn.com/oldnewthing/archive/2004/10/25/247180.aspx

+0

Theo liên kết trong câu hỏi ban đầu của tôi, __ImageBase chỉ là địa chỉ tải ưa thích, không phải lúc nào cũng là địa chỉ tải thực. – pauldoo

+1

Bạn nghi ngờ Raymond Chen? Các cuộc thảo luận tại liên kết chứng minh một sự hiểu lầm cơ bản của một hằng số linker, nhưng bình luận cuối cùng là chính xác. –

+4

Err ... __ImageBase là một biểu tượng. Nếu nó không được cố định khi các .dll hoặc .exe được tải, sẽ không có bất kỳ biểu tượng khác và tất cả mọi thứ sẽ phá vỡ. Vì vậy, nó hợp lệ để sử dụng nó vì địa chỉ của nó được cố định tại thời gian tải hình ảnh. – MSN

Các vấn đề liên quan