Subject: Re: Cygwin | Cygwin Compatibility Issue report ID 386608.
From: Corinna Vinschen <[email-masked]>
To: "Anuja Singh (MP Tech Consulting LLC)" <[email-masked]>
Cc: [email-masked]
Date: Fri, 27 Apr 2012 12:15:19 +0200
List-Id: <cygwin.cygwin.com>

Hi Anuja Singh,

thanks for your input!

Just for you information, cygwin AT cygwin DOT com is a *public* mailing
list, publically archived at http://cygwin.com/ml/cygwin/
This mailing list is the right forum for Cygwin bug reports and
discussions, but be aware that your company disclaimer has no meaning at
all here.

Technical reply below.

On Apr 27 00:05, Anuja Singh (MP Tech Consulting LLC) wrote:
> Hi Cygwin Support,
> [...]
> Tester/Developer Notes: 
>       	Cygwin manually scans ntdll.dll to find the address of the global variable used to access the current working directory. It fails to do this on Windows 8, hence the 	error every time the DLL loads. The error of this function is as follows:
>              "find_fast_cwd: WARNING: Couldn't compute FAST_CWD pointer". 

Thanks for the report.  It had been fixed for the Developer Preview, but
I just saw that it is broken again for the Consumer Preview.  I'll take
a stab at fixing that in the next couple of days.

> 	Cygwin is taking a direct dependency on a global variable in ntdll.dll which will likely break the app every time the DLL revs.  You should consider using other methods 	to maintain compatibility.

Yes, we search for this variable manually, and we are aware that an
upstream change in ntdll.dll might break Cygwin in this regard.
Fortunately, if Cygwin can't find this global variable, it has a backup
method to set the CWD as it needs to, so CYgwin applications will run,
nevertheless.

Please let me explain the motivation behind using this undocumented
global variable.  Keep in mind that Cygwin is a POSIX emulation layer,
so there are certain expectations from the application's point of view.

The only call in the Win32 subsystem to change the CWD is
SetCurrentDirectory.  SetCurrentDirectory has a couple of disadvantages:

- SetCurrentDirectory only supports paths of up to MAX_PATH - 1 chars,
  including a trailing backslash.  That's an absolute restriction, even
  when using the UNICODE API (static buffer).  Cygwin supports up to 32K
  paths, just like the UNICODE API usually does.

- SetCurrentDirectory fails for directories with strict permissions even
  for processes with the SE_BACKUP_NAME privilege enabled.  The reason
  is apparently that SetCurrentDirectory calls NtOpenFile without the
  FILE_OPEN_FOR_BACKUP_INTENT flag set.  An admin user should be able to
  chdir into any directory.

- SetCurrentDirectory does not support case-sensitivity.  Cygwin does.

- Unlinking a CWD fails because SetCurrentDirectory calls NtOpenFile
  without the FILE_SHARE_DELETE sharing mode set.  Cygwin supports this
  notion.

Therefore we decided to do without SetCurrentDirectory and to manipulate
the CWD manually.  In the first place, the CWD handle is created with
FILE_SHARE_DELETE sharing mode and with the FILE_OPEN_FOR_BACKUP_INTENT
flag set.  This worked fine up to Windows Server 2003 R2.

But it broke with Windows Vista in a subtil way.  It turned out that
Vista introduced some structure we call "struct FAST_CWD".  The problem
now being that the CWD handle is not only stored in the
RTL_USER_PROCESS_PARAMETERS block, but additionally in a dynamically
allocated FAST_CWD block. 

To make a long story short, unfortunately this structure and how to
access it is not documented, nor is the global variable keeping its
address exported from ntdll.dll.

Obviously, we didn't want to drop the much more POSIX-like behaviour of
Cygwin's chdir call with Vista.  So the result was that we added code to
figure out where the global variable is stored, plus a heuristic which
tries to evaluate the layout of the FAST_CWD structure.  All the code to
do this you can find in the CVS repository, in the file path.cc:
http://cygwin.com/cgi-bin/cvsweb.cgi/src/winsup/cygwin/path.cc?rev=1.661&content-type=text/x-cvsweb-markup&cvsroot=src
starting at about line 3500.  The structure layout is defined in
cygheap.h:
http://cygwin.com/cgi-bin/cvsweb.cgi/src/winsup/cygwin/cygheap.h?rev=1.158&content-type=text/x-cvsweb-markup&cvsroot=src
at about line 220.

So we are willing to keep this code in shape, even if the layout of the
code and the structure changes again.

However, I'm wondering if there is a chance that Microsoft could open up
this part of ntdll.dll and export the global variable and document the
layout of the structure we call "FAST_CWD".

Alternatively, if there is any other way to accomplish the above in an
officially blessed way, we would certainly be eager to learn it.

Is there a chance to discuss this issue with one of the developers or
program managers of the kernel team?

Thanks in advance,
Corinna

-- 
Corinna Vinschen                  Please, send mails regarding Cygwin to
Cygwin Project Co-Leader          cygwin AT cygwin DOT com
Red Hat

--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple