summaryrefslogtreecommitdiffstats
path: root/src/corelib/io/qfilesystemengine_win.cpp
diff options
context:
space:
mode:
authorOliver Wolff <oliver.wolff@digia.com>2013-09-02 12:57:51 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-10-11 12:22:53 +0200
commite31be2964e9b06baa887b600d7bda2e8b8ff82a4 (patch)
tree0a6d63e7b6bba6ccdc7ad1dd254b960af6c25b9f /src/corelib/io/qfilesystemengine_win.cpp
parentda0cb32b8ee7cc4a991a59420a411898e63a660e (diff)
Added initial file system support for winrt
While some functionality is not available for winphone (QFileSystemEngine::tempPath), some functionality can be fully supported. Other cases like checking for stale processes which is needed by QLockFile cannot be covered that easily as obtaining information about other processes is limited due to sandboxing. Change-Id: I9ea80ae2b421eea1ddfd4c5bc2f4b6f8adaee85f Done-with: Kamil Trzcinski Reviewed-by: Friedemann Kleint <Friedemann.Kleint@digia.com> Reviewed-by: Maurice Kalinowski <maurice.kalinowski@digia.com>
Diffstat (limited to 'src/corelib/io/qfilesystemengine_win.cpp')
-rw-r--r--src/corelib/io/qfilesystemengine_win.cpp157
1 files changed, 136 insertions, 21 deletions
diff --git a/src/corelib/io/qfilesystemengine_win.cpp b/src/corelib/io/qfilesystemengine_win.cpp
index 57231b57a9..105c8d34dd 100644
--- a/src/corelib/io/qfilesystemengine_win.cpp
+++ b/src/corelib/io/qfilesystemengine_win.cpp
@@ -63,13 +63,26 @@
# include <types.h>
#endif
#include <objbase.h>
-#include <shlobj.h>
+#ifndef Q_OS_WINRT
+# include <shlobj.h>
+# include <accctrl.h>
+#endif
#include <initguid.h>
-#include <accctrl.h>
#include <ctype.h>
#include <limits.h>
-#define SECURITY_WIN32
-#include <security.h>
+#ifndef Q_OS_WINRT
+# define SECURITY_WIN32
+# include <security.h>
+#else // !Q_OS_WINRT
+# include <wrl.h>
+# include <windows.foundation.h>
+# include <windows.storage.h>
+
+using namespace Microsoft::WRL;
+using namespace Microsoft::WRL::Wrappers;
+using namespace ABI::Windows::Foundation;
+using namespace ABI::Windows::Storage;
+#endif // Q_OS_WINRT
#ifndef SPI_GETPLATFORMTYPE
#define SPI_GETPLATFORMTYPE 257
@@ -141,7 +154,7 @@ QT_BEGIN_NAMESPACE
Q_CORE_EXPORT int qt_ntfs_permission_lookup = 0;
-#if defined(Q_OS_WINCE)
+#if defined(Q_OS_WINCE) || defined(Q_OS_WINRT)
static QString qfsPrivateCurrentDir = QLatin1String("");
// As none of the functions we try to resolve do exist on Windows CE
// we use QT_NO_LIBRARY to shorten everything up a little bit.
@@ -289,14 +302,14 @@ static bool resolveUNCLibs()
}
#endif
triedResolve = true;
-#if !defined(Q_OS_WINCE)
+#if !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT)
HINSTANCE hLib = QSystemLibrary::load(L"Netapi32");
if (hLib) {
ptrNetShareEnum = (PtrNetShareEnum)GetProcAddress(hLib, "NetShareEnum");
if (ptrNetShareEnum)
ptrNetApiBufferFree = (PtrNetApiBufferFree)GetProcAddress(hLib, "NetApiBufferFree");
}
-#endif
+#endif // !Q_OS_WINCE && !Q_OS_WINRT
}
return ptrNetShareEnum && ptrNetApiBufferFree;
}
@@ -304,7 +317,7 @@ static bool resolveUNCLibs()
static QString readSymLink(const QFileSystemEntry &link)
{
QString result;
-#if !defined(Q_OS_WINCE)
+#if !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT)
HANDLE handle = CreateFile((wchar_t*)link.nativeFilePath().utf16(),
FILE_READ_EA,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
@@ -347,11 +360,11 @@ static QString readSymLink(const QFileSystemEntry &link)
result.replace(0,matchVolName.matchedLength(), QString::fromWCharArray(buffer));
}
}
-#endif
+#endif // !Q_OS_WINCE && !Q_OS_WINRT
}
#else
Q_UNUSED(link);
-#endif // Q_OS_WINCE
+#endif // Q_OS_WINCE || Q_OS_WINRT
return result;
}
@@ -432,7 +445,11 @@ static inline bool getFindData(QString path, WIN32_FIND_DATA &findData)
// can't handle drives
if (!path.endsWith(QLatin1Char(':'))) {
+#ifndef Q_OS_WINRT
HANDLE hFind = ::FindFirstFile((wchar_t*)path.utf16(), &findData);
+#else
+ HANDLE hFind = ::FindFirstFileEx((const wchar_t*)path.utf16(), FindExInfoStandard, &findData, FindExSearchNameMatch, NULL, 0);
+#endif
if (hFind != INVALID_HANDLE_VALUE) {
::FindClose(hFind);
return true;
@@ -506,7 +523,7 @@ QString QFileSystemEngine::nativeAbsoluteFilePath(const QString &path)
{
// can be //server or //server/share
QString absPath;
-#if !defined(Q_OS_WINCE)
+#if !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT)
QVarLengthArray<wchar_t, MAX_PATH> buf(qMax(MAX_PATH, path.size() + 1));
wchar_t *fileName = 0;
DWORD retLen = GetFullPathName((wchar_t*)path.utf16(), buf.size(), buf.data(), &fileName);
@@ -516,12 +533,17 @@ QString QFileSystemEngine::nativeAbsoluteFilePath(const QString &path)
}
if (retLen != 0)
absPath = QString::fromWCharArray(buf.data(), retLen);
-#else
+#elif !defined(Q_OS_WINCE)
+ if (QDir::isRelativePath(path))
+ absPath = QDir::toNativeSeparators(QDir::cleanPath(QDir::currentPath() + QLatin1Char('/') + path));
+ else
+ absPath = QDir::toNativeSeparators(QDir::cleanPath(path));
+#else // Q_OS_WINRT
if (path.startsWith(QLatin1Char('/')) || path.startsWith(QLatin1Char('\\')))
absPath = QDir::toNativeSeparators(path);
else
absPath = QDir::toNativeSeparators(QDir::cleanPath(qfsPrivateCurrentDir + QLatin1Char('/') + path));
-#endif
+#endif // Q_OS_WINCE
// This is really ugly, but GetFullPathName strips off whitespace at the end.
// If you for instance write ". " in the lineedit of QFileDialog,
// (which is an invalid filename) this function will strip the space off and viola,
@@ -548,9 +570,17 @@ QFileSystemEntry QFileSystemEngine::absoluteName(const QFileSystemEntry &entry)
ret = entry.filePath();
#endif
} else {
+#ifndef Q_OS_WINRT
ret = QDir::cleanPath(QDir::currentPath() + QLatin1Char('/') + entry.filePath());
+#else
+ // Some WinRT APIs do not support absolute paths (due to sandboxing).
+ // Thus the port uses the executable's directory as its root directory
+ // and treats paths relative to that as absolute paths.
+ ret = QDir::cleanPath(QDir::current().relativeFilePath(entry.filePath()));
+#endif
}
+#ifndef Q_OS_WINRT
// The path should be absolute at this point.
// From the docs :
// Absolute paths begin with the directory separator "/"
@@ -563,6 +593,7 @@ QFileSystemEntry QFileSystemEngine::absoluteName(const QFileSystemEntry &entry)
// Force uppercase drive letters.
ret[0] = ret.at(0).toUpper();
}
+#endif // !Q_OS_WINRT
return QFileSystemEntry(ret, QFileSystemEntry::FromInternalPath());
}
@@ -590,18 +621,24 @@ typedef struct _FILE_ID_INFO {
static inline QByteArray fileId(HANDLE handle)
{
QByteArray result;
+#ifndef Q_OS_WINRT
BY_HANDLE_FILE_INFORMATION info;
if (GetFileInformationByHandle(handle, &info)) {
result = QByteArray::number(uint(info.nFileIndexLow), 16);
result += ':';
result += QByteArray::number(uint(info.nFileIndexHigh), 16);
}
+#else // !Q_OS_WINRT
+ Q_UNUSED(handle);
+ Q_UNIMPLEMENTED();
+#endif // Q_OS_WINRT
return result;
}
// File ID for Windows starting from version 8.
QByteArray fileIdWin8(HANDLE handle)
{
+#ifndef Q_OS_WINRT
typedef BOOL (WINAPI* GetFileInformationByHandleExType)(HANDLE, Q_FILE_INFO_BY_HANDLE_CLASS, void *, DWORD);
// Dynamically resolve GetFileInformationByHandleEx (Vista onwards).
@@ -621,6 +658,16 @@ QByteArray fileIdWin8(HANDLE handle)
result += QByteArray((char *)&infoEx.FileId, sizeof(infoEx.FileId)).toHex();
}
}
+#else // !Q_OS_WINRT
+ QByteArray result;
+ FILE_ID_INFO infoEx;
+ if (GetFileInformationByHandleEx(handle, FileIdInfo,
+ &infoEx, sizeof(FILE_ID_INFO))) {
+ result = QByteArray::number(infoEx.VolumeSerialNumber, 16);
+ result += ':';
+ result += QByteArray((char *)infoEx.FileId.Identifier, sizeof(infoEx.FileId.Identifier)).toHex();
+ }
+#endif // Q_OS_WINRT
return result;
}
#endif // !Q_OS_WINCE
@@ -631,8 +678,13 @@ QByteArray QFileSystemEngine::id(const QFileSystemEntry &entry)
#ifndef Q_OS_WINCE
QByteArray result;
const HANDLE handle =
+#ifndef Q_OS_WINRT
CreateFile((wchar_t*)entry.nativeFilePath().utf16(), GENERIC_READ,
FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+#else // !Q_OS_WINRT
+ CreateFile2((const wchar_t*)entry.nativeFilePath().utf16(), GENERIC_READ,
+ FILE_SHARE_READ, OPEN_EXISTING, NULL);
+#endif // Q_OS_WINRT
if (handle) {
result = QSysInfo::windowsVersion() >= QSysInfo::WV_WINDOWS8 ?
fileIdWin8(handle) : fileId(handle);
@@ -810,7 +862,7 @@ static bool tryDriveUNCFallback(const QFileSystemEntry &fname, QFileSystemMetaDa
{
bool entryExists = false;
DWORD fileAttrib = 0;
-#if !defined(Q_OS_WINCE)
+#if !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT)
if (fname.isDriveRoot()) {
// a valid drive ??
DWORD drivesBitmask = ::GetLogicalDrives();
@@ -851,7 +903,7 @@ static bool tryDriveUNCFallback(const QFileSystemEntry &fname, QFileSystemMetaDa
fileAttrib = FILE_ATTRIBUTE_DIRECTORY;
entryExists = true;
}
-#if !defined(Q_OS_WINCE)
+#if !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT)
}
#endif
if (entryExists)
@@ -894,12 +946,27 @@ bool QFileSystemEngine::fillMetaData(HANDLE fHandle, QFileSystemMetaData &data,
{
data.entryFlags &= ~what;
clearWinStatData(data);
+#ifndef Q_OS_WINRT
BY_HANDLE_FILE_INFORMATION fileInfo;
UINT oldmode = SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
if (GetFileInformationByHandle(fHandle , &fileInfo)) {
data.fillFromFindInfo(fileInfo);
}
SetErrorMode(oldmode);
+#else // !Q_OS_WINRT
+ FILE_FULL_DIR_INFO fileInfo;
+ if (GetFileInformationByHandleEx(fHandle, FileFullDirectoryInfo, &fileInfo, sizeof(fileInfo))) {
+ data.fillFromFileAttribute(fileInfo.FileAttributes);
+ data.creationTime_.dwHighDateTime = fileInfo.CreationTime.HighPart;
+ data.creationTime_.dwLowDateTime = fileInfo.CreationTime.LowPart;
+ data.lastAccessTime_.dwHighDateTime = fileInfo.LastAccessTime.HighPart;
+ data.lastAccessTime_.dwLowDateTime = fileInfo.LastAccessTime.LowPart;
+ data.lastWriteTime_.dwHighDateTime = fileInfo.LastWriteTime.HighPart;
+ data.lastWriteTime_.dwLowDateTime = fileInfo.LastWriteTime.LowPart;
+ data.fileAttribute_ & FILE_ATTRIBUTE_DIRECTORY ? data.size_ = 0 : data.size_ = fileInfo.AllocationSize.QuadPart;
+ data.knownFlagsMask |= data.Times | data.SizeAttribute;
+ }
+#endif // Q_OS_WINRT
return data.hasFlags(what);
}
@@ -931,7 +998,9 @@ bool QFileSystemEngine::fillMetaData(const QFileSystemEntry &entry, QFileSystemM
}
if (what & QFileSystemMetaData::WinStatFlags) {
+#ifndef Q_OS_WINRT
UINT oldmode = SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
+#endif
clearWinStatData(data);
WIN32_FIND_DATA findData;
// The memory structure for WIN32_FIND_DATA is same as WIN32_FILE_ATTRIBUTE_DATA
@@ -943,11 +1012,15 @@ bool QFileSystemEngine::fillMetaData(const QFileSystemEntry &entry, QFileSystemM
} else {
if (!tryFindFallback(fname, data))
if (!tryDriveUNCFallback(fname, data)) {
+#ifndef Q_OS_WINRT
SetErrorMode(oldmode);
+#endif
return false;
}
}
+#ifndef Q_OS_WINRT
SetErrorMode(oldmode);
+#endif
}
if (what & QFileSystemMetaData::Permissions)
@@ -1000,7 +1073,14 @@ static bool isDirPath(const QString &dirPath, bool *existed)
if (path.length() == 2 && path.at(1) == QLatin1Char(':'))
path += QLatin1Char('\\');
+#ifndef Q_OS_WINRT
DWORD fileAttrib = ::GetFileAttributes((wchar_t*)QFSFileEnginePrivate::longFileName(path).utf16());
+#else // Q_OS_WINRT
+ DWORD fileAttrib = INVALID_FILE_ATTRIBUTES;
+ WIN32_FILE_ATTRIBUTE_DATA data;
+ if (::GetFileAttributesEx((const wchar_t*)QFSFileEnginePrivate::longFileName(path).utf16(), GetFileExInfoStandard, &data))
+ fileAttrib = data.dwFileAttributes;
+#endif // Q_OS_WINRT
if (fileAttrib == INVALID_FILE_ATTRIBUTES) {
int errorCode = GetLastError();
if (errorCode == ERROR_ACCESS_DENIED || errorCode == ERROR_SHARING_VIOLATION) {
@@ -1152,12 +1232,13 @@ QString QFileSystemEngine::homePath()
QString QFileSystemEngine::tempPath()
{
QString ret;
+#ifndef Q_OS_WINRT
wchar_t tempPath[MAX_PATH];
const DWORD len = GetTempPath(MAX_PATH, tempPath);
#ifdef Q_OS_WINCE
if (len)
ret = QString::fromWCharArray(tempPath, len);
-#else
+#else // Q_OS_WINCE
if (len) { // GetTempPath() can return short names, expand.
wchar_t longTempPath[MAX_PATH];
const DWORD longLen = GetLongPathName(tempPath, longTempPath, MAX_PATH);
@@ -1165,12 +1246,33 @@ QString QFileSystemEngine::tempPath()
QString::fromWCharArray(longTempPath, longLen) :
QString::fromWCharArray(tempPath, len);
}
-#endif
+#endif // !Q_OS_WINCE
if (!ret.isEmpty()) {
while (ret.endsWith(QLatin1Char('\\')))
ret.chop(1);
ret = QDir::fromNativeSeparators(ret);
}
+#else // !Q_OS_WINRT
+ // According to http://msdn.microsoft.com/en-us/library/windows/apps/windows.storage.applicationdata.temporaryfolder.aspx
+ // the API is not available on winphone which should cause one of the functions
+ // below to fail
+ ComPtr<IApplicationDataStatics> applicationDataStatics;
+ if (FAILED(GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Storage_ApplicationData).Get(), &applicationDataStatics)))
+ return ret;
+ ComPtr<IApplicationData> applicationData;
+ if (FAILED(applicationDataStatics->get_Current(&applicationData)))
+ return ret;
+ ComPtr<IStorageFolder> tempFolder;
+ if (FAILED(applicationData->get_TemporaryFolder(&tempFolder)))
+ return ret;
+ ComPtr<IStorageItem> tempFolderItem;
+ if (FAILED(tempFolder.As(&tempFolderItem)))
+ return ret;
+ HSTRING path;
+ if (FAILED(tempFolderItem->get_Path(&path)))
+ return ret;
+ ret = QString::fromWCharArray(WindowsGetStringRawBuffer(path, nullptr));
+#endif // Q_OS_WINRT
if (ret.isEmpty()) {
#if !defined(Q_OS_WINCE)
ret = QLatin1String("C:/tmp");
@@ -1189,7 +1291,7 @@ bool QFileSystemEngine::setCurrentPath(const QFileSystemEntry &entry)
if(!(meta.exists() && meta.isDirectory()))
return false;
-#if !defined(Q_OS_WINCE)
+#if !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT)
//TODO: this should really be using nativeFilePath(), but that returns a path in long format \\?\c:\foo
//which causes many problems later on when it's returned through currentPath()
return ::SetCurrentDirectory(reinterpret_cast<const wchar_t*>(QDir::toNativeSeparators(entry.filePath()).utf16())) != 0;
@@ -1202,7 +1304,7 @@ bool QFileSystemEngine::setCurrentPath(const QFileSystemEntry &entry)
QFileSystemEntry QFileSystemEngine::currentPath()
{
QString ret;
-#if !defined(Q_OS_WINCE)
+#if !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT)
DWORD size = 0;
wchar_t currentName[PATH_MAX];
size = ::GetCurrentDirectory(PATH_MAX, currentName);
@@ -1218,13 +1320,13 @@ QFileSystemEntry QFileSystemEngine::currentPath()
}
if (ret.length() >= 2 && ret[1] == QLatin1Char(':'))
ret[0] = ret.at(0).toUpper(); // Force uppercase drive letters.
-#else
+#else // !Q_OS_WINCE && !Q_OS_WINRT
//TODO - a race condition exists when using currentPath / setCurrentPath from multiple threads
if (qfsPrivateCurrentDir.isEmpty())
qfsPrivateCurrentDir = QCoreApplication::applicationDirPath();
ret = qfsPrivateCurrentDir;
-#endif
+#endif // Q_OS_WINCE || Q_OS_WINRT
return QFileSystemEntry(ret, QFileSystemEntry::FromNativePath());
}
@@ -1242,8 +1344,16 @@ bool QFileSystemEngine::createLink(const QFileSystemEntry &source, const QFileSy
//static
bool QFileSystemEngine::copyFile(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error)
{
+#ifndef Q_OS_WINRT
bool ret = ::CopyFile((wchar_t*)source.nativeFilePath().utf16(),
(wchar_t*)target.nativeFilePath().utf16(), true) != 0;
+#else // !Q_OS_WINRT
+ COPYFILE2_EXTENDED_PARAMETERS copyParams = {
+ sizeof(copyParams), COPY_FILE_FAIL_IF_EXISTS, NULL, NULL, NULL
+ };
+ bool ret = ::CopyFile2((const wchar_t*)source.nativeFilePath().utf16(),
+ (const wchar_t*)target.nativeFilePath().utf16(), &copyParams) != 0;
+#endif // Q_OS_WINRT
if(!ret)
error = QSystemError(::GetLastError(), QSystemError::NativeError);
return ret;
@@ -1252,8 +1362,13 @@ bool QFileSystemEngine::copyFile(const QFileSystemEntry &source, const QFileSyst
//static
bool QFileSystemEngine::renameFile(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error)
{
+#ifndef Q_OS_WINRT
bool ret = ::MoveFile((wchar_t*)source.nativeFilePath().utf16(),
(wchar_t*)target.nativeFilePath().utf16()) != 0;
+#else // !Q_OS_WINRT
+ bool ret = ::MoveFileEx((const wchar_t*)source.nativeFilePath().utf16(),
+ (const wchar_t*)target.nativeFilePath().utf16(), 0) != 0;
+#endif // Q_OS_WINRT
if(!ret)
error = QSystemError(::GetLastError(), QSystemError::NativeError);
return ret;