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:
Diffstat (limited to 'winsup/cygwin/path.cc')
-rw-r--r--winsup/cygwin/path.cc517
1 files changed, 264 insertions, 253 deletions
diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc
index d1a881c39..fdef934b8 100644
--- a/winsup/cygwin/path.cc
+++ b/winsup/cygwin/path.cc
@@ -57,7 +57,6 @@
#include <winnetwk.h>
#include <winnls.h>
#include <shlobj.h>
-#include <sys/param.h>
#include <sys/cygwin.h>
#include "cygerrno.h"
#include "security.h"
@@ -74,6 +73,8 @@
#include <wchar.h>
#include <wctype.h>
+bool dos_file_warning = true;
+
suffix_info stat_suffixes[] =
{
suffix_info ("", 1),
@@ -112,8 +113,7 @@ muto NO_COPY cwdstuff::cwd_lock;
static const GUID GUID_shortcut
= { 0x00021401L, 0, 0, {0xc0, 0, 0, 0, 0, 0, 0, 0x46}};
-enum
-{
+enum {
WSH_FLAG_IDLIST = 0x01, /* Contains an ITEMIDLIST. */
WSH_FLAG_FILE = 0x02, /* Contains a file locator element. */
WSH_FLAG_DESC = 0x04, /* Contains a description. */
@@ -124,24 +124,24 @@ enum
};
struct win_shortcut_hdr
-{
- DWORD size; /* Header size in bytes. Must contain 0x4c. */
- GUID magic; /* GUID of shortcut files. */
- DWORD flags; /* Content flags. See above. */
-
- /* The next fields from attr to icon_no are always set to 0 in Cygwin
- and U/Win shortcuts. */
- DWORD attr; /* Target file attributes. */
- FILETIME ctime; /* These filetime items are never touched by the */
- FILETIME mtime; /* system, apparently. Values don't matter. */
- FILETIME atime;
- DWORD filesize; /* Target filesize. */
- DWORD icon_no; /* Icon number. */
-
- DWORD run; /* Values defined in winuser.h. Use SW_NORMAL. */
- DWORD hotkey; /* Hotkey value. Set to 0. */
- DWORD dummy[2]; /* Future extension probably. Always 0. */
-};
+ {
+ DWORD size; /* Header size in bytes. Must contain 0x4c. */
+ GUID magic; /* GUID of shortcut files. */
+ DWORD flags; /* Content flags. See above. */
+
+ /* The next fields from attr to icon_no are always set to 0 in Cygwin
+ and U/Win shortcuts. */
+ DWORD attr; /* Target file attributes. */
+ FILETIME ctime; /* These filetime items are never touched by the */
+ FILETIME mtime; /* system, apparently. Values don't matter. */
+ FILETIME atime;
+ DWORD filesize; /* Target filesize. */
+ DWORD icon_no; /* Icon number. */
+
+ DWORD run; /* Values defined in winuser.h. Use SW_NORMAL. */
+ DWORD hotkey; /* Hotkey value. Set to 0. */
+ DWORD dummy[2]; /* Future extension probably. Always 0. */
+ };
/* Return non-zero if PATH1 is a prefix of PATH2.
Both are assumed to be of the same path style and / vs \ usage.
@@ -719,13 +719,7 @@ path_conv::check (const char *src, unsigned opt,
sym.pflags |= pflags_or;
- if (!dev.exists ())
- {
- error = ENXIO;
- return;
- }
-
- if (iscygdrive_dev (dev))
+ if (dev.get_major () == DEV_CYGDRIVE_MAJOR)
{
if (!component)
fileattr = FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_READONLY;
@@ -737,27 +731,29 @@ path_conv::check (const char *src, unsigned opt,
}
goto out;
}
- else if (isdev_dev (dev))
+ else if (dev == FH_DEV)
{
- /* Just make sure that the path handling goes on as with FH_FS. */
+ dev = FH_FS;
+#if 0
+ fileattr = getfileattr (THIS_path, sym.pflags & MOUNT_NOPOSIX);
+ if (!component && fileattr == INVALID_FILE_ATTRIBUTES)
+ {
+ fileattr = FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_READONLY;
+ goto out;
+ }
+#endif
}
else if (isvirtual_dev (dev))
{
/* FIXME: Calling build_fhandler here is not the right way to handle this. */
fhandler_virtual *fh = (fhandler_virtual *) build_fh_dev (dev, path_copy);
- virtual_ftype_t file_type;
- if (!fh)
- file_type = virt_none;
- else
+ virtual_ftype_t file_type = fh->exists ();
+ if (file_type == virt_symlink)
{
- file_type = fh->exists ();
- if (file_type == virt_symlink)
- {
- fh->fill_filebuf ();
- symlen = sym.set (fh->get_filebuf ());
- }
- delete fh;
+ fh->fill_filebuf ();
+ symlen = sym.set (fh->get_filebuf ());
}
+ delete fh;
switch (file_type)
{
case virt_directory:
@@ -884,27 +880,9 @@ is_virtual_symlink:
if (!component)
{
- /* Make sure that /dev always exists. */
- fileattr = isdev_dev (dev) ? FILE_ATTRIBUTE_DIRECTORY
- : sym.fileattr;
+ fileattr = sym.fileattr;
path_flags = sym.pflags;
}
- else if (isdev_dev (dev))
- {
- /* If we're looking for a file below /dev, which doesn't exist,
- make sure that the device type is converted to FH_FS, so that
- subsequent code handles the file correctly.
- Unless /dev itself doesn't exist on disk. In that case /dev
- is handled as virtual filesystem, and virtual filesystems are
- read-only. The PC_KEEP_HANDLE check allows to check for
- a call from an informational system call. In that case we
- just stick to ENOENT, and the device type doesn't matter
- anyway. */
- if (sym.error == ENOENT && !(opt & PC_KEEP_HANDLE))
- sym.error = EROFS;
- else
- dev = FH_FS;
- }
/* If symlink.check found an existing non-symlink file, then
it sets the appropriate flag. It also sets any suffix found
@@ -1153,7 +1131,7 @@ out:
if (opt & PC_CTTY)
path_flags |= PATH_CTTY;
- if (opt & PC_POSIX)
+ if ((opt & PC_POSIX))
{
if (tail < path_end && tail > path_copy + 1)
*tail = '/';
@@ -1352,8 +1330,8 @@ normalize_win32_path (const char *src, char *dst, char *&tail)
if ((tail - dst) >= NT_MAX_PATH)
return ENAMETOOLONG;
}
- if (tail > dst + 1 && tail[-1] == '.' && tail[-2] == '\\')
- tail--;
+ if (tail > dst + 1 && tail[-1] == '.' && tail[-2] == '\\')
+ tail--;
*tail = '\0';
debug_printf ("%s = normalize_win32_path (%s)", dst, src_start);
return 0;
@@ -1474,6 +1452,10 @@ conv_path_list (const char *src, char *dst, size_t size,
/* Create a symlink from FROMPATH to TOPATH. */
+/* If TRUE create symlinks as Windows shortcuts, if false create symlinks
+ as normal files with magic number and system bit set. */
+bool allow_winsymlinks = false;
+
extern "C" int
symlink (const char *oldpath, const char *newpath)
{
@@ -2372,6 +2354,8 @@ restart:
bool had_ext = !!*ext_here;
while (suffix.next ())
{
+ bool no_ea = false;
+
error = 0;
get_nt_native_path (suffix.path, upath, pflags & PATH_DOS);
if (h)
@@ -2402,6 +2386,7 @@ restart:
root dir which has EAs enabled? */
|| status == STATUS_INVALID_PARAMETER))
{
+ no_ea = true;
/* If EAs are not supported, there's no sense to check them again
with suffixes attached. So we set eabuf/easize to 0 here once. */
if (status == STATUS_EAS_NOT_SUPPORTED
@@ -2803,8 +2788,7 @@ readlink (const char *path, char *buf, size_t buflen)
return -1;
}
- size_t pathbuf_len = strlen (pathbuf.get_win32 ());
- ssize_t len = MIN (buflen, pathbuf_len);
+ ssize_t len = min (buflen, strlen (pathbuf.get_win32 ()));
memcpy (buf, pathbuf.get_win32 (), len);
/* errno set by symlink.check if error */
@@ -3204,14 +3188,11 @@ realpath (const char *path, char *resolved)
if (efault.faulted (EFAULT))
return NULL;
- /* Win32 drive letter paths have to be converted to a POSIX path first,
- because path_conv leaves the incoming path untouched except for
- converting backslashes to forward slashes. */
char *tpath;
if (isdrive (path))
{
tpath = tp.c_get ();
- mount_table->conv_to_posix_path (path, tpath, 0);
+ mount_table->cygdrive_posix_path (path, tpath, 0);
}
else
tpath = (char *) path;
@@ -3535,132 +3516,205 @@ copy_cwd_str (PUNICODE_STRING tgt, PUNICODE_STRING src)
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE. */
-void
-fcwd_access_t::SetFSCharacteristics (LONG val)
-{
+/* 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)
/* Special case FSCharacteristics. Didn't exist originally. */
- switch (fast_cwd_version ())
+ void SetFSCharacteristics (LONG val)
{
- case FCWD_OLD:
- break;
- case FCWD_W7:
- f7.FSCharacteristics = val;
- break;
- case FCWD_W8:
- f8.FSCharacteristics = val;
- break;
+ switch (fast_cwd_version)
+ {
+ case FCWD_OLD:
+ break;
+ case FCWD_W7:
+ f7.FSCharacteristics = val;
+ break;
+ case FCWD_W8:
+ f8.FSCharacteristics = val;
+ break;
+ }
}
-}
-
-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)
+public:
+ void CopyPath (UNICODE_STRING &target)
{
- /* 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);
+ /* 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::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)
+ void Free (PVOID heap)
{
- SetFSCharacteristics (0);
- if (name != &ro_u_pipedir)
+ /* Decrement the reference count. If it's down to 0, free
+ structure from heap. */
+ if (this && InterlockedDecrement (&ReferenceCount ()) == 0)
{
- IO_STATUS_BLOCK io;
- FILE_FS_DEVICE_INFORMATION ffdi;
- if (NT_SUCCESS (NtQueryVolumeInformationFile (dir, &io, &ffdi,
- sizeof ffdi, FileFsDeviceInformation)))
- SetFSCharacteristics (ffdi.Characteristics);
+ /* 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);
}
}
- 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 ())
+ void FillIn (HANDLE dir, PUNICODE_STRING name, ULONG old_dismount_count)
{
- 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));
+ /* 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);
}
- 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;
-}
+ static void 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)
+ {
+ 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));
+ }
+ f_cwd->DirectoryHandle () = dir;
+ }
+ static void 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;
+ }
+};
+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;
#define peek32(x) (*(uint32_t *)(x))
@@ -3670,9 +3724,8 @@ fcwd_access_t::SetVersionFromPointer (PBYTE buf_p, bool is_buffer)
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, 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... */
+ 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... */
static fcwd_access_t **
find_fast_cwd_pointer ()
{
@@ -3700,64 +3753,31 @@ find_fast_cwd_pointer ()
/* ...which should be followed by "mov edi, crit-sect-addr" then
"push edi", or by just a single "push crit-sect-addr". */
const uint8_t *movedi = pushedi + 1;
- const uint8_t *mov_pfast_cwd;
- if (movedi[0] == 0x8b && movedi[1] == 0xff) /* mov edi,edi -> W8 */
- {
- /* Windows 8 CP 32 bit (after a Windows Update?) does not call
- RtlEnterCriticalSection. For some reason the function manipulates
- the FastPebLock manually, kind of like RtlEnterCriticalSection has
- been converted to an inline function.
-
- Next we search for a `mov eax, some address'. This address points
- to the LockCount member of the FastPebLock structure, so the address
- is equal to FastPebLock + 4. */
- const uint8_t *moveax = (const uint8_t *) memchr (movedi, 0xb8, 16);
- if (!moveax)
- return NULL;
- offset = (ptrdiff_t) peek32 (moveax + 1) - 4;
- /* Compare the address with the known PEB lock as stored in the PEB. */
- if ((PRTL_CRITICAL_SECTION) offset != NtCurrentTeb ()->Peb->FastPebLock)
- return NULL;
- /* Now search for the mov instruction fetching the address of the global
- PFAST_CWD *. */
- mov_pfast_cwd = moveax;
- do
- {
- mov_pfast_cwd = (const uint8_t *) memchr (++mov_pfast_cwd, 0x8b, 48);
- }
- while (mov_pfast_cwd && mov_pfast_cwd[1] != 0x1d
- && (mov_pfast_cwd - moveax) < 48);
- if (!mov_pfast_cwd || mov_pfast_cwd[1] != 0x1d)
- return NULL;
- }
+ if (movedi[0] == 0xbf && movedi[5] == 0x57)
+ rcall = movedi + 6;
+ else if (movedi[0] == 0x68)
+ rcall = movedi + 5;
else
- {
- if (movedi[0] == 0xbf && movedi[5] == 0x57)
- rcall = movedi + 6;
- else if (movedi[0] == 0x68)
- rcall = movedi + 5;
- else
- return NULL;
- /* Compare the address used for the critical section with the known
- PEB lock as stored in the PEB. */
- if ((PRTL_CRITICAL_SECTION) peek32 (movedi + 1)
- != NtCurrentTeb ()->Peb->FastPebLock)
- return NULL;
- /* To check we are seeing the right code, we check our expectation that
- the next instruction is a relative call into RtlEnterCriticalSection. */
- if (rcall[0] != 0xe8)
- return NULL;
- /* Check that this is a relative call to RtlEnterCriticalSection. */
- offset = (ptrdiff_t) peek32 (rcall + 1);
- if (rcall + 5 + offset != ent_crit)
- return NULL;
- mov_pfast_cwd = rcall + 5;
- }
+ return NULL;
+ /* Compare the address used for the critical section with the known
+ PEB lock as stored in the PEB. */
+ if ((PRTL_CRITICAL_SECTION) peek32 (movedi + 1)
+ != NtCurrentTeb ()->Peb->FastPebLock)
+ return NULL;
+ /* To check we are seeing the right code, we check our expectation that
+ the next instruction is a relative call into RtlEnterCriticalSection. */
+ if (rcall[0] != 0xe8)
+ return NULL;
+ /* Check that this is a relative call to RtlEnterCriticalSection. */
+ offset = (ptrdiff_t) peek32 (rcall + 1);
+ if (rcall + 5 + offset != ent_crit)
+ return NULL;
/* After locking the critical section, the code should read the global
PFAST_CWD * pointer that is guarded by that critical section. */
- if (mov_pfast_cwd[0] != 0x8b)
+ const uint8_t *movesi = rcall + 5;
+ if (movesi[0] != 0x8b)
return NULL;
- return (fcwd_access_t **) peek32 (mov_pfast_cwd + 2);
+ return (fcwd_access_t **) peek32 (movesi + 2);
}
static fcwd_access_t **
@@ -3936,13 +3956,8 @@ cwdstuff::init ()
if (win32.Buffer)
override_win32_cwd (true, SharedUserData.DismountCount);
else
- {
- /* 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);
- }
+ /* Initially re-open the cwd to allow POSIX semantics. */
+ set (NULL, NULL);
}
/* Chdir and fill out the elements of a cwdstuff struct. */
@@ -4311,15 +4326,11 @@ etc::test_file_change (int n)
bool
etc::dir_changed (int n)
{
- /* io MUST be static because NtNotifyChangeDirectoryFile works asynchronously.
- It may write into io after the function has left, which may result in all
- sorts of stack corruption. */
- static IO_STATUS_BLOCK io NO_COPY;
- static HANDLE changed_h NO_COPY;
-
if (!change_possible[n])
{
+ static HANDLE changed_h NO_COPY;
NTSTATUS status;
+ IO_STATUS_BLOCK io;
if (!changed_h)
{