Fix FileName::realPath() on Windows

The realPath() implementation on Windows works only for files and
not for directories. By using an API available starting from Vista
it is possible to fix it in a simple way.

I also took into account using the Qt QFileInfo::canonicalFilePath(),
but it turns out to not work when a path component is a junction
(tested with Qt 5.14.1).

Due to this, it is not possible compiling or using LyX on Windows
versions earlier than Vista.
This commit is contained in:
Enrico Forestieri 2020-02-23 22:48:35 +01:00
parent 0daceae649
commit 5873a382de
4 changed files with 14 additions and 38 deletions

2
README
View File

@ -27,7 +27,7 @@ What do I need to run LyX?
Either: Either:
* a Unix-like system (including Windows with Cygwin) * a Unix-like system (including Windows with Cygwin)
* Windows 2000 or newer * Windows Vista or newer
* Mac OS 10.4 or newer * Mac OS 10.4 or newer
A decent LaTeX2e installation (e.g. TeX Live for Linux, MikTeX for A decent LaTeX2e installation (e.g. TeX Live for Linux, MikTeX for

View File

@ -11,6 +11,10 @@
#include <config.h> #include <config.h>
#ifdef _WIN32
# define _WIN32_WINNT 0x0600
#endif
#include "support/convert.h" #include "support/convert.h"
#include "support/debug.h" #include "support/debug.h"
#include "support/filetools.h" #include "support/filetools.h"

View File

@ -38,6 +38,7 @@
#include <io.h> #include <io.h>
#include <direct.h> // _getdrive #include <direct.h> // _getdrive
#include <fileapi.h> // GetFinalPathNameByHandle
#include <shlobj.h> // SHGetFolderPath #include <shlobj.h> // SHGetFolderPath
#include <windef.h> #include <windef.h>
#include <shellapi.h> #include <shellapi.h>
@ -594,45 +595,18 @@ string real_path(string const & path)
// See http://msdn.microsoft.com/en-us/library/aa366789(VS.85).aspx // See http://msdn.microsoft.com/en-us/library/aa366789(VS.85).aspx
QString const qpath = get_long_path(toqstr(path)); QString const qpath = get_long_path(toqstr(path));
HANDLE hpath = CreateFileW((wchar_t *) qpath.utf16(), GENERIC_READ, HANDLE hpath = CreateFileW((wchar_t *) qpath.utf16(), GENERIC_READ,
FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); FILE_SHARE_READ, NULL, OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS, NULL);
if (hpath == INVALID_HANDLE_VALUE) { if (hpath == INVALID_HANDLE_VALUE) {
// The file cannot be accessed. // The file cannot be accessed.
return path; return path;
} }
// Get the file size.
DWORD size_hi = 0;
DWORD size_lo = GetFileSize(hpath, &size_hi);
if (size_lo == 0 && size_hi == 0) {
// A zero-length file cannot be mapped.
CloseHandle(hpath);
return path;
}
// Create a file mapping object.
HANDLE hmap = CreateFileMapping(hpath, NULL, PAGE_READONLY, 0, 1, NULL);
if (!hmap) {
CloseHandle(hpath);
return path;
}
// Create a file mapping to get the file name.
void * pmem = MapViewOfFile(hmap, FILE_MAP_READ, 0, 0, 1);
if (!pmem) {
CloseHandle(hmap);
CloseHandle(hpath);
return path;
}
TCHAR realpath[MAX_PATH + 1]; TCHAR realpath[MAX_PATH + 1];
if (!GetMappedFileName(GetCurrentProcess(), pmem, realpath, MAX_PATH)) { DWORD size = GetFinalPathNameByHandle(hpath, realpath, MAX_PATH, VOLUME_NAME_NT);
UnmapViewOfFile(pmem); if (size > MAX_PATH) {
CloseHandle(hmap);
CloseHandle(hpath); CloseHandle(hpath);
return path; return path;
} }
@ -678,8 +652,6 @@ string real_path(string const & path)
while (*p++) ; while (*p++) ;
} while (!found && *p); } while (!found && *p);
} }
UnmapViewOfFile(pmem);
CloseHandle(hmap);
CloseHandle(hpath); CloseHandle(hpath);
string const retpath = subst(string(realpath), '\\', '/'); string const retpath = subst(string(realpath), '\\', '/');
return FileName::fromFilesystemEncoding(retpath).absFileName(); return FileName::fromFilesystemEncoding(retpath).absFileName();

View File

@ -36,13 +36,13 @@
*/ */
#if defined(__MINGW32__) || defined(__CYGWIN__) || defined(__CYGWIN32__) #if defined(__MINGW32__) || defined(__CYGWIN__) || defined(__CYGWIN32__)
# if defined(WINVER) # if defined(WINVER)
# if WINVER < 0x0500 # if WINVER < 0x0600
# error WINVER must be >= 0x0500 # error WINVER must be >= 0x0600
# endif # endif
# else # else
# define WINVER 0x0500 # define WINVER 0x0600
# endif # endif
# define _WIN32_IE 0x0500 # define _WIN32_IE 0x0600
#endif #endif
#include <windows.h> #include <windows.h>