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:
-rw-r--r--winsup/cygwin/ChangeLog22
-rw-r--r--winsup/cygwin/ntdll.h58
-rw-r--r--winsup/cygwin/strfuncs.cc21
-rw-r--r--winsup/cygwin/syscalls.cc267
4 files changed, 294 insertions, 74 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index dcef6f846..0aee7f3a9 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,25 @@
+2007-08-12 Corinna Vinschen <corinna@vinschen.de>
+
+ * ntdll.h: Add descriptive comments to special Rtl functions.
+ (STATUS_OBJECT_PATH_NOT_FOUND): Define.
+ (STATUS_BUFFER_OVERFLOW): Define.
+ (FILE_SUPERSEDED): Define.
+ (FILE_OPENED): Define.
+ (FILE_CREATED): Define.
+ (FILE_OVERWRITTEN): Define.
+ (FILE_EXISTS): Define.
+ (FILE_DOES_NOT_EXIST): Define.
+ (PIO_APC_ROUTINE): Typedef.
+ (NtFsControlFile): Fix parameter types to use PIO_APC_ROUTINE.
+ (NtWriteFile): Declare.
+ (RtlInt64ToHexUnicodeString): Declare.
+ * strfuncs.cc: Include ntdll.h.
+ (RtlInt64ToHexUnicodeString): New function.
+ * syscalls.cc (try_to_bin): Rewrite using native NT functions.
+ Only try to create recycle bin after unsuccessfully trying to move
+ file. Also try to create special files in recycle bin so that Windows
+ Explorer isn't unnecessarily stampeded.
+
2007-08-10 Corinna Vinschen <corinna@vinschen.de>
* path.cc (fillout_mntent): Fix calculation of unicode buffer size.
diff --git a/winsup/cygwin/ntdll.h b/winsup/cygwin/ntdll.h
index 1475dd68e..3c94010ca 100644
--- a/winsup/cygwin/ntdll.h
+++ b/winsup/cygwin/ntdll.h
@@ -20,6 +20,7 @@
#define STATUS_ACCESS_DENIED ((NTSTATUS) 0xc0000022)
#define STATUS_BUFFER_TOO_SMALL ((NTSTATUS) 0xc0000023)
#define STATUS_OBJECT_NAME_NOT_FOUND ((NTSTATUS) 0xc0000034)
+#define STATUS_OBJECT_PATH_NOT_FOUND ((NTSTATUS) 0xc000003A)
#define STATUS_SHARING_VIOLATION ((NTSTATUS) 0xc0000043)
#define STATUS_DELETE_PENDING ((NTSTATUS) 0xc0000056)
#define STATUS_WORKING_SET_QUOTA ((NTSTATUS) 0xc00000a1)
@@ -27,6 +28,7 @@
#define STATUS_DIRECTORY_NOT_EMPTY ((NTSTATUS) 0xc0000101)
#define STATUS_NOT_ALL_ASSIGNED ((NTSTATUS) 0x00000106)
#define STATUS_INVALID_LEVEL ((NTSTATUS) 0xc0000148)
+#define STATUS_BUFFER_OVERFLOW ((NTSTATUS) 0x80000005)
#define STATUS_NO_MORE_FILES ((NTSTATUS) 0x80000006)
#define PDI_MODULES 0x01
#define PDI_HEAPS 0x04
@@ -41,6 +43,13 @@
#define WSLE_PAGE_SHARE_COUNT_MASK 0x0E0
#define WSLE_PAGE_SHAREABLE 0x100
+#define FILE_SUPERSEDED 0
+#define FILE_OPENED 1
+#define FILE_CREATED 2
+#define FILE_OVERWRITTEN 3
+#define FILE_EXISTS 4
+#define FILE_DOES_NOT_EXIST 5
+
/* Device Characteristics. */
#define FILE_REMOVABLE_MEDIA 0x00000001
#define FILE_READ_ONLY_DEVICE 0x00000002
@@ -736,6 +745,8 @@ typedef struct _FILE_FULL_EA_INFORMATION
CHAR EaName[1];
} FILE_FULL_EA_INFORMATION, *PFILE_FULL_EA_INFORMATION;
+typedef VOID NTAPI (*PIO_APC_ROUTINE)(PVOID, PIO_STATUS_BLOCK, ULONG);
+
/* Function declarations for ntdll.dll. These don't appear in any
standard Win32 header. */
extern "C"
@@ -753,7 +764,7 @@ extern "C"
PTOKEN_GROUPS, PTOKEN_PRIVILEGES, PTOKEN_OWNER,
PTOKEN_PRIMARY_GROUP, PTOKEN_DEFAULT_DACL,
PTOKEN_SOURCE);
- NTSTATUS NTAPI NtFsControlFile (HANDLE, HANDLE, PVOID, PVOID,
+ NTSTATUS NTAPI NtFsControlFile (HANDLE, HANDLE, PIO_APC_ROUTINE, PVOID,
PIO_STATUS_BLOCK, ULONG, PVOID, ULONG,
PVOID, ULONG);
NTSTATUS NTAPI NtLockVirtualMemory (HANDLE, PVOID *, ULONG *, ULONG);
@@ -799,6 +810,9 @@ extern "C"
PSECURITY_DESCRIPTOR);
NTSTATUS NTAPI NtUnlockVirtualMemory (HANDLE, PVOID *, ULONG *, ULONG);
NTSTATUS NTAPI NtUnmapViewOfSection (HANDLE, PVOID);
+ NTSTATUS NTAPI NtWriteFile (HANDLE, HANDLE, PIO_APC_ROUTINE, PVOID,
+ PIO_STATUS_BLOCK, PVOID, ULONG, PLARGE_INTEGER,
+ PULONG);
NTSTATUS NTAPI RtlAppendUnicodeToString (PUNICODE_STRING, PCWSTR);
NTSTATUS NTAPI RtlAppendUnicodeStringToString (PUNICODE_STRING,
PUNICODE_STRING);
@@ -830,8 +844,11 @@ extern "C"
BOOLEAN);
/* A few Rtl functions are either actually macros, or they just don't
- exist even though they would be a big help. We implement them here
- as inline functions. */
+ exist even though they would be a big help. We implement them here,
+ partly as inline functions. */
+
+ /* RtlInitEmptyUnicodeString is defined as a macro in wdm.h, but that file
+ is missing entirely in w32api. */
inline
VOID NTAPI RtlInitEmptyUnicodeString(PUNICODE_STRING dest, PCWSTR buf,
USHORT len)
@@ -840,6 +857,11 @@ extern "C"
dest->MaximumLength = len;
dest->Buffer = (PWSTR) buf;
}
+ /* Like RtlInitEmptyUnicodeString, but initialize Length to len, too.
+ This is for instance useful when creating a UNICODE_STRING from an
+ NtQueryInformationFile info buffer, where the length of the filename
+ is known, but you can't rely on the string being 0-terminated.
+ If you know it's 0-terminated, just use RtlInitUnicodeString(). */
inline
VOID NTAPI RtlInitCountedUnicodeString (PUNICODE_STRING dest, PCWSTR buf,
USHORT len)
@@ -847,20 +869,29 @@ extern "C"
dest->Length = dest->MaximumLength = len;
dest->Buffer = (PWSTR) buf;
}
+ /* Split path into dirname and basename part. This function does not
+ copy anything! It just initializes the dirname and basename
+ UNICODE_STRINGs so that their Buffer members point to the right spot
+ into path's Buffer, and the Length (and MaximumLength) members are set
+ to match the dirname part and the basename part.
+ Note that dirname's Length is set so that it also includes the trailing
+ backslash. If you don't need it, just subtract sizeof(WCHAR) from
+ dirname.Length. */
inline
- VOID NTAPI RtlSplitUnicodePath (PUNICODE_STRING path, PUNICODE_STRING dir,
- PUNICODE_STRING file)
+ VOID NTAPI RtlSplitUnicodePath (PUNICODE_STRING path, PUNICODE_STRING dirname,
+ PUNICODE_STRING basename)
{
USHORT len = path->Length / sizeof (WCHAR);
while (len > 0 && path->Buffer[--len] != L'\\')
;
++len;
- if (dir)
- RtlInitCountedUnicodeString (dir, path->Buffer, len * sizeof (WCHAR));
- if (file)
- RtlInitCountedUnicodeString (file, &path->Buffer[len],
+ if (dirname)
+ RtlInitCountedUnicodeString (dirname, path->Buffer, len * sizeof (WCHAR));
+ if (basename)
+ RtlInitCountedUnicodeString (basename, &path->Buffer[len],
path->Length - len * sizeof (WCHAR));
}
+ /* Check if prefix is a prefix of path. */
inline
BOOLEAN NTAPI RtlEqualUnicodePathPrefix (PUNICODE_STRING path, PCWSTR prefix,
BOOLEAN caseinsensitive)
@@ -873,6 +904,7 @@ extern "C"
? pref.Length : path->Length);
return RtlEqualUnicodeString (&p, &pref, caseinsensitive);
}
+ /* Check if sufffix is a sufffix of path. */
inline
BOOL NTAPI RtlEqualUnicodePathSuffix (PUNICODE_STRING path, PCWSTR suffix,
BOOLEAN caseinsensitive)
@@ -888,4 +920,12 @@ extern "C"
RtlInitCountedUnicodeString (&p, path->Buffer, path->Length);
return RtlEqualUnicodeString (&p, &suf, caseinsensitive);
}
+ /* Implemented in strfuncs.cc. Create a Hex UNICODE_STRING from a given
+ 64 bit integer value. If append is TRUE, append the hex string,
+ otherwise overwrite dest. Returns either STAUTUS_SUCCESS, or
+ STATUS_BUFFER_OVERFLOW, if the unicode buffer is too small (hasn't
+ room for 16 WCHARs). */
+ NTSTATUS NTAPI RtlInt64ToHexUnicodeString (ULONGLONG value,
+ PUNICODE_STRING dest,
+ BOOLEAN append);
}
diff --git a/winsup/cygwin/strfuncs.cc b/winsup/cygwin/strfuncs.cc
index c0029fb1f..91ed160c3 100644
--- a/winsup/cygwin/strfuncs.cc
+++ b/winsup/cygwin/strfuncs.cc
@@ -12,6 +12,7 @@ details. */
#include "winsup.h"
#include <winbase.h>
#include <winnls.h>
+#include <ntdll.h>
codepage_type current_codepage = ansi_cp;
@@ -41,3 +42,23 @@ sys_mbstowcs (WCHAR *tgt, const char *src, int len)
int res = MultiByteToWideChar (get_cp (), 0, src, -1, tgt, len);
return res;
}
+
+static WCHAR hex_wchars[] = L"0123456789abcdef";
+
+NTSTATUS NTAPI
+RtlInt64ToHexUnicodeString (ULONGLONG value, PUNICODE_STRING dest,
+ BOOLEAN append)
+{
+ USHORT len = append ? dest->Length : 0;
+ if (dest->MaximumLength - len < 16 * (int) sizeof (WCHAR))
+ return STATUS_BUFFER_OVERFLOW;
+ PWCHAR end = (PWCHAR) ((PBYTE) dest->Buffer + len);
+ register PWCHAR p = end + 16;
+ while (p-- > end)
+ {
+ *p = hex_wchars[value & 0xf];
+ value >>= 4;
+ }
+ dest->Length += 16 * sizeof (WCHAR);
+ return STATUS_SUCCESS;
+}
diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc
index 89cff28f9..2ac5f267f 100644
--- a/winsup/cygwin/syscalls.cc
+++ b/winsup/cygwin/syscalls.cc
@@ -139,94 +139,231 @@ dup2 (int oldfd, int newfd)
return cygheap->fdtab.dup2 (oldfd, newfd);
}
+static char desktop_ini[] =
+ "[.ShellClassInfo]\r\nCLSID={645FF040-5081-101B-9F08-00AA002F954E}\r\n";
+static BYTE info2[] =
+{
+ 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x20, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
static void
try_to_bin (path_conv &win32_path, HANDLE h)
{
NTSTATUS status;
+ OBJECT_ATTRIBUTES attr;
IO_STATUS_BLOCK io;
- char recycler[CYG_MAX_PATH + 20];
+ HANDLE rootdir = NULL, recyclerdir = NULL;
+ USHORT recycler_base_len = 0, recycler_user_len = 0;
+ UNICODE_STRING root, recycler, fname;
+ WCHAR recyclerbuf[NAME_MAX + 1]; /* Enough for recycler + SID + filename */
+ PFILE_NAME_INFORMATION pfni;
+ PFILE_INTERNAL_INFORMATION pfii;
+ PFILE_RENAME_INFORMATION pfri;
+ BYTE infobuf[sizeof (FILE_NAME_INFORMATION ) + 32767 * sizeof (WCHAR)];
- rootdir (win32_path, recycler);
- char *c = recycler + strlen (recycler);
- if (wincap.has_recycle_dot_bin ())
+ pfni = (PFILE_NAME_INFORMATION) infobuf;
+ status = NtQueryInformationFile (h, &io, pfni, sizeof infobuf,
+ FileNameInformation);
+ if (!NT_SUCCESS (status))
{
- strcpy (c, "$Recycle.Bin"); /* NTFS and FAT since Vista */
- c += 12;
+ debug_printf ("NtQueryInformationFile (FileNameInformation) failed, %08x",
+ status);
+ goto out;
}
- else if (win32_path.fs_is_ntfs ())
+ /* The filename could change, the parent dir not. So we split both paths
+ and take the prefix. However, there are two special cases:
+ - The handle refers to the root dir of the volume.
+ - The handle refers to the recycler or a subdir.
+ Both cases are handled by just returning and not even trying to move
+ them into the recycler. */
+ if (pfni->FileNameLength == 2) /* root dir. */
+ goto out;
+ /* Initialize recycler path. */
+ RtlInitEmptyUnicodeString (&recycler, recyclerbuf, sizeof recyclerbuf);
+ if (wincap.has_recycle_dot_bin ()) /* NTFS and FAT since Vista */
+ RtlAppendUnicodeToString (&recycler, L"\\$Recycle.Bin\\");
+ else if (win32_path.fs_is_ntfs ()) /* NTFS up to 2K3 */
+ RtlAppendUnicodeToString (&recycler, L"\\RECYCLER\\");
+ else if (win32_path.fs_is_fat ()) /* FAT up to 2K3 */
+ RtlAppendUnicodeToString (&recycler, L"\\Recycled\\");
+ else
+ goto out;
+ /* Is the file a subdir of the recycler? */
+ RtlInitCountedUnicodeString(&fname, pfni->FileName, pfni->FileNameLength);
+ if (RtlEqualUnicodePathPrefix (&fname, recycler.Buffer, TRUE))
+ goto out;
+ /* Is fname the recycler? Temporarily hide trailing backslash. */
+ recycler.Length -= sizeof (WCHAR);
+ if (RtlEqualUnicodeString (&fname, &recycler, TRUE))
+ goto out;
+
+ /* Create root dir path from file name information. */
+ RtlSplitUnicodePath (&fname, &fname, NULL);
+ RtlSplitUnicodePath (win32_path.get_nt_native_path (), &root, NULL);
+ root.Length -= fname.Length - sizeof (WCHAR);
+
+ /* Open root directory. */
+ InitializeObjectAttributes (&attr, &root, OBJ_CASE_INSENSITIVE, NULL, NULL);
+ status = NtOpenFile (&rootdir, FILE_TRAVERSE, &attr, &io,
+ FILE_SHARE_VALID_FLAGS, FILE_OPEN_FOR_BACKUP_INTENT);
+ if (!NT_SUCCESS (status))
{
- strcpy (c, "RECYCLER"); /* NTFS up to 2K3 */
- c += 8;
+ debug_printf ("NtOpenFile (%S) failed, %08x", &root, status);
+ goto out;
}
- else if (win32_path.fs_is_fat ())
+
+ /* Strip leading backslash */
+ ++recycler.Buffer;
+ recycler.Length -= sizeof (WCHAR);
+ /* Store length of recycler base dir, should it be necessary to create it. */
+ recycler_base_len = recycler.Length;
+ /* On NTFS the recycler dir contains user specific subdirs, which are the
+ actual recycle bins per user. The name if this dir is the string
+ representation of the user SID. */
+ if (win32_path.fs_is_ntfs ())
{
- strcpy (c, "Recycled"); /* FAT up to 2K3 */
- c += 8;
+ UNICODE_STRING sid;
+ WCHAR sidbuf[128];
+ /* Unhide trailing backslash. */
+ recycler.Length += sizeof (WCHAR);
+ RtlInitEmptyUnicodeString (&sid, sidbuf, sizeof sidbuf);
+ /* In contrast to what MSDN claims, this function is already available
+ since NT4. */
+ RtlConvertSidToUnicodeString (&sid, cygheap->user.sid (), FALSE);
+ RtlAppendUnicodeStringToString (&recycler, &sid);
+ recycler_user_len = recycler.Length;
}
- else
- return;
-
- /* Yes, we can really do that. Typically the recycle bin is created
- by the first user actually using the bin. The permissions are the
- default permissions propagated from the root directory. */
- if (GetFileAttributes (recycler) == INVALID_FILE_ATTRIBUTES)
+ /* Create hopefully unique filename. */
+ RtlAppendUnicodeToString (&recycler, L"\\cyg");
+ pfii = (PFILE_INTERNAL_INFORMATION) infobuf;
+ status = NtQueryInformationFile (h, &io, pfii, sizeof infobuf,
+ FileInternalInformation);
+ if (!NT_SUCCESS (status))
{
- if (!CreateDirectory (recycler, NULL))
+ debug_printf ("NtQueryInformationFile (FileInternalInformation) failed, "
+ "%08x", status);
+ goto out;
+ }
+ RtlInt64ToHexUnicodeString (pfii->FileId.QuadPart, &recycler, TRUE);
+ /* Shoot. */
+ pfri = (PFILE_RENAME_INFORMATION) infobuf;
+ pfri->ReplaceIfExists = TRUE;
+ pfri->RootDirectory = rootdir;
+ pfri->FileNameLength = recycler.Length;
+ memcpy (pfri->FileName, recycler.Buffer, recycler.Length);
+ status = NtSetInformationFile (h, &io, pfri, sizeof infobuf,
+ FileRenameInformation);
+ if (status == STATUS_OBJECT_PATH_NOT_FOUND)
+ {
+ /* Ok, so the recycler and/or the recycler/SID directory don't exist.
+ First reopen root dir with permission to create subdirs. */
+ NtClose (rootdir);
+ status = NtOpenFile (&rootdir, FILE_ADD_SUBDIRECTORY, &attr, &io,
+ FILE_SHARE_VALID_FLAGS, FILE_OPEN_FOR_BACKUP_INTENT);
+ if (!NT_SUCCESS (status))
{
- debug_printf ("Can't create folder %s, %E", recycler);
- return;
+ debug_printf ("NtOpenFile (%S) failed, %08x", &recycler, status);
+ goto out;
}
- SetFileAttributes (recycler,
- FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
- }
-
- /* Up to Windows 2003 Server, the default settings for the top level recycle
- bin are so that everybody has the right to create files in it. Starting
- with Vista, users are by default not allowed to create files in that
- directory, only subdirectories. Too bad, but that requires to move
- files to the user's own recycler subdir. Instead of adding yet another
- special case, we just move the stuff to the user's recycler, especially
- since only shared files are moved at all. */
- if (win32_path.fs_is_ntfs ())
- {
- *c++ = '\\';
- cygheap->user.get_windows_id (c);
- while (*c)
- ++c;
- if (GetFileAttributes (recycler) == INVALID_FILE_ATTRIBUTES)
+ /* Then check if recycler exists by opening and potentially creating it.
+ Yes, we can really do that. Typically the recycle bin is created
+ by the first user actually using the bin. The permissions are the
+ default permissions propagated from the root directory. */
+ InitializeObjectAttributes (&attr, &recycler, OBJ_CASE_INSENSITIVE,
+ rootdir, NULL);
+ recycler.Length = recycler_base_len;
+ status = NtCreateFile (&recyclerdir,
+ READ_CONTROL
+ | (win32_path.fs_is_ntfs () ? 0 : FILE_ADD_FILE),
+ &attr, &io, NULL,
+ FILE_ATTRIBUTE_DIRECTORY
+ | FILE_ATTRIBUTE_SYSTEM
+ | FILE_ATTRIBUTE_HIDDEN,
+ FILE_SHARE_VALID_FLAGS, FILE_OPEN_IF,
+ FILE_DIRECTORY_FILE, NULL, 0);
+ if (!NT_SUCCESS (status))
{
- if (!CreateDirectory (recycler,
- sec_user ((PSECURITY_ATTRIBUTES) alloca (1024),
- cygheap->user.sid ())))
+ debug_printf ("NtCreateFile (%S) failed, %08x", &recycler, status);
+ goto out;
+ }
+ /* Next, if necessary, check if the recycler/SID dir exists and
+ create it if not. */
+ if (win32_path.fs_is_ntfs ())
+ {
+ NtClose (recyclerdir);
+ recycler.Length = recycler_user_len;
+ status = NtCreateFile (&recyclerdir, READ_CONTROL | FILE_ADD_FILE,
+ &attr, &io, NULL, FILE_ATTRIBUTE_DIRECTORY
+ | FILE_ATTRIBUTE_SYSTEM
+ | FILE_ATTRIBUTE_HIDDEN,
+ FILE_SHARE_VALID_FLAGS, FILE_OPEN_IF,
+ FILE_DIRECTORY_FILE, NULL, 0);
+ if (!NT_SUCCESS (status))
+ {
+ debug_printf ("NtCreateFile (%S) failed, %08x",
+ &recycler, status);
+ goto out;
+ }
+ }
+ /* The desktop.ini and INFO2 (pre-Vista) files are expected by
+ Windows Explorer. Otherwise, the created bin is treated as
+ corrupted */
+ if (io.Information == FILE_CREATED)
+ {
+ HANDLE fh;
+ RtlInitUnicodeString (&fname, L"desktop.ini");
+ InitializeObjectAttributes (&attr, &fname, OBJ_CASE_INSENSITIVE,
+ recyclerdir, NULL);
+ status = NtCreateFile (&fh, FILE_GENERIC_WRITE, &attr, &io, NULL,
+ FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN,
+ FILE_SHARE_VALID_FLAGS, FILE_CREATE,
+ FILE_SYNCHRONOUS_IO_NONALERT
+ | FILE_NON_DIRECTORY_FILE, NULL, 0);
+ if (!NT_SUCCESS (status))
+ debug_printf ("NtCreateFile (%S) failed, %08x", &recycler, status);
+ else
+ {
+ status = NtWriteFile (fh, NULL, NULL, NULL, &io, desktop_ini,
+ sizeof desktop_ini - 1, NULL, NULL);
+ if (!NT_SUCCESS (status))
+ debug_printf ("NtWriteFile (%S) failed, %08x", &fname, status);
+ NtClose (fh);
+ }
+ if (!wincap.has_recycle_dot_bin ()) /* No INFO2 file since Vista */
{
- debug_printf ("Can't create folder %s, %E", recycler);
- return;
+ RtlInitUnicodeString (&fname, L"INFO2");
+ status = NtCreateFile (&fh, FILE_GENERIC_WRITE, &attr, &io, NULL,
+ FILE_ATTRIBUTE_ARCHIVE
+ | FILE_ATTRIBUTE_HIDDEN,
+ FILE_SHARE_VALID_FLAGS, FILE_CREATE,
+ FILE_SYNCHRONOUS_IO_NONALERT
+ | FILE_NON_DIRECTORY_FILE, NULL, 0);
+ if (!NT_SUCCESS (status))
+ debug_printf ("NtCreateFile (%S) failed, %08x",
+ &recycler, status);
+ else
+ {
+ status = NtWriteFile (fh, NULL, NULL, NULL, &io, info2,
+ sizeof info2, NULL, NULL);
+ if (!NT_SUCCESS (status))
+ debug_printf ("NtWriteFile (%S) failed, %08x",
+ &fname, status);
+ NtClose (fh);
+ }
}
- SetFileAttributes (recycler,
- FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
}
+ NtClose (recyclerdir);
+ /* Shoot again. */
+ status = NtSetInformationFile (h, &io, pfri, sizeof infobuf,
+ FileRenameInformation);
}
-
- /* Create hopefully unique filename. */
- __small_sprintf (c, "\\cyg%016X", hash_path_name (myself->uid,
- win32_path.get_win32 ()));
- c += 20;
-
- /* Length of the WCHAR path in bytes. */
- ULONG len = 2 * (c - recycler);
- /* Choose size big enough to fit a local native NT path into it. */
- ULONG size = sizeof (FILE_RENAME_INFORMATION) + len + 10;
- PFILE_RENAME_INFORMATION pfri = (PFILE_RENAME_INFORMATION) alloca (size);
-
- pfri->ReplaceIfExists = TRUE;
- pfri->RootDirectory = NULL;
- UNICODE_STRING uname = { 0, len + 10, pfri->FileName };
- get_nt_native_path (recycler, uname);
- pfri->FileNameLength = uname.Length;
- status = NtSetInformationFile (h, &io, pfri, size, FileRenameInformation);
if (!NT_SUCCESS (status))
debug_printf ("Move %s to %s failed, status = %p", win32_path.get_win32 (),
recycler, status);
+out:
+ if (rootdir)
+ NtClose (rootdir);
}
static NTSTATUS