Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

User Environment Variables

13 views
Skip to first unread message

Tony Proctor

unread,
Oct 10, 2006, 1:29:00 PM10/10/06
to
I've noticed that if I run a Windows Service, or DCOM Server, or an IIS
worker process (e.g. when Anon. authentication set), under a specific
Windows account, then the environment variables for that account are not
loaded.

I presume this is something to do with the profile for that user not being
loaded.

Q1: What's the recommended way to do this such that it's independent of
whoever might be logged on interactive (i.e. not dependent on them, or
affecting them), and independent of any other Service or Component doing the
same thing under a different Windows account?

Q2: In the specific case of IIS, how can I do this for the base account in
which the worker process has been configured to run, as opposed to any
impersonated account when handling a client request?

Q3: Are the associated Regional Settings handled in a similar way. Does the
user profile have be loaded in order for them to be effective?

Tony Proctor


Brian Muth

unread,
Oct 10, 2006, 11:38:41 PM10/10/06
to

"Tony Proctor" <tony_proctor@aimtechnology_NoMoreSPAM_.com> wrote in message
news:eIIxUGJ7...@TK2MSFTNGP02.phx.gbl...

> I've noticed that if I run a Windows Service, or DCOM Server, or an IIS
> worker process (e.g. when Anon. authentication set), under a specific
> Windows account, then the environment variables for that account are not
> loaded.
>
> I presume this is something to do with the profile for that user not being
> loaded.
>
> Q1: What's the recommended way to do this such that it's independent of
> whoever might be logged on interactive (i.e. not dependent on them, or
> affecting them), and independent of any other Service or Component doing
> the
> same thing under a different Windows account?
>

Run as a specific account. Speaking for COM+ objects, you can use
LoadUserProfile if you need the profile settings associated with the
account. You should avoid calling this more than once since it is a
relatively expensive operation.


> Q2: In the specific case of IIS, how can I do this for the base account in
> which the worker process has been configured to run, as opposed to any
> impersonated account when handling a client request?
>

I'm not sure what you mean by "worker process". You are talking about the
ASP interpreter or ASP.NET? These are two different animals. In the case of
the ASP Interpreter, by default it is impersonating the calling user. If the
user is "Anonymous", then the IUSR_<computer> account is used. You can
always stop impersonating momentarily by calling CoRevertToSelf().

Brian


Tony Proctor

unread,
Oct 11, 2006, 6:05:09 AM10/11/06
to
Re Q1: Is the performance of LoadUserProfile any different if the profile
has already been loaded? For instance, when independent threads are trying
to ensure it has been loaded, or if that user just happens to be logged on
interactively at the time?.

Re Q2: Sorry Brian, I meant as ASP environment, and by 'worker process' I
meant the DLLHOST (IIS5) or w3wp (IIS6). With anonymous authentication, I
know it could be running as the IUSR or IWAM account (depending on the
running mode), or a specific account set in the Directory Security tab. I
wasn't sure how to ensure the profile is loaded for _that_ account as
opposed to any that might be being impersonated on the current thread. For
instance, if the token passed to LoadUserProfile was returned by
OpenProcessToken, would that do what I expect?

Tony Proctor

"Brian Muth" <bm...@mvps.org> wrote in message
news:OQN1$aO7GH...@TK2MSFTNGP04.phx.gbl...

Brian Muth

unread,
Oct 11, 2006, 11:57:27 AM10/11/06
to

"Tony Proctor" <tony_proctor@aimtechnology_NoMoreSPAM_.com> wrote in message
news:e$ij9yR7G...@TK2MSFTNGP03.phx.gbl...

> Re Q1: Is the performance of LoadUserProfile any different if the profile
> has already been loaded?

I really don't know, although it would be a simple matter to set up an
experiment and find out. Why not try it and let us know? My suspicion is it
is still costly. After all, it was deliberately left out as part of the
startup of a COM+ application for a reason.


>
> Re Q2: Sorry Brian, I meant as ASP environment, and by 'worker process' I
> meant the DLLHOST (IIS5) or w3wp (IIS6). With anonymous authentication, I
> know it could be running as the IUSR or IWAM account (depending on the
> running mode), or a specific account set in the Directory Security tab. I
> wasn't sure how to ensure the profile is loaded for _that_ account as
> opposed to any that might be being impersonated on the current thread. For
> instance, if the token passed to LoadUserProfile was returned by
> OpenProcessToken, would that do what I expect?

You would expect the user profile associated with the IUSR_<computer> or
IWAM_<computer> account. If you used OpenThreadToken you would get the user
profile of the impersonated user account.

