I called Create­Environment­Block with a process’s token, but I didn’t get that process’s environment

Raymond Chen

A customer found that when they obtained the token to a process with Open­Process­Token and passed that token to Create­Environment­Block, the returned environment variables didn’t match the actual environment variables of the other process. Is Create­Environment­Block broken?

No, Create­Environment­Block is not broken. The thing that’s broken is your expectations.

Nowhere does it say that Create­Environment­Block copies the environment of another process. After all, it’s not called Copy­Process­Environment­Block. Indeed, the handle that you pass to Create­Environment­Block isn’t even a process handle!

What Create­Environment­Block does is create a new environment block for the user specified by the token. This is the mechanism that the system uses to create the initial environment for a user when they log in.

Environment variables are local to a process, and there is no documented way of extracting them. We asked the customer why they needed to extract the environment variables of another process. We never heard back.

8 comments

Leave a comment

  • Joshua Hudson 0

    Sounds like a diagnostic tool. On modern Unix variants you can get this stuff out of PS if you are the user of the process you want to look at.

    I wouldn’t be surprised if there’s a decent way to get this out of a process on Windows but I only came up with a terrible way. Hint: GetEnviornmentVariable has to be implemented somehow.

    • Henke37 0

      My gut says that the PEB has it. So use NtQueryInformationProcess to get the PEB base address and ReadProcessMemory to extract the data. I would consider the relevant struct part to be “stable enough” for widespread use. But it’s still not officially documented.

    • Neil Rashbrook 0

      There’s an edge case whereby if you’re the debugger of the process then you can just ask the process to call GetEnvironmentVariable for you.

    • Wilhelm Payne 0

      I’m certain that there is a way because Process Explorer is able to display the environment for processes on the system.

      • Me Gusta 0

        The most obvious way would be to inject a DLL.

  • Uwe Baemayr 0

    I had to do something like this in a COM surrogate when I ported an in-process COM server component from 32-bit to 64-bit. The large MFC-based hosting application needed to stay 32-bit (for now) so I had it invoke the new 64-bit COM component out-of-process using the surrogate. Then I discovered that the surrogate does not inherit the creator’s environment (it needed the PATH and a few other variables), and always starts up in C:\WINDOWS\SYSTEM32. Since it was my component, adding an interface to set the environment and current working directory solved the problem, but it would have been easier if that information could have been gleaned by the surrogate-hosted component.

    • Joshua Hudson 0

      Hmmm; I had the reverse problem and found the simplest solution was to launch the executable that would contain the COM component myself. Oh well.

  • Dan Weiss 0

    If you really really needed to know what the environment in another process was, you could use code injection and ask from within that process.

Feedback usabilla icon