diff options
Diffstat (limited to 'src/plugins/platforms/winrt/qwinrtfileengine.cpp')
-rw-r--r-- | src/plugins/platforms/winrt/qwinrtfileengine.cpp | 554 |
1 files changed, 0 insertions, 554 deletions
diff --git a/src/plugins/platforms/winrt/qwinrtfileengine.cpp b/src/plugins/platforms/winrt/qwinrtfileengine.cpp deleted file mode 100644 index 962e4ab938..0000000000 --- a/src/plugins/platforms/winrt/qwinrtfileengine.cpp +++ /dev/null @@ -1,554 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the plugins 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 The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/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 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qwinrtfileengine.h" - -#include <QtCore/QDateTime> -#include <QtCore/QCoreApplication> -#include <QtCore/QHash> -#include <QtCore/qfunctions_winrt.h> -#include <QtCore/private/qfsfileengine_p.h> - -#include <wrl.h> -#include <windows.storage.h> -#include <robuffer.h> - -using namespace Microsoft::WRL; -using namespace Microsoft::WRL::Wrappers; -using namespace ABI::Windows::Foundation; -using namespace ABI::Windows::Storage; -using namespace ABI::Windows::Storage::Streams; - -typedef IAsyncOperationCompletedHandler<IRandomAccessStream *> StreamCompletedHandler; -typedef IAsyncOperationWithProgressCompletedHandler<IBuffer *, UINT32> StreamReadCompletedHandler; - -QT_BEGIN_NAMESPACE - -#define RETURN_AND_SET_ERROR_IF_FAILED(error, ret) \ - setError(error, qt_error_string(hr)); \ - if (FAILED(hr)) \ - return ret; - -Q_GLOBAL_STATIC(QWinRTFileEngineHandler, handlerInstance) - -class QWinRTFileEngineHandlerPrivate -{ -public: - QHash<QString, ComPtr<IStorageItem>> files; -}; - -class QWinRTFileEnginePrivate -{ -public: - QWinRTFileEnginePrivate(const QString &fileName, IStorageItem *file) - : fileName(fileName), file(file), openMode(QIODevice::NotOpen) - { - HRESULT hr; - hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Storage_Streams_Buffer).Get(), - IID_PPV_ARGS(&bufferFactory)); - Q_ASSERT_SUCCEEDED(hr); - - lastSeparator = fileName.size() - 1; - for (int i = lastSeparator; i >= 0; --i) { - if (fileName.at(i).unicode() == '/' || fileName.at(i).unicode() == '\\') { - lastSeparator = i; - break; - } - } - - firstDot = fileName.size(); - for (int i = lastSeparator; i < fileName.size(); ++i) { - if (fileName.at(i).unicode() == '.') { - firstDot = i; - break; - } - } - } - - ComPtr<IBufferFactory> bufferFactory; - - QString fileName; - int lastSeparator; - int firstDot; - ComPtr<IStorageItem> file; - ComPtr<IRandomAccessStream> stream; - QIODevice::OpenMode openMode; - - qint64 pos; - -private: - QWinRTFileEngineHandler *q_ptr; - Q_DECLARE_PUBLIC(QWinRTFileEngineHandler) -}; - - -QWinRTFileEngineHandler::QWinRTFileEngineHandler() - : d_ptr(new QWinRTFileEngineHandlerPrivate) -{ -} - -void QWinRTFileEngineHandler::registerFile(const QString &fileName, IStorageItem *file) -{ - handlerInstance->d_func()->files.insert(QDir::cleanPath(fileName), file); -} - -IStorageItem *QWinRTFileEngineHandler::registeredFile(const QString &fileName) -{ - return handlerInstance->d_func()->files.value(fileName).Get(); -} - -QAbstractFileEngine *QWinRTFileEngineHandler::create(const QString &fileName) const -{ - Q_D(const QWinRTFileEngineHandler); - - QHash<QString, ComPtr<IStorageItem>>::const_iterator file = d->files.find(fileName); - if (file != d->files.end()) - return new QWinRTFileEngine(fileName, file.value().Get()); - - return nullptr; -} - -static HRESULT getDestinationFolder(const QString &fileName, const QString &newFileName, - IStorageItem *file, IStorageFolder **folder) -{ - HRESULT hr; - ComPtr<IAsyncOperation<StorageFolder *>> op; - QFileInfo newFileInfo(newFileName); - QFileInfo fileInfo(fileName); - if (fileInfo.dir() == newFileInfo.dir()) { - ComPtr<IStorageItem2> item; - hr = file->QueryInterface(IID_PPV_ARGS(&item)); - Q_ASSERT_SUCCEEDED(hr); - - hr = item->GetParentAsync(&op); - } else { - ComPtr<IStorageFolderStatics> folderFactory; - hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Storage_StorageFolder).Get(), - IID_PPV_ARGS(&folderFactory)); - Q_ASSERT_SUCCEEDED(hr); - - const QString newFilePath = QDir::toNativeSeparators(newFileInfo.absolutePath()); - HStringReference nativeNewFilePath(reinterpret_cast<LPCWSTR>(newFilePath.utf16()), - uint(newFilePath.length())); - hr = folderFactory->GetFolderFromPathAsync(nativeNewFilePath.Get(), &op); - } - if (FAILED(hr)) - return hr; - return QWinRTFunctions::await(op, folder); -} - -QWinRTFileEngine::QWinRTFileEngine(const QString &fileName, IStorageItem *file) - : d_ptr(new QWinRTFileEnginePrivate(fileName, file)) -{ -} - -bool QWinRTFileEngine::open(QIODevice::OpenMode openMode) -{ - Q_D(QWinRTFileEngine); - - FileAccessMode fileAccessMode = (openMode & QIODevice::WriteOnly) - ? FileAccessMode_ReadWrite : FileAccessMode_Read; - - HRESULT hr; - ComPtr<IStorageFile> file; - hr = d->file.As(&file); - RETURN_AND_SET_ERROR_IF_FAILED(QFileDevice::OpenError, false); - - ComPtr<IAsyncOperation<IRandomAccessStream *>> op; - hr = file->OpenAsync(fileAccessMode, &op); - RETURN_AND_SET_ERROR_IF_FAILED(QFileDevice::OpenError, false); - - hr = QWinRTFunctions::await(op, d->stream.GetAddressOf()); - RETURN_AND_SET_ERROR_IF_FAILED(QFileDevice::OpenError, false); - - const ProcessOpenModeResult res = processOpenModeFlags(openMode); - if (!res.ok) { - setError(QFileDevice::OpenError, res.error); - return false; - } - d->openMode = res.openMode; - if (d->openMode & QIODevice::Truncate) { - if (!setSize(0)) { - close(); - setError(QFileDevice::OpenError, QLatin1String("Could not truncate file")); - return false; - } - } - - return SUCCEEDED(hr); -} - -bool QWinRTFileEngine::close() -{ - Q_D(QWinRTFileEngine); - - if (!d->stream) - return false; - - ComPtr<IClosable> closable; - HRESULT hr = d->stream.As(&closable); - Q_ASSERT_SUCCEEDED(hr); - - hr = closable->Close(); - RETURN_AND_SET_ERROR_IF_FAILED(QFileDevice::UnspecifiedError, false); - d->stream.Reset(); - d->openMode = QIODevice::NotOpen; - return SUCCEEDED(hr); -} - -bool QWinRTFileEngine::flush() -{ - Q_D(QWinRTFileEngine); - - if (!d->stream) - return false; - - if (!(d->openMode & QIODevice::WriteOnly)) - return true; - - ComPtr<IOutputStream> stream; - HRESULT hr = d->stream.As(&stream); - RETURN_AND_SET_ERROR_IF_FAILED(QFileDevice::WriteError, false); - ComPtr<IAsyncOperation<bool>> flushOp; - hr = stream->FlushAsync(&flushOp); - RETURN_AND_SET_ERROR_IF_FAILED(QFileDevice::WriteError, false); - boolean flushed; - hr = QWinRTFunctions::await(flushOp, &flushed); - RETURN_AND_SET_ERROR_IF_FAILED(QFileDevice::WriteError, false); - - return true; -} - -qint64 QWinRTFileEngine::size() const -{ - Q_D(const QWinRTFileEngine); - - if (!d->stream) - return 0; - - UINT64 size; - HRESULT hr; - hr = d->stream->get_Size(&size); - RETURN_IF_FAILED("Failed to get file size", return 0); - - return qint64(size); -} - -bool QWinRTFileEngine::setSize(qint64 size) -{ - Q_D(QWinRTFileEngine); - if (!d->stream) { - setError(QFileDevice::ResizeError, QLatin1String("File must be open to be resized")); - return false; - } - - if (size < 0) { - setError(QFileDevice::ResizeError, QLatin1String("File size cannot be negative")); - return false; - } - - HRESULT hr = d->stream->put_Size(static_cast<quint64>(size)); - RETURN_AND_SET_ERROR_IF_FAILED(QFileDevice::ResizeError, false); - if (!flush()) { - setError(QFileDevice::ResizeError, QLatin1String("Could not flush file")); - return false; - } - - return true; -} - -qint64 QWinRTFileEngine::pos() const -{ - Q_D(const QWinRTFileEngine); - return d->pos; -} - -bool QWinRTFileEngine::seek(qint64 pos) -{ - Q_D(QWinRTFileEngine); - - if (!d->stream) - return false; - - HRESULT hr = d->stream->Seek(UINT64(pos)); - RETURN_AND_SET_ERROR_IF_FAILED(QFileDevice::PositionError, false); - d->pos = pos; - return SUCCEEDED(hr); -} - -bool QWinRTFileEngine::remove() -{ - Q_D(QWinRTFileEngine); - - ComPtr<IAsyncAction> op; - HRESULT hr = d->file->DeleteAsync(StorageDeleteOption_Default, &op); - RETURN_AND_SET_ERROR_IF_FAILED(QFileDevice::RemoveError, false); - - hr = QWinRTFunctions::await(op); - RETURN_AND_SET_ERROR_IF_FAILED(QFileDevice::RemoveError, false); - return SUCCEEDED(hr); -} - -bool QWinRTFileEngine::copy(const QString &newName) -{ - Q_D(QWinRTFileEngine); - - HRESULT hr; - ComPtr<IStorageFolder> destinationFolder; - hr = getDestinationFolder(d->fileName, newName, d->file.Get(), destinationFolder.GetAddressOf()); - RETURN_AND_SET_ERROR_IF_FAILED(QFileDevice::CopyError, false); - - ComPtr<IStorageFile> file; - hr = d->file.As(&file); - RETURN_AND_SET_ERROR_IF_FAILED(QFileDevice::CopyError, false); - - const QString destinationName = QFileInfo(newName).fileName(); - HStringReference nativeDestinationName(reinterpret_cast<LPCWSTR>(destinationName.utf16()), - uint(destinationName.length())); - ComPtr<IAsyncOperation<StorageFile *>> op; - hr = file->CopyOverloadDefaultOptions(destinationFolder.Get(), nativeDestinationName.Get(), &op); - RETURN_AND_SET_ERROR_IF_FAILED(QFileDevice::CopyError, false); - - ComPtr<IStorageFile> newFile; - hr = QWinRTFunctions::await(op, newFile.GetAddressOf()); - RETURN_AND_SET_ERROR_IF_FAILED(QFileDevice::CopyError, false); - return SUCCEEDED(hr); -} - -bool QWinRTFileEngine::rename(const QString &newName) -{ - Q_D(QWinRTFileEngine); - - HRESULT hr; - ComPtr<IStorageFolder> destinationFolder; - hr = getDestinationFolder(d->fileName, newName, d->file.Get(), destinationFolder.GetAddressOf()); - RETURN_AND_SET_ERROR_IF_FAILED(QFileDevice::RenameError, false); - - const QString destinationName = QFileInfo(newName).fileName(); - HStringReference nativeDestinationName(reinterpret_cast<LPCWSTR>(destinationName.utf16()), - uint(destinationName.length())); - ComPtr<IAsyncAction> op; - hr = d->file->RenameAsyncOverloadDefaultOptions(nativeDestinationName.Get(), &op); - RETURN_AND_SET_ERROR_IF_FAILED(QFileDevice::RenameError, false); - return SUCCEEDED(hr); -} - -bool QWinRTFileEngine::renameOverwrite(const QString &newName) -{ - Q_D(QWinRTFileEngine); - - HRESULT hr; - ComPtr<IStorageFolder> destinationFolder; - hr = getDestinationFolder(d->fileName, newName, d->file.Get(), destinationFolder.GetAddressOf()); - RETURN_AND_SET_ERROR_IF_FAILED(QFileDevice::RenameError, false); - - const QString destinationName = QFileInfo(newName).fileName(); - HStringReference nativeDestinationName(reinterpret_cast<LPCWSTR>(destinationName.utf16()), - uint(destinationName.length())); - ComPtr<IAsyncAction> op; - hr = d->file->RenameAsync(nativeDestinationName.Get(), NameCollisionOption_ReplaceExisting, &op); - RETURN_AND_SET_ERROR_IF_FAILED(QFileDevice::RenameError, false); - return SUCCEEDED(hr); -} - -QAbstractFileEngine::FileFlags QWinRTFileEngine::fileFlags(FileFlags type) const -{ - Q_D(const QWinRTFileEngine); - - FileFlags flags = ExistsFlag|ReadOwnerPerm|ReadUserPerm|WriteOwnerPerm|WriteUserPerm; - - HRESULT hr; - FileAttributes attributes; - hr = d->file->get_Attributes(&attributes); - RETURN_IF_FAILED("Failed to get file attributes", return flags); - if (attributes & FileAttributes_ReadOnly) - flags ^= WriteUserPerm; - if (attributes & FileAttributes_Directory) - flags |= DirectoryType; - else - flags |= FileType; - - return type & flags; -} - -bool QWinRTFileEngine::setPermissions(uint perms) -{ - Q_UNUSED(perms); - Q_UNIMPLEMENTED(); - return false; -} - -QString QWinRTFileEngine::fileName(FileName type) const -{ - Q_D(const QWinRTFileEngine); - - switch (type) { - default: - case DefaultName: - case AbsoluteName: - case CanonicalName: - break; - case BaseName: - return d->lastSeparator < 0 - ? d->fileName : d->fileName.mid(d->lastSeparator, d->firstDot - d->lastSeparator); - case PathName: - case AbsolutePathName: - case CanonicalPathName: - return d->fileName.mid(0, d->lastSeparator); - case LinkName: - case BundleName: - return QString(); - } - return d->fileName; -} - -QDateTime QWinRTFileEngine::fileTime(FileTime type) const -{ - Q_D(const QWinRTFileEngine); - - HRESULT hr; - DateTime dateTime = { 0 }; - switch (type) { - case BirthTime: - hr = d->file->get_DateCreated(&dateTime); - RETURN_IF_FAILED("Failed to get file creation time", return QDateTime()); - break; - case MetadataChangeTime: - case ModificationTime: - case AccessTime: { - ComPtr<IAsyncOperation<FileProperties::BasicProperties *>> op; - hr = d->file->GetBasicPropertiesAsync(&op); - RETURN_IF_FAILED("Failed to initiate file properties", return QDateTime()); - ComPtr<FileProperties::IBasicProperties> properties; - hr = QWinRTFunctions::await(op, properties.GetAddressOf()); - RETURN_IF_FAILED("Failed to get file properties", return QDateTime()); - hr = properties->get_DateModified(&dateTime); - RETURN_IF_FAILED("Failed to get file date", return QDateTime()); - } - break; - } - - SYSTEMTIME systemTime; - FileTimeToSystemTime((const FILETIME *)&dateTime, &systemTime); - QDate date(systemTime.wYear, systemTime.wMonth, systemTime.wDay); - QTime time(systemTime.wHour, systemTime.wMinute, systemTime.wSecond, systemTime.wMilliseconds); - return QDateTime(date, time); -} - -qint64 QWinRTFileEngine::read(char *data, qint64 maxlen) -{ - Q_D(QWinRTFileEngine); - - if (!d->stream) - return -1; - - ComPtr<IInputStream> stream; - HRESULT hr = d->stream.As(&stream); - RETURN_AND_SET_ERROR_IF_FAILED(QFileDevice::ReadError, -1); - - UINT32 length = UINT32(qBound(quint64(0), quint64(maxlen), quint64(UINT32_MAX))); - ComPtr<IBuffer> buffer; - hr = d->bufferFactory->Create(length, &buffer); - RETURN_AND_SET_ERROR_IF_FAILED(QFileDevice::ReadError, -1); - - ComPtr<IAsyncOperationWithProgress<IBuffer *, UINT32>> op; - hr = stream->ReadAsync(buffer.Get(), length, InputStreamOptions_None, &op); - RETURN_AND_SET_ERROR_IF_FAILED(QFileDevice::ReadError, -1); - - // Quoting MSDN IInputStream::ReadAsync() documentation: - // "Depending on the implementation, the data that's read might be placed - // into the input buffer, or it might be returned in a different buffer." - // Using GetAddressOf can cause ref counting errors leaking the original - // buffer. - ComPtr<IBuffer> effectiveBuffer; - hr = QWinRTFunctions::await(op, effectiveBuffer.GetAddressOf()); - RETURN_AND_SET_ERROR_IF_FAILED(QFileDevice::ReadError, -1); - - hr = effectiveBuffer->get_Length(&length); - RETURN_AND_SET_ERROR_IF_FAILED(QFileDevice::ReadError, -1); - - ComPtr<Windows::Storage::Streams::IBufferByteAccess> byteArrayAccess; - hr = effectiveBuffer.As(&byteArrayAccess); - RETURN_AND_SET_ERROR_IF_FAILED(QFileDevice::ReadError, -1); - - byte *bytes; - hr = byteArrayAccess->Buffer(&bytes); - RETURN_AND_SET_ERROR_IF_FAILED(QFileDevice::ReadError, -1); - memcpy(data, bytes, length); - return qint64(length); -} - -qint64 QWinRTFileEngine::write(const char *data, qint64 maxlen) -{ - Q_D(QWinRTFileEngine); - - if (!d->stream) - return -1; - - ComPtr<IOutputStream> stream; - HRESULT hr = d->stream.As(&stream); - RETURN_AND_SET_ERROR_IF_FAILED(QFileDevice::WriteError, -1); - - UINT32 length = UINT32(qBound(quint64(0), quint64(maxlen), quint64(UINT_MAX))); - ComPtr<IBuffer> buffer; - hr = d->bufferFactory->Create(length, &buffer); - RETURN_AND_SET_ERROR_IF_FAILED(QFileDevice::WriteError, -1); - hr = buffer->put_Length(length); - RETURN_AND_SET_ERROR_IF_FAILED(QFileDevice::WriteError, -1); - - ComPtr<Windows::Storage::Streams::IBufferByteAccess> byteArrayAccess; - hr = buffer.As(&byteArrayAccess); - RETURN_AND_SET_ERROR_IF_FAILED(QFileDevice::WriteError, -1); - - byte *bytes; - hr = byteArrayAccess->Buffer(&bytes); - RETURN_AND_SET_ERROR_IF_FAILED(QFileDevice::WriteError, -1); - memcpy(bytes, data, length); - - ComPtr<IAsyncOperationWithProgress<UINT32, UINT32>> op; - hr = stream->WriteAsync(buffer.Get(), &op); - RETURN_AND_SET_ERROR_IF_FAILED(QFileDevice::WriteError, -1); - - hr = QWinRTFunctions::await(op, &length); - RETURN_AND_SET_ERROR_IF_FAILED(QFileDevice::WriteError, -1); - - return qint64(length); -} - -QT_END_NAMESPACE |