HTH

Brian

Tony Proctor

unread,
Oct 11, 2006, 1:54:05 PM10/11/06
to
Thanks Brian. I will report back when some figures, ...when I get it working
of course.

At the moment, my worker process is configured to run under a specific local
admin account (i.e. not IUSR/IWAM). I have called LoadUserProfile using a
token from OpenProcessToken, but there are no user-level environment
variables loaded for that account, only system ones. Do I have to do
something special to get them into the current environment?

Tony Proctor

"Brian Muth" <bm...@mvps.org> wrote in message

news:um8a03U7...@TK2MSFTNGP02.phx.gbl...

Brian Muth

unread,
Oct 11, 2006, 3:13:17 PM10/11/06
to
Should be there. Have you checked under HKEY_CURRENT_USER\Environment after
calling LoadUserProfile?

See the steps outlined here: http://tinyurl.com/gwnny

Brian


Tony Proctor

unread,
Oct 11, 2006, 3:52:20 PM10/11/06
to
Not sure what's happening yet.

If I open the process token then I get no user variables at all. It could be
that using the process token is equivalent to looking at the IUSR/IWAM
account, rather than the dedicated local account I have configured it to run
under. I know you said that the thread token, rather than the process token,
would return the impersonated account, but I didn't realise that the account
configured for the virtual directory's security ended up being impersonated.

If I open the thread token instead then I still don't get any user-level
environment variables, and HKEY_CURRENT_USER doesn't point to my account.
However, if I use the profile handle to look in the registry then I see all
the variables inside the KEY_USERS area.

...I know I've done something silly, somewhere

Tony Proctor

"Brian Muth" <bm...@mvps.org> wrote in message

news:eZ4lPlW7...@TK2MSFTNGP03.phx.gbl...

Tony Proctor

unread,
Oct 12, 2006, 10:43:26 AM10/12/06
to
OK, sorry about this Brian but I'm not having much look here. I have tried
two scenarios so far...

1) Using a process token from:
OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY Or TOKEN_DUPLICATE Or
TOKEN_IMPERSONATE, hToken)
This fails with 'Access Denied' (=5)

2) Using a thread token from:
OpenThreadToken(GetCurrentThread(), TOKEN_QUERY Or TOKEN_DUPLICATE Or
TOKEN_IMPERSONATE, 1, hToken)
Irrespective of whether OpenAsSelf is 0 or 1, this works insomuch as I get a
profile handle back that shows me the user's hive. However,
HKEY_CURRENT_USER isn't pointing to the same place, and the
GetEnvironmentVariable API doesn't see my User Environment Variables.

In both cases, I was using the token to load the user's profile as follows:

Private Function LoadProfileFromToken(sUserName As String, hToken As Long)
As Long
Dim tPI As PROFILEINFO
Dim lpPI As Long

tPI.dwSize = LenB(tPI)
tPI.dwFlags = PI_NOUI
tPI.dwFlags = 0
tPI.lpUserName = StrPtr(sUserName)
tPI.lpProfilePath = 0
tPI.lpDefaultPath = 0
tPI.lpServerName = 0
tPI.lpPolicyPath = 0

lpPI = VarPtr(tPI)

If LoadUserProfile(hToken, lpPI) Then
LoadProfileFromToken = tPI.hProfile
...etc...

This code is all in a DLL accessed by an ASP page.

[Many thanks for staying with me on this]

Tony Proctor


"Brian Muth" <bm...@mvps.org> wrote in message

news:eZ4lPlW7...@TK2MSFTNGP03.phx.gbl...

Brian Muth

unread,
Oct 12, 2006, 3:04:38 PM10/12/06
to

"Tony Proctor" <tony_proctor@aimtechnology_NoMoreSPAM_.com> wrote in message
news:egoRF7W7...@TK2MSFTNGP03.phx.gbl...

> Not sure what's happening yet.
>
> If I open the process token then I get no user variables at all. It could
> be
> that using the process token is equivalent to looking at the IUSR/IWAM
> account, rather than the dedicated local account I have configured it to
> run
> under. I know you said that the thread token, rather than the process
> token,
> would return the impersonated account, but I didn't realise that the
> account
> configured for the virtual directory's security ended up being
> impersonated.
>
> If I open the thread token instead then I still don't get any user-level
> environment variables, and HKEY_CURRENT_USER doesn't point to my account.

