This is the mail archive of the mailing list for the Cygwin project.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Sorting environment

A number of years back there was a discussion on this mailing list <> regarding sorting of the environment, and there was some suggestion that it might or might not be necessary. There may have also been some later discussion as to what exactly is involved in sorting the environment the way Windows wants it, although I can't find any such discussion, and the current implementation in Cygwin is incorrect (see below).

On Windows 95, the environment is not sorted. When a new environment variable is added, it removes any existing value from the environment block, and puts the new value on the end. I haven't tried any other editions of the Windows 95 family, but I suspect the situation is the same throughout that family of operating systems.

Under Windows 2000 (and presumably the rest of the NT family), the environment is sorted. The current Cygwin code <> is doing this by means of qsort, effectively using strcmp as the sorting function (in env_sort).

The Microsoft documentation states that the sort order is "case-insensitive, Unicode order, without regard to locale". This being the case, the use of strcmp is clearly incorrect. In fact under Windows environment variable names are case insensitive, so this is important - using strcmp means that a lower case environment variable will come out of position and may not be found by a Windows program calling the GetEnvironmentVariable API call, or there may be (incorrectly) two instances of the environment variable if the Windows program tries to change it using the SetEnvironmentVariable API call.

strcmp being incorrect, stricmp would be better, however Windows NT versions use NTDLL.RtlCompareUnicodeString as the comparison function for performing this sort (actually, they don't perform the sort, rather they assume the environment is sorted, and seek through it when setting to find the correct location to insert the new variable), so the ideal thing to do would be to convert the byte strings to Unicode and perform the comparison using that API call. It is probably best to convert before seeking the equals sign, since this avoids any nastiness associated with "=" being the second byte in a two byte character.

The Windows 95 family of operating systems do not have NTDLL.RtlCompareUnicodeString, so if there is a perceived need to sort there, the following is probably the nearest substitute to what is done under NT:


CompareString( lcid,
*(TCHAR **) pv1, -1,
*(TCHAR **) pv2, -1);

The foregoing is also generally useful for calls to CreateProcess in which lpEnvironment will be set. The Microsoft documentation at this point is woefully inadequate, and without the information above it is difficult to construct a correct environment block to pass in this parameter.

For further information, see the MSDN library under:

"Changing Environment Variables", under "Using
Processes and Threads"


It would probably also be convenient for anybody who finds this message through a search engine if I point out that lpEnvironment is not an envp pointer, rather it is of the form "VAR1=val1\0VAR2=val2\0....VARn=valn\0\0"
WARNING: DO NOT add my email address to any mailing list or
database without my PRIOR, EXPLICIT permission.
Fight spam in Australia - Join CAUBE.AU -
Troy Rollo, Technical Director, CorVu Australasia

Unsubscribe info:
Bug reporting:

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]