summaryrefslogtreecommitdiffstats
path: root/winsup/cygwin/cygheap.h
diff options
context:
space:
mode:
Diffstat (limited to 'winsup/cygwin/cygheap.h')
-rw-r--r--winsup/cygwin/cygheap.h92
1 files changed, 91 insertions, 1 deletions
diff --git a/winsup/cygwin/cygheap.h b/winsup/cygwin/cygheap.h
index 054297bd7..154ad6a84 100644
--- a/winsup/cygwin/cygheap.h
+++ b/winsup/cygwin/cygheap.h
@@ -204,7 +204,87 @@ public:
/* cwd cache stuff. */
-class muto;
+enum fcwd_version_t {
+ FCWD_OLD,
+ FCWD_W7,
+ FCWD_W8
+};
+
+/* 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;
+ };
+
+#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 SetFSCharacteristics (LONG val);
+ static fcwd_version_t &fast_cwd_version (void);
+
+public:
+ void CopyPath (UNICODE_STRING &target);
+ void Free (PVOID heap);
+ void FillIn (HANDLE dir, PUNICODE_STRING name, ULONG old_dismount_count);
+ static void SetDirHandleFromBufferPointer (PWCHAR buf_p, HANDLE dir);
+ static void SetVersionFromPointer (PBYTE buf_p, bool is_buffer);
+};
class cwdstuff
{
@@ -217,6 +297,16 @@ private:
a native Win32 application. See cwdstuff::set for
how it gets set. See child_info_spawn::worker for how
it's evaluated. */
+
+ friend class fcwd_access_t;
+ /* 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. */
+ fcwd_access_t **fast_cwd_ptr;
+ /* 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. */
+ fcwd_version_t fast_cwd_version;
void override_win32_cwd (bool, ULONG);
public: