Sorting environment

Troy Rollo troy@corvu.com.au
Mon Dec 30 22:21:00 GMT 2002


A number of years back there was a discussion on this mailing list 
<http://sources.redhat.com/ml/cygwin/1997-04/msg00159.html> 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 
<http://sources.redhat.com/cgi-bin/cvsweb.cgi/src/winsup/cygwin/environ.cc?rev=1.90&content-type=text/x-cvsweb-markup&cvsroot=src> 
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:

	DWORD   lcid = MAKELCID(
				MAKELANGID(LANG_ENGLISH,
					   SUBLANG_ENGLISH_US),
				SORT_DEFAULT);

	CompareString(	lcid,
			NORM_IGNORECASE | SORT_STRINGSORT,
			*(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"

     CreateProcess

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 - http://www.caube.org.au/
Troy Rollo, Technical Director, CorVu Australasia	 troy@corvu.com.au


--
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
Bug reporting:         http://cygwin.com/bugs.html
Documentation:         http://cygwin.com/docs.html
FAQ:                   http://cygwin.com/faq/



More information about the Cygwin mailing list