Load order and DLL entry order of implicitly linked DLLs, Environment variables 
Author Message
 Load order and DLL entry order of implicitly linked DLLs, Environment variables

I want to know if this assumption is broken, or might be in the future:
  If I implicitly link with a DLL, and put it's .lib as the first, will
its DLL entry point (DllMain) get called before the CRT's (assuming
either my application links with the release or debug CRT DLL, or
another implicitly linked DLL does)?

I remember back with Michael Kaplan's MSLU, he mentioned: "The simple
rule for the linker is that references are resolved from left to right
(and if it cannot find the symbol, it starts back at the beginning,
finally using the DEFAULTLIB location if it still cannot find the
symbol)." [1], and suggested putting unicows.lib in the front of the
list.  So does this apply to load order that the OS loader uses, and the
order that each DLL's entry point is called?

Matt Pietrek has probably written an article about it, and there might
be an MSDN article written about it, so any links would be appreciated.

Why do I care about this you might be wondering?  An app I'm working on
uses a 3rd party DLL that depends on an environment variable.
Unfortunately, it apparently does a "getenv" to get this environment
variable.  For some awful reason, which I wish somebody could really
explain to me, MSVCRT makes a *copy* of the environment strings.  Any
calls to putenv or getenv use the copy, not the "live" environment
variables.  If you have one DLL that's using /MD (Multithreaded DLL),
and one that's using /MDd (Debug Multithreaded DLL), they'll both get a
snapshot of the environment block when their DLL entry point executes
(_CRTDLL_INIT).  A putenv in one isn't seen by a getenv in the other.

Ideally, I'd like to not put in an environment variable during install,
but set it when the executable runs.  I have a couple ideas of how to do
this, but the current 2 that are in the lead are:

1. Have a DLL that gets implicitly linked.  Force a reference to it so
it loads.  Put the .lib at the front of the list.  In it's DllMain, do a
SetEnvironmentVariable.  Hope that the MSVCRT.dll's DLL entry point
doesn't get loaded until after mine (oleaut32.dll, and others might load
it in before the 3rd party DLL).
2. Have a DLL that links to the same CRT as the 3rd party DLL does.  Do
a putenv so that the copy they both use is updated.

I'd really like to get option 1 to work.

Thanks!
-Daniel

[1] < http://www.*-*-*.com/ ;



Mon, 30 May 2005 14:39:21 GMT  
 Load order and DLL entry order of implicitly linked DLLs, Environment variables


writes
Quote:
>I want to know if this assumption is broken, or might be in the future:
>If I implicitly link with a DLL, and put it's .lib as the first, will

I don't see how you can simultaneously "implicitly link with a DLL, and
put it's .lib as the first". Should I read "explicitly" where you write
"implicitly".

Quote:
>its DLL entry point (DllMain) get called before the CRT's (assuming
>either my application links with the release or debug CRT DLL, or
>another implicitly linked DLL does)?

If you care about such things, you need to control them. LoadLibrary()
may be your friend.

Quote:

>I remember back with Michael Kaplan's MSLU, he mentioned: "The simple
>rule for the linker is that references are resolved from left to right
>(and if it cannot find the symbol, it starts back at the beginning,
>finally using the DEFAULTLIB location if it still cannot find the
>symbol)." [1], and suggested putting unicows.lib in the front of the
>list.  So does this apply to load order that the OS loader uses, and
>the order that each DLL's entry point is called?

>Matt Pietrek has probably written an article about it, and there might
>be an MSDN article written about it, so any links would be appreciated.

I have none!

Quote:

>Why do I care about this you might be wondering?  An app I'm working on
>uses a 3rd party DLL that depends on an environment variable.
>Unfortunately, it apparently does a "getenv" to get this environment
>variable.  For some awful reason, which I wish somebody could really
>explain to me, MSVCRT makes a *copy* of the environment strings.  Any
>calls to putenv or getenv use the copy, not the "live" environment
>variables.  If you have one DLL that's using /MD (Multithreaded DLL),
>and one that's using /MDd (Debug Multithreaded DLL), they'll both get a
>snapshot of the environment block when their DLL entry point executes
>(_CRTDLL_INIT).  A putenv in one isn't seen by a getenv in the other.

I suggest you putenv() what you want and then LoadLibrary() the 3rd
party DLL.

Quote:

>Ideally, I'd like to not put in an environment variable during install,
>but set it when the executable runs.  I have a couple ideas of how to
>do this, but the current 2 that are in the lead are:

