Re: How to get imagebase after a DLL gets loaded

Tech-Archive recommends: Fix windows errors by optimizing your registry




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

Your original response to the OP's question should have been:
"Nonsense...."

There was nothing nonsensical in the OP's question......

Of course, and William provided a sensible answer.

Does the following make sense to you?

If William's approach is "illogical", and if William's approach is a valid
answer to a question, then that question must be nonsensical, because it
does not make sense that an illogical answer is valid for a sensible
question.

But, this conclusion contradicts your statement above that there was
"nothing nonsensical" to the question!!!

So, if the question is not-nonsensical, then a valid answer to the question
must be not-illogical???

How can you claim to believe that the question is not-nonsensical, yet
believe that a valid answer to the question is illogical?

That IS illogical!!!




It is impossible that such a situation could possibly come about wherein
code
executing from within a DLL would not have access to the global variable
assigned-to during DllMain PROCESS_ATTACH."

The OP was speaking about getting DLL's address from the client code -
this is why he mentioned LoadLibrary() and MapViewofFile() calls.......

The OP asked "how to get imagebase after a DLL gets loaded". The solution
provided by William (to use VirtualQuery()) was purported to be "illogical"
and "of no use" by you, because it is "easily available" from "within the
DLL code itself", specifically: passed as a parameter to DllMain().

For any readers following along, the choice to obtain the value at run-time,
even though it could be saved away in a global variable in DllMain, is
completely logical and very useful, and, from a software design perspective,
simply a choice.

This discussion continues only so that people reading along who might have
thought "oh, that Mr. Bassov has pronounced that approach as illlogical, and
supporters of that choice as insane, and, look... no response! He must be
right!"

"My company is having me write the once-and-forever <whatever> function,
which needs the DLL imagebase. According to Mr. Bassov, the only logical
and sane approach is to define a global variable
MY_FUNC_CODE_GLOBAL_HINSTANCE, and tell whoever uses my .C file that all
they have to do is assign to it the hInstance in DllMain."

It is valid to make this a requirement. It does not scale as the project
grows. Soon, everyone has a global variable that needs initializing in
DllMain!!

Regardless, it is not illogical nor insane to choose a design that does have
this requirement, and instead do as William suggests: obtain the value at
run-time.

Indeed, the OP's question is exactly that: how to obtain the value after it
is loaded, after DllMain completes. Perhaps they wonder which is better,
introduce a new symbol into the global namespace and have it initialized in
DllMain, pass it as a parameter to an initialization function, pass it as a
parameter to every function that needs it, or obtain it at run-time?





This is what the thread was originally about. The question about
getting base address from the DLL module itself arised later, i.e. at
the moment when Will came up with his example of a dialog box in DLL.
This is what this thread dealt with in between Will's example and your
very first post. You have introduced static linking and its logical
equivalents into the discussion......

The OP asked "how to get imagebase after a DLL gets loaded". William
provided the answer.

That would have been the end of it (except perhaps other ways of getting the
value), but the discussion continued because you characterized the idea of
obtaining the value at run-time as "illogical" and "of no use", because "the
value is readily available from DllMain".

Moreover, anyone suggesting that there are situations where using a global
variable has unnecessary negative repercussions is, in your words, "insane".

By extension, Anton considers the OP to be "insane" and his design
"illogical". Otherwise, were he sane and logical, he would not be in the
situation where the question would even be asked, because he would have
saved the value from DllMain in a global variable, and referred to it by
name, thereby eliminating the need to ask the question.

I am sure that those reading along now see that there are very good reasons
for choosing William's approach, the OP being one of them.





I speak about code-snippets pasted into DLL source. I speak about C++
classes whose definitions are included. I speak about static libraries
linked-to by DLLs.

Why????? How is it related to the topic of a discussion between me and
Will, let alone the OP's original question????? Are the above examples
going to turn up as a separate module(s) in the address space of a
client process, so that the question about the base adress may arise,
in the first place?????

The question was "how to get imagebase after a DLL gets loaded". This
presupposes that saving the value in DllMain is not an option.

William pointed out that VirtualQuery() will do so, but you labelled such an
approach as "illogical", and discouraged the poster and all readers to
discount his advice.

My contribution was to offer readers evidence that the approach is not only
completely logical, it is even desirable, from the perspective of developing
re-usable software.

Your response was to label me as "insane".

I continue on simply to ensure that readers don't assume that my withdrawal
from the discussion is a tacit acceptance that your characterization is
correct.

Otherwise, this discussion would have ended a long time ago with the answer
given by William.




I speak about DLLs implicitly-linked to other DLLs.

As I can see, in your opinion, "DLLs implicitly-linked to other DLLs"
belong in the same group with the things you have mentioned above, as
far as module's base address is concerned...

I speak about the need to communicate information between:

1) source code files you write
2) macros or classes provided in a header
3) code you "link in" statically
4) code you "link to" dynamically
5) code that executes in different run-levels

All of these are just situations wherein "imagebase" (or whatever) needs to
be shared among "units of organization". These "units of organization"
differ according to the implementation. "EXTERN" is suitable for 1), 2) and
3). "EXPORT" is required for 4). "IOCTLs" are required for 5). Situations
involving 1) are relevant regardless of run-level, or how the code is
eventually packaged (.exe, .dll, .lib). Situation 2) can be ameliorated by
moving source code around among the files. Situation 4) is subject to
silent "variable not correctly initialized" failures. Situation 3) is like
4), but can impact the build with "unresolved externals".

User-level DLLs rarely need to worry about 5), but occasionally the issue
does come up. The typical solution involves using IOCTLs. This is another
instance of the "specially-named global variable". Both sides have to agree
on the "name" of the IOCTL. This works, of course, but there are issues.
So, if the choice is available that each side can independently calculate
the information that would otherwise need to be communicated, that choice
may be taken.

