Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2012-03-05 15:50:25 +0400
committerCorinna Vinschen <corinna@vinschen.de>2012-03-05 15:50:25 +0400
commita3904c655efec2edc27f72b68280afb4a144cc9a (patch)
tree397b8ea082ac19d78d5c8521c2a4a2517415e83d /winsup/cygwin/path.cc
parent75effa37fcb63c1e72918f6689660e4c3b11a5e8 (diff)
* cygheap.h (enum fcwd_version_t): Move here from path.cc.
(class fcwd_access_t): Ditto. Only declare methods. (class cwdstuff): Move fast_cwd_ptr and fast_cwd_version from shared DLL section here. * path.cc: Keep fcwd_access_t method definitions. (fcwd_access_t::fast_cwd_version): New method. (find_fast_cwd_pointer): Change comment. Mention test on W8CP. (cwdstuff::init): Initialize fast_cwd_ptr and fast_cwd_version.
Diffstat (limited to 'winsup/cygwin/path.cc')
-rw-r--r--winsup/cygwin/path.cc315
1 files changed, 124 insertions, 191 deletions
diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc
index 4bc47e100..aa0521d4f 100644
--- a/winsup/cygwin/path.cc
+++ b/winsup/cygwin/path.cc
@@ -3510,205 +3510,132 @@ copy_cwd_str (PUNICODE_STRING tgt, PUNICODE_STRING src)
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE. */
-/* This class is used to store the CWD starting with Windows Vista.
- The CWD storage in the RTL_USER_PROCESS_PARAMETERS block is only
- an afterthought now. The actual CWD storage is a FAST_CWD structure
- which is allocated on the process heap. The new method only requires
- minimal locking and it's much more multi-thread friendly. Presumably
- it minimizes contention when accessing the CWD.
- The class fcwd_access_t is supposed to encapsulate the gory implementation
- details depending on OS version from the calling functions. */
-class fcwd_access_t {
- /* This is the layout used in Windows 8 developer preview. */
- struct FAST_CWD_8 {
- LONG ReferenceCount; /* Only release when this is 0. */
- HANDLE DirectoryHandle;
- ULONG OldDismountCount; /* Reflects the system DismountCount
- at the time the CWD has been set. */
- UNICODE_STRING Path; /* Path's Buffer member always refers
- to the following Buffer array. */
- LONG FSCharacteristics; /* Taken from FileFsDeviceInformation */
- WCHAR Buffer[MAX_PATH];
- };
- /* This is the layout used in Windows 7 and Vista. */
- struct FAST_CWD_7 {
- UNICODE_STRING Path; /* Path's Buffer member always refers
- to the following Buffer array. */
- HANDLE DirectoryHandle;
- LONG FSCharacteristics; /* Taken from FileFsDeviceInformation */
- LONG ReferenceCount; /* Only release when this is 0. */
- ULONG OldDismountCount; /* Reflects the system DismountCount
- at the time the CWD has been set. */
- WCHAR Buffer[MAX_PATH];
- };
- /* This is the old FAST_CWD structure up to the patch from KB 2393802,
- release in February 2011. */
- struct FAST_CWD_OLD {
- LONG ReferenceCount; /* Only release when this is 0. */
- HANDLE DirectoryHandle;
- ULONG OldDismountCount; /* Reflects the system DismountCount
- at the time the CWD has been set. */
- UNICODE_STRING Path; /* Path's Buffer member always refers
- to the following Buffer array. */
- WCHAR Buffer[MAX_PATH];
- };
- union {
- FAST_CWD_OLD fold;
- FAST_CWD_7 f7;
- FAST_CWD_8 f8;
- };
-
- /* Type of FAST_CWD used on this system. Keeping this information available
- in shared memory avoids to test for the version every time around.
- Default to new version. */
- enum fcwd_version_t {
- FCWD_OLD,
- FCWD_W7,
- FCWD_W8
- };
- static fcwd_version_t fast_cwd_version;
-
-#define IMPLEMENT(type, name) \
- type name () { \
- switch (fast_cwd_version) { \
- case FCWD_OLD: \
- default: \
- return fold.name; \
- case FCWD_W7: \
- return f7.name; \
- case FCWD_W8: \
- return f8.name; \
- } \
- }
- IMPLEMENT (LONG &, ReferenceCount)
- IMPLEMENT (HANDLE &, DirectoryHandle)
- IMPLEMENT (ULONG &, OldDismountCount)
- IMPLEMENT (UNICODE_STRING &, Path)
- IMPLEMENT (WCHAR *, Buffer)
+void
+fcwd_access_t::SetFSCharacteristics (LONG val)
+{
/* Special case FSCharacteristics. Didn't exist originally. */
- void SetFSCharacteristics (LONG val)
+ switch (fast_cwd_version ())
{
- switch (fast_cwd_version)
- {
- case FCWD_OLD:
- break;
- case FCWD_W7:
- f7.FSCharacteristics = val;
- break;
- case FCWD_W8:
- f8.FSCharacteristics = val;
- break;
- }
- }
-public:
- void CopyPath (UNICODE_STRING &target)
- {
- /* Copy the Path contents over into the UNICODE_STRING referenced by
- target. This is used to set the CurrentDirectoryName in the
- user parameter block. */
- target = Path ();
- }
- void Free (PVOID heap)
- {
- /* Decrement the reference count. If it's down to 0, free
- structure from heap. */
- if (this && InterlockedDecrement (&ReferenceCount ()) == 0)
- {
- /* In contrast to pre-Vista, the handle on init is always a
- fresh one and not the handle inherited from the parent
- process. So we always have to close it here. However, the
- handle could be NULL, if we cd'ed into a virtual dir. */
- HANDLE h = DirectoryHandle ();
- if (h)
- NtClose (h);
- RtlFreeHeap (heap, 0, this);
- }
+ case FCWD_OLD:
+ break;
+ case FCWD_W7:
+ f7.FSCharacteristics = val;
+ break;
+ case FCWD_W8:
+ f8.FSCharacteristics = val;
+ break;
}
- void FillIn (HANDLE dir, PUNICODE_STRING name, ULONG old_dismount_count)
+}
+
+fcwd_version_t &
+fcwd_access_t::fast_cwd_version ()
+{
+ return cygheap->cwd.fast_cwd_version;
+}
+
+void
+fcwd_access_t::CopyPath (UNICODE_STRING &target)
+{
+ /* Copy the Path contents over into the UNICODE_STRING referenced by
+ target. This is used to set the CurrentDirectoryName in the
+ user parameter block. */
+ target = Path ();
+}
+
+void
+fcwd_access_t::Free (PVOID heap)
+{
+ /* Decrement the reference count. If it's down to 0, free
+ structure from heap. */
+ if (this && InterlockedDecrement (&ReferenceCount ()) == 0)
{
- /* Fill in all values into this FAST_CWD structure. */
- DirectoryHandle () = dir;
- ReferenceCount () = 1;
- OldDismountCount () = old_dismount_count;
- /* The new structure stores the device characteristics of the
- volume holding the dir. RtlGetCurrentDirectory_U checks
- if the FILE_REMOVABLE_MEDIA flag is set and, if so, checks if
- the volume is still the same as the one used when opening
- the directory handle.
- We don't call NtQueryVolumeInformationFile for the \\?\PIPE,
- though. It just returns STATUS_INVALID_HANDLE anyway. */
- if (fast_cwd_version != FCWD_OLD)
- {
- SetFSCharacteristics (0);
- if (name != &ro_u_pipedir)
- {
- IO_STATUS_BLOCK io;
- FILE_FS_DEVICE_INFORMATION ffdi;
- if (NT_SUCCESS (NtQueryVolumeInformationFile (dir, &io, &ffdi,
- sizeof ffdi, FileFsDeviceInformation)))
- SetFSCharacteristics (ffdi.Characteristics);
- }
- }
- RtlInitEmptyUnicodeString (&Path (), Buffer (),
- MAX_PATH * sizeof (WCHAR));
- copy_cwd_str (&Path (), name);
+ /* In contrast to pre-Vista, the handle on init is always a
+ fresh one and not the handle inherited from the parent
+ process. So we always have to close it here. However, the
+ handle could be NULL, if we cd'ed into a virtual dir. */
+ HANDLE h = DirectoryHandle ();
+ if (h)
+ NtClose (h);
+ RtlFreeHeap (heap, 0, this);
}
+}
- static void SetDirHandleFromBufferPointer (PWCHAR buf_p, HANDLE dir)
+void
+fcwd_access_t::FillIn (HANDLE dir, PUNICODE_STRING name,
+ ULONG old_dismount_count)
+{
+ /* Fill in all values into this FAST_CWD structure. */
+ DirectoryHandle () = dir;
+ ReferenceCount () = 1;
+ OldDismountCount () = old_dismount_count;
+ /* The new structure stores the device characteristics of the
+ volume holding the dir. RtlGetCurrentDirectory_U checks
+ if the FILE_REMOVABLE_MEDIA flag is set and, if so, checks if
+ the volume is still the same as the one used when opening
+ the directory handle.
+ We don't call NtQueryVolumeInformationFile for the \\?\PIPE,
+ though. It just returns STATUS_INVALID_HANDLE anyway. */
+ if (fast_cwd_version () != FCWD_OLD)
{
- /* Input: The buffer pointer as it's stored in the user parameter block
- and a directory handle.
- This function computes the address to the FAST_CWD structure based
- on the version and overwrites the directory handle. It is only
- used if we couldn't figure out the address of fast_cwd_ptr. */
- fcwd_access_t *f_cwd;
- switch (fast_cwd_version)
+ SetFSCharacteristics (0);
+ if (name != &ro_u_pipedir)
{
- case FCWD_OLD:
- default:
- f_cwd = (fcwd_access_t *)
- ((PBYTE) buf_p - __builtin_offsetof (FAST_CWD_OLD, Buffer));
- case FCWD_W7:
- f_cwd = (fcwd_access_t *)
- ((PBYTE) buf_p - __builtin_offsetof (FAST_CWD_7, Buffer));
- case FCWD_W8:
- f_cwd = (fcwd_access_t *)
- ((PBYTE) buf_p - __builtin_offsetof (FAST_CWD_8, Buffer));
+ IO_STATUS_BLOCK io;
+ FILE_FS_DEVICE_INFORMATION ffdi;
+ if (NT_SUCCESS (NtQueryVolumeInformationFile (dir, &io, &ffdi,
+ sizeof ffdi, FileFsDeviceInformation)))
+ SetFSCharacteristics (ffdi.Characteristics);
}
- f_cwd->DirectoryHandle () = dir;
}
- static void SetVersionFromPointer (PBYTE buf_p, bool is_buffer)
+ RtlInitEmptyUnicodeString (&Path (), Buffer (),
+ MAX_PATH * sizeof (WCHAR));
+ copy_cwd_str (&Path (), name);
+}
+
+void
+fcwd_access_t::SetDirHandleFromBufferPointer (PWCHAR buf_p, HANDLE dir)
+{
+ /* Input: The buffer pointer as it's stored in the user parameter block
+ and a directory handle.
+ This function computes the address to the FAST_CWD structure based
+ on the version and overwrites the directory handle. It is only
+ used if we couldn't figure out the address of fast_cwd_ptr. */
+ fcwd_access_t *f_cwd;
+ switch (fast_cwd_version ())
{
- /* Given a pointer to the FAST_CWD structure (is_buffer == false) or a
- pointer to the Buffer within (is_buffer == true), this function
- computes the FAST_CWD version by checking that Path.MaximumLength
- equals MAX_PATH, and that Path.Buffer == Buffer. */
- if (is_buffer)
- buf_p -= __builtin_offsetof (FAST_CWD_8, Buffer);
- fcwd_access_t *f_cwd = (fcwd_access_t *) buf_p;
- if (f_cwd->f8.Path.MaximumLength == MAX_PATH * sizeof (WCHAR)
- && f_cwd->f8.Path.Buffer == f_cwd->f8.Buffer)
- fast_cwd_version = FCWD_W8;
- else if (f_cwd->f7.Path.MaximumLength == MAX_PATH * sizeof (WCHAR)
- && f_cwd->f7.Path.Buffer == f_cwd->f7.Buffer)
- fast_cwd_version = FCWD_W7;
- else
- fast_cwd_version = FCWD_OLD;
+ case FCWD_OLD:
+ default:
+ f_cwd = (fcwd_access_t *)
+ ((PBYTE) buf_p - __builtin_offsetof (FAST_CWD_OLD, Buffer));
+ case FCWD_W7:
+ f_cwd = (fcwd_access_t *)
+ ((PBYTE) buf_p - __builtin_offsetof (FAST_CWD_7, Buffer));
+ case FCWD_W8:
+ f_cwd = (fcwd_access_t *)
+ ((PBYTE) buf_p - __builtin_offsetof (FAST_CWD_8, Buffer));
}
-};
-fcwd_access_t::fcwd_version_t fcwd_access_t::fast_cwd_version
- __attribute__((section (".cygwin_dll_common"), shared))
- = fcwd_access_t::FCWD_W7;
-/* fast_cwd_ptr is a pointer to the global RtlpCurDirRef pointer in
- ntdll.dll pointing to the FAST_CWD structure which constitutes the CWD.
- Unfortunately RtlpCurDirRef is not exported from ntdll.dll.
- We put the pointer into the common shared DLL segment. This allows to
- restrict the call to find_fast_cwd_pointer() to once per Cygwin session
- per user session. This works, because ASLR randomizes the load address
- of DLLs only once at boot time. */
-static fcwd_access_t **fast_cwd_ptr
- __attribute__((section (".cygwin_dll_common"), shared))
- = (fcwd_access_t **) -1;
+ f_cwd->DirectoryHandle () = dir;
+}
+
+void
+fcwd_access_t::SetVersionFromPointer (PBYTE buf_p, bool is_buffer)
+{
+ /* Given a pointer to the FAST_CWD structure (is_buffer == false) or a
+ pointer to the Buffer within (is_buffer == true), this function
+ computes the FAST_CWD version by checking that Path.MaximumLength
+ equals MAX_PATH, and that Path.Buffer == Buffer. */
+ if (is_buffer)
+ buf_p -= __builtin_offsetof (FAST_CWD_8, Buffer);
+ fcwd_access_t *f_cwd = (fcwd_access_t *) buf_p;
+ if (f_cwd->f8.Path.MaximumLength == MAX_PATH * sizeof (WCHAR)
+ && f_cwd->f8.Path.Buffer == f_cwd->f8.Buffer)
+ fast_cwd_version () = FCWD_W8;
+ else if (f_cwd->f7.Path.MaximumLength == MAX_PATH * sizeof (WCHAR)
+ && f_cwd->f7.Path.Buffer == f_cwd->f7.Buffer)
+ fast_cwd_version () = FCWD_W7;
+ else
+ fast_cwd_version () = FCWD_OLD;
+}
#define peek32(x) (*(uint32_t *)(x))
@@ -3718,8 +3645,9 @@ static fcwd_access_t **fast_cwd_ptr
Therefore we have to use some knowledge to figure out the address.
This code has been tested on Vista 32/64 bit, Server 2008 32/64 bit,
- Windows 7 32/64 bit, and Server 2008 R2 (which is only 64 bit anyway).
- There's some hope that this will still work for Windows 8... */
+ Windows 7 32/64 bit, Server 2008 R2 (which is only 64 bit anyway),
+ and W8CP 32/64 bit. There's some hope this will still work for
+ Windows 8 RTM... */
static fcwd_access_t **
find_fast_cwd_pointer ()
{
@@ -3950,8 +3878,13 @@ cwdstuff::init ()
if (win32.Buffer)
override_win32_cwd (true, SharedUserData.DismountCount);
else
- /* Initially re-open the cwd to allow POSIX semantics. */
- set (NULL, NULL);
+ {
+ /* Initialize fast_cwd stuff. */
+ fast_cwd_ptr = (fcwd_access_t **) -1;
+ fast_cwd_version = FCWD_W7;
+ /* Initially re-open the cwd to allow POSIX semantics. */
+ set (NULL, NULL);
+ }
}
/* Chdir and fill out the elements of a cwdstuff struct. */