Alternatively, use a setenvandload process to CreateProcess your
process. You should be able to do both jobs in one .EXE file by
distinguishing startup conditions.

Quote:

>1. Have a DLL that gets implicitly linked.  Force a reference to it so
>it loads.  Put the .lib at the front of the list.  In it's DllMain, do
>a SetEnvironmentVariable.  Hope that the MSVCRT.dll's DLL entry point
>doesn't get loaded until after mine (oleaut32.dll, and others might
>load it in before the 3rd party DLL).

That is an unportable option. Write your own WinMainCRTStartup() or
MainCRTStartup(). The /ENTRY link option allows you to choose the name
if you don't like the default. It is worth looking at Matt Pietrek's
2001-01 "Under the Hood" MSDN Magazine article "Reduce EXE and DLL Size
with LIBCTINY.LIB" - I have no URL as I'm reading it on an MSDN disk.

Quote:
>2. Have a DLL that links to the same CRT as the 3rd party DLL does.  Do
>a putenv so that the copy they both use is updated.

>I'd really like to get option 1 to work.

In parallel with solving your problem, go to your 3rd party dll. Read
the documentation and, if the question is not answered, make a support
call.
--
Walter Briscoe


Mon, 30 May 2005 17:17:29 GMT  
 Load order and DLL entry order of implicitly linked DLLs, Environment variables


<snip>

Quote:
> I suggest you putenv() what you want and then LoadLibrary() the 3rd
> party DLL.

Or, alternatively, create a stub executable, which
sets the environment variable, then spawns the
real exe. The spawned process will pick up the
modified environment.


Mon, 30 May 2005 21:40:29 GMT  
 Load order and DLL entry order of implicitly linked DLLs, Environment variables
... deleted ...

Quote:

> 1. Have a DLL that gets implicitly linked.  Force a reference to it so
> it loads.  Put the .lib at the front of the list.  In it's DllMain, do a
> SetEnvironmentVariable.  Hope that the MSVCRT.dll's DLL entry point
> doesn't get loaded until after mine (oleaut32.dll, and others might load
> it in before the 3rd party DLL).

I would not thrust the linker to garanty the order of loading of DLL,
I'm sure you can find the rules, but the assumptions might change with
versions, switches and god knows what. Look into Detours from
microsoft, it has a nice utilility: "SetDll" that garanty that a dll
will be loaded first.

Quote:
> 2. Have a DLL that links to the same CRT as the 3rd party DLL does.  Do
> a putenv so that the copy they both use is updated.

this only work, I think, if the third party dll link to a CRT in a
DLL, if it has a static copy of the CRT you are out of luck. And to
link to the same CRT of the DLL, you usually need to use the same
compiler version.

Quote:

> I'd really like to get option 1 to work.

another suggestion:
tell the third party compagny that environnement vars are not cool!
My gosh this look like a unix port turn bad.
Well unix programs do not turn bad, they are bad from the beginning :)

Quote:

> Thanks!
no sweat
> -Daniel

Daniel Anderson


Mon, 30 May 2005 22:11:07 GMT  
 Load order and DLL entry order of implicitly linked DLLs, Environment variables

Quote:



> <snip>

>>I suggest you putenv() what you want and then LoadLibrary() the 3rd
>>party DLL.

> Or, alternatively, create a stub executable, which
> sets the environment variable, then spawns the
> real exe. The spawned process will pick up the
> modified environment.

Thanks.  This was another alternative that I knew would work, but was
hoping to avoid :-)

-Daniel



Tue, 31 May 2005 00:42:04 GMT  
 Load order and DLL entry order of implicitly linked DLLs, Environment variables

Quote:
>>I want to know if this assumption is broken, or might be in the future:
>>If I implicitly link with a DLL, and put it's .lib as the first, will

> I don't see how you can simultaneously "implicitly link with a DLL, and
> put it's .lib as the first". Should I read "explicitly" where you write
> "implicitly".

Implicitly linking is what its called:

<http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vcco...>

The "implicit" part refers to the loading of the DLL (as compared to an
explicit LoadLibrary).

Quote:
>>its DLL entry point (DllMain) get called before the CRT's (assuming
>>either my application links with the release or debug CRT DLL, or
>>another implicitly linked DLL does)?

> If you care about such things, you need to control them. LoadLibrary()
> may be your friend.

I probably should have elaborated on this.  Let's say that your
executable links to the import library for kernel32.dll, oleaut32.dll,
and others.  These "implicity linked" DLLs and their dependencies will
be loaded before your application's entry point is called (where you
could call LoadLibrary).  If you link to MSVCRT.dll (/MD or /MDd), or if
any of the DLLs loaded depend on MSVCRT.dll, it will also be loaded
before your executable's entry point is called.  When MSVCRT.dll is
loaded, during its entry point () it makes a copy of the live
envrionment variables.  You can see the code in _CRTDLL_INIT in crtlib.c.

So to set the environment before MSVCRT.dll makes a copy, you have to do
it before MSVCRT.dll gets loaded.  If your executable doesn't reference
a DLL that uses MSVCRT.dll (like oleaut32.dll), and if your app doesn't
use MSVCRT.dll, then you could do SetEnvrionmentVariable before doing a
LoadLibrary of a DLL that does use MSVCRT.dll, and the CRT would get
your changes.

However, if one of the DLLs that gets implicitly loaded uses MSVCRT.dll,
a LoadLibrary, even in your application's entry point, is too late.

Quote:
>>1. Have a DLL that gets implicitly linked.  Force a reference to it so
>>it loads.  Put the .lib at the front of the list.  In it's DllMain, do
>>a SetEnvironmentVariable.  Hope that the MSVCRT.dll's DLL entry point
>>doesn't get loaded until after mine (oleaut32.dll, and others might
>>load it in before the 3rd party DLL).

> That is an unportable option. Write your own WinMainCRTStartup() or
> MainCRTStartup(). The /ENTRY link option allows you to choose the name
> if you don't like the default. It is worth looking at Matt Pietrek's
> 2001-01 "Under the Hood" MSDN Magazine article "Reduce EXE and DLL Size
> with LIBCTINY.LIB" - I have no URL as I'm reading it on an MSDN disk.

The OS loads the DLLs you implicitly reference (and calls their entry
points) before it calls you application's entry point.  It's part of how
the Portable Executable format and the Windows loader works.

With option 1, I'd be using the implicit loading of my DLL (with its
import library listed first), so that my DLL that calls
SetEnvironmentVariable changes the environment before MSVCRT.dll gets
loaded and makes its copy of the environment.

The trick is that by having my DLL implicitly loaded as soon as
possible, I get changes to the environment that are picked up when
MSVCRT.dll gets loaded, and its entry point executed.

option 1 does work now - but I was looking for a bit of confirmation
that the order you specify import libraries to the linkner effects the
order the OS loads the DLLs and calls their entry points.  From my test,
it is currently this way on all Windows OSes 95-.Net Server and on all
Microsoft compilers.

Why doesn't putenv and getenv just wrap SetEnvironmentVariable and
GetEnvrionmentVariable anyway ;->

Thanks,
-Daniel



Tue, 31 May 2005 06:03:59 GMT  
 Load order and DLL entry order of implicitly linked DLLs, Environment variables
Quote:

> Look into Detours from microsoft, it has a nice utilility:

 > "SetDll" that garanty that a dll will be loaded first.

Thanks.  I'll look at this.

Quote:
> this only work, I think, if the third party dll link to a CRT in a
> DLL, if it has a static copy of the CRT you are out of luck. And to
> link to the same CRT of the DLL, you usually need to use the same
> compiler version.

Exactly.  But if it has a static copy of the CRT, then the copy of the
environment doesn't happen until the 3rd party dll itself gets loaded.
And you're right, if the 3rd party app uses the CRT, you'd need to be
hooked up with the exact same CRT for a putenv to effect that CRT's copy
of the environment (or you'd have to update the environment before it
made its copy).

Quote:
> tell the third party compagny that environnement vars are not cool!
> My gosh this look like a unix port turn bad.
> Well unix programs do not turn bad, they are bad from the beginning :)

Yes :)  I only seem to see environment variables used with ports from
unix (except for the PATH statement used for LoadLibrary - which can be
solved with SetEnvironmentVariable before LoadLibrary).  The 3rd party
app in question is actually Multigen's API for reading .flt files (3D
models).  I've also recently seen a handful of Rational tools that are
obvious ports from UNIX that use a bunch of environment variables.

Thanks,
-Daniel



Tue, 31 May 2005 06:11:13 GMT  
 Load order and DLL entry order of implicitly linked DLLs, Environment variables


<snip>

Quote:
> I probably should have elaborated on this.  Let's say that your
> executable links to the import library for kernel32.dll, oleaut32.dll,
> and others.  These "implicity linked" DLLs and their dependencies will
> be loaded before your application's entry point is called (where you
> could call LoadLibrary).  If you link to MSVCRT.dll (/MD or /MDd), or
if
> any of the DLLs loaded depend on MSVCRT.dll, it will also be loaded
> before your executable's entry point is called.  When MSVCRT.dll is
> loaded, during its entry point () it makes a copy of the live
> envrionment variables.  You can see the code in _CRTDLL_INIT in

