diff options
Diffstat (limited to 'src/corelib/io')
34 files changed, 1002 insertions, 397 deletions
diff --git a/src/corelib/io/io.pri b/src/corelib/io/io.pri index 649493f8b7..3f2f025aeb 100644 --- a/src/corelib/io/io.pri +++ b/src/corelib/io/io.pri @@ -94,7 +94,6 @@ SOURCES += \ io/qloggingregistry.cpp win32 { - SOURCES += io/qsettings_win.cpp SOURCES += io/qfsfileengine_win.cpp SOURCES += io/qlockfile_win.cpp @@ -102,11 +101,12 @@ win32 { HEADERS += io/qfilesystemwatcher_win_p.h SOURCES += io/qfilesystemengine_win.cpp SOURCES += io/qfilesystemiterator_win.cpp - SOURCES += io/qstandardpaths_win.cpp !winrt { + SOURCES += io/qsettings_win.cpp HEADERS += io/qwindowspipewriter_p.h SOURCES += io/qwindowspipewriter.cpp + SOURCES += io/qstandardpaths_win.cpp wince* { SOURCES += io/qprocess_wince.cpp @@ -119,6 +119,8 @@ win32 { io/qwinoverlappedionotifier.cpp \ io/qwindowspipereader.cpp } + } else { + SOURCES += io/qstandardpaths_winrt.cpp } } else:unix|integrity { SOURCES += \ diff --git a/src/corelib/io/qdatastream.cpp b/src/corelib/io/qdatastream.cpp index af5605f8c7..a6fbffee7e 100644 --- a/src/corelib/io/qdatastream.cpp +++ b/src/corelib/io/qdatastream.cpp @@ -251,7 +251,7 @@ QT_BEGIN_NAMESPACE return retVal; enum { - DefaultStreamVersion = QDataStream::Qt_5_2 + DefaultStreamVersion = QDataStream::Qt_5_3 }; /*! @@ -541,6 +541,7 @@ void QDataStream::setByteOrder(ByteOrder bo) \value Qt_5_0 Version 13 (Qt 5.0) \value Qt_5_1 Version 14 (Qt 5.1) \value Qt_5_2 Version 15 (Qt 5.2) + \value Qt_5_3 Same as Qt_5_2 \sa setVersion(), version() */ diff --git a/src/corelib/io/qdatastream.h b/src/corelib/io/qdatastream.h index f107e801b6..28f1d51a12 100644 --- a/src/corelib/io/qdatastream.h +++ b/src/corelib/io/qdatastream.h @@ -87,8 +87,9 @@ public: Qt_4_9 = Qt_4_8, Qt_5_0 = 13, Qt_5_1 = 14, - Qt_5_2 = 15 -#if QT_VERSION >= 0x050300 + Qt_5_2 = 15, + Qt_5_3 = Qt_5_2 +#if QT_VERSION >= 0x050400 #error Add the datastream version for this Qt version #endif }; diff --git a/src/corelib/io/qdebug.h b/src/corelib/io/qdebug.h index 9ed5f6e951..00177b659e 100644 --- a/src/corelib/io/qdebug.h +++ b/src/corelib/io/qdebug.h @@ -80,7 +80,9 @@ public: inline QDebug &operator=(const QDebug &other); inline ~QDebug() { if (!--stream->ref) { - if(stream->message_output) { + if (stream->space && stream->buffer.endsWith(QLatin1Char(' '))) + stream->buffer.chop(1); + if (stream->message_output) { QT_TRY { qt_message_output(stream->type, stream->context, @@ -172,6 +174,7 @@ template <class T> inline QDebug operator<<(QDebug debug, const QList<T> &list) #endif { + const bool oldSetting = debug.autoInsertSpaces(); debug.nospace() << '('; for (typename QList<T>::size_type i = 0; i < list.count(); ++i) { if (i) @@ -179,7 +182,8 @@ inline QDebug operator<<(QDebug debug, const QList<T> &list) debug << list.at(i); } debug << ')'; - return debug.space(); + debug.setAutoInsertSpaces(oldSetting); + return debug.maybeSpace(); } #if defined(FORCE_UREF) @@ -190,7 +194,9 @@ template <typename T> inline QDebug operator<<(QDebug debug, const QVector<T> &vec) #endif { + const bool oldSetting = debug.autoInsertSpaces(); debug.nospace() << "QVector"; + debug.setAutoInsertSpaces(oldSetting); return operator<<(debug, vec.toList()); } @@ -202,13 +208,15 @@ template <class aKey, class aT> inline QDebug operator<<(QDebug debug, const QMap<aKey, aT> &map) #endif { + const bool oldSetting = debug.autoInsertSpaces(); debug.nospace() << "QMap("; for (typename QMap<aKey, aT>::const_iterator it = map.constBegin(); it != map.constEnd(); ++it) { debug << '(' << it.key() << ", " << it.value() << ')'; } debug << ')'; - return debug.space(); + debug.setAutoInsertSpaces(oldSetting); + return debug.maybeSpace(); } #if defined(FORCE_UREF) @@ -219,12 +227,14 @@ template <class aKey, class aT> inline QDebug operator<<(QDebug debug, const QHash<aKey, aT> &hash) #endif { + const bool oldSetting = debug.autoInsertSpaces(); debug.nospace() << "QHash("; for (typename QHash<aKey, aT>::const_iterator it = hash.constBegin(); it != hash.constEnd(); ++it) debug << '(' << it.key() << ", " << it.value() << ')'; debug << ')'; - return debug.space(); + debug.setAutoInsertSpaces(oldSetting); + return debug.maybeSpace(); } #if defined(FORCE_UREF) @@ -235,14 +245,18 @@ template <class T1, class T2> inline QDebug operator<<(QDebug debug, const QPair<T1, T2> &pair) #endif { + const bool oldSetting = debug.autoInsertSpaces(); debug.nospace() << "QPair(" << pair.first << ',' << pair.second << ')'; - return debug.space(); + debug.setAutoInsertSpaces(oldSetting); + return debug.maybeSpace(); } template <typename T> inline QDebug operator<<(QDebug debug, const QSet<T> &set) { + const bool oldSetting = debug.autoInsertSpaces(); debug.nospace() << "QSet"; + debug.setAutoInsertSpaces(oldSetting); return operator<<(debug, set.toList()); } @@ -254,6 +268,7 @@ template <class T> inline QDebug operator<<(QDebug debug, const QContiguousCache<T> &cache) #endif { + const bool oldSetting = debug.autoInsertSpaces(); debug.nospace() << "QContiguousCache("; for (int i = cache.firstIndex(); i <= cache.lastIndex(); ++i) { debug << cache[i]; @@ -261,7 +276,8 @@ inline QDebug operator<<(QDebug debug, const QContiguousCache<T> &cache) debug << ", "; } debug << ')'; - return debug.space(); + debug.setAutoInsertSpaces(oldSetting); + return debug.maybeSpace(); } #if defined(FORCE_UREF) @@ -272,6 +288,7 @@ template <class T> inline QDebug operator<<(QDebug debug, const QFlags<T> &flags) #endif { + const bool oldSetting = debug.autoInsertSpaces(); debug.nospace() << "QFlags("; bool needSeparator = false; for (uint i = 0; i < sizeof(T) * 8; ++i) { @@ -284,7 +301,8 @@ inline QDebug operator<<(QDebug debug, const QFlags<T> &flags) } } debug << ')'; - return debug.space(); + debug.setAutoInsertSpaces(oldSetting); + return debug.maybeSpace(); } QT_END_NAMESPACE diff --git a/src/corelib/io/qdir.cpp b/src/corelib/io/qdir.cpp index 015f4cfe14..3075e0fb12 100644 --- a/src/corelib/io/qdir.cpp +++ b/src/corelib/io/qdir.cpp @@ -2144,7 +2144,7 @@ QString QDir::cleanPath(const QString &path) name.replace(dir_separator, QLatin1Char('/')); bool allowUncPaths = false; -#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) //allow unc paths +#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) //allow unc paths allowUncPaths = true; #endif diff --git a/src/corelib/io/qdiriterator.cpp b/src/corelib/io/qdiriterator.cpp index 5b48c4c7db..79cdec9674 100644 --- a/src/corelib/io/qdiriterator.cpp +++ b/src/corelib/io/qdiriterator.cpp @@ -477,7 +477,7 @@ QDirIterator::~QDirIterator() /*! Advances the iterator to the next entry, and returns the file path of this new entry. If hasNext() returns \c false, this function does nothing, and - returns a null QString. + returns an empty QString. You can call fileName() or filePath() to get the current entry file name or path, or fileInfo() to get a QFileInfo for the current entry. diff --git a/src/corelib/io/qfilesystemengine_win.cpp b/src/corelib/io/qfilesystemengine_win.cpp index 257f18a6bb..dbc6d28846 100644 --- a/src/corelib/io/qfilesystemengine_win.cpp +++ b/src/corelib/io/qfilesystemengine_win.cpp @@ -63,13 +63,28 @@ # 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> +# include <Windows.ApplicationModel.h> + +using namespace Microsoft::WRL; +using namespace Microsoft::WRL::Wrappers; +using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::Storage; +using namespace ABI::Windows::ApplicationModel; +#endif // Q_OS_WINRT #ifndef SPI_GETPLATFORMTYPE #define SPI_GETPLATFORMTYPE 257 @@ -141,7 +156,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 +304,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 +319,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 +362,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 +447,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 +525,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 +535,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 +572,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 +595,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 +623,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 +660,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 +680,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 +864,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 +905,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 +948,32 @@ 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_BASIC_INFO fileBasicInfo; + if (GetFileInformationByHandleEx(fHandle, FileBasicInfo, &fileBasicInfo, sizeof(fileBasicInfo))) { + data.fillFromFileAttribute(fileBasicInfo.FileAttributes); + data.creationTime_.dwHighDateTime = fileBasicInfo.CreationTime.HighPart; + data.creationTime_.dwLowDateTime = fileBasicInfo.CreationTime.LowPart; + data.lastAccessTime_.dwHighDateTime = fileBasicInfo.LastAccessTime.HighPart; + data.lastAccessTime_.dwLowDateTime = fileBasicInfo.LastAccessTime.LowPart; + data.lastWriteTime_.dwHighDateTime = fileBasicInfo.LastWriteTime.HighPart; + data.lastWriteTime_.dwLowDateTime = fileBasicInfo.LastWriteTime.LowPart; + if (!(data.fileAttribute_ & FILE_ATTRIBUTE_DIRECTORY)) { + FILE_STANDARD_INFO fileStandardInfo; + if (GetFileInformationByHandleEx(fHandle, FileStandardInfo, &fileStandardInfo, sizeof(fileStandardInfo))) + data.size_ = fileStandardInfo.EndOfFile.QuadPart; + } else + data.size_ = 0; + data.knownFlagsMask |= QFileSystemMetaData::Times | QFileSystemMetaData::SizeAttribute; + } +#endif // Q_OS_WINRT return data.hasFlags(what); } @@ -931,7 +1005,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 +1019,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) @@ -1006,7 +1086,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) { @@ -1100,6 +1187,30 @@ QString QFileSystemEngine::rootPath() { #if defined(Q_OS_WINCE) QString ret = QLatin1String("/"); +#elif defined(Q_OS_WINRT) + // We specify the package root as root directory + QString ret = QLatin1String("/"); + // Get package location + ComPtr<IPackageStatics> statics; + if (FAILED(GetActivationFactory(HStringReference(RuntimeClass_Windows_ApplicationModel_Package).Get(), &statics))) + return ret; + ComPtr<IPackage> package; + if (FAILED(statics->get_Current(&package))) + return ret; + ComPtr<IStorageFolder> installedLocation; + if (FAILED(package->get_InstalledLocation(&installedLocation))) + return ret; + + ComPtr<IStorageItem> item; + if (FAILED(installedLocation.As(&item))) + return ret; + + HSTRING finalWinPath; + if (FAILED(item->get_Path(&finalWinPath))) + return ret; + + ret = QDir::fromNativeSeparators(QString::fromWCharArray(WindowsGetStringRawBuffer(finalWinPath, nullptr))); + #else QString ret = QString::fromLatin1(qgetenv("SystemDrive").constData()); if (ret.isEmpty()) @@ -1158,12 +1269,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); @@ -1171,12 +1283,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 = QDir::fromNativeSeparators(QString::fromWCharArray(WindowsGetStringRawBuffer(path, nullptr))); +#endif // Q_OS_WINRT if (ret.isEmpty()) { #if !defined(Q_OS_WINCE) ret = QLatin1String("C:/tmp"); @@ -1195,7 +1328,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; @@ -1208,7 +1341,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); @@ -1224,13 +1357,17 @@ 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()) +#ifndef Q_OS_WINRT qfsPrivateCurrentDir = QCoreApplication::applicationDirPath(); +#else + qfsPrivateCurrentDir = QDir::rootPath(); +#endif ret = qfsPrivateCurrentDir; -#endif +#endif // Q_OS_WINCE || Q_OS_WINRT return QFileSystemEntry(ret, QFileSystemEntry::FromNativePath()); } @@ -1248,8 +1385,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(), ©Params) != 0; +#endif // Q_OS_WINRT if(!ret) error = QSystemError(::GetLastError(), QSystemError::NativeError); return ret; @@ -1258,8 +1403,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; diff --git a/src/corelib/io/qfilesystementry.cpp b/src/corelib/io/qfilesystementry.cpp index 3934c6a673..42a724670e 100644 --- a/src/corelib/io/qfilesystementry.cpp +++ b/src/corelib/io/qfilesystementry.cpp @@ -170,6 +170,12 @@ void QFileSystemEntry::resolveNativeFilePath() const #else m_nativeFilePath = QFile::encodeName(QDir::toNativeSeparators(m_filePath)); #endif +#ifdef Q_OS_WINRT + while (m_nativeFilePath.startsWith(QLatin1Char('\\'))) + m_nativeFilePath.remove(0,1); + if (m_nativeFilePath.isEmpty()) + m_nativeFilePath.append(QLatin1Char('.')); +#endif } } diff --git a/src/corelib/io/qfilesystemiterator_unix.cpp b/src/corelib/io/qfilesystemiterator_unix.cpp index bfedd3f70c..0b59aa169a 100644 --- a/src/corelib/io/qfilesystemiterator_unix.cpp +++ b/src/corelib/io/qfilesystemiterator_unix.cpp @@ -105,8 +105,8 @@ bool QFileSystemIterator::advance(QFileSystemEntry &fileEntry, QFileSystemMetaDa if (!dir) return false; -#if defined(Q_OS_QNX) && defined(__EXT_QNX__READDIR_R) - lastError = _readdir_r(dir, mt_file.data(), &dirEntry, direntSize); +#if defined(Q_OS_QNX) && defined(QT_EXT_QNX_READDIR_R) + lastError = QT_EXT_QNX_READDIR_R(dir, mt_file.data(), &dirEntry, direntSize); if (lastError) return false; #elif defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_CYGWIN) diff --git a/src/corelib/io/qfilesystemiterator_win.cpp b/src/corelib/io/qfilesystemiterator_win.cpp index 90232f7cfc..dda96bd45a 100644 --- a/src/corelib/io/qfilesystemiterator_win.cpp +++ b/src/corelib/io/qfilesystemiterator_win.cpp @@ -39,10 +39,12 @@ ** ****************************************************************************/ -#if _WIN32_WINNT < 0x0500 -#undef _WIN32_WINNT -#define _WIN32_WINNT 0x0500 -#endif +#if !defined(WINAPI_FAMILY) +# if _WIN32_WINNT < 0x0500 +# undef _WIN32_WINNT +# define _WIN32_WINNT 0x0500 +# endif // _WIN32_WINNT < 0x500 +#endif // !WINAPI_FAMILY #include "qfilesystemiterator_p.h" #include "qfilesystemengine_p.h" @@ -73,6 +75,10 @@ QFileSystemIterator::QFileSystemIterator(const QFileSystemEntry &entry, QDir::Fi if (!nativePath.endsWith(QLatin1Char('\\'))) nativePath.append(QLatin1Char('\\')); nativePath.append(QLatin1Char('*')); +#ifdef Q_OS_WINRT + if (nativePath.startsWith(QLatin1Char('\\'))) + nativePath.remove(0, 1); +#endif if (!dirPath.endsWith(QLatin1Char('/'))) dirPath.append(QLatin1Char('/')); if ((filters & (QDir::Dirs|QDir::Drives)) && (!(filters & (QDir::Files)))) diff --git a/src/corelib/io/qfilesystemmetadata_p.h b/src/corelib/io/qfilesystemmetadata_p.h index 1abc9b7ec4..de79ec32d3 100644 --- a/src/corelib/io/qfilesystemmetadata_p.h +++ b/src/corelib/io/qfilesystemmetadata_p.h @@ -219,7 +219,9 @@ public: #if defined(Q_OS_WIN) inline void fillFromFileAttribute(DWORD fileAttribute, bool isDriveRoot = false); inline void fillFromFindData(WIN32_FIND_DATA &findData, bool setLinkType = false, bool isDriveRoot = false); +# ifndef Q_OS_WINRT inline void fillFromFindInfo(BY_HANDLE_FILE_INFORMATION &fileInfo); +# endif #endif private: friend class QFileSystemEngine; @@ -340,6 +342,7 @@ inline void QFileSystemMetaData::fillFromFindData(WIN32_FIND_DATA &findData, boo } } +#ifndef Q_OS_WINRT inline void QFileSystemMetaData::fillFromFindInfo(BY_HANDLE_FILE_INFORMATION &fileInfo) { fillFromFileAttribute(fileInfo.dwFileAttributes); @@ -355,7 +358,8 @@ inline void QFileSystemMetaData::fillFromFindInfo(BY_HANDLE_FILE_INFORMATION &fi } knownFlagsMask |= Times | SizeAttribute; } -#endif +#endif // !Q_OS_WINRT +#endif // Q_OS_WIN QT_END_NAMESPACE diff --git a/src/corelib/io/qfilesystemwatcher_inotify.cpp b/src/corelib/io/qfilesystemwatcher_inotify.cpp index c731f3d417..5fd20c6d74 100644 --- a/src/corelib/io/qfilesystemwatcher_inotify.cpp +++ b/src/corelib/io/qfilesystemwatcher_inotify.cpp @@ -129,9 +129,9 @@ # define __NR_inotify_rm_watch 271 # define __NR_inotify_init1 314 #elif defined (__avr32__) -# define __NR_inotify_init 240 -# define __NR_inotify_add_watch 241 -# define __NR_inotify_rm_watch 242 +# define __NR_inotify_init 240 +# define __NR_inotify_add_watch 241 +# define __NR_inotify_rm_watch 242 // no inotify_init1 for AVR32 #elif defined (__mc68000__) # define __NR_inotify_init 284 diff --git a/src/corelib/io/qfsfileengine_unix.cpp b/src/corelib/io/qfsfileengine_unix.cpp index a5f077bd0b..064a1a511f 100644 --- a/src/corelib/io/qfsfileengine_unix.cpp +++ b/src/corelib/io/qfsfileengine_unix.cpp @@ -45,6 +45,7 @@ #include "private/qcore_unix_p.h" #include "qfilesystementry_p.h" #include "qfilesystemengine_p.h" +#include "qcoreapplication.h" #ifndef QT_NO_FSFILEENGINE @@ -142,6 +143,16 @@ static inline bool setCloseOnExec(int fd) return fd != -1 && fcntl(fd, F_SETFD, FD_CLOEXEC) != -1; } +static inline QString msgOpenDirectory() +{ + const char message[] = QT_TRANSLATE_NOOP("QIODevice", "file to open is a directory"); +#ifndef QT_BOOTSTRAPPED + return QIODevice::tr(message); +#else + return QLatin1String(message); +#endif +} + /*! \internal */ @@ -169,7 +180,7 @@ bool QFSFileEnginePrivate::nativeOpen(QIODevice::OpenMode openMode) // we had received EISDIR anyway. if (QFileSystemEngine::fillMetaData(fd, metaData) && metaData.isDirectory()) { - q->setError(QFile::OpenError, QLatin1String("file to open is a directory")); + q->setError(QFile::OpenError, msgOpenDirectory()); QT_CLOSE(fd); return false; } @@ -210,7 +221,7 @@ bool QFSFileEnginePrivate::nativeOpen(QIODevice::OpenMode openMode) // we had received EISDIR anyway. if (QFileSystemEngine::fillMetaData(QT_FILENO(fh), metaData) && metaData.isDirectory()) { - q->setError(QFile::OpenError, QLatin1String("file to open is a directory")); + q->setError(QFile::OpenError, msgOpenDirectory()); fclose(fh); return false; } diff --git a/src/corelib/io/qfsfileengine_win.cpp b/src/corelib/io/qfsfileengine_win.cpp index 2b38019674..c974daab06 100644 --- a/src/corelib/io/qfsfileengine_win.cpp +++ b/src/corelib/io/qfsfileengine_win.cpp @@ -60,14 +60,18 @@ # 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> #include <stdio.h> -#define SECURITY_WIN32 -#include <security.h> +#ifndef Q_OS_WINRT +# define SECURITY_WIN32 +# include <security.h> +#endif #ifndef PATH_MAX #define PATH_MAX FILENAME_MAX @@ -93,7 +97,7 @@ QString QFSFileEnginePrivate::longFileName(const QString &path) return path; QString absPath = QFileSystemEngine::nativeAbsoluteFilePath(path); -#if !defined(Q_OS_WINCE) +#if !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) QString prefix = QLatin1String("\\\\?\\"); if (isUncPath(absPath)) { prefix.append(QLatin1String("UNC\\")); // "\\\\?\\UNC\\" @@ -121,11 +125,12 @@ bool QFSFileEnginePrivate::nativeOpen(QIODevice::OpenMode openMode) if (openMode & QIODevice::WriteOnly) accessRights |= GENERIC_WRITE; - SECURITY_ATTRIBUTES securityAtts = { sizeof(SECURITY_ATTRIBUTES), NULL, FALSE }; // WriteOnly can create files, ReadOnly cannot. DWORD creationDisp = (openMode & QIODevice::WriteOnly) ? OPEN_ALWAYS : OPEN_EXISTING; // Create the file handle. +#ifndef Q_OS_WINRT + SECURITY_ATTRIBUTES securityAtts = { sizeof(SECURITY_ATTRIBUTES), NULL, FALSE }; fileHandle = CreateFile((const wchar_t*)fileEntry.nativeFilePath().utf16(), accessRights, shareMode, @@ -133,6 +138,13 @@ bool QFSFileEnginePrivate::nativeOpen(QIODevice::OpenMode openMode) creationDisp, FILE_ATTRIBUTE_NORMAL, NULL); +#else // !Q_OS_WINRT + fileHandle = CreateFile2((const wchar_t*)fileEntry.nativeFilePath().utf16(), + accessRights, + shareMode, + creationDisp, + NULL); +#endif // Q_OS_WINRT // Bail out on error. if (fileHandle == INVALID_HANDLE_VALUE) { @@ -473,7 +485,7 @@ int QFSFileEnginePrivate::nativeHandle() const */ bool QFSFileEnginePrivate::nativeIsSequential() const { -#if !defined(Q_OS_WINCE) +#if !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) HANDLE handle = fileHandle; if (fh || fd != -1) handle = (HANDLE)_get_osfhandle(fh ? QT_FILENO(fh) : fd); @@ -577,7 +589,7 @@ bool QFSFileEngine::setCurrentPath(const QString &path) QString QFSFileEngine::currentPath(const QString &fileName) { -#if !defined(Q_OS_WINCE) +#if !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) QString ret; //if filename is a drive: then get the pwd of that drive if (fileName.length() >= 2 && @@ -596,10 +608,10 @@ QString QFSFileEngine::currentPath(const QString &fileName) if (ret.length() >= 2 && ret[1] == QLatin1Char(':')) ret[0] = ret.at(0).toUpper(); // Force uppercase drive letters. return ret; -#else +#else // !Q_OS_WINCE && !Q_OS_WINRT Q_UNUSED(fileName); return QFileSystemEngine::currentPath().filePath(); -#endif +#endif // Q_OS_WINCE || Q_OS_WINRT } QString QFSFileEngine::homePath() @@ -620,7 +632,7 @@ QString QFSFileEngine::tempPath() QFileInfoList QFSFileEngine::drives() { QFileInfoList ret; -#if !defined(Q_OS_WINCE) +#if !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) #if defined(Q_OS_WIN32) quint32 driveBits = (quint32) GetLogicalDrives() & 0x3ffffff; #endif @@ -633,10 +645,10 @@ QFileInfoList QFSFileEngine::drives() driveBits = driveBits >> 1; } return ret; -#else +#else // !Q_OS_WINCE && !Q_OS_WINRT ret.append(QFileInfo(QLatin1String("/"))); return ret; -#endif +#endif // Q_OS_WINCE || Q_OS_WINRT } bool QFSFileEnginePrivate::doStat(QFileSystemMetaData::MetaDataFlags flags) const @@ -661,7 +673,7 @@ bool QFSFileEnginePrivate::doStat(QFileSystemMetaData::MetaDataFlags flags) cons bool QFSFileEngine::link(const QString &newName) { -#if !defined(Q_OS_WINCE) +#if !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) #if !defined(QT_NO_LIBRARY) bool ret = false; @@ -707,7 +719,7 @@ bool QFSFileEngine::link(const QString &newName) Q_UNUSED(newName); return false; #endif // QT_NO_LIBRARY -#else +#elif defined(Q_OS_WINCE) QString linkName = newName; linkName.replace(QLatin1Char('/'), QLatin1Char('\\')); if (!linkName.endsWith(QLatin1String(".lnk"))) @@ -720,7 +732,11 @@ bool QFSFileEngine::link(const QString &newName) if (!ret) setError(QFile::RenameError, qt_error_string()); return ret; -#endif // Q_OS_WINCE +#else // Q_OS_WINCE + Q_UNUSED(newName); + Q_UNIMPLEMENTED(); + return false; +#endif // Q_OS_WINRT } /*! @@ -937,6 +953,7 @@ QDateTime QFSFileEngine::fileTime(FileTime time) const uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, QFile::MemoryMapFlags flags) { +#ifndef Q_OS_WINPHONE Q_Q(QFSFileEngine); Q_UNUSED(flags); if (openMode == QFile::NotOpen) { @@ -980,7 +997,11 @@ uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, // first create the file mapping handle DWORD protection = (openMode & QIODevice::WriteOnly) ? PAGE_READWRITE : PAGE_READONLY; +#ifndef Q_OS_WINRT mapHandle = ::CreateFileMapping(handle, 0, protection, 0, 0, 0); +#else + mapHandle = ::CreateFileMappingFromApp(handle, 0, protection, 0, 0); +#endif if (mapHandle == NULL) { q->setError(QFile::PermissionsError, qt_error_string()); #ifdef Q_USE_DEPRECATED_MAP_API @@ -998,15 +1019,23 @@ uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, DWORD offsetHi = offset >> 32; DWORD offsetLo = offset & Q_UINT64_C(0xffffffff); SYSTEM_INFO sysinfo; +#ifndef Q_OS_WINRT ::GetSystemInfo(&sysinfo); +#else + ::GetNativeSystemInfo(&sysinfo); +#endif DWORD mask = sysinfo.dwAllocationGranularity - 1; DWORD extra = offset & mask; if (extra) offsetLo &= ~mask; // attempt to create the map +#ifndef Q_OS_WINRT LPVOID mapAddress = ::MapViewOfFile(mapHandle, access, offsetHi, offsetLo, size + extra); +#else + LPVOID mapAddress = ::MapViewOfFileFromApp(mapHandle, access, offset, size); +#endif if (mapAddress) { uchar *address = extra + static_cast<uchar*>(mapAddress); maps[address] = extra; @@ -1025,11 +1054,18 @@ uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, ::CloseHandle(mapHandle); mapHandle = NULL; +#else // !Q_OS_WINPHONE + Q_UNUSED(offset); + Q_UNUSED(size); + Q_UNUSED(flags); + Q_UNIMPLEMENTED(); +#endif // Q_OS_WINPHONE return 0; } bool QFSFileEnginePrivate::unmap(uchar *ptr) { +#ifndef Q_OS_WINPHONE Q_Q(QFSFileEngine); if (!maps.contains(ptr)) { q->setError(QFile::PermissionsError, qt_error_string(ERROR_ACCESS_DENIED)); @@ -1048,6 +1084,11 @@ bool QFSFileEnginePrivate::unmap(uchar *ptr) } return true; +#else // !Q_OS_WINPHONE + Q_UNUSED(ptr); + Q_UNIMPLEMENTED(); + return false; +#endif // Q_OS_WINPHONE } QT_END_NAMESPACE diff --git a/src/corelib/io/qlockfile_win.cpp b/src/corelib/io/qlockfile_win.cpp index b5f6d9f3da..28f6b02a64 100644 --- a/src/corelib/io/qlockfile_win.cpp +++ b/src/corelib/io/qlockfile_win.cpp @@ -52,7 +52,6 @@ QT_BEGIN_NAMESPACE QLockFile::LockError QLockFilePrivate::tryLock_sys() { - SECURITY_ATTRIBUTES securityAtts = { sizeof(SECURITY_ATTRIBUTES), NULL, FALSE }; const QFileSystemEntry fileEntry(fileName); // When writing, allow others to read. // When reading, QFile will allow others to read and write, all good. @@ -60,6 +59,8 @@ QLockFile::LockError QLockFilePrivate::tryLock_sys() // but Windows doesn't allow recreating it while this handle is open anyway, // so this would only create confusion (can't lock, but no lock file to read from). const DWORD dwShareMode = FILE_SHARE_READ; +#ifndef Q_OS_WINRT + SECURITY_ATTRIBUTES securityAtts = { sizeof(SECURITY_ATTRIBUTES), NULL, FALSE }; HANDLE fh = CreateFile((const wchar_t*)fileEntry.nativeFilePath().utf16(), GENERIC_WRITE, dwShareMode, @@ -67,6 +68,13 @@ QLockFile::LockError QLockFilePrivate::tryLock_sys() CREATE_NEW, // error if already exists FILE_ATTRIBUTE_NORMAL, NULL); +#else // !Q_OS_WINRT + HANDLE fh = CreateFile2((const wchar_t*)fileEntry.nativeFilePath().utf16(), + GENERIC_WRITE, + dwShareMode, + CREATE_NEW, // error if already exists + NULL); +#endif // Q_OS_WINRT if (fh == INVALID_HANDLE_VALUE) { const DWORD lastError = GetLastError(); switch (lastError) { @@ -112,6 +120,9 @@ bool QLockFilePrivate::isApparentlyStale() const if (!getLockInfo(&pid, &hostname, &appname)) return false; + // On WinRT there seems to be no way of obtaining information about other + // processes due to sandboxing +#ifndef Q_OS_WINRT HANDLE procHandle = ::OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid); if (!procHandle) return true; @@ -120,6 +131,7 @@ bool QLockFilePrivate::isApparentlyStale() const ::CloseHandle(procHandle); if (dwR == WAIT_TIMEOUT) return true; +#endif // !Q_OS_WINRT const qint64 age = QFileInfo(fileName).lastModified().msecsTo(QDateTime::currentDateTime()); return staleLockTime > 0 && age > staleLockTime; } diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp index ab2a69d054..483650afcb 100644 --- a/src/corelib/io/qprocess.cpp +++ b/src/corelib/io/qprocess.cpp @@ -2388,14 +2388,14 @@ int QProcess::execute(const QString &program) identifier of the started process. */ bool QProcess::startDetached(const QString &program, - const QStringList &arguments, - const QString &workingDirectory, + const QStringList &arguments, + const QString &workingDirectory, qint64 *pid) { return QProcessPrivate::startDetached(program, - arguments, - workingDirectory, - pid); + arguments, + workingDirectory, + pid); } /*! @@ -2414,7 +2414,7 @@ bool QProcess::startDetached(const QString &program, The started process will run as a regular standalone process. */ bool QProcess::startDetached(const QString &program, - const QStringList &arguments) + const QStringList &arguments) { return QProcessPrivate::startDetached(program, arguments); } diff --git a/src/corelib/io/qprocess_unix.cpp b/src/corelib/io/qprocess_unix.cpp index 3c6d294916..4076ec5855 100644 --- a/src/corelib/io/qprocess_unix.cpp +++ b/src/corelib/io/qprocess_unix.cpp @@ -1107,7 +1107,7 @@ bool QProcessPrivate::waitForStarted(int msecs) #if defined (QPROCESS_DEBUG) qDebug("QProcessPrivate::waitForStarted(%d) waiting for child to start (fd = %d)", msecs, - childStartedPipe[0]); + childStartedPipe[0]); #endif fd_set fds; @@ -1172,32 +1172,32 @@ bool QProcessPrivate::waitForReadyRead(int msecs) if (ret == 0) { processError = QProcess::Timedout; q->setErrorString(QProcess::tr("Process operation timed out")); - return false; - } + return false; + } - if (childStartedPipe[0] != -1 && FD_ISSET(childStartedPipe[0], &fdread)) { + if (childStartedPipe[0] != -1 && FD_ISSET(childStartedPipe[0], &fdread)) { if (!_q_startupNotification()) return false; - } + } bool readyReadEmitted = false; - if (stdoutChannel.pipe[0] != -1 && FD_ISSET(stdoutChannel.pipe[0], &fdread)) { - bool canRead = _q_canReadStandardOutput(); + if (stdoutChannel.pipe[0] != -1 && FD_ISSET(stdoutChannel.pipe[0], &fdread)) { + bool canRead = _q_canReadStandardOutput(); if (processChannel == QProcess::StandardOutput && canRead) readyReadEmitted = true; - } - if (stderrChannel.pipe[0] != -1 && FD_ISSET(stderrChannel.pipe[0], &fdread)) { - bool canRead = _q_canReadStandardError(); + } + if (stderrChannel.pipe[0] != -1 && FD_ISSET(stderrChannel.pipe[0], &fdread)) { + bool canRead = _q_canReadStandardError(); if (processChannel == QProcess::StandardError && canRead) readyReadEmitted = true; - } + } if (readyReadEmitted) return true; - if (stdinChannel.pipe[1] != -1 && FD_ISSET(stdinChannel.pipe[1], &fdwrite)) - _q_canWrite(); + if (stdinChannel.pipe[1] != -1 && FD_ISSET(stdinChannel.pipe[1], &fdwrite)) + _q_canWrite(); - if (deathPipe[0] == -1 || FD_ISSET(deathPipe[0], &fdread)) { + if (deathPipe[0] == -1 || FD_ISSET(deathPipe[0], &fdread)) { if (_q_processDied()) return false; } @@ -1248,26 +1248,26 @@ bool QProcessPrivate::waitForBytesWritten(int msecs) } if (ret == 0) { - processError = QProcess::Timedout; - q->setErrorString(QProcess::tr("Process operation timed out")); - return false; - } + processError = QProcess::Timedout; + q->setErrorString(QProcess::tr("Process operation timed out")); + return false; + } - if (childStartedPipe[0] != -1 && FD_ISSET(childStartedPipe[0], &fdread)) { - if (!_q_startupNotification()) - return false; - } + if (childStartedPipe[0] != -1 && FD_ISSET(childStartedPipe[0], &fdread)) { + if (!_q_startupNotification()) + return false; + } - if (stdinChannel.pipe[1] != -1 && FD_ISSET(stdinChannel.pipe[1], &fdwrite)) - return _q_canWrite(); + if (stdinChannel.pipe[1] != -1 && FD_ISSET(stdinChannel.pipe[1], &fdwrite)) + return _q_canWrite(); - if (stdoutChannel.pipe[0] != -1 && FD_ISSET(stdoutChannel.pipe[0], &fdread)) - _q_canReadStandardOutput(); + if (stdoutChannel.pipe[0] != -1 && FD_ISSET(stdoutChannel.pipe[0], &fdread)) + _q_canReadStandardOutput(); - if (stderrChannel.pipe[0] != -1 && FD_ISSET(stderrChannel.pipe[0], &fdread)) - _q_canReadStandardError(); + if (stderrChannel.pipe[0] != -1 && FD_ISSET(stderrChannel.pipe[0], &fdread)) + _q_canReadStandardError(); - if (deathPipe[0] == -1 || FD_ISSET(deathPipe[0], &fdread)) { + if (deathPipe[0] == -1 || FD_ISSET(deathPipe[0], &fdread)) { if (_q_processDied()) return false; } @@ -1317,29 +1317,29 @@ bool QProcessPrivate::waitForFinished(int msecs) if (ret < 0) { break; } - if (ret == 0) { - processError = QProcess::Timedout; - q->setErrorString(QProcess::tr("Process operation timed out")); - return false; - } - - if (childStartedPipe[0] != -1 && FD_ISSET(childStartedPipe[0], &fdread)) { - if (!_q_startupNotification()) - return false; - } - if (stdinChannel.pipe[1] != -1 && FD_ISSET(stdinChannel.pipe[1], &fdwrite)) - _q_canWrite(); - - if (stdoutChannel.pipe[0] != -1 && FD_ISSET(stdoutChannel.pipe[0], &fdread)) - _q_canReadStandardOutput(); - - if (stderrChannel.pipe[0] != -1 && FD_ISSET(stderrChannel.pipe[0], &fdread)) - _q_canReadStandardError(); - - if (deathPipe[0] == -1 || FD_ISSET(deathPipe[0], &fdread)) { + if (ret == 0) { + processError = QProcess::Timedout; + q->setErrorString(QProcess::tr("Process operation timed out")); + return false; + } + + if (childStartedPipe[0] != -1 && FD_ISSET(childStartedPipe[0], &fdread)) { + if (!_q_startupNotification()) + return false; + } + if (stdinChannel.pipe[1] != -1 && FD_ISSET(stdinChannel.pipe[1], &fdwrite)) + _q_canWrite(); + + if (stdoutChannel.pipe[0] != -1 && FD_ISSET(stdoutChannel.pipe[0], &fdread)) + _q_canReadStandardOutput(); + + if (stderrChannel.pipe[0] != -1 && FD_ISSET(stderrChannel.pipe[0], &fdread)) + _q_canReadStandardError(); + + if (deathPipe[0] == -1 || FD_ISSET(deathPipe[0], &fdread)) { if (_q_processDied()) return true; - } + } } return false; } diff --git a/src/corelib/io/qprocess_win.cpp b/src/corelib/io/qprocess_win.cpp index fc2adb783e..d7050034bd 100644 --- a/src/corelib/io/qprocess_win.cpp +++ b/src/corelib/io/qprocess_win.cpp @@ -623,7 +623,7 @@ static BOOL QT_WIN_CALLBACK qt_terminateApp(HWND hwnd, LPARAM procId) DWORD currentProcId = 0; GetWindowThreadProcessId(hwnd, ¤tProcId); if (currentProcId == (DWORD)procId) - PostMessage(hwnd, WM_CLOSE, 0, 0); + PostMessage(hwnd, WM_CLOSE, 0, 0); return TRUE; } diff --git a/src/corelib/io/qresource.cpp b/src/corelib/io/qresource.cpp index c16b8d79a2..bfd0eef64f 100644 --- a/src/corelib/io/qresource.cpp +++ b/src/corelib/io/qresource.cpp @@ -1092,8 +1092,8 @@ QResource::unregisterResource(const QString &rccFilename, const QString &resourc for(int i = 0; i < list->size(); ++i) { QResourceRoot *res = list->at(i); if(res->type() == QResourceRoot::Resource_File) { - QDynamicFileResourceRoot *root = reinterpret_cast<QDynamicFileResourceRoot*>(res); - if(root->mappingFile() == rccFilename && root->mappingRoot() == r) { + QDynamicFileResourceRoot *root = reinterpret_cast<QDynamicFileResourceRoot*>(res); + if (root->mappingFile() == rccFilename && root->mappingRoot() == r) { resourceList()->removeAt(i); if(!root->ref.deref()) { delete root; @@ -1101,7 +1101,7 @@ QResource::unregisterResource(const QString &rccFilename, const QString &resourc } return false; } - } + } } return false; } @@ -1163,16 +1163,16 @@ QResource::unregisterResource(const uchar *rccData, const QString &resourceRoot) for(int i = 0; i < list->size(); ++i) { QResourceRoot *res = list->at(i); if(res->type() == QResourceRoot::Resource_Buffer) { - QDynamicBufferResourceRoot *root = reinterpret_cast<QDynamicBufferResourceRoot*>(res); - if(root->mappingBuffer() == rccData && root->mappingRoot() == r) { + QDynamicBufferResourceRoot *root = reinterpret_cast<QDynamicBufferResourceRoot*>(res); + if (root->mappingBuffer() == rccData && root->mappingRoot() == r) { resourceList()->removeAt(i); if(!root->ref.deref()) { delete root; return true; } - return false; + return false; } - } + } } return false; } @@ -1381,13 +1381,13 @@ QString QResourceFileEngine::fileName(FileName file) const { Q_D(const QResourceFileEngine); if(file == BaseName) { - int slash = d->resource.fileName().lastIndexOf(QLatin1Char('/')); - if (slash == -1) - return d->resource.fileName(); - return d->resource.fileName().mid(slash + 1); + int slash = d->resource.fileName().lastIndexOf(QLatin1Char('/')); + if (slash == -1) + return d->resource.fileName(); + return d->resource.fileName().mid(slash + 1); } else if(file == PathName || file == AbsolutePathName) { const QString path = (file == AbsolutePathName) ? d->resource.absoluteFilePath() : d->resource.fileName(); - const int slash = path.lastIndexOf(QLatin1Char('/')); + const int slash = path.lastIndexOf(QLatin1Char('/')); if (slash == -1) return QLatin1String(":"); else if (slash <= 1) diff --git a/src/corelib/io/qsettings.cpp b/src/corelib/io/qsettings.cpp index 35b3ed4e3d..a3727a6a4b 100644 --- a/src/corelib/io/qsettings.cpp +++ b/src/corelib/io/qsettings.cpp @@ -78,14 +78,27 @@ #ifdef Q_OS_WIN // for homedirpath reading from registry # include <private/qsystemlibrary_p.h> # include <qt_windows.h> +# ifndef Q_OS_WINRT +# include <shlobj.h> +# endif +#endif + +#ifdef 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 #ifndef CSIDL_COMMON_APPDATA -#define CSIDL_COMMON_APPDATA 0x0023 // All Users\Application Data +#define CSIDL_COMMON_APPDATA 0x0023 // All Users\Application Data #endif #ifndef CSIDL_APPDATA -#define CSIDL_APPDATA 0x001a // <username>\Application Data +#define CSIDL_APPDATA 0x001a // <username>\Application Data #endif #ifdef Q_AUTOTEST_EXPORT @@ -365,7 +378,7 @@ after_loop: // see also qsettings_win.cpp and qsettings_mac.cpp -#if !defined(Q_OS_WIN) && !defined(Q_OS_MAC) +#if defined(Q_OS_WINRT) || (!defined(Q_OS_WIN) && !defined(Q_OS_MAC)) QSettingsPrivate *QSettingsPrivate::create(QSettings::Format format, QSettings::Scope scope, const QString &organization, const QString &application) { @@ -373,7 +386,7 @@ QSettingsPrivate *QSettingsPrivate::create(QSettings::Format format, QSettings:: } #endif -#if !defined(Q_OS_WIN) +#if defined(Q_OS_WINRT) || !defined(Q_OS_WIN) QSettingsPrivate *QSettingsPrivate::create(const QString &fileName, QSettings::Format format) { return new QConfFileSettingsPrivate(fileName, format); @@ -1021,23 +1034,14 @@ void QConfFileSettingsPrivate::initAccess() sync(); // loads the files the first time } -#ifdef Q_OS_WIN +#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) static QString windowsConfigPath(int type) { QString result; -#ifndef Q_OS_WINCE - QSystemLibrary library(QLatin1String("shell32")); -#else - QSystemLibrary library(QLatin1String("coredll")); -#endif // Q_OS_WINCE - typedef BOOL (WINAPI*GetSpecialFolderPath)(HWND, LPWSTR, int, BOOL); - GetSpecialFolderPath SHGetSpecialFolderPath = (GetSpecialFolderPath)library.resolve("SHGetSpecialFolderPathW"); - if (SHGetSpecialFolderPath) { - wchar_t path[MAX_PATH]; - SHGetSpecialFolderPath(0, path, type, false); + wchar_t path[MAX_PATH]; + if (SHGetSpecialFolderPath(0, path, type, false)) result = QString::fromWCharArray(path); - } if (result.isEmpty()) { switch (type) { @@ -1063,7 +1067,40 @@ static QString windowsConfigPath(int type) return result; } -#endif // Q_OS_WIN +#elif defined(Q_OS_WINRT) // Q_OS_WIN && !Q_OS_WINRT +static QString windowsConfigPath(int type) +{ + static QString result; + while (result.isEmpty()) { + ComPtr<IApplicationDataStatics> applicationDataStatics; + if (FAILED(GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Storage_ApplicationData).Get(), &applicationDataStatics))) + return result; + ComPtr<IApplicationData> applicationData; + if (FAILED(applicationDataStatics->get_Current(&applicationData))) + return result; + ComPtr<IStorageFolder> localFolder; + if (FAILED(applicationData->get_LocalFolder(&localFolder))) + return result; + ComPtr<IStorageItem> localFolderItem; + if (FAILED(localFolder.As(&localFolderItem))) + return result; + HSTRING path; + if (FAILED(localFolderItem->get_Path(&path))) + return result; + result = QString::fromWCharArray(WindowsGetStringRawBuffer(path, nullptr)); + } + + switch (type) { + case CSIDL_COMMON_APPDATA: + return result + QLatin1String("\\qt-common"); + case CSIDL_APPDATA: + return result + QLatin1String("\\qt-user"); + default: + break; + } + return result; +} +#endif // Q_OS_WINRT static inline int pathHashKey(QSettings::Format format, QSettings::Scope scope) { @@ -1449,10 +1486,18 @@ void QConfFileSettingsPrivate::syncConfFile(int confFileNo) QString writeSemName = QLatin1String("QSettingsWriteSem "); writeSemName.append(file.fileName()); +#ifndef Q_OS_WINRT writeSemaphore = CreateSemaphore(0, 1, 1, reinterpret_cast<const wchar_t *>(writeSemName.utf16())); +#else + writeSemaphore = CreateSemaphoreEx(0, 1, 1, reinterpret_cast<const wchar_t *>(writeSemName.utf16()), 0, SEMAPHORE_ALL_ACCESS); +#endif if (writeSemaphore) { +#ifndef Q_OS_WINRT WaitForSingleObject(writeSemaphore, INFINITE); +#else + WaitForSingleObjectEx(writeSemaphore, INFINITE, FALSE); +#endif } else { setStatus(QSettings::AccessError); return; @@ -1465,11 +1510,19 @@ void QConfFileSettingsPrivate::syncConfFile(int confFileNo) QString readSemName(QLatin1String("QSettingsReadSem ")); readSemName.append(file.fileName()); +#ifndef Q_OS_WINRT readSemaphore = CreateSemaphore(0, FileLockSemMax, FileLockSemMax, reinterpret_cast<const wchar_t *>(readSemName.utf16())); +#else + readSemaphore = CreateSemaphoreEx(0, FileLockSemMax, FileLockSemMax, reinterpret_cast<const wchar_t *>(readSemName.utf16()), 0, SEMAPHORE_ALL_ACCESS); +#endif if (readSemaphore) { for (int i = 0; i < numReadLocks; ++i) +#ifndef Q_OS_WINRT WaitForSingleObject(readSemaphore, INFINITE); +#else + WaitForSingleObjectEx(readSemaphore, INFINITE, FALSE); +#endif } else { setStatus(QSettings::AccessError); if (writeSemaphore != 0) { diff --git a/src/corelib/io/qsettings.h b/src/corelib/io/qsettings.h index a720b3d709..f44b99d009 100644 --- a/src/corelib/io/qsettings.h +++ b/src/corelib/io/qsettings.h @@ -117,7 +117,7 @@ public: QSettings(Scope scope, const QString &organization, const QString &application = QString(), QObject *parent = 0); QSettings(Format format, Scope scope, const QString &organization, - const QString &application = QString(), QObject *parent = 0); + const QString &application = QString(), QObject *parent = 0); QSettings(const QString &fileName, Format format, QObject *parent = 0); explicit QSettings(QObject *parent = 0); #else diff --git a/src/corelib/io/qstandardpaths.cpp b/src/corelib/io/qstandardpaths.cpp index 2207b8c43e..c145ec4bad 100644 --- a/src/corelib/io/qstandardpaths.cpp +++ b/src/corelib/io/qstandardpaths.cpp @@ -72,34 +72,199 @@ QT_BEGIN_NAMESPACE methods such as QStandardPaths::writableLocation, QStandardPaths::standardLocations, and QStandardPaths::displayName. - \value DesktopLocation Returns the user's desktop directory. - \value DocumentsLocation Returns the user's document. - \value FontsLocation Returns the user's fonts. - \value ApplicationsLocation Returns the user's applications. - \value MusicLocation Returns the user's music. - \value MoviesLocation Returns the user's movies. - \value PicturesLocation Returns the user's pictures. - \value TempLocation Returns the system's temporary directory. - \value HomeLocation Returns the user's home directory. + Some of the values in this enum represent a user configuration. Such enum + values will return the same paths in different applications, so they could + be used to share data with other applications. Other values are specific to + this application. Each enum value in the table below describes whether it's + application-specific or generic. + + Application-specific directories should be assumed to be unreachable by + other applications. Therefore, files placed there might not be readable by + other applications, even if run by the same user. On the other hand, generic + directories should be assumed to be accessible by all applications run by + this user, but should still be assumed to be unreachable by applications by + other users. + + The only exception is QStandardPaths::TempLocation (which is the same as + QDir::tempPath()): the path returned may be application-specific, but files + stored there may be accessed by other applications run by the same user. + + Data interchange with other users is out of the scope of QStandardPaths. + + \value DesktopLocation Returns the user's desktop directory. This is a generic value. + On systems with no concept of a desktop, this is the same as + QStandardPaths::HomeLocation. + \value DocumentsLocation Returns the directory containing user document files. + This is a generic value. The returned path is never empty. + \value FontsLocation Returns the directory containing user's fonts. This is a generic value. + Note that installing fonts may require additional, platform-specific operations. + \value ApplicationsLocation Returns the directory containing the user applications + (either executables, application bundles, or shortcuts to them). This is a generic value. + Note that installing applications may require additional, platform-specific operations. + Files, folders or shortcuts in this directory are platform-specific. + \value MusicLocation Returns the directory containing the user's music or other audio files. + This is a generic value. If no directory specific for music files exists, a sensible + fallback for storing user documents is returned. + \value MoviesLocation Returns the directory containing the user's movies and videos. + This is a generic value. If no directory specific for movie files exists, a sensible + fallback for storing user documents is returned. + \value PicturesLocation Returns the directory containing the user's pictures or photos. + This is a generic value. If no directory specific for picture files exists, a sensible + fallback for storing user documents is returned. + \value TempLocation Returns a directory where temporary files can be stored. The returned value + might be application-specific, shared among other applications for this user, or even + system-wide. The returned path is never empty. + \value HomeLocation Returns the user's home directory (the same as QDir::homePath()). On Unix + systems, this is equal to the HOME environment variable. This value might be + generic or application-specific, but the returned path is never empty. \value DataLocation Returns a directory location where persistent - application data can be stored. QCoreApplication::organizationName - and QCoreApplication::applicationName are appended to the directory location - returned for GenericDataLocation. + application data can be stored. This is an application-specific directory. To obtain a + path to store data to be shared with other applications, use + QStandardPaths::GenericDataLocation. The returned path is never empty. \value CacheLocation Returns a directory location where user-specific - non-essential (cached) data should be written. - \value GenericCacheLocation Returns a directory location where user-specific - non-essential (cached) data, shared across applications, should be written. + non-essential (cached) data should be written. This is an application-specific directory. + The returned path is never empty. + \value GenericCacheLocation Returns a directory location where user-specific non-essential + (cached) data, shared across applications, should be written. This is a generic value. + Note that the returned path may be empty if the system has no concept of shared cache. \value GenericDataLocation Returns a directory location where persistent - data shared across applications can be stored. + data shared across applications can be stored. This is a generic value. The returned + path is never empty. \value RuntimeLocation Returns a directory location where runtime communication - files should be written. For instance unix local sockets. + files should be written, like Unix local sockets. This is a generic value. + The returned path may be empty on some systems. \value ConfigLocation Returns a directory location where user-specific - configuration files should be written. + configuration files should be written. This may be either a generic value + or application-specific, and the returned path is never empty. + \value DownloadLocation Returns a directory for user's downloaded files. This is a generic value. + If no directory specific for downloads exists, a sensible fallback for storing user + documents is returned. \value GenericConfigLocation Returns a directory location where user-specific configuration files shared between multiple applications should be written. This is a generic value and the returned path is never empty. - \value DownloadLocation Returns a directory for user's downloaded files. + The following table gives examples of paths on different operating systems. + The first path is the writable path (unless noted). Other, additional + paths, if any, represent non-writable locations. + + \table + \header \li Path type \li OS X \li Windows + \row \li DesktopLocation + \li "~/Desktop" + \li "C:/Users/<USER>/Desktop" + \row \li DocumentsLocation + \li "~/Documents" + \li "C:/Users/<USER>/Documents" + \row \li FontsLocation + \li "/System/Library/Fonts" (not writable) + \li "C:/Windows/Fonts" (not writable) + \row \li ApplicationsLocation + \li "/Applications" (not writable) + \li "C:/Users/<USER>/AppData/Roaming/Microsoft/Windows/Start Menu/Programs" + \row \li MusicLocation + \li "~/Music" + \li "C:/Users/<USER>/Music" + \row \li MoviesLocation + \li "~/Movies" + \li "C:/Users/<USER>/Videos" + \row \li PicturesLocation + \li "~/Pictures" + \li "C:/Users/<USER>/Pictures" + \row \li TempLocation + \li randomly generated by the OS + \li "C:/Users/<USER>/AppData/Local/Temp" + \row \li HomeLocation + \li "~" + \li "C:/Users/<USER>" + \row \li DataLocation + \li "~/Library/Application Support/<APPNAME>", "/Library/Application Support/<APPNAME>". "<APPDIR>/../Resources" + \li "C:/Users/<USER>/AppData/Local/<APPNAME>", "C:/ProgramData/<APPNAME>", "<APPDIR>", "<APPDIR>/data" + \row \li CacheLocation + \li "~/Library/Caches/<APPNAME>", "/Library/Caches/<APPNAME>" + \li "C:/Users/<USER>/AppData/Local/<APPNAME>/cache" + \row \li GenericDataLocation + \li "~/Library/Application Support", "/Library/Application Support" + \li "C:/Users/<USER>/AppData/Local", "C:/ProgramData" + \row \li RuntimeLocation + \li "~/Library/Application Support" + \li "C:/Users/<USER>" + \row \li ConfigLocation + \li "~/Library/Preferences" + \li "C:/Users/<USER>/AppData/Local/<APPNAME>", "C:/ProgramData/<APPNAME>" + \row \li GenericConfigLocation + \li "~/Library/Preferences" + \li "C:/Users/<USER>/AppData/Local", "C:/ProgramData" + \row \li DownloadLocation + \li "~/Documents" + \li "C:/Users/<USER>/Documents" + \row \li GenericCacheLocation + \li "~/Library/Caches", "/Library/Caches" + \li "C:/Users/<USER>/AppData/Local/cache" + \endtable + + \table + \header \li Path type \li Blackberry \li Linux (including Android) + \row \li DesktopLocation + \li "<APPROOT>/data" + \li "~/Desktop" + \row \li DocumentsLocation + \li "<APPROOT>/shared/documents" + \li "~/Documents" + \row \li FontsLocation + \li "/base/usr/fonts" (not writable) + \li "~/.fonts" + \row \li ApplicationsLocation + \li not supported (directory not readable) + \li "~/.local/share/applications", "/usr/local/share/applications", "/usr/share/applications" + \row \li MusicLocation + \li "<APPROOT>/shared/music" + \li "~/Music" + \row \li MoviesLocation + \li "<APPROOT>/shared/videos" + \li "~/Videos" + \row \li PicturesLocation + \li "<APPROOT>/shared/photos" + \li "~/Pictures" + \row \li TempLocation + \li "/var/tmp" + \li "/tmp" + \row \li HomeLocation + \li "<APPROOT>/data" + \li "~" + \row \li DataLocation + \li "<APPROOT>/data", "<APPROOT>/app/native/assets" + \li "~/.local/share/<APPNAME>", "/usr/local/share/<APPNAME>", "/usr/share/<APPNAME>" + \row \li CacheLocation + \li "<APPROOT>/data/Cache" + \li "~/.cache/<APPNAME>" + \row \li GenericDataLocation + \li "<APPROOT>/shared/misc" + \li "~/.local/share", "/usr/local/share", "/usr/share" + \row \li RuntimeLocation + \li "/var/tmp" + \li "/run/user/<USER>" + \row \li ConfigLocation + \li "<APPROOT>/data/Settings" + \li "~/.config", "/etc/xdg" + \row \li GenericConfigLocation + \li "<APPROOT>/data/Settings" + \li "~/.config", "/etc/xdg" + \row \li DownloadLocation + \li "<APPROOT>/shared/downloads" + \li "~/Downloads" + \row \li GenericCacheLocation + \li "<APPROOT>/data/Cache" (there is no shared cache) + \li "~/.cache" + \endtable + + In the table above, \c <APPNAME> is usually the organization name, the + application name, or both, or a unique name generated at packaging. + Similarly, <APPROOT> is the location where this application is installed + (often a sandbox). <APPDIR> is the directory containing the application + executable. + + The paths above should not be relied upon, as they may change according to + OS configuration, locale, or they may change in future Qt versions. \sa writableLocation(), standardLocations(), displayName(), locate(), locateAll() */ diff --git a/src/corelib/io/qstandardpaths_blackberry.cpp b/src/corelib/io/qstandardpaths_blackberry.cpp index 815756ff9a..ec2e61bd15 100644 --- a/src/corelib/io/qstandardpaths_blackberry.cpp +++ b/src/corelib/io/qstandardpaths_blackberry.cpp @@ -103,10 +103,17 @@ QString QStandardPaths::writableLocation(StandardLocation type) QStringList QStandardPaths::standardLocations(StandardLocation type) { + QStringList dirs; + if (type == FontsLocation) return QStringList(QLatin1String("/base/usr/fonts")); - return QStringList(writableLocation(type)); + if (type == DataLocation) + dirs.append(QDir::homePath() + testModeInsert() + QLatin1String("native/assets")); + + const QString localDir = writableLocation(type); + dirs.prepend(localDir); + return dirs; } QT_END_NAMESPACE diff --git a/src/corelib/io/qstandardpaths_mac.cpp b/src/corelib/io/qstandardpaths_mac.cpp index 0efdfae253..aff9112fb7 100644 --- a/src/corelib/io/qstandardpaths_mac.cpp +++ b/src/corelib/io/qstandardpaths_mac.cpp @@ -47,6 +47,7 @@ #include <qcoreapplication.h> #endif +#include <CoreFoundation/CoreFoundation.h> #include <ApplicationServices/ApplicationServices.h> QT_BEGIN_NAMESPACE @@ -184,6 +185,30 @@ QStringList QStandardPaths::standardLocations(StandardLocation type) dirs.append(path); } + if (type == DataLocation) { + CFBundleRef mainBundle = CFBundleGetMainBundle(); + if (mainBundle) { + CFURLRef bundleUrl = CFBundleCopyBundleURL(mainBundle); + CFStringRef cfBundlePath = CFURLCopyPath(bundleUrl); + QString bundlePath = QCFString::toQString(cfBundlePath); + CFRelease(cfBundlePath); + CFRelease(bundleUrl); + + CFURLRef resourcesUrl = CFBundleCopyResourcesDirectoryURL(mainBundle); + CFStringRef cfResourcesPath = CFURLCopyPath(bundleUrl); + QString resourcesPath = QCFString::toQString(cfResourcesPath); + CFRelease(cfResourcesPath); + CFRelease(resourcesUrl); + + // Handle bundled vs unbundled executables. CFBundleGetMainBundle() returns + // a valid bundle in both cases. CFBundleCopyResourcesDirectoryURL() returns + // an absolute path for unbundled executables. + if (resourcesPath.startsWith(QLatin1Char('/'))) + dirs.append(resourcesPath); + else + dirs.append(bundlePath + resourcesPath); + } + } const QString localDir = writableLocation(type); dirs.prepend(localDir); return dirs; diff --git a/src/corelib/io/qstandardpaths_win.cpp b/src/corelib/io/qstandardpaths_win.cpp index 6a79c7c00b..a0344a0206 100644 --- a/src/corelib/io/qstandardpaths_win.cpp +++ b/src/corelib/io/qstandardpaths_win.cpp @@ -68,21 +68,6 @@ QT_BEGIN_NAMESPACE -typedef BOOL (WINAPI*GetSpecialFolderPath)(HWND, LPWSTR, int, BOOL); -static GetSpecialFolderPath resolveGetSpecialFolderPath() -{ - static GetSpecialFolderPath gsfp = 0; - if (!gsfp) { -#ifndef Q_OS_WINCE - QSystemLibrary library(QLatin1String("shell32")); -#else - QSystemLibrary library(QLatin1String("coredll")); -#endif // Q_OS_WINCE - gsfp = (GetSpecialFolderPath)library.resolve("SHGetSpecialFolderPathW"); - } - return gsfp; -} - static QString convertCharArray(const wchar_t *path) { return QDir::fromNativeSeparators(QString::fromWCharArray(path)); @@ -92,10 +77,6 @@ QString QStandardPaths::writableLocation(StandardLocation type) { QString result; - static GetSpecialFolderPath SHGetSpecialFolderPath = resolveGetSpecialFolderPath(); - if (!SHGetSpecialFolderPath) - return QString(); - wchar_t path[MAX_PATH]; switch (type) { @@ -185,8 +166,7 @@ QStringList QStandardPaths::standardLocations(StandardLocation type) // type-specific handling goes here #ifndef Q_OS_WINCE - static GetSpecialFolderPath SHGetSpecialFolderPath = resolveGetSpecialFolderPath(); - if (SHGetSpecialFolderPath) { + { wchar_t path[MAX_PATH]; switch (type) { case ConfigLocation: // same as DataLocation, on Windows (oversight, but too late to fix it) @@ -204,6 +184,12 @@ QStringList QStandardPaths::standardLocations(StandardLocation type) #endif } dirs.append(result); +#ifndef QT_BOOTSTRAPPED + if (type != GenericDataLocation) { + dirs.append(QCoreApplication::applicationDirPath()); + dirs.append(QCoreApplication::applicationDirPath() + QLatin1String("/data")); + } +#endif } break; default: diff --git a/src/corelib/io/qstandardpaths_winrt.cpp b/src/corelib/io/qstandardpaths_winrt.cpp new file mode 100644 index 0000000000..9b6a088a30 --- /dev/null +++ b/src/corelib/io/qstandardpaths_winrt.cpp @@ -0,0 +1,127 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qstandardpaths.h" + +#include <qdir.h> +#include <private/qsystemlibrary_p.h> +#include <qcoreapplication.h> +#include <qstringlist.h> + +#include <qt_windows.h> + +#include <wrl.h> +#include <windows.foundation.h> +#include <windows.storage.h> +#include <Windows.ApplicationModel.h> + +using namespace Microsoft::WRL; +using namespace Microsoft::WRL::Wrappers; +using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::Storage; +using namespace ABI::Windows::ApplicationModel; + +#ifndef QT_NO_STANDARDPATHS + +QT_BEGIN_NAMESPACE + +static QString convertCharArray(const wchar_t *path) +{ + return QDir::fromNativeSeparators(QString::fromWCharArray(path)); +} + +QString QStandardPaths::writableLocation(StandardLocation type) +{ + QString result; + + switch (type) { + case ConfigLocation: // same as DataLocation, on Windows + case DataLocation: + case GenericDataLocation: { + ComPtr<IApplicationDataStatics> applicationDataStatics; + if (FAILED(GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Storage_ApplicationData).Get(), &applicationDataStatics))) + break; + ComPtr<IApplicationData> applicationData; + if (FAILED(applicationDataStatics->get_Current(&applicationData))) + break; + ComPtr<IStorageFolder> settingsFolder; + if (FAILED(applicationData->get_LocalFolder(&settingsFolder))) + break; + ComPtr<IStorageItem> settingsFolderItem; + if (FAILED(settingsFolder.As(&settingsFolderItem))) + break; + HSTRING path; + if (FAILED(settingsFolderItem->get_Path(&path))) + break; + result = convertCharArray(WindowsGetStringRawBuffer(path, nullptr)); + if (isTestModeEnabled()) + result += QLatin1String("/qttest"); + break; + } + case CacheLocation: + return writableLocation(DataLocation) + QLatin1String("/cache"); + + case GenericCacheLocation: + return writableLocation(GenericDataLocation) + QLatin1String("/cache"); + + case RuntimeLocation: + case HomeLocation: + result = QDir::homePath(); + break; + + case TempLocation: + result = QDir::tempPath(); + break; + default: + Q_UNIMPLEMENTED(); + } + return result; + +} + +QStringList QStandardPaths::standardLocations(StandardLocation type) +{ + return QStringList(writableLocation(type)); +} + +QT_END_NAMESPACE + +#endif // QT_NO_STANDARDPATHS diff --git a/src/corelib/io/qtemporaryfile.cpp b/src/corelib/io/qtemporaryfile.cpp index b3cb4e43f8..3cade0ed25 100644 --- a/src/corelib/io/qtemporaryfile.cpp +++ b/src/corelib/io/qtemporaryfile.cpp @@ -77,7 +77,7 @@ typedef int NativeFileHandle; /* * Copyright (c) 1987, 1993 - * The Regents of the University of California. All rights reserved. + * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -151,18 +151,27 @@ static bool createFileFromTemplate(NativeFileHandle &file, for (;;) { // Atomically create file and obtain handle #if defined(Q_OS_WIN) +# ifndef Q_OS_WINRT file = CreateFile((const wchar_t *)path.constData(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL); +# else // !Q_OS_WINRT + file = CreateFile2((const wchar_t *)path.constData(), + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, CREATE_NEW, + NULL); +# endif // Q_OS_WINRT if (file != INVALID_HANDLE_VALUE) return true; DWORD err = GetLastError(); if (err == ERROR_ACCESS_DENIED) { - DWORD attributes = GetFileAttributes((const wchar_t *)path.constData()); - if (attributes == INVALID_FILE_ATTRIBUTES) { + WIN32_FILE_ATTRIBUTE_DATA attributes; + if (!GetFileAttributesEx((const wchar_t *)path.constData(), + GetFileExInfoStandard, &attributes) + || attributes.dwFileAttributes == INVALID_FILE_ATTRIBUTES) { // Potential write error (read-only parent directory, etc.). error = QSystemError(err, QSystemError::NativeError); return false; @@ -336,7 +345,7 @@ bool QTemporaryFileEngine::open(QIODevice::OpenMode openMode) d->fileEntry = QFileSystemEntry(filename, QFileSystemEntry::FromNativePath()); -#if !defined(Q_OS_WIN) +#if !defined(Q_OS_WIN) || defined(Q_OS_WINRT) d->closeFileHandle = true; #endif diff --git a/src/corelib/io/qurlidna.cpp b/src/corelib/io/qurlidna.cpp index 988d076025..bf2c07e0e0 100644 --- a/src/corelib/io/qurlidna.cpp +++ b/src/corelib/io/qurlidna.cpp @@ -73,7 +73,7 @@ inline bool operator<(const NameprepCaseFoldingEntry &one, uint other) { return one.uc < other; } static const NameprepCaseFoldingEntry NameprepCaseFolding[] = { -/* { 0x0041, { 0x0061, 0x0000, 0x0000, 0x0000 } }, +/* { 0x0041, { 0x0061, 0x0000, 0x0000, 0x0000 } }, { 0x0042, { 0x0062, 0x0000, 0x0000, 0x0000 } }, { 0x0043, { 0x0063, 0x0000, 0x0000, 0x0000 } }, { 0x0044, { 0x0064, 0x0000, 0x0000, 0x0000 } }, diff --git a/src/corelib/io/qurlrecode.cpp b/src/corelib/io/qurlrecode.cpp index 80fc0319fe..74a981b654 100644 --- a/src/corelib/io/qurlrecode.cpp +++ b/src/corelib/io/qurlrecode.cpp @@ -40,6 +40,7 @@ ****************************************************************************/ #include "qurl.h" +#include "private/qutfcodec_p.h" QT_BEGIN_NAMESPACE @@ -232,110 +233,73 @@ static void ensureDetached(QString &result, ushort *&output, const ushort *begin } } -// returns true if we performed an UTF-8 decoding -static bool encodedUtf8ToUtf16(QString &result, ushort *&output, const ushort *begin, const ushort *&input, - const ushort *end, ushort decoded) +namespace { +struct QUrlUtf8Traits : public QUtf8BaseTraitsNoAscii { - int charsNeeded; - uint min_uc; - uint uc; - - if (decoded <= 0xC1) { - // an UTF-8 first character must be at least 0xC0 - // however, all 0xC0 and 0xC1 first bytes can only produce overlong sequences - return false; - } else if (decoded < 0xe0) { - charsNeeded = 2; - min_uc = 0x80; - uc = decoded & 0x1f; - } else if (decoded < 0xf0) { - charsNeeded = 3; - min_uc = 0x800; - uc = decoded & 0x0f; - } else if (decoded < 0xf5) { - charsNeeded = 4; - min_uc = 0x10000; - uc = decoded & 0x07; - } else { - // the last Unicode character is U+10FFFF - // it's encoded in UTF-8 as "\xF4\x8F\xBF\xBF" - // therefore, a byte higher than 0xF4 is not the UTF-8 first byte - return false; + // override: our "bytes" are three percent-encoded UTF-16 characters + static void appendByte(ushort *&ptr, uchar b) + { + // b >= 0x80, by construction, so percent-encode + *ptr++ = '%'; + *ptr++ = encodeNibble(b >> 4); + *ptr++ = encodeNibble(b & 0xf); } - // are there enough remaining? - if (end - input < 3*charsNeeded) - return false; + static uchar peekByte(const ushort *ptr, int n = 0) + { + // decodePercentEncoding returns ushort(-1) if it can't decode, + // which means we return 0xff, which is not a valid continuation byte. + // If ptr[i * 3] is not '%', we'll multiply by zero and return 0, + // also not a valid continuation byte (if it's '%', we multiply by 1). + return uchar(decodePercentEncoding(ptr + n * 3)) + * uchar(ptr[n * 3] == '%'); + } - if (input[3] != '%') - return false; + static qptrdiff availableBytes(const ushort *ptr, const ushort *end) + { + return (end - ptr) / 3; + } - // first continuation character - decoded = decodePercentEncoding(input + 3); - if ((decoded & 0xc0) != 0x80) - return false; - uc <<= 6; - uc |= decoded & 0x3f; - - if (charsNeeded > 2) { - if (input[6] != '%') - return false; - - // second continuation character - decoded = decodePercentEncoding(input + 6); - if ((decoded & 0xc0) != 0x80) - return false; - uc <<= 6; - uc |= decoded & 0x3f; - - if (charsNeeded > 3) { - if (input[9] != '%') - return false; - - // third continuation character - decoded = decodePercentEncoding(input + 9); - if ((decoded & 0xc0) != 0x80) - return false; - uc <<= 6; - uc |= decoded & 0x3f; - } + static void advanceByte(const ushort *&ptr, int n = 1) + { + ptr += n * 3; } +}; +} - // we've decoded something; safety-check it - if (uc < min_uc) - return false; - if (QChar::isSurrogate(uc) || uc > QChar::LastValidCodePoint) +// returns true if we performed an UTF-8 decoding +static bool encodedUtf8ToUtf16(QString &result, ushort *&output, const ushort *begin, const ushort *&input, + const ushort *end, ushort decoded) +{ + uint ucs4, *dst = &ucs4; + const ushort *src = input + 3;// skip the %XX that yielded \a decoded + int charsNeeded = QUtf8Functions::fromUtf8<QUrlUtf8Traits>(decoded, dst, src, end); + if (charsNeeded < 0) return false; - if (!QChar::requiresSurrogates(uc)) { + if (!QChar::requiresSurrogates(ucs4)) { // UTF-8 decoded and no surrogates are required // detach if necessary - ensureDetached(result, output, begin, input, end, -9 * charsNeeded + 1); - *output++ = uc; + // possibilities are: 6 chars (%XX%XX) -> one char; 9 chars (%XX%XX%XX) -> one char + ensureDetached(result, output, begin, input, end, -3 * charsNeeded + 1); + *output++ = ucs4; } else { // UTF-8 decoded to something that requires a surrogate pair - ensureDetached(result, output, begin, input, end, -9 * charsNeeded + 2); - *output++ = QChar::highSurrogate(uc); - *output++ = QChar::lowSurrogate(uc); + // compressing from %XX%XX%XX%XX (12 chars) to two + ensureDetached(result, output, begin, input, end, -10); + *output++ = QChar::highSurrogate(ucs4); + *output++ = QChar::lowSurrogate(ucs4); } - input += charsNeeded * 3 - 1; + + input = src - 1; return true; } static void unicodeToEncodedUtf8(QString &result, ushort *&output, const ushort *begin, const ushort *&input, const ushort *end, ushort decoded) { - uint uc = decoded; - if (QChar::isHighSurrogate(uc)) { - if (input < end && QChar::isLowSurrogate(input[1])) - uc = QChar::surrogateToUcs4(uc, input[1]); - } - - // note: we will encode bad UTF-16 to UTF-8 - // but they don't get decoded back - - // calculate the utf8 length - int utf8len = uc >= 0x10000 ? 4 : uc >= 0x800 ? 3 : 2; + // calculate the utf8 length and ensure enough space is available + int utf8len = QChar::isHighSurrogate(decoded) ? 4 : decoded >= 0x800 ? 3 : 2; // detach if (!output) { @@ -357,50 +321,32 @@ static void unicodeToEncodedUtf8(QString &result, ushort *&output, const ushort } } - // write the sequence - if (uc < 0x800) { - // first of two bytes - uchar c = 0xc0 | uchar(uc >> 6); + ++input; + int res = QUtf8Functions::toUtf8<QUrlUtf8Traits>(decoded, output, input, end); + --input; + if (res < 0) { + // bad surrogate pair sequence + // we will encode bad UTF-16 to UTF-8 + // but they don't get decoded back + + // first of three bytes + uchar c = 0xe0 | uchar(decoded >> 12); *output++ = '%'; - *output++ = encodeNibble(c >> 4); + *output++ = 'E'; *output++ = encodeNibble(c & 0xf); - } else { - uchar c; - if (uc > 0xFFFF) { - // first two of four bytes - c = 0xf0 | uchar(uc >> 18); - *output++ = '%'; - *output++ = 'F'; - *output++ = encodeNibble(c & 0xf); - // continuation byte - c = 0x80 | (uchar(uc >> 12) & 0x3f); - *output++ = '%'; - *output++ = encodeNibble(c >> 4); - *output++ = encodeNibble(c & 0xf); - - // this was a surrogate pair - ++input; - } else { - // first of three bytes - c = 0xe0 | uchar(uc >> 12); - *output++ = '%'; - *output++ = 'E'; - *output++ = encodeNibble(c & 0xf); - } + // second byte + c = 0x80 | (uchar(decoded >> 6) & 0x3f); + *output++ = '%'; + *output++ = encodeNibble(c >> 4); + *output++ = encodeNibble(c & 0xf); - // continuation byte - c = 0x80 | (uchar(uc >> 6) & 0x3f); + // third byte + c = 0x80 | (decoded & 0x3f); *output++ = '%'; *output++ = encodeNibble(c >> 4); *output++ = encodeNibble(c & 0xf); } - - // continuation byte - uchar c = 0x80 | (uc & 0x3f); - *output++ = '%'; - *output++ = encodeNibble(c >> 4); - *output++ = encodeNibble(c & 0xf); } static int recode(QString &result, const ushort *begin, const ushort *end, QUrl::ComponentFormattingOptions encoding, diff --git a/src/corelib/io/qwindowspipereader.cpp b/src/corelib/io/qwindowspipereader.cpp index fc9d191a90..df65aebcff 100644 --- a/src/corelib/io/qwindowspipereader.cpp +++ b/src/corelib/io/qwindowspipereader.cpp @@ -173,7 +173,8 @@ bool QWindowsPipeReader::canReadLine() const \internal Will be called whenever the read operation completes. */ -void QWindowsPipeReader::notified(DWORD numberOfBytesRead, DWORD errorCode, OVERLAPPED *notifiedOverlapped) +void QWindowsPipeReader::notified(quint32 numberOfBytesRead, quint32 errorCode, + OVERLAPPED *notifiedOverlapped) { if (&overlapped != notifiedOverlapped) return; diff --git a/src/corelib/io/qwindowspipereader_p.h b/src/corelib/io/qwindowspipereader_p.h index ea3d3c271f..78ac8eb76d 100644 --- a/src/corelib/io/qwindowspipereader_p.h +++ b/src/corelib/io/qwindowspipereader_p.h @@ -94,7 +94,7 @@ Q_SIGNALS: void pipeClosed(); private Q_SLOTS: - void notified(DWORD numberOfBytesRead, DWORD errorCode, OVERLAPPED *notifiedOverlapped); + void notified(quint32 numberOfBytesRead, quint32 errorCode, OVERLAPPED *notifiedOverlapped); private: bool completeAsyncRead(DWORD bytesRead, DWORD errorCode); diff --git a/src/corelib/io/qwindowspipewriter.cpp b/src/corelib/io/qwindowspipewriter.cpp index 1808081d01..daa8068734 100644 --- a/src/corelib/io/qwindowspipewriter.cpp +++ b/src/corelib/io/qwindowspipewriter.cpp @@ -114,7 +114,7 @@ void QWindowsPipeWriter::run() if (quitNow) { lock.unlock(); quitNow = false; - break; + break; } QByteArray copy = data; @@ -153,7 +153,7 @@ void QWindowsPipeWriter::run() totalWritten += written; #if defined QPIPEWRITER_DEBUG qDebug("QWindowsPipeWriter::run() wrote %d %d/%d bytes", - written, int(totalWritten), int(maxlen)); + written, int(totalWritten), int(maxlen)); #endif lock.lock(); data.remove(0, written); diff --git a/src/corelib/io/qwinoverlappedionotifier.cpp b/src/corelib/io/qwinoverlappedionotifier.cpp index 914264e69e..33583afb78 100644 --- a/src/corelib/io/qwinoverlappedionotifier.cpp +++ b/src/corelib/io/qwinoverlappedionotifier.cpp @@ -43,8 +43,11 @@ #include <qdebug.h> #include <qmutex.h> #include <qpointer.h> +#include <qqueue.h> #include <qset.h> #include <qthread.h> +#include <qt_windows.h> +#include <private/qobject_p.h> QT_BEGIN_NAMESPACE @@ -79,6 +82,46 @@ QT_BEGIN_NAMESPACE \warning This class is only available on Windows. */ +struct IOResult +{ + IOResult(DWORD n = 0, DWORD e = 0, OVERLAPPED *p = 0) + : numberOfBytes(n), errorCode(e), overlapped(p) + {} + + DWORD numberOfBytes; + DWORD errorCode; + OVERLAPPED *overlapped; +}; + + +class QWinIoCompletionPort; + +class QWinOverlappedIoNotifierPrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QWinOverlappedIoNotifier) +public: + QWinOverlappedIoNotifierPrivate() + : hHandle(INVALID_HANDLE_VALUE) + { + } + + void notify(DWORD numberOfBytes, DWORD errorCode, OVERLAPPED *overlapped); + OVERLAPPED *_q_notified(); + + static QWinIoCompletionPort *iocp; + static HANDLE iocpInstanceLock; + static unsigned int iocpInstanceRefCount; + HANDLE hHandle; + HANDLE hSemaphore; + HANDLE hResultsMutex; + QQueue<IOResult> results; +}; + +QWinIoCompletionPort *QWinOverlappedIoNotifierPrivate::iocp = 0; +HANDLE QWinOverlappedIoNotifierPrivate::iocpInstanceLock = CreateMutex(NULL, FALSE, NULL); +unsigned int QWinOverlappedIoNotifierPrivate::iocpInstanceRefCount = 0; + + class QWinIoCompletionPort : protected QThread { public: @@ -109,11 +152,13 @@ public: CloseHandle(hQueueDrainedEvent); } - void registerNotifier(QWinOverlappedIoNotifier *notifier) + void registerNotifier(QWinOverlappedIoNotifierPrivate *notifier) { - HANDLE hIOCP = CreateIoCompletionPort(notifier->hHandle, hPort, reinterpret_cast<ULONG_PTR>(notifier), 0); + const HANDLE hHandle = notifier->hHandle; + HANDLE hIOCP = CreateIoCompletionPort(hHandle, hPort, + reinterpret_cast<ULONG_PTR>(notifier), 0); if (!hIOCP) { - qErrnoWarning("Can't associate file handle %x with I/O completion port.", notifier->hHandle); + qErrnoWarning("Can't associate file handle %x with I/O completion port.", hHandle); return; } mutex.lock(); @@ -123,7 +168,7 @@ public: QThread::start(); } - void unregisterNotifier(QWinOverlappedIoNotifier *notifier) + void unregisterNotifier(QWinOverlappedIoNotifierPrivate *notifier) { mutex.lock(); notifiers.remove(notifier); @@ -176,7 +221,8 @@ protected: continue; } - QWinOverlappedIoNotifier *notifier = reinterpret_cast<QWinOverlappedIoNotifier *>(pulCompletionKey); + QWinOverlappedIoNotifierPrivate *notifier + = reinterpret_cast<QWinOverlappedIoNotifierPrivate *>(pulCompletionKey); mutex.lock(); if (notifiers.contains(notifier)) notifier->notify(dwBytesRead, errorCode, overlapped); @@ -188,57 +234,62 @@ private: const ULONG_PTR finishThreadKey; const ULONG_PTR drainQueueKey; HANDLE hPort; - QSet<QWinOverlappedIoNotifier *> notifiers; + QSet<QWinOverlappedIoNotifierPrivate *> notifiers; QMutex mutex; QMutex drainQueueMutex; HANDLE hQueueDrainedEvent; }; -QWinIoCompletionPort *QWinOverlappedIoNotifier::iocp = 0; -HANDLE QWinOverlappedIoNotifier::iocpInstanceLock = CreateMutex(NULL, FALSE, NULL); -unsigned int QWinOverlappedIoNotifier::iocpInstanceRefCount = 0; QWinOverlappedIoNotifier::QWinOverlappedIoNotifier(QObject *parent) - : QObject(parent), - hHandle(INVALID_HANDLE_VALUE) + : QObject(*new QWinOverlappedIoNotifierPrivate, parent) { - WaitForSingleObject(iocpInstanceLock, INFINITE); - if (!iocp) - iocp = new QWinIoCompletionPort; - iocpInstanceRefCount++; - ReleaseMutex(iocpInstanceLock); - - hSemaphore = CreateSemaphore(NULL, 0, 255, NULL); - hResultsMutex = CreateMutex(NULL, FALSE, NULL); - connect(this, &QWinOverlappedIoNotifier::_q_notify, - this, &QWinOverlappedIoNotifier::_q_notified, Qt::QueuedConnection); + Q_D(QWinOverlappedIoNotifier); + WaitForSingleObject(d->iocpInstanceLock, INFINITE); + if (!d->iocp) + d->iocp = new QWinIoCompletionPort; + d->iocpInstanceRefCount++; + ReleaseMutex(d->iocpInstanceLock); + + d->hSemaphore = CreateSemaphore(NULL, 0, 255, NULL); + d->hResultsMutex = CreateMutex(NULL, FALSE, NULL); + connect(this, SIGNAL(_q_notify()), this, SLOT(_q_notified()), Qt::QueuedConnection); } QWinOverlappedIoNotifier::~QWinOverlappedIoNotifier() { + Q_D(QWinOverlappedIoNotifier); setEnabled(false); - CloseHandle(hResultsMutex); - CloseHandle(hSemaphore); + CloseHandle(d->hResultsMutex); + CloseHandle(d->hSemaphore); - WaitForSingleObject(iocpInstanceLock, INFINITE); - if (!--iocpInstanceRefCount) { - delete iocp; - iocp = 0; + WaitForSingleObject(d->iocpInstanceLock, INFINITE); + if (!--d->iocpInstanceRefCount) { + delete d->iocp; + d->iocp = 0; } - ReleaseMutex(iocpInstanceLock); + ReleaseMutex(d->iocpInstanceLock); } -void QWinOverlappedIoNotifier::setHandle(HANDLE h) +void QWinOverlappedIoNotifier::setHandle(Qt::HANDLE h) { - hHandle = h; + Q_D(QWinOverlappedIoNotifier); + d->hHandle = h; +} + +Qt::HANDLE QWinOverlappedIoNotifier::handle() const +{ + Q_D(const QWinOverlappedIoNotifier); + return d->hHandle; } void QWinOverlappedIoNotifier::setEnabled(bool enabled) { + Q_D(QWinOverlappedIoNotifier); if (enabled) - iocp->registerNotifier(this); + d->iocp->registerNotifier(d); else - iocp->unregisterNotifier(this); + d->iocp->unregisterNotifier(d); } /*! @@ -249,18 +300,19 @@ void QWinOverlappedIoNotifier::setEnabled(bool enabled) */ bool QWinOverlappedIoNotifier::waitForNotified(int msecs, OVERLAPPED *overlapped) { - if (!iocp->isRunning()) { + Q_D(QWinOverlappedIoNotifier); + if (!d->iocp->isRunning()) { qWarning("Called QWinOverlappedIoNotifier::waitForNotified on inactive notifier."); return false; } forever { if (msecs == 0) - iocp->drainQueue(); - DWORD result = WaitForSingleObject(hSemaphore, msecs == -1 ? INFINITE : DWORD(msecs)); + d->iocp->drainQueue(); + DWORD result = WaitForSingleObject(d->hSemaphore, msecs == -1 ? INFINITE : DWORD(msecs)); if (result == WAIT_OBJECT_0) { - ReleaseSemaphore(hSemaphore, 1, NULL); - if (_q_notified() == overlapped) + ReleaseSemaphore(d->hSemaphore, 1, NULL); + if (d->_q_notified() == overlapped) return true; continue; } else if (result == WAIT_TIMEOUT) { @@ -275,25 +327,30 @@ bool QWinOverlappedIoNotifier::waitForNotified(int msecs, OVERLAPPED *overlapped /*! * Note: This function runs in the I/O completion port thread. */ -void QWinOverlappedIoNotifier::notify(DWORD numberOfBytes, DWORD errorCode, OVERLAPPED *overlapped) +void QWinOverlappedIoNotifierPrivate::notify(DWORD numberOfBytes, DWORD errorCode, + OVERLAPPED *overlapped) { + Q_Q(QWinOverlappedIoNotifier); WaitForSingleObject(hResultsMutex, INFINITE); results.enqueue(IOResult(numberOfBytes, errorCode, overlapped)); ReleaseMutex(hResultsMutex); ReleaseSemaphore(hSemaphore, 1, NULL); - emit _q_notify(); + emit q->_q_notify(); } -OVERLAPPED *QWinOverlappedIoNotifier::_q_notified() +OVERLAPPED *QWinOverlappedIoNotifierPrivate::_q_notified() { + Q_Q(QWinOverlappedIoNotifier); if (WaitForSingleObject(hSemaphore, 0) == WAIT_OBJECT_0) { WaitForSingleObject(hResultsMutex, INFINITE); IOResult ioresult = results.dequeue(); ReleaseMutex(hResultsMutex); - emit notified(ioresult.numberOfBytes, ioresult.errorCode, ioresult.overlapped); + emit q->notified(ioresult.numberOfBytes, ioresult.errorCode, ioresult.overlapped); return ioresult.overlapped; } return 0; } QT_END_NAMESPACE + +#include "moc_qwinoverlappedionotifier_p.cpp" diff --git a/src/corelib/io/qwinoverlappedionotifier_p.h b/src/corelib/io/qwinoverlappedionotifier_p.h index 451bedf7cf..f90fd2e615 100644 --- a/src/corelib/io/qwinoverlappedionotifier_p.h +++ b/src/corelib/io/qwinoverlappedionotifier_p.h @@ -54,58 +54,35 @@ // #include <qobject.h> -#include <qt_windows.h> -#include <qqueue.h> + +typedef struct _OVERLAPPED OVERLAPPED; QT_BEGIN_NAMESPACE -class QWinIoCompletionPort; +class QWinOverlappedIoNotifierPrivate; class Q_CORE_EXPORT QWinOverlappedIoNotifier : public QObject { Q_OBJECT + Q_DISABLE_COPY(QWinOverlappedIoNotifier) + Q_DECLARE_PRIVATE(QWinOverlappedIoNotifier) + Q_PRIVATE_SLOT(d_func(), OVERLAPPED *_q_notified()) + friend class QWinIoCompletionPort; public: QWinOverlappedIoNotifier(QObject *parent = 0); ~QWinOverlappedIoNotifier(); - void setHandle(HANDLE h); - HANDLE handle() const { return hHandle; } + void setHandle(Qt::HANDLE h); + Qt::HANDLE handle() const; void setEnabled(bool enabled); bool waitForNotified(int msecs, OVERLAPPED *overlapped); Q_SIGNALS: - void notified(DWORD numberOfBytes, DWORD errorCode, OVERLAPPED *overlapped); + void notified(quint32 numberOfBytes, quint32 errorCode, OVERLAPPED *overlapped); +#if !defined(Q_QDOC) void _q_notify(); - -private Q_SLOTS: - OVERLAPPED *_q_notified(); - -private: - void notify(DWORD numberOfBytes, DWORD errorCode, OVERLAPPED *overlapped); - -private: - static QWinIoCompletionPort *iocp; - static HANDLE iocpInstanceLock; - static unsigned int iocpInstanceRefCount; - HANDLE hHandle; - HANDLE hSemaphore; - HANDLE hResultsMutex; - - struct IOResult - { - IOResult(DWORD n = 0, DWORD e = 0, OVERLAPPED *p = 0) - : numberOfBytes(n), errorCode(e), overlapped(p) - {} - - DWORD numberOfBytes; - DWORD errorCode; - OVERLAPPED *overlapped; - }; - - QQueue<IOResult> results; - - friend class QWinIoCompletionPort; +#endif }; QT_END_NAMESPACE |