Mercurial > vim
comparison src/os_win32.c @ 23819:7237ed5f89bd v8.2.2451
patch 8.2.2451: MS-Windows: Extended Attributes not preserved
Commit: https://github.com/vim/vim/commit/e7bebc495d4014d7bc81f863939c35268cb8e97d
Author: Bram Moolenaar <Bram@vim.org>
Date: Mon Feb 1 20:50:37 2021 +0100
patch 8.2.2451: MS-Windows: Extended Attributes not preserved
Problem: MS-Windows: Extended Attributes not preserved.
Solution: Preserve Extended Attributes when writing a file. (Ken Takata,
closes #7765)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Mon, 01 Feb 2021 21:00:03 +0100 |
parents | b545334ae654 |
children | c1de90bc6e63 |
comparison
equal
deleted
inserted
replaced
23818:8103ec7fda36 | 23819:7237ed5f89bd |
---|---|
31 #include <limits.h> | 31 #include <limits.h> |
32 | 32 |
33 // cproto fails on missing include files | 33 // cproto fails on missing include files |
34 #ifndef PROTO | 34 #ifndef PROTO |
35 # include <process.h> | 35 # include <process.h> |
36 # include <winternl.h> | |
36 #endif | 37 #endif |
37 | 38 |
38 #undef chdir | 39 #undef chdir |
39 #ifdef __GNUC__ | 40 #ifdef __GNUC__ |
40 # ifndef __MINGW32__ | 41 # ifndef __MINGW32__ |
7252 vim_free(fromw); | 7253 vim_free(fromw); |
7253 vim_free(tow); | 7254 vim_free(tow); |
7254 } | 7255 } |
7255 | 7256 |
7256 /* | 7257 /* |
7258 * ntdll.dll definitions | |
7259 */ | |
7260 #define FileEaInformation 7 | |
7261 #ifndef STATUS_SUCCESS | |
7262 # define STATUS_SUCCESS ((NTSTATUS) 0x00000000L) | |
7263 #endif | |
7264 | |
7265 typedef struct _FILE_FULL_EA_INFORMATION_ { | |
7266 ULONG NextEntryOffset; | |
7267 UCHAR Flags; | |
7268 UCHAR EaNameLength; | |
7269 USHORT EaValueLength; | |
7270 CHAR EaName[1]; | |
7271 } FILE_FULL_EA_INFORMATION_, *PFILE_FULL_EA_INFORMATION_; | |
7272 | |
7273 typedef struct _FILE_EA_INFORMATION_ { | |
7274 ULONG EaSize; | |
7275 } FILE_EA_INFORMATION_, *PFILE_EA_INFORMATION_; | |
7276 | |
7277 typedef NTSTATUS (NTAPI *PfnNtOpenFile)( | |
7278 PHANDLE FileHandle, | |
7279 ACCESS_MASK DesiredAccess, | |
7280 POBJECT_ATTRIBUTES ObjectAttributes, | |
7281 PIO_STATUS_BLOCK IoStatusBlock, | |
7282 ULONG ShareAccess, | |
7283 ULONG OpenOptions); | |
7284 typedef NTSTATUS (NTAPI *PfnNtClose)( | |
7285 HANDLE Handle); | |
7286 typedef NTSTATUS (NTAPI *PfnNtSetEaFile)( | |
7287 HANDLE FileHandle, | |
7288 PIO_STATUS_BLOCK IoStatusBlock, | |
7289 PVOID Buffer, | |
7290 ULONG Length); | |
7291 typedef NTSTATUS (NTAPI *PfnNtQueryEaFile)( | |
7292 HANDLE FileHandle, | |
7293 PIO_STATUS_BLOCK IoStatusBlock, | |
7294 PVOID Buffer, | |
7295 ULONG Length, | |
7296 BOOLEAN ReturnSingleEntry, | |
7297 PVOID EaList, | |
7298 ULONG EaListLength, | |
7299 PULONG EaIndex, | |
7300 BOOLEAN RestartScan); | |
7301 typedef NTSTATUS (NTAPI *PfnNtQueryInformationFile)( | |
7302 HANDLE FileHandle, | |
7303 PIO_STATUS_BLOCK IoStatusBlock, | |
7304 PVOID FileInformation, | |
7305 ULONG Length, | |
7306 FILE_INFORMATION_CLASS FileInformationClass); | |
7307 typedef VOID (NTAPI *PfnRtlInitUnicodeString)( | |
7308 PUNICODE_STRING DestinationString, | |
7309 PCWSTR SourceString); | |
7310 | |
7311 PfnNtOpenFile pNtOpenFile = NULL; | |
7312 PfnNtClose pNtClose = NULL; | |
7313 PfnNtSetEaFile pNtSetEaFile = NULL; | |
7314 PfnNtQueryEaFile pNtQueryEaFile = NULL; | |
7315 PfnNtQueryInformationFile pNtQueryInformationFile = NULL; | |
7316 PfnRtlInitUnicodeString pRtlInitUnicodeString = NULL; | |
7317 | |
7318 /* | |
7319 * Load ntdll.dll functions. | |
7320 */ | |
7321 static BOOL | |
7322 load_ntdll(void) | |
7323 { | |
7324 static int loaded = -1; | |
7325 | |
7326 if (loaded == -1) | |
7327 { | |
7328 HMODULE hNtdll = GetModuleHandle("ntdll.dll"); | |
7329 if (hNtdll != NULL) | |
7330 { | |
7331 pNtOpenFile = (PfnNtOpenFile) GetProcAddress(hNtdll, "NtOpenFile"); | |
7332 pNtClose = (PfnNtClose) GetProcAddress(hNtdll, "NtClose"); | |
7333 pNtSetEaFile = (PfnNtSetEaFile) | |
7334 GetProcAddress(hNtdll, "NtSetEaFile"); | |
7335 pNtQueryEaFile = (PfnNtQueryEaFile) | |
7336 GetProcAddress(hNtdll, "NtQueryEaFile"); | |
7337 pNtQueryInformationFile = (PfnNtQueryInformationFile) | |
7338 GetProcAddress(hNtdll, "NtQueryInformationFile"); | |
7339 pRtlInitUnicodeString = (PfnRtlInitUnicodeString) | |
7340 GetProcAddress(hNtdll, "RtlInitUnicodeString"); | |
7341 } | |
7342 if (pNtOpenFile == NULL | |
7343 || pNtClose == NULL | |
7344 || pNtSetEaFile == NULL | |
7345 || pNtQueryEaFile == NULL | |
7346 || pNtQueryInformationFile == NULL | |
7347 || pRtlInitUnicodeString == NULL) | |
7348 loaded = FALSE; | |
7349 else | |
7350 loaded = TRUE; | |
7351 } | |
7352 return (BOOL) loaded; | |
7353 } | |
7354 | |
7355 /* | |
7356 * Copy extended attributes (EA) from file "from" to file "to". | |
7357 */ | |
7358 static void | |
7359 copy_extattr(char_u *from, char_u *to) | |
7360 { | |
7361 char_u *fromf = NULL; | |
7362 char_u *tof = NULL; | |
7363 WCHAR *fromw = NULL; | |
7364 WCHAR *tow = NULL; | |
7365 UNICODE_STRING u; | |
7366 HANDLE h; | |
7367 OBJECT_ATTRIBUTES oa; | |
7368 IO_STATUS_BLOCK iosb; | |
7369 FILE_EA_INFORMATION_ eainfo = {0}; | |
7370 void *ea = NULL; | |
7371 | |
7372 if (!load_ntdll()) | |
7373 return; | |
7374 | |
7375 // Convert the file names to the fully qualified object names. | |
7376 fromf = alloc(STRLEN(from) + 5); | |
7377 tof = alloc(STRLEN(to) + 5); | |
7378 if (fromf == NULL || tof == NULL) | |
7379 goto theend; | |
7380 STRCPY(fromf, "\\??\\"); | |
7381 STRCAT(fromf, from); | |
7382 STRCPY(tof, "\\??\\"); | |
7383 STRCAT(tof, to); | |
7384 | |
7385 // Convert the names to wide characters. | |
7386 fromw = enc_to_utf16(fromf, NULL); | |
7387 tow = enc_to_utf16(tof, NULL); | |
7388 if (fromw == NULL || tow == NULL) | |
7389 goto theend; | |
7390 | |
7391 // Get the EA. | |
7392 pRtlInitUnicodeString(&u, fromw); | |
7393 InitializeObjectAttributes(&oa, &u, 0, NULL, NULL); | |
7394 if (pNtOpenFile(&h, FILE_READ_EA, &oa, &iosb, 0, | |
7395 FILE_NON_DIRECTORY_FILE) != STATUS_SUCCESS) | |
7396 goto theend; | |
7397 pNtQueryInformationFile(h, &iosb, &eainfo, sizeof(eainfo), | |
7398 FileEaInformation); | |
7399 if (eainfo.EaSize != 0) | |
7400 { | |
7401 ea = alloc(eainfo.EaSize); | |
7402 if (ea != NULL) | |
7403 { | |
7404 if (pNtQueryEaFile(h, &iosb, ea, eainfo.EaSize, FALSE, | |
7405 NULL, 0, NULL, TRUE) != STATUS_SUCCESS) | |
7406 { | |
7407 vim_free(ea); | |
7408 ea = NULL; | |
7409 } | |
7410 } | |
7411 } | |
7412 pNtClose(h); | |
7413 | |
7414 // Set the EA. | |
7415 if (ea != NULL) | |
7416 { | |
7417 pRtlInitUnicodeString(&u, tow); | |
7418 InitializeObjectAttributes(&oa, &u, 0, NULL, NULL); | |
7419 if (pNtOpenFile(&h, FILE_WRITE_EA, &oa, &iosb, 0, | |
7420 FILE_NON_DIRECTORY_FILE) != STATUS_SUCCESS) | |
7421 goto theend; | |
7422 | |
7423 pNtSetEaFile(h, &iosb, ea, eainfo.EaSize); | |
7424 pNtClose(h); | |
7425 } | |
7426 | |
7427 theend: | |
7428 vim_free(fromf); | |
7429 vim_free(tof); | |
7430 vim_free(fromw); | |
7431 vim_free(tow); | |
7432 vim_free(ea); | |
7433 } | |
7434 | |
7435 /* | |
7257 * Copy file attributes from file "from" to file "to". | 7436 * Copy file attributes from file "from" to file "to". |
7258 * For Windows NT and later we copy info streams. | 7437 * For Windows NT and later we copy info streams. |
7259 * Always returns zero, errors are ignored. | 7438 * Always returns zero, errors are ignored. |
7260 */ | 7439 */ |
7261 int | 7440 int |
7262 mch_copy_file_attribute(char_u *from, char_u *to) | 7441 mch_copy_file_attribute(char_u *from, char_u *to) |
7263 { | 7442 { |
7264 // File streams only work on Windows NT and later. | 7443 // File streams only work on Windows NT and later. |
7265 copy_infostreams(from, to); | 7444 copy_infostreams(from, to); |
7445 copy_extattr(from, to); | |
7266 return 0; | 7446 return 0; |
7267 } | 7447 } |
7268 | 7448 |
7269 #if defined(MYRESETSTKOFLW) || defined(PROTO) | 7449 #if defined(MYRESETSTKOFLW) || defined(PROTO) |
7270 /* | 7450 /* |