Re: How to get imagebase after a DLL gets loaded




"anton bassov" <soviet_bloke@xxxxxxxxxxx> wrote in message
news:1165929802.810928.325690@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Kevin,

It seems like you have not written much code that was reused, because
otherwise the value in this would not be so hard for you to see.

Actually, I am in the kernel mode, so that there is not that much code
to share down there.

Hopefully you can appreciate that the needs of others might be such that the
sharing of code happens frequently, and is a goal to keep in mind when
writing new code.


In fact, apparently, this is why I immediately
noticed Will's illogical design -

Hopefully you can now see that what appears illogical from one perspective
can be completely logical when viewed from another.


in the kernel mode you have to save
any piece of info that you may need, because you may be unable to get
it at the point when you need it

Hopefully you realize now that kernel-mode-specific habits are not valid
constraints for application-level code, such as that given in the original
example: dialogbox support code.





For library writers, not only do they not know the name of the target
module,

Surprisingly enough, but this is true as well - if we are speaking
about DLL's, the library ABC that they write may be renamed to XYZ,
and, at this point, it will be appear under the name XYZ in the
address space of the target process, so that if makes a call to
GetModuleHandle("ABC") from its code, this call may fail.... Besides
that, the library may be just static, so that it may not have its own
name in the address space, in the first place

they do not know the names of any of the variables within the module.

Not suprizing at all - the above statement is plain nonsense....

Your design requires this:

DLLMain(...)
case PROCESS_ATTACH:
CRT_hInstance = hInstance;
MY_SUPER_COOL_LIBRARY_hInstance = hInstance;
SOMEONE_ELSES_LIB_Global_hInstance = hInstance;
break;

The alternative is for the C runtime to obtain the hInstance at run-time,
rather than require me to instantiate a pre-defined variable and assign it
myself in DllMain.



Although you have no clue about names of variables in your client code,
how can you be unaware of the names of variables in DLL module that you
write???

Because I used William's code-snippet that does <whatever cool thing it
does>, and all I had to do was add it to my source. I did not also have to
add a specially-named global variable and additional code to DllMain,
because he obtains hInstance at run-time.



Are you sure you understand what the term "module" means???

A DLL can link to a static library that can be written to require a
specially-named symbol to be instantiated by the code using the library.

Your suggestion is that if code from a static library that is linked into a
module needs the HINSTANCE, then that static library should fail to link
unless the code linking to the library instantiates that variable.

The alternative is to write the static library code such that it does not
require any additional symbols to be defined and initialized, and instead
obtain the needed information at run-time.




Unless the library writer requires the user of the code to instantiate a
variable using a specific name,

Insane idea...... More on this below.

Implementing a library that requires users of the library to instantiate
specially-named symbols is NOT insane.

If the library routine needs a value that is accessible at run-time, but the
cost of checking that at run-time is too high, then it can be made a
requirement that the code using the library maintain the value.

The approach that requires the user-of-the-library to instantiate a variable
is not insane nor illogical, and neither is the opposite. They are both
perfectly valid approaches to the design of software.



so that it is resolved at link-time.

Again, nonsense - the only things linker deals with are EXPORTS.....

During the process of building the DLL, the linker deals with EXTERNs.


Objectively, it cannot know anything about non-exported stuff, so that
it has no clue about
the names of variables that are private to the library the code is
linked against....
Btw, why such obsession with names of variables, in the first place???
More on this below.

Because you claim it to be "illogical" that a solution is designed to obtain
at run-time that which can be obtained at initialization time.

Code that is written by someone else, and is used in your code, can not
predict what variable name you will use at initialization time. Thus, it
must require you to instantiate it with a special name, and initialize it in
DllMain.





William uses the design pattern of obtaining a value at run-time within
his
library routine, so that clients of his library routine do not need to
instantiate specially-named variables, or call an otherwise unnecessary
initialization routine.

In fact, the very idea of sharing NAMES of variables between the
library and its client code seems to be your very own "invention" - no
one, apart from you, has ever suggested doing something like that.

Hopefully you realize now that your kernel-mode experience has not exposed
you to requirements that are applicable to other kinds of software projects.


After all, the whole idea contradicts the very basic principles of the
structured programming. In other words, I am not surprized at
all..........

Some third-party libraries DO require that you instantiate a pre-defined
variable in your source code.

Even if you do not link to a library, any C++ header that defines a class
that contains a static variable requires that that variable be instantiated
in your code somewhere. This is not insane, nor illogical. It is a design
choice.



Actually, if you don't mind, could you please tell us why you believe
saving a module handle in a global variable may somehow involve sharing
variables between modules, in the first place???

Hopefully you realize that the author of a module may be using code that was
authored elsewhere and elsewhen.

If that elsewhere-code needs, for example, the HINSTANCE, it can obtain that
in two ways:

1) require the caller-code to instantiate a specially named variable and
initialize it in DllMain
or
2) obtain the value at run-time.



It sounds like William writes the kind of code that other programmers
could
find useful

If he said that he intends to use it in a code, exported by a *STATIC*
library, there would be no discussion whatsoever...



However, once static library does not have its own base address, the
whole thing would be just irrevevant in context of this thread, which
speaks about obtaining DLL's base address.
Therefore, he made it clear that he speaks about DLL modules...

Hopefully you understand now that a DLL module that links to a static
library, or includes a C++ header that defines a class with a static member,
or includes code emailed by a colleague / coworker, that NOT requiring the
user of the code to instantiate and initialize a specially-named variable,
is not ILLOGICAL.




.. so I can understand how that does not make sense to you

..and, hence, once we speak about DLLs here, his approach does not make
any sense, and not only to me....

Hopefully you understand that there are projects where much of the code that
goes into a DLL, or static .LIB, or into the database of gold-code, is not
written by the authoer of the DLL.

Surely you can see that it would be impractical for all sources of code to
require the author of the DLL to instantiate a specially-named "global
HINSTANCE" variable, one per code-source, and initialize them all in
DllMain.



Don't get me wrong - I am speaking strictly about logical design (in
practical terms, Will's
approach will work just fine in his case - I don't argue about that).
However, it does not necessarily mean that he should advertize it as
something usefull....

Hopefully you can see that outside of the narrow spectrum of code that you
focus on, the technique described herein and implemented by Will's code is
extremely useful.

Most hopefully, readers that have been following along are not confused by
your deprecations regarding this design choice, and will in the future
endeavor to reduce the number of symbols their code requires
users-of-their-code to instantiate and initialization.

Minimizing the numbers of these symbols is a laudable design choice, and
library writers should take heed. Otherwise, users of your code will
grumble: "why do I need to update DllMain to get the
<value-available-at-runtime>!!!! Why don't they just call
<function-that-returns-value>!!!"




.



Relevant Pages

  • Re: How to get imagebase after a DLL gets loaded
    ... During the process of building the DLL, ... Implementing a library that requires users of the library to instantiate ... predict what variable name you will use at initialization time. ... Some third-party libraries DO require that you instantiate a pre-defined ...
    (microsoft.public.win32.programmer.kernel)
  • Re: FileNotFoundException
    ... class to instantiate from configuration and uses reflection to perform the ... misread the part about reflection. ... >> Adam Clauss ... >>> It turns out one of the libraries I use instantiates a class using ...
    (microsoft.public.dotnet.languages.csharp)
  • global variables in shared libraries
    ... to be included in Debian, I feel that I should not be slaughtered ... I have a question about shared libraries. ... I have come up with two ways to deal without global variables in C: ... The first is to expect the user to instantiate a struct, ...
    (Debian-User)
  • Re: Unit Testing in C++
    ... I'm quite curious on how you would go to perform unit testing in C++. ... One way is to use one of the 'lot' of libraries available for the ... Therefore you write a unti of test code to instantiate one or more instances ...
    (comp.programming)
  • Re: Passing template struct as an argument to a template function
    ... > types could be used to instantiate templates? ... Let's say that some of my template functions, ... > compiler is in no way a good idea. ... Majority of libraries on the market are still template-free. ...
    (comp.lang.cpp)