Tony, I just don't follow your language. It's not clear you are following
all the steps. After you open the thread token, do you call LoadUserProfile?
Do you correctly use the last parameter returned (hProfile) as the parameter
to RegOpenKeyEx?

When you say "HKEY_CURRENT_USER doesn't point to my account" I have no clue
what you mean. Who's account is "my account"?

Brian

Tony Proctor

unread,
Oct 12, 2006, 3:57:38 PM10/12/06
to
I thought I said in a previous post, Brian, that I'd configured my virtual
directory to run under a local admin account, and it's that account I'm
talking about. I checked using both GetUsernameEx and
GetUserProfileDirectory that my code was running under this account, and
even the locale settings appeared to be correct for that account. My main
issue was that User environment variables for that account were not loaded.

The earlier post I'd sent today showed some code that already answers the
question about my calls to LoadUserProfile. So, yes I do call it, and I do
extract a valid hProfile handle afterwards.

What I was trying to say in my last post - which I admit was a bit hurried -
was that when using the thread token, I got back a valid hProfile pointing
to my hive, and I could see my User environment variables under there.
However, when using HKEY_CURRENT_USER instead of hProfile then I didn't see
the same hive. I sort of assumed that since the thread was running as (or
impersonating) this local admin account that HKEY_CURRENT_USER would be
pointing to the relevant hive, or at least after calling LoadUserProfile. In
effect, I don't know which hive it happens to be pointing to but the
contents are not the same as the ones under hProfile. Also, the
GetEnvironmentVariable API doesn't find my User variables.

Tony Proctor

"Brian Muth" <bm...@mvps.org> wrote in message

news:OQWBFFj...@TK2MSFTNGP05.phx.gbl...

Brian Muth

unread,
Oct 12, 2006, 6:41:17 PM10/12/06
to

"Tony Proctor" <tony_proctor@aimtechnology_NoMoreSPAM_.com> wrote in message
news:uQxysij7...@TK2MSFTNGP02.phx.gbl...

>I thought I said in a previous post, Brian, that I'd configured my virtual
> directory to run under a local admin account, and it's that account I'm
> talking about. I checked using both GetUsernameEx and
> GetUserProfileDirectory that my code was running under this account, and
> even the locale settings appeared to be correct for that account. My main
> issue was that User environment variables for that account were not
> loaded.
>
> The earlier post I'd sent today showed some code that already answers the
> question about my calls to LoadUserProfile. So, yes I do call it, and I do
> extract a valid hProfile handle afterwards.
>
> What I was trying to say in my last post - which I admit was a bit
> hurried -
> was that when using the thread token, I got back a valid hProfile pointing
> to my hive, and I could see my User environment variables under there.
> However, when using HKEY_CURRENT_USER instead of hProfile then I didn't
> see
> the same hive. I sort of assumed that since the thread was running as (or
> impersonating) this local admin account that HKEY_CURRENT_USER would be
> pointing to the relevant hive, or at least after calling LoadUserProfile.

