|
Windows Vista environment variables
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: 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: 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
| ||||||