Windows Vista environment variables
Gynvael Coldwind (GynvaelColdwind) <gynvaelvexilliumorg> Friday, August 3 2007 10:16.24 CDT


Hi,

I'm currently writing a tutorial (in polish) about Windows .bat scripts. While doing it, I came up with a question: What is the maximum size of a value of an environment variable ? The answer isn't so simple as it may seem.

Let's start with the .bat side of the problem. In this scripting language there is a complex instruction called SET that can set environment variables, enumerate environment variables, prompt the users for values, and even do math. I'll focus on the variable handling side of SET.

The syntax is simple: SET name=value. If we want to display the value of variable name, then SET name or SET ne will do.

So now we write SET sth=AAAAAAAAAAA....1.megabyte.of.A..AAAA and check the systems maximum environment variable length. Oh ? No. Wait. The cmd.exe interpreter says something about "line too long". Oh. So let's check maximum lengths of lines in that case!

Windows NT4  : 2048
Windows 2000 : 2048
Windows XP   : 8192
Windows 2003 : 8192
Windows Vista: it depends

Microsoft Windows Vista is a strange case. Mainly if there is the SET command present, the lines length is unlimited. So setting an environment variable with SET under Vista is not limited by the interpreter. Rather then that, it is limited by the system! Or is it ?

SET command is implemented using SetEnvironmentVariableW API. We can read in MSDN:

The total size of the environment block for a process may not exceed 32,767 characters.

OK. But let's test this. Let's set a 1mb variable data and use SET to print it out. The system should truncate it to 32767 bytes, or less. I've have run a few tests that went like this:
1. Set up the 1mb variable
2. Execute a Windows XXX interpreter
3. Run SET to show the variable

The results are:
Windows Vista: 8192 bytes, \n char was "eaten"
Windows 2003 : The variable was not shown
Windows XP   : The variable was not shown
Windows 2000 : The variable was not shown
Windows NT4  : The interpreter has crashed

OK. It looks like the cmd.exe's SET can't display large variables. I've made a small C program that enumerated environmental variables using the char *envp parameter of main() function.

I've run it only on Vista at this time, and it showed that the whole 1mb of data was saved in the environment variable!

Didn't MSDN said something about there being a limit?

As I said earlier, SET is implemented by SetEnvironmentVariableW. And yes, SetEnvironmentVariableW allows creating environmental variables with an unlimited (limited-by-memory ofc) size (I've checked with 512mb, it works).

But the ANSI version of the API, SetEnvironmentVariableA, does not allow variables larger then 32727. Strange, A version has a size check, W version doesn't. Very strange.

After a little analysis it seems that neither version has a check. The ANSI version fails because RtlInitAnsiStringEx API doesn't allow wide-char string larger then 0xFFFE:


cmp eax, 0FFFEh ; EAX == length of string in wide char
ja loc_ERROR
...
ERROR:
mov eax, 0C0000106h ; STATUS_NAME_TOO_LONG
pop ebp
retn 8


OK. So ...W works with large variables, ...A doesn't. Is this the case on other windows versions ? A simple test program will show that:


#include <stdio.h>
#include <windows.h>

static char big_c[1024*1024];
static short big_s[1024*1024];

int
main(void)
{
  int i;

  for(i = 0; i < 1024*1024 - 1; i++)
  {
    big_c[i] = 'A';
    big_s[i] = 'A';
  }

  printf("W: %i\n", SetEnvironmentVariableW(L"S",big_s));
  printf("A: %i\n", SetEnvironmentVariableA("A",big_c));

  system("cmd.exe");

  return 0;
}



It outputs 0 on fail and 1 on OK. It tests the ...W and ...A versions of the commands with a 1mln chars variable. I've run this code on few Windows versions, and here are the results:

Windows Vista: W 1, A 0
Windows XP   : W 0, A 0
Windows 2000 : W 1, A 0
Windows NT4  : W 1, A 0

At the executed shell, I've also run SET and the envp enumerating tool to see what's up:

Windows Vista: SET shows 8192, envp has all the data
Windows 2000 : SET skips the variable, envp shows 32769 chars (including the variable name)
Windows NT4  : SET crashes cmd.exe, envp shows 32770 chars (including the variable name)

Interesting. Does Vista have more in common with 2000 then XP ? Why does it allow large env. variables (they are well handled and does not crash anything... but they eat a lot of RAM... try setting a 128mb env value and running 10 calc.exe ;>). Only MS knows ;>>>

G.C.

Comments
Posted: Wednesday, December 31 1969 18:00.00 CST