Patch 8.2.2451

6 views
Skip to first unread message

Bram Moolenaar

unread,
Feb 1, 2021, 2:51:49 PM2/1/21
to vim...@googlegroups.com

Patch 8.2.2451
Problem: MS-Windows: Extended Attributes not preserved.
Solution: Preserve Extended Attributes when writing a file. (Ken Takata,
closes #7765)
Files: src/os_win32.c


*** ../vim-8.2.2450/src/os_win32.c 2020-12-18 19:49:52.345571854 +0100
--- src/os_win32.c 2021-02-01 20:50:12.478466893 +0100
***************
*** 33,38 ****
--- 33,39 ----
// cproto fails on missing include files
#ifndef PROTO
# include <process.h>
+ # include <winternl.h>
#endif

#undef chdir
***************
*** 7254,7259 ****
--- 7255,7438 ----
}

/*
+ * ntdll.dll definitions
+ */
+ #define FileEaInformation 7
+ #ifndef STATUS_SUCCESS
+ # define STATUS_SUCCESS ((NTSTATUS) 0x00000000L)
+ #endif
+
+ typedef struct _FILE_FULL_EA_INFORMATION_ {
+ ULONG NextEntryOffset;
+ UCHAR Flags;
+ UCHAR EaNameLength;
+ USHORT EaValueLength;
+ CHAR EaName[1];
+ } FILE_FULL_EA_INFORMATION_, *PFILE_FULL_EA_INFORMATION_;
+
+ typedef struct _FILE_EA_INFORMATION_ {
+ ULONG EaSize;
+ } FILE_EA_INFORMATION_, *PFILE_EA_INFORMATION_;
+
+ typedef NTSTATUS (NTAPI *PfnNtOpenFile)(
+ PHANDLE FileHandle,
+ ACCESS_MASK DesiredAccess,
+ POBJECT_ATTRIBUTES ObjectAttributes,
+ PIO_STATUS_BLOCK IoStatusBlock,
+ ULONG ShareAccess,
+ ULONG OpenOptions);
+ typedef NTSTATUS (NTAPI *PfnNtClose)(
+ HANDLE Handle);
+ typedef NTSTATUS (NTAPI *PfnNtSetEaFile)(
+ HANDLE FileHandle,
+ PIO_STATUS_BLOCK IoStatusBlock,
+ PVOID Buffer,
+ ULONG Length);
+ typedef NTSTATUS (NTAPI *PfnNtQueryEaFile)(
+ HANDLE FileHandle,
+ PIO_STATUS_BLOCK IoStatusBlock,
+ PVOID Buffer,
+ ULONG Length,
+ BOOLEAN ReturnSingleEntry,
+ PVOID EaList,
+ ULONG EaListLength,
+ PULONG EaIndex,
+ BOOLEAN RestartScan);
+ typedef NTSTATUS (NTAPI *PfnNtQueryInformationFile)(
+ HANDLE FileHandle,
+ PIO_STATUS_BLOCK IoStatusBlock,
+ PVOID FileInformation,
+ ULONG Length,
+ FILE_INFORMATION_CLASS FileInformationClass);
+ typedef VOID (NTAPI *PfnRtlInitUnicodeString)(
+ PUNICODE_STRING DestinationString,
+ PCWSTR SourceString);
+
+ PfnNtOpenFile pNtOpenFile = NULL;
+ PfnNtClose pNtClose = NULL;
+ PfnNtSetEaFile pNtSetEaFile = NULL;
+ PfnNtQueryEaFile pNtQueryEaFile = NULL;
+ PfnNtQueryInformationFile pNtQueryInformationFile = NULL;
+ PfnRtlInitUnicodeString pRtlInitUnicodeString = NULL;
+
+ /*
+ * Load ntdll.dll functions.
+ */
+ static BOOL
+ load_ntdll(void)
+ {
+ static int loaded = -1;
+
+ if (loaded == -1)
+ {
+ HMODULE hNtdll = GetModuleHandle("ntdll.dll");
+ if (hNtdll != NULL)
+ {
+ pNtOpenFile = (PfnNtOpenFile) GetProcAddress(hNtdll, "NtOpenFile");
+ pNtClose = (PfnNtClose) GetProcAddress(hNtdll, "NtClose");
+ pNtSetEaFile = (PfnNtSetEaFile)
+ GetProcAddress(hNtdll, "NtSetEaFile");
+ pNtQueryEaFile = (PfnNtQueryEaFile)
+ GetProcAddress(hNtdll, "NtQueryEaFile");
+ pNtQueryInformationFile = (PfnNtQueryInformationFile)
+ GetProcAddress(hNtdll, "NtQueryInformationFile");
+ pRtlInitUnicodeString = (PfnRtlInitUnicodeString)
+ GetProcAddress(hNtdll, "RtlInitUnicodeString");
+ }
+ if (pNtOpenFile == NULL
+ || pNtClose == NULL
+ || pNtSetEaFile == NULL
+ || pNtQueryEaFile == NULL
+ || pNtQueryInformationFile == NULL
+ || pRtlInitUnicodeString == NULL)
+ loaded = FALSE;
+ else
+ loaded = TRUE;
+ }
+ return (BOOL) loaded;
+ }
+
+ /*
+ * Copy extended attributes (EA) from file "from" to file "to".
+ */
+ static void
+ copy_extattr(char_u *from, char_u *to)
+ {
+ char_u *fromf = NULL;
+ char_u *tof = NULL;
+ WCHAR *fromw = NULL;
+ WCHAR *tow = NULL;
+ UNICODE_STRING u;
+ HANDLE h;
+ OBJECT_ATTRIBUTES oa;
+ IO_STATUS_BLOCK iosb;
+ FILE_EA_INFORMATION_ eainfo = {0};
+ void *ea = NULL;
+
+ if (!load_ntdll())
+ return;
+
+ // Convert the file names to the fully qualified object names.
+ fromf = alloc(STRLEN(from) + 5);
+ tof = alloc(STRLEN(to) + 5);
+ if (fromf == NULL || tof == NULL)
+ goto theend;
+ STRCPY(fromf, "\\??\\");
+ STRCAT(fromf, from);
+ STRCPY(tof, "\\??\\");
+ STRCAT(tof, to);
+
+ // Convert the names to wide characters.
+ fromw = enc_to_utf16(fromf, NULL);
+ tow = enc_to_utf16(tof, NULL);
+ if (fromw == NULL || tow == NULL)
+ goto theend;
+
+ // Get the EA.
+ pRtlInitUnicodeString(&u, fromw);
+ InitializeObjectAttributes(&oa, &u, 0, NULL, NULL);
+ if (pNtOpenFile(&h, FILE_READ_EA, &oa, &iosb, 0,
+ FILE_NON_DIRECTORY_FILE) != STATUS_SUCCESS)
+ goto theend;
+ pNtQueryInformationFile(h, &iosb, &eainfo, sizeof(eainfo),
+ FileEaInformation);
+ if (eainfo.EaSize != 0)
+ {
+ ea = alloc(eainfo.EaSize);
+ if (ea != NULL)
+ {
+ if (pNtQueryEaFile(h, &iosb, ea, eainfo.EaSize, FALSE,
+ NULL, 0, NULL, TRUE) != STATUS_SUCCESS)
+ {
+ vim_free(ea);
+ ea = NULL;
+ }
+ }
+ }
+ pNtClose(h);
+
+ // Set the EA.
+ if (ea != NULL)
+ {
+ pRtlInitUnicodeString(&u, tow);
+ InitializeObjectAttributes(&oa, &u, 0, NULL, NULL);
+ if (pNtOpenFile(&h, FILE_WRITE_EA, &oa, &iosb, 0,
+ FILE_NON_DIRECTORY_FILE) != STATUS_SUCCESS)
+ goto theend;
+
+ pNtSetEaFile(h, &iosb, ea, eainfo.EaSize);
+ pNtClose(h);
+ }
+
+ theend:
+ vim_free(fromf);
+ vim_free(tof);
+ vim_free(fromw);
+ vim_free(tow);
+ vim_free(ea);
+ }
+
+ /*
* Copy file attributes from file "from" to file "to".
* For Windows NT and later we copy info streams.
* Always returns zero, errors are ignored.
***************
*** 7263,7268 ****
--- 7442,7448 ----
{
// File streams only work on Windows NT and later.
copy_infostreams(from, to);
+ copy_extattr(from, to);
return 0;
}

*** ../vim-8.2.2450/src/version.c 2021-02-01 20:34:57.249893201 +0100
--- src/version.c 2021-02-01 20:47:46.815122290 +0100
***************
*** 752,753 ****
--- 752,755 ----
{ /* Add new patch number below this line */
+ /**/
+ 2451,
/**/

--
Microsoft's definition of a boolean: TRUE, FALSE, MAYBE
"Embrace and extend"...?

/// Bram Moolenaar -- Br...@Moolenaar.net -- http://www.Moolenaar.net \\\
/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\ an exciting new programming language -- http://www.Zimbu.org ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
Reply all
Reply to author
Forward
0 new messages