It is not "illogical" or "insane" to choose to perform the calculation
instead of using an IOCTL, just to eliminate the need to maintain
synchronization between the user- and kernel-mode code (the name/code of the
ioctl).

By the same token, it is not "illogical" or "insane" to decide to obtain the
value of "imagebase" at run-time, just to eliminate the need to maintain
synchronization between the caller- and callee-code (the name of the global
variable that is initialized in dllmain).






"Excerpts" below prove that you don't see any difference here
whatsoever.....


There is no distinction between the code executing in the DLL and code
linked-in from a static library, or code compiled in via a C++ header or
macro.

This explain quite a lot.....

Therefore, in your opinion, either "code linked-in from a static
library, or code compiled in via a C++ header or macro" appears as a
separate module in the address space of a process, or DLL does not need
to be loaded as a separate module....

You do not need to try and find a distinction, because I said "no
distinction".

So, let me try to be clearer: "there is no distinction between the 'code
compiled from source code into the DLL' and 'code linked-into the DLL from a
static library' ".

What is the point of this? The point is that you made a great distinction
regarding "CODE EXECUTING FROM WITHIN THE DLL" -- because it would "very
easily" be able to access the global variable that was initialized in
DllMain.

But, all of the different sources that go into the DLL (the code you write,
the .libs you link to, the headers you include), all must agree on the
special-name assigned to the variable that holds the imagebase value, if one
is to follow the only "logical, sane" approach of 1 global variable,
initialized in DllMain.

If William distributes his useful library, do I need to add a new variable
to be initialized in DllMain, or not?

If William wants me to use his library, then it would be more likely if he
did not require me to modify DllMain. I am loathe to modify that function.
It is "golden". Any modifications to that trigger a whole series of
regression tests.

But, if William wants Anton to stop calling him "incapable of logical
thought", he will have no choice but require users of his library to add
"YET_ANOTHER_GLOBAL_HINSTANCE = hInstance".

If everyone followed Anton's design principle, DllMain would be chock-full
of HINSTANCE-related assignments. At a certain point, someone would say:
"this is insane!! Why don't these people just figure out how to figure out
the value at run-time!!!"

Then, someone would finally ask, "how do you get the imagebase after a DLL
gets loaded?"

Oh!! That's what started this whole thing!!! Poor, insane, illogical fool.






I cannot say anything about your opinion on the former in so far, but
the "masterpiece" below *DEFINITELY* proves that, in your opinion, the
later is the case:

In fact, I maintain a DLL that needs an imagebase, but not it's own.

The above excerpt is truly a masterpiece....

In other words, you believe that *DLL* may easily get away without
being loaded as a separate module in the address space.......

I don't know how you came to whatever conclusion that actually is (!!!), but
the original words were " a DLL that needs an imagebase, but not it's own".

In other words: "functions that reside in a DLL operate using the imagebase
of a DLL, but not necessarily the DLL that contains the functions" -- maybe,
but not necessarily. A resource-handling library, probably much like
William's.

It is an equally valid design choice to use William's approach and obtain
the value at run-time, vs. the choice I made, which was to pass it as a
parameter, vs. the only approach you view as "logical", that being to assign
to a specially-named variable from within DllMain.

But, if the caller-DLL dynamically linked to the called-DLL, how would the
called-DLL get the imagebase of the caller-DLL? An agreed-upon exported
variable name? A parameter to the function?

Or, thanks to William, get the return address off the stack, and use
VirtualQuery()?







In any case, I am out of it - sorry, but you are just unfit for a
discussion....

Very well then!!

So, to summarize, for those readers who were wondering if William's design
choice was logical or not, the answer is: logical.


P.S.:

I think the key indicator regarding where Anton is confused is this
statement : "how can you be unaware of the names of variables in DLL module
that you write???".

From his perspective (that being: typing in the code of custom kernel-mode
drivers designed by others), it is inconceivable that code would exist in an
executable module of his that was not typed in by himself, for that module,
at that time. So, naturally, his approach works well for him.

Anton's description of William's design as "illogical" is really just a
testament to the narrowness of the scope of his programming career.

Minimizing the coupling between modules (source code files, executable
binaries, paired user- vs. kernel-code) is definitely something to consider
when weighing all the trade-offs involved in developing software.

.



Relevant Pages

  • Re: How to get imagebase after a DLL gets loaded
    ... and William provided a sensible answer. ... assigned-to during DllMain PROCESS_ATTACH." ... The OP asked "how to get imagebase after a DLL gets loaded". ...
    (microsoft.public.win32.programmer.kernel)
  • Re: How to get imagebase after a DLL gets loaded
    ... and William provided a sensible answer. ... assigned-to during DllMain PROCESS_ATTACH." ... The OP asked "how to get imagebase after a DLL gets loaded". ...
    (microsoft.public.win32.programmer.kernel)
  • Re: OTOH, you folks are smart ...
    ... for DllMain or any code to be executed before DoSomethingis called. ... to make a DLL ... I am the SDK user. ... *appears* to me to be because of the order the libraries get processed. ...
    (microsoft.public.vc.mfc)
  • Re: MTA with Thread Pool API
    ... I would definitely try to avoid calling any winuser functions ffrom DllMain ... Microsoft technical article says to do for proper connection pooling. ... The SDK is very clear that you must call the CoInit functions once per ... I thought about moving all the code into a DLL, ...
    (microsoft.public.win32.programmer.kernel)
  • Re: [DLL - COM] Adding a DLL Directory
    ... "William" wrote in message ... The DLL is registered with a wrong path. ... registry now actually points to the DLL file. ... Mr. Babbage, if you put into the machine wrong figures, will the right ...
    (microsoft.public.win32.programmer.ole)