Drop has_fast_cwd flag
This commit is contained in:
parent
90e6582918
commit
ffcef702e7
@ -3894,12 +3894,11 @@ fcwd_access_t::Free (PVOID heap)
|
|||||||
{
|
{
|
||||||
/* Decrement the reference count. If it's down to 0, free
|
/* Decrement the reference count. If it's down to 0, free
|
||||||
structure from heap. */
|
structure from heap. */
|
||||||
if (this && InterlockedDecrement (&ReferenceCount ()) == 0)
|
if (InterlockedDecrement (&ReferenceCount ()) == 0)
|
||||||
{
|
{
|
||||||
/* In contrast to pre-Vista, the handle on init is always a
|
/* The handle on init is always a fresh one, not the handle inherited
|
||||||
fresh one and not the handle inherited from the parent
|
from the parent process. We always have to close it here.
|
||||||
process. So we always have to close it here. However, the
|
Note: The handle could be NULL, if we cd'ed into a virtual dir. */
|
||||||
handle could be NULL, if we cd'ed into a virtual dir. */
|
|
||||||
HANDLE h = DirectoryHandle ();
|
HANDLE h = DirectoryHandle ();
|
||||||
if (h)
|
if (h)
|
||||||
NtClose (h);
|
NtClose (h);
|
||||||
@ -4247,113 +4246,89 @@ cwdstuff::override_win32_cwd (bool init, ULONG old_dismount_count)
|
|||||||
UNICODE_STRING &upp_cwd_str = peb.ProcessParameters->CurrentDirectoryName;
|
UNICODE_STRING &upp_cwd_str = peb.ProcessParameters->CurrentDirectoryName;
|
||||||
HANDLE &upp_cwd_hdl = peb.ProcessParameters->CurrentDirectoryHandle;
|
HANDLE &upp_cwd_hdl = peb.ProcessParameters->CurrentDirectoryHandle;
|
||||||
|
|
||||||
if (wincap.has_fast_cwd ())
|
if (fast_cwd_ptr == (fcwd_access_t **) -1)
|
||||||
|
fast_cwd_ptr = find_fast_cwd ();
|
||||||
|
if (fast_cwd_ptr)
|
||||||
{
|
{
|
||||||
if (fast_cwd_ptr == (fcwd_access_t **) -1)
|
/* Default method starting with Vista. If we got a valid value for
|
||||||
fast_cwd_ptr = find_fast_cwd ();
|
fast_cwd_ptr, we can simply replace the RtlSetCurrentDirectory_U
|
||||||
if (fast_cwd_ptr)
|
function entirely, just as on pre-Vista. */
|
||||||
|
PVOID heap = peb.ProcessHeap;
|
||||||
|
/* First allocate a new fcwd_access_t structure on the heap.
|
||||||
|
The new fcwd_access_t structure is 4 byte bigger than the old one,
|
||||||
|
but we simply don't care, so we allocate always room for the
|
||||||
|
new one. */
|
||||||
|
fcwd_access_t *f_cwd = (fcwd_access_t *)
|
||||||
|
RtlAllocateHeap (heap, 0, sizeof (fcwd_access_t));
|
||||||
|
if (!f_cwd)
|
||||||
{
|
{
|
||||||
/* Default method starting with Vista. If we got a valid value for
|
debug_printf ("RtlAllocateHeap failed");
|
||||||
fast_cwd_ptr, we can simply replace the RtlSetCurrentDirectory_U
|
return;
|
||||||
function entirely, just as on pre-Vista. */
|
|
||||||
PVOID heap = peb.ProcessHeap;
|
|
||||||
/* First allocate a new fcwd_access_t structure on the heap.
|
|
||||||
The new fcwd_access_t structure is 4 byte bigger than the old one,
|
|
||||||
but we simply don't care, so we allocate always room for the
|
|
||||||
new one. */
|
|
||||||
fcwd_access_t *f_cwd = (fcwd_access_t *)
|
|
||||||
RtlAllocateHeap (heap, 0, sizeof (fcwd_access_t));
|
|
||||||
if (!f_cwd)
|
|
||||||
{
|
|
||||||
debug_printf ("RtlAllocateHeap failed");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
/* Fill in the values. */
|
|
||||||
f_cwd->FillIn (dir, error ? &ro_u_pipedir : &win32,
|
|
||||||
old_dismount_count);
|
|
||||||
/* Use PEB lock when switching fast_cwd_ptr to the new FAST_CWD
|
|
||||||
structure and writing the CWD to the user process parameter
|
|
||||||
block. This is equivalent to calling RtlAcquirePebLock/
|
|
||||||
RtlReleasePebLock, but without having to go through the FS
|
|
||||||
selector again. */
|
|
||||||
RtlEnterCriticalSection (peb.FastPebLock);
|
|
||||||
fcwd_access_t *old_cwd = *fast_cwd_ptr;
|
|
||||||
*fast_cwd_ptr = f_cwd;
|
|
||||||
f_cwd->CopyPath (upp_cwd_str);
|
|
||||||
upp_cwd_hdl = dir;
|
|
||||||
RtlLeaveCriticalSection (peb.FastPebLock);
|
|
||||||
old_cwd->Free (heap);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* This is more a hack, and it's only used on Vista and later if we
|
|
||||||
failed to find the fast_cwd_ptr value. What we do here is to call
|
|
||||||
RtlSetCurrentDirectory_U and let it set up a new FAST_CWD
|
|
||||||
structure. Afterwards, compute the address of that structure
|
|
||||||
utilizing the fact that the buffer address in the user process
|
|
||||||
parameter block is actually pointing to the buffer in that
|
|
||||||
FAST_CWD structure. Then replace the directory handle in that
|
|
||||||
structure with our own handle and close the original one.
|
|
||||||
|
|
||||||
Note that the call to RtlSetCurrentDirectory_U also closes our
|
|
||||||
old dir handle, so there won't be any handle left open.
|
|
||||||
|
|
||||||
This method is prone to two race conditions:
|
|
||||||
|
|
||||||
- Due to the way RtlSetCurrentDirectory_U opens the directory
|
|
||||||
handle, the directory is locked against deletion or renaming
|
|
||||||
between the RtlSetCurrentDirectory_U and the subsequent NtClose
|
|
||||||
call.
|
|
||||||
|
|
||||||
- When another thread calls SetCurrentDirectory at exactly the
|
|
||||||
same time, a crash might occur, or worse, unrelated data could
|
|
||||||
be overwritten or NtClose could be called on an unrelated handle.
|
|
||||||
|
|
||||||
Therefore, use this *only* as a fallback. */
|
|
||||||
if (!init)
|
|
||||||
{
|
|
||||||
NTSTATUS status =
|
|
||||||
RtlSetCurrentDirectory_U (error ? &ro_u_pipedir : &win32);
|
|
||||||
if (!NT_SUCCESS (status))
|
|
||||||
{
|
|
||||||
debug_printf ("RtlSetCurrentDirectory_U(%S) failed, %y",
|
|
||||||
error ? &ro_u_pipedir : &win32, status);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (upp_cwd_hdl == NULL)
|
|
||||||
return;
|
|
||||||
RtlEnterCriticalSection (peb.FastPebLock);
|
|
||||||
fcwd_access_t::SetDirHandleFromBufferPointer(upp_cwd_str.Buffer, dir);
|
|
||||||
h = upp_cwd_hdl;
|
|
||||||
upp_cwd_hdl = dir;
|
|
||||||
RtlLeaveCriticalSection (peb.FastPebLock);
|
|
||||||
/* 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. */
|
|
||||||
NtClose (h);
|
|
||||||
}
|
}
|
||||||
|
/* Fill in the values. */
|
||||||
|
f_cwd->FillIn (dir, error ? &ro_u_pipedir : &win32,
|
||||||
|
old_dismount_count);
|
||||||
|
/* Use PEB lock when switching fast_cwd_ptr to the new FAST_CWD
|
||||||
|
structure and writing the CWD to the user process parameter
|
||||||
|
block. This is equivalent to calling RtlAcquirePebLock/
|
||||||
|
RtlReleasePebLock, but without having to go through the FS
|
||||||
|
selector again. */
|
||||||
|
RtlEnterCriticalSection (peb.FastPebLock);
|
||||||
|
fcwd_access_t *old_cwd = *fast_cwd_ptr;
|
||||||
|
*fast_cwd_ptr = f_cwd;
|
||||||
|
f_cwd->CopyPath (upp_cwd_str);
|
||||||
|
upp_cwd_hdl = dir;
|
||||||
|
RtlLeaveCriticalSection (peb.FastPebLock);
|
||||||
|
if (old_cwd)
|
||||||
|
old_cwd->Free (heap);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* This method is used for all pre-Vista OSes. We simply set the values
|
/* This is more a hack, and it's only used on Vista and later if we
|
||||||
for the CWD in the user process parameter block entirely by ourselves
|
failed to find the fast_cwd_ptr value. What we do here is to call
|
||||||
under PEB lock condition. This is how RtlSetCurrentDirectory_U worked
|
RtlSetCurrentDirectory_U and let it set up a new FAST_CWD
|
||||||
in these older OSes, so we're safe.
|
structure. Afterwards, compute the address of that structure
|
||||||
|
utilizing the fact that the buffer address in the user process
|
||||||
|
parameter block is actually pointing to the buffer in that
|
||||||
|
FAST_CWD structure. Then replace the directory handle in that
|
||||||
|
structure with our own handle and close the original one.
|
||||||
|
|
||||||
Note that we can't just RtlEnterCriticalSection (peb.FastPebLock)
|
Note that the call to RtlSetCurrentDirectory_U also closes our
|
||||||
on pre-Vista. RtlAcquirePebLock was way more complicated back then. */
|
old dir handle, so there won't be any handle left open.
|
||||||
RtlAcquirePebLock ();
|
|
||||||
|
This method is prone to two race conditions:
|
||||||
|
|
||||||
|
- Due to the way RtlSetCurrentDirectory_U opens the directory
|
||||||
|
handle, the directory is locked against deletion or renaming
|
||||||
|
between the RtlSetCurrentDirectory_U and the subsequent NtClose
|
||||||
|
call.
|
||||||
|
|
||||||
|
- When another thread calls SetCurrentDirectory at exactly the
|
||||||
|
same time, a crash might occur, or worse, unrelated data could
|
||||||
|
be overwritten or NtClose could be called on an unrelated handle.
|
||||||
|
|
||||||
|
Therefore, use this *only* as a fallback. */
|
||||||
if (!init)
|
if (!init)
|
||||||
copy_cwd_str (&upp_cwd_str, error ? &ro_u_pipedir : &win32);
|
{
|
||||||
|
NTSTATUS status =
|
||||||
|
RtlSetCurrentDirectory_U (error ? &ro_u_pipedir : &win32);
|
||||||
|
if (!NT_SUCCESS (status))
|
||||||
|
{
|
||||||
|
debug_printf ("RtlSetCurrentDirectory_U(%S) failed, %y",
|
||||||
|
error ? &ro_u_pipedir : &win32, status);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (upp_cwd_hdl == NULL)
|
||||||
|
return;
|
||||||
|
RtlEnterCriticalSection (peb.FastPebLock);
|
||||||
|
fcwd_access_t::SetDirHandleFromBufferPointer(upp_cwd_str.Buffer, dir);
|
||||||
h = upp_cwd_hdl;
|
h = upp_cwd_hdl;
|
||||||
upp_cwd_hdl = dir;
|
upp_cwd_hdl = dir;
|
||||||
RtlReleasePebLock ();
|
RtlLeaveCriticalSection (peb.FastPebLock);
|
||||||
/* Only on init, the handle is potentially a native handle. However,
|
/* The handle on init is always a fresh one, not the handle inherited
|
||||||
if it's identical to dir, it's the inherited handle from a Cygwin
|
from the parent process. We always have to close it here. */
|
||||||
parent process and must not be closed. */
|
NtClose (h);
|
||||||
if (h && h != dir)
|
|
||||||
NtClose (h);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,7 +25,6 @@ wincaps wincap_xpsp2 __attribute__((section (".cygwin_dll_common"), shared)) = {
|
|||||||
has_gaa_largeaddress_bug:false,
|
has_gaa_largeaddress_bug:false,
|
||||||
has_transactions:false,
|
has_transactions:false,
|
||||||
has_broken_alloc_console:false,
|
has_broken_alloc_console:false,
|
||||||
has_fast_cwd:false,
|
|
||||||
has_restricted_raw_disk_access:false,
|
has_restricted_raw_disk_access:false,
|
||||||
use_dont_resolve_hack:true,
|
use_dont_resolve_hack:true,
|
||||||
has_console_logon_sid:false,
|
has_console_logon_sid:false,
|
||||||
@ -51,7 +50,6 @@ wincaps wincap_2003 __attribute__((section (".cygwin_dll_common"), shared)) = {
|
|||||||
has_gaa_largeaddress_bug:false,
|
has_gaa_largeaddress_bug:false,
|
||||||
has_transactions:false,
|
has_transactions:false,
|
||||||
has_broken_alloc_console:false,
|
has_broken_alloc_console:false,
|
||||||
has_fast_cwd:false,
|
|
||||||
has_restricted_raw_disk_access:false,
|
has_restricted_raw_disk_access:false,
|
||||||
use_dont_resolve_hack:true,
|
use_dont_resolve_hack:true,
|
||||||
has_console_logon_sid:false,
|
has_console_logon_sid:false,
|
||||||
@ -77,7 +75,6 @@ wincaps wincap_vista __attribute__((section (".cygwin_dll_common"), shared)) = {
|
|||||||
has_gaa_largeaddress_bug:true,
|
has_gaa_largeaddress_bug:true,
|
||||||
has_transactions:true,
|
has_transactions:true,
|
||||||
has_broken_alloc_console:false,
|
has_broken_alloc_console:false,
|
||||||
has_fast_cwd:true,
|
|
||||||
has_restricted_raw_disk_access:true,
|
has_restricted_raw_disk_access:true,
|
||||||
use_dont_resolve_hack:false,
|
use_dont_resolve_hack:false,
|
||||||
has_console_logon_sid:false,
|
has_console_logon_sid:false,
|
||||||
@ -103,7 +100,6 @@ wincaps wincap_7 __attribute__((section (".cygwin_dll_common"), shared)) = {
|
|||||||
has_gaa_largeaddress_bug:true,
|
has_gaa_largeaddress_bug:true,
|
||||||
has_transactions:true,
|
has_transactions:true,
|
||||||
has_broken_alloc_console:true,
|
has_broken_alloc_console:true,
|
||||||
has_fast_cwd:true,
|
|
||||||
has_restricted_raw_disk_access:true,
|
has_restricted_raw_disk_access:true,
|
||||||
use_dont_resolve_hack:false,
|
use_dont_resolve_hack:false,
|
||||||
has_console_logon_sid:true,
|
has_console_logon_sid:true,
|
||||||
@ -129,7 +125,6 @@ wincaps wincap_8 __attribute__((section (".cygwin_dll_common"), shared)) = {
|
|||||||
has_gaa_largeaddress_bug:false,
|
has_gaa_largeaddress_bug:false,
|
||||||
has_transactions:true,
|
has_transactions:true,
|
||||||
has_broken_alloc_console:true,
|
has_broken_alloc_console:true,
|
||||||
has_fast_cwd:true,
|
|
||||||
has_restricted_raw_disk_access:true,
|
has_restricted_raw_disk_access:true,
|
||||||
use_dont_resolve_hack:false,
|
use_dont_resolve_hack:false,
|
||||||
has_console_logon_sid:true,
|
has_console_logon_sid:true,
|
||||||
@ -155,7 +150,6 @@ wincaps wincap_10 __attribute__((section (".cygwin_dll_common"), shared)) = {
|
|||||||
has_gaa_largeaddress_bug:false,
|
has_gaa_largeaddress_bug:false,
|
||||||
has_transactions:true,
|
has_transactions:true,
|
||||||
has_broken_alloc_console:true,
|
has_broken_alloc_console:true,
|
||||||
has_fast_cwd:true,
|
|
||||||
has_restricted_raw_disk_access:true,
|
has_restricted_raw_disk_access:true,
|
||||||
use_dont_resolve_hack:false,
|
use_dont_resolve_hack:false,
|
||||||
has_console_logon_sid:true,
|
has_console_logon_sid:true,
|
||||||
@ -181,7 +175,6 @@ wincaps wincap_10_1511 __attribute__((section (".cygwin_dll_common"), shared)) =
|
|||||||
has_gaa_largeaddress_bug:false,
|
has_gaa_largeaddress_bug:false,
|
||||||
has_transactions:true,
|
has_transactions:true,
|
||||||
has_broken_alloc_console:true,
|
has_broken_alloc_console:true,
|
||||||
has_fast_cwd:true,
|
|
||||||
has_restricted_raw_disk_access:true,
|
has_restricted_raw_disk_access:true,
|
||||||
use_dont_resolve_hack:false,
|
use_dont_resolve_hack:false,
|
||||||
has_console_logon_sid:true,
|
has_console_logon_sid:true,
|
||||||
|
@ -18,7 +18,6 @@ struct wincaps
|
|||||||
unsigned has_gaa_largeaddress_bug : 1;
|
unsigned has_gaa_largeaddress_bug : 1;
|
||||||
unsigned has_transactions : 1;
|
unsigned has_transactions : 1;
|
||||||
unsigned has_broken_alloc_console : 1;
|
unsigned has_broken_alloc_console : 1;
|
||||||
unsigned has_fast_cwd : 1;
|
|
||||||
unsigned has_restricted_raw_disk_access : 1;
|
unsigned has_restricted_raw_disk_access : 1;
|
||||||
unsigned use_dont_resolve_hack : 1;
|
unsigned use_dont_resolve_hack : 1;
|
||||||
unsigned has_console_logon_sid : 1;
|
unsigned has_console_logon_sid : 1;
|
||||||
@ -69,7 +68,6 @@ public:
|
|||||||
bool IMPLEMENT (has_gaa_largeaddress_bug)
|
bool IMPLEMENT (has_gaa_largeaddress_bug)
|
||||||
bool IMPLEMENT (has_transactions)
|
bool IMPLEMENT (has_transactions)
|
||||||
bool IMPLEMENT (has_broken_alloc_console)
|
bool IMPLEMENT (has_broken_alloc_console)
|
||||||
bool IMPLEMENT (has_fast_cwd)
|
|
||||||
bool IMPLEMENT (has_restricted_raw_disk_access)
|
bool IMPLEMENT (has_restricted_raw_disk_access)
|
||||||
bool IMPLEMENT (use_dont_resolve_hack)
|
bool IMPLEMENT (use_dont_resolve_hack)
|
||||||
bool IMPLEMENT (has_console_logon_sid)
|
bool IMPLEMENT (has_console_logon_sid)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user