crtlib.c.

Problem: MSVCRT is a known DLL, and is mapped
into every process address space.

Otherwise, the example is accurate, and you may still be
able to catch it before _initialization_ of MSVCRT;
I've never tried it.

<snip>

Quote:
> Why doesn't putenv and getenv just wrap SetEnvironmentVariable and
> GetEnvrionmentVariable anyway ;->


fiddled with the environment block in too many different
ways. Here's a thought, though; how about if MS offered
a #define switch to make getenv and putenv wrapper
GEV and SEV? Then the stinking legacy code could
work and still get past this idiocy.


Tue, 31 May 2005 06:17:37 GMT  
 Load order and DLL entry order of implicitly linked DLLs, Environment variables

Quote:

> Implicitly linking is what its called:

> <http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vcco...>

That link was for VC6.  Here's the one for VC7 as well:

<http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vcco...>

-Daniel



Tue, 31 May 2005 06:21:15 GMT  
 Load order and DLL entry order of implicitly linked DLLs, Environment variables

Quote:

> Problem: MSVCRT is a known DLL, and is mapped
> into every process address space.

That's not quite true.  Just make an exe that only uses kernel32.dll
(take out the .lib of everything else), and statically link to the CRT,
or use tinycrt [1] (or use a non-Microsoft compiler).  I tried it, and
MSVCRT.dll is never loaded ;->

-Daniel

[1] <http://www.microsoft.com/msj/defaulttop.asp?page=/msj/archive/s569.htm>



Tue, 31 May 2005 06:42:50 GMT  
 Load order and DLL entry order of implicitly linked DLLs, Environment variables


Quote:

> > Problem: MSVCRT is a known DLL, and is mapped
> > into every process address space.

> That's not quite true.  Just make an exe that only uses kernel32.dll
> (take out the .lib of everything else), and statically link to the
CRT,
> or use tinycrt [1] (or use a non-Microsoft compiler).  I tried it, and
> MSVCRT.dll is never loaded ;->

You are correct, if nothing uses it. I was playing
with it a bit, and I _think_ your idea will work
fine in all cases. I intend to keep playing around
with it for my own information.


Tue, 31 May 2005 10:17:13 GMT  
 Load order and DLL entry order of implicitly linked DLLs, Environment variables


writes
Quote:
>>>I want to know if this assumption is broken, or might be in the future:
>>>If I implicitly link with a DLL, and put it's .lib as the first, will
>>  I don't see how you can simultaneously "implicitly link with a DLL,
>>and
>> put it's .lib as the first". Should I read "explicitly" where you write
>> "implicitly".

>Implicitly linking is what its called:

><http://msdn.microsoft.com/library/default.asp?url=/library/en-
>us/vccore98/html/_core_using_implicit_linking.asp>

>The "implicit" part refers to the loading of the DLL (as compared to an
>explicit LoadLibrary).

My apologies. I had not appreciated that "implicit linking" had a
technical meaning. Unless I use /nodefaultlib in a link call, various
.lib files are used to resolve names in my inputs. I confused that with
"implicit linking".

I note you have successful experience of "detours". I downloaded it
recently but found it opaque. I shall go back to it.

Thanks for starting a REALLY interesting thread.
--
Walter Briscoe



Tue, 31 May 2005 16:18:16 GMT  
 Load order and DLL entry order of implicitly linked DLLs, Environment variables

Quote:

>> Or, alternatively, create a stub executable, which
>> sets the environment variable, then spawns the
>> real exe. The spawned process will pick up the
>> modified environment.

>Thanks.  This was another alternative that I knew would work, but was
>hoping to avoid :-)

Here is a simpler solution.
You could write a batch file that sets the environment variable and calls
the exe.
Then call the batch file to run the program.

Hope this helps.

Thank you,
Bobby Mattappally
Microsoft VC++/C# Team

This posting is provided "AS IS" with no warranties, and confers no rights.

--------------------

Quote:
>Date: Thu, 12 Dec 2002 09:42:04 -0700

>User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.1)
Gecko/20020826
>X-Accept-Language: en-us, en
>MIME-Version: 1.0




>> <snip>

>>>I suggest you putenv() what you want and then LoadLibrary() the 3rd
>>>party DLL.

>> Or, alternatively, create a stub executable, which
>> sets the environment variable, then spawns the
>> real exe. The spawned process will pick up the
>> modified environment.