Thanks for the clarification. I can't fault anything that you have done.
Just be sure that the OpenAsSelf parameter is set to TRUE so you don't get
the impersonated token. Also, I would go into Component Services and look at
the identity of the COM+ application representing the IIS web site you have
set up, just to confirm you are seeing the chosen local admin account. (It
will probably look like: IIS--{Default Web Site//Root/MySite})

Other than that, I'm at a loss as to further suggestions.

Brian

Tony Proctor

unread,
Oct 13, 2006, 9:25:49 AM10/13/06
to
Well, some progress Brian....but more questions too...

It appears the difference between using HKEY_CURRENT_ROOT and hProfile to
look at the hive was a bug on my part (I had a old key kept open). Hence, I
can see the user environment variables using both keys now.

However, GetEnvironmentVariable still refuses to show the same variables to
me. I wonder if this is because it's using an older edition of the active
environment block, and that isn't changed by the LoadProfile call.
Interestingly, ExpandEnvironmentStringsForUser _does_ use these variables,
and I can easily use that as alternative to Get EnvironmentVariable. I just
whish I understood why it was necessary :-(

I also found that OpenThreadToken fails with error 1008 if you're in the
IDE. I did a Google and found a few people reporting this, but no
explanation there either

On the subject of performance, LoadUserProfile is definitely a _lot_ quicker
if the profile is already loaded, e.g. if that user is currently logged on
interactive, or another thread has called LoadUserProfile and not called
UnloadUserProfile.

Tony Proctor

P.S. I'm using W2K here so I couldn't check Component Services


"Brian Muth" <bm...@mvps.org> wrote in message

news:%237q$I%23k7GH...@TK2MSFTNGP04.phx.gbl...

Tony Proctor

unread,
Oct 13, 2006, 3:46:57 PM10/13/06
to
Interestingly Brian, I found that out-of-process DCOM Servers behave the
same way regarding User Environment Variables when they're configured to run
under a specific account (i.e. set on the Identity tab of dcomcnfg). Only
System variables are loaded. Although I can now find and make use of the
User variables, it appears I cannot force them to be loaded for general use
(i.e. via GetEnvironmentVariable and the like). It seems fairly deliberate.
I wonder if it's a security issue

Tony Proctor

"Brian Muth" <bm...@mvps.org> wrote in message

news:%237q$I%23k7GH...@TK2MSFTNGP04.phx.gbl...

Tony Proctor

unread,
Oct 16, 2006, 5:41:34 AM10/16/06
to
For anyone else browsing this thread in the future, I think this issue may
be covered by Q149419. It's quite an old article but I haven't found any
later retraction of it

Tony Proctor

"Brian Muth" <bm...@mvps.org> wrote in message

news:%237q$I%23k7GH...@TK2MSFTNGP04.phx.gbl...

Ben Voigt

unread,
Oct 17, 2006, 4:19:09 PM10/17/06
to

"Tony Proctor" <tony_proctor@aimtechnology_NoMoreSPAM_.com> wrote in message
news:%23YmYZBw...@TK2MSFTNGP02.phx.gbl...

> Interestingly Brian, I found that out-of-process DCOM Servers behave the
> same way regarding User Environment Variables when they're configured to
> run
> under a specific account (i.e. set on the Identity tab of dcomcnfg). Only
> System variables are loaded. Although I can now find and make use of the
> User variables, it appears I cannot force them to be loaded for general
> use
> (i.e. via GetEnvironmentVariable and the like). It seems fairly
> deliberate.
> I wonder if it's a security issue

No, I believe it's because your app gets an independent copy of the
environment, "Process Environment Block", when it starts. Changes to
environment variables with e.g. putenv are process-local. However, I think
you should be able to spawn a new process that has the updated environment.

You can see the same behavior if you have a command prompt open and you use
the System control panel to change environment variables. The new values
are only visible to command prompts opened after the change was made.

Tony Proctor

unread,
Oct 18, 2006, 5:07:43 AM10/18/06
to
You misunderstand Ben. I'm not modifying the environment. My user variables
are pre-declared. However, they are not made available to either my ASP app
when the virtual directory is given a specific account to RunAs, or an
out-of-process DCOM servers when similarly configured. The initial
environment block presented to my code in both these scenarios _only_
contains the system variables - no user variables at all. Hence my
assumption that this must be a deliberate policy in Windows (see later
reference to a 'Q' article that may explain it).

Tony Proctor

"Ben Voigt" <r...@nospam.nospam> wrote in message
news:eIBaCmi8...@TK2MSFTNGP05.phx.gbl...

Ben Voigt

unread,
Oct 18, 2006, 1:06:36 PM10/18/06
to

"Tony Proctor" <tony_proctor@aimtechnology_NoMoreSPAM_.com> wrote in message
news:O5MSgTp8...@TK2MSFTNGP04.phx.gbl...

> You misunderstand Ben. I'm not modifying the environment. My user
> variables
> are pre-declared. However, they are not made available to either my ASP
> app
> when the virtual directory is given a specific account to RunAs, or an
> out-of-process DCOM servers when similarly configured. The initial
> environment block presented to my code in both these scenarios _only_
> contains the system variables - no user variables at all. Hence my
> assumption that this must be a deliberate policy in Windows (see later
> reference to a 'Q' article that may explain it).
>
> Tony Proctor
>

My point was that, to enable local modifications to the environment block,
your copy is disassociated from the environment settings during process
startup. So anything you do to change the settings, like edit the registry,
load a user profile, etc, won't be reflected in your copy.

You could however load the user profile and then modify your local
environment to match.


Tony Proctor

unread,
Oct 18, 2006, 2:55:21 PM10/18/06
to
This happens even if the user's profile is loaded - and I don't mean by
doing it manually. I checked some scenarios where HKEY_CURRENT_USER was
already pointing to right hive when my code started, and those user
environment variables were _still_ not loaded. I know what you're saying,
but I think you're on the wrong track Ben.

Tony Proctor

"Ben Voigt" <r...@nospam.nospam> wrote in message

news:eh0xGft8...@TK2MSFTNGP02.phx.gbl...

0 new messages