March 28th, 2024

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

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.

Topics
Code

Author

Raymond has been involved in the evolution of Windows for more than 30 years. In 2003, he began a Web site known as The Old New Thing which has grown in popularity far beyond his wildest imagination, a development which still gives him the heebie-jeebies. The Web site spawned a book, coincidentally also titled The Old New Thing (Addison Wesley 2007). He occasionally appears on the Windows Dev Docs Twitter account to tell stories which convey no useful information.

8 comments

Discussion is closed. Login to edit/delete existing comments.

  • Dan Weiss

    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.

  • Uwe Baemayr

    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....

    Read more
    • Joshua Hudson

      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.

  • Joshua Hudson

    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.

    • Wilhelm Payne

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

      • Me Gusta

        The most obvious way would be to inject a DLL.

    • Neil Rashbrook

      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.

    • Henke37

      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.