>Thanks.  This was another alternative that I knew would work, but was
>hoping to avoid :-)

>-Daniel



Mon, 11 Jul 2005 06:16:54 GMT  
 Load order and DLL entry order of implicitly linked DLLs, Environment variables

Quote:

> Here is a simpler solution.
> You could write a batch file that sets the environment variable and calls
> the exe.
> Then call the batch file to run the program.

Thanks for the reply!

This doesn't work for us for a few reasons.  We want something a lot
more transparent.

I am currently using the following solution:

1. I have a DLL (that I call EnvConfig.dll) with no other DLL
dependencies other than kernel32.dll.  EnvConfig.dll is put into the
same directory as the executable.
2. EnvConfig.dll uses the ATL Min CRT to further reduce code size and
dependancies.
3. In the entry point (DllMain), it does some SetEnvironmentVariable
calls (well, it looks for a special file in the application's directory,
and reads it to figure out what variables to munge and how).
4. EnvConfig.dll exports a variable, simply so that an application can
reference the variable, and implicitly link to the DLL.
5. An application implicitly links to the DLL by referencing that
exported variable, and placing the import library (EnvConfig.lib) before
any other library in the linker settings.
6. When the application runs, the operating system first loads
implicitly linked DLLs.  It seems to do this in the order they are
referenced in the linker settings for the application.  If an implicitly
linked DLL has other DLL dependencies, the OS loads those other DLLS (or
makes sure they've already been loaded) before loading the DLL in
question (and does it in the order referenced in the linker settings for
the DLL).
7. After loading the DLLs that were implicitly referenced, the operating
system then calls the entry point for each DLL, in the order that they
were loaded.  It doesn't seem to call any of the entry points until all
the implicitly linked DLLs are loaded.
8. When the application runs, the application's EXE gets loaded first,
then ntdll.dll gets loaded, then kernel32.dll gets loaded, then
EnvConfig.dll (the application references EnvConfig first, but EnvConfig
implicitly links to kernel32.dll, and kernel32.dll implicitly links to
ntdll.dll), and the other DLLs get loaded in order.
9. Then the entry points for the DLLs get called.  So first ntdll.dll,
then kernel32.dll, then EnvConfig.dll.  The DLL entry point for
EnvConfig.dll gets called before the entry point for any CRT's entry
point (where the CRT makes a copy of the environment variables).  This
means that changes EnvConfig makes to the live environment are picked up
by the C runtime's copy.

It works great on all Windows operating systems through Windows Server
2003 RC2.  What I'd like to know is if I can depend in the future on the
operating system loading these DLLs in order, then calling their entry
points in order (based on the linker settings).  A pointer to an article
or book confirming this would be great (or someone with access to the
source code for the loader :-) ).

Thanks!
-Daniel



Tue, 12 Jul 2005 03:34:29 GMT  
 Load order and DLL entry order of implicitly linked DLLs, Environment variables

Quote:
>It works great on all Windows operating systems through Windows Server
>2003 RC2.  What I'd like to know is if I can depend in the future on the
>operating system loading these DLLs in order, then calling their entry
>points in order (based on the linker settings).

This is the way the loader works now. It is unlikey to change.
But we won't be able to guarantee that this won't change in future OSes.

Hope this helps.

Thank you,
Bobby Mattappally
Microsoft VC++/C# Team

This posting is provided "AS IS" with no warranties, and confers no rights.

--------------------

Quote:
>Date: Thu, 23 Jan 2003 12:34:29 -0700

>User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.2.1)
Gecko/20021130
>X-Accept-Language: en-us, en

>> Here is a simpler solution.
>> You could write a batch file that sets the environment variable and
calls
>> the exe.
>> Then call the batch file to run the program.

>Thanks for the reply!



Tue, 12 Jul 2005 08:53:13 GMT  
 
 [ 15 post ] 

 Relevant Pages 

1. Does order of loading multiple dlls matter?

2. Implicit dll linking order

3. (DLL,RC) search order for resource in EXE and DLL

4. Loading Delphi's Dlls implicitly by Visual C++

5. Unloading of Implicitly Loaded DLL

6. DLL dialog doesn't load anymore once changed to statically link DLL

7. byte order and bit order

8. High order/low order problem

9. Writting low-order or high-order bytes

10. Socket Program(Host Order/Network Order)

11. loading an MFC DLL that was originally an extension dll from a non MFC dLL

12. link error, entry point not found in MSDIS100.DLL

 

 
Powered by phpBB® Forum Software