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 -- [email protected] -- 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    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/202102011951.111JphTa1313651%40masaka.moolenaar.net.

Raspunde prin e-mail lui