Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qfsfileengine_win.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qplatformdefs.h"
5#include "private/qabstractfileengine_p.h"
6#include "private/qfiledevice_p.h"
7#include "private/qfsfileengine_p.h"
9#include <qdebug.h>
10
11#include "qfile.h"
12#include "qdir.h"
13#include "qvarlengtharray.h"
14#include "qdatetime.h"
15#include "qt_windows.h"
16
17#include <sys/types.h>
18#include <direct.h>
19#include <winioctl.h>
20#include <objbase.h>
21#include <shlobj.h>
22#include <accctrl.h>
23#include <initguid.h>
24#include <ctype.h>
25#include <limits.h>
26#include <stdio.h>
27#define SECURITY_WIN32
28#include <security.h>
29
30#include <memory>
31
32#ifndef PATH_MAX
33#define PATH_MAX FILENAME_MAX
34#endif
35
37
38using namespace Qt::StringLiterals;
39
40static inline bool isUncPath(const QString &path)
41{
42 // Starts with \\, but not \\.
43 return (path.startsWith("\\\\"_L1)
44 && path.size() > 2 && path.at(2) != u'.');
45}
46
50QString QFSFileEnginePrivate::longFileName(const QString &path)
51{
52 if (path.startsWith("\\\\.\\"_L1))
53 return path;
54
55 QString absPath = QFileSystemEngine::nativeAbsoluteFilePath(path);
56 QString prefix = "\\\\?\\"_L1;
57 if (isUncPath(absPath)) {
58 prefix.append("UNC\\"_L1); // "\\\\?\\UNC\\"
59 absPath.remove(0, 2);
60 }
61 return prefix + absPath;
62}
63
64/*
65 \internal
66*/
67bool QFSFileEnginePrivate::nativeOpen(QIODevice::OpenMode openMode,
68 std::optional<QFile::Permissions> permissions)
69{
70 Q_Q(QFSFileEngine);
71
72 // All files are opened in share mode (both read and write).
73 DWORD shareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
74
75 int accessRights = 0;
77 accessRights |= GENERIC_READ;
79 accessRights |= GENERIC_WRITE;
80
81 // WriteOnly can create files, ReadOnly cannot.
82 DWORD creationDisp = (openMode & QIODevice::NewOnly)
83 ? CREATE_NEW
85 ? OPEN_ALWAYS
86 : OPEN_EXISTING;
87 // Create the file handle.
88 QNativeFilePermissions nativePermissions(permissions, false);
89 if (!nativePermissions.isOk())
90 return false;
91
92 fileHandle = CreateFile((const wchar_t*)fileEntry.nativeFilePath().utf16(),
93 accessRights,
94 shareMode,
95 nativePermissions.securityAttributes(),
96 creationDisp,
97 FILE_ATTRIBUTE_NORMAL,
98 NULL);
99
100 // Bail out on error.
101 if (fileHandle == INVALID_HANDLE_VALUE) {
102 q->setError(QFile::OpenError, qt_error_string());
103 return false;
104 }
105
106 // Truncate the file after successfully opening it if Truncate is passed.
108 q->setSize(0);
109
110 return true;
111}
112
113/*
114 \internal
115*/
117{
118 Q_Q(QFSFileEngine);
119 if (fh || fd != -1) {
120 // stdlib / stdio mode.
121 return closeFdFh();
122 }
123
124 // Windows native mode.
125 bool ok = true;
126
127 if (cachedFd != -1) {
128 if (::_close(cachedFd) && !::CloseHandle(fileHandle)) {
130 ok = false;
131 }
132
133 // System handle is closed with associated file descriptor.
134 fileHandle = INVALID_HANDLE_VALUE;
135 cachedFd = -1;
136
137 return ok;
138 }
139
140 if ((fileHandle == INVALID_HANDLE_VALUE || !::CloseHandle(fileHandle))) {
142 ok = false;
143 }
144 fileHandle = INVALID_HANDLE_VALUE;
145 return ok;
146}
147
148/*
149 \internal
150*/
152{
153 if (fh) {
154 // Buffered stdlib mode.
155 return flushFh();
156 }
157 if (fd != -1) {
158 // Unbuffered stdio mode; always succeeds (no buffer).
159 return true;
160 }
161
162 // Windows native mode; flushing is unnecessary.
163 return true;
164}
165
166/*
167 \internal
168 \since 5.1
169*/
171{
172 if (fh || fd != -1) {
173 // stdlib / stdio mode. No API available.
174 return false;
175 }
176 return FlushFileBuffers(fileHandle);
177}
178
179/*
180 \internal
181*/
183{
184 Q_Q(const QFSFileEngine);
185 QFSFileEngine *thatQ = const_cast<QFSFileEngine *>(q);
186
187 // ### Don't flush; for buffered files, we should get away with ftell.
188 thatQ->flush();
189
190 // Always retrieve the current information
192 bool filled = false;
193 if (fileHandle != INVALID_HANDLE_VALUE && openMode != QIODevice::NotOpen )
194 filled = QFileSystemEngine::fillMetaData(fileHandle, metaData,
196 else
198
199 if (!filled) {
201 return 0;
202 }
203 return metaData.size();
204}
205
206/*
207 \internal
208*/
210{
211 Q_Q(const QFSFileEngine);
212 QFSFileEngine *thatQ = const_cast<QFSFileEngine *>(q);
213
214 if (fh || fd != -1) {
215 // stdlib / stido mode.
216 return posFdFh();
217 }
218
219 // Windows native mode.
220 if (fileHandle == INVALID_HANDLE_VALUE)
221 return 0;
222
223 LARGE_INTEGER currentFilePos;
224 LARGE_INTEGER offset;
225 offset.QuadPart = 0;
226 if (!::SetFilePointerEx(fileHandle, offset, &currentFilePos, FILE_CURRENT)) {
227 thatQ->setError(QFile::UnspecifiedError, qt_error_string());
228 return 0;
229 }
230
231 return qint64(currentFilePos.QuadPart);
232}
233
234/*
235 \internal
236*/
238{
239 Q_Q(QFSFileEngine);
240
241 if (fh || fd != -1) {
242 // stdlib / stdio mode.
243 return seekFdFh(pos);
244 }
245
246 LARGE_INTEGER currentFilePos;
247 LARGE_INTEGER offset;
248 offset.QuadPart = pos;
249 if (!::SetFilePointerEx(fileHandle, offset, &currentFilePos, FILE_BEGIN)) {
251 return false;
252 }
253
254 return true;
255}
256
257/*
258 \internal
259*/
261{
262 Q_Q(QFSFileEngine);
263
264 if (fh || fd != -1) {
265 // stdio / stdlib mode.
266 if (fh && nativeIsSequential() && feof(fh)) {
268 return -1;
269 }
270
271 return readFdFh(data, maxlen);
272 }
273
274 // Windows native mode.
275 if (fileHandle == INVALID_HANDLE_VALUE)
276 return -1;
277
278 qint64 bytesToRead = maxlen;
279
280 // Reading on Windows fails with ERROR_NO_SYSTEM_RESOURCES when
281 // the chunks are too large, so we limit the block size to 32MB.
282 static const qint64 maxBlockSize = 32 * 1024 * 1024;
283
284 qint64 totalRead = 0;
285 do {
286 DWORD blockSize = DWORD(qMin(bytesToRead, maxBlockSize));
287 DWORD bytesRead;
288 if (!ReadFile(fileHandle, data + totalRead, blockSize, &bytesRead, NULL)) {
289 if (totalRead == 0) {
290 // Note: only return failure if the first ReadFile fails.
291 q->setError(QFile::ReadError, qt_error_string());
292 return -1;
293 }
294 break;
295 }
296 if (bytesRead == 0)
297 break;
298 totalRead += bytesRead;
299 bytesToRead -= bytesRead;
300 } while (totalRead < maxlen);
301 return totalRead;
302}
303
304/*
305 \internal
306*/
308{
309 Q_Q(QFSFileEngine);
310
311 if (fh || fd != -1) {
312 // stdio / stdlib mode.
313 return readLineFdFh(data, maxlen);
314 }
315
316 // Windows native mode.
317 if (fileHandle == INVALID_HANDLE_VALUE)
318 return -1;
319
320 // ### No equivalent in Win32?
321 return q->QAbstractFileEngine::readLine(data, maxlen);
322}
323
324/*
325 \internal
326*/
328{
329 Q_Q(QFSFileEngine);
330
331 if (fh || fd != -1) {
332 // stdio / stdlib mode.
333 return writeFdFh(data, len);
334 }
335
336 // Windows native mode.
337 if (fileHandle == INVALID_HANDLE_VALUE)
338 return -1;
339
340 qint64 bytesToWrite = len;
341
342 // Writing on Windows fails with ERROR_NO_SYSTEM_RESOURCES when
343 // the chunks are too large, so we limit the block size to 32MB.
344 qint64 totalWritten = 0;
345 do {
346 const DWORD currentBlockSize = DWORD(qMin(bytesToWrite, qint64(32 * 1024 * 1024)));
347 DWORD bytesWritten;
348 if (!WriteFile(fileHandle, data + totalWritten, currentBlockSize, &bytesWritten, NULL)) {
349 if (totalWritten == 0) {
350 // Note: Only return error if the first WriteFile failed.
351 q->setError(QFile::WriteError, qt_error_string());
352 return -1;
353 }
354 break;
355 }
356 if (bytesWritten == 0)
357 break;
358 totalWritten += bytesWritten;
359 bytesToWrite -= bytesWritten;
360 } while (totalWritten < len);
361 return qint64(totalWritten);
362}
363
364/*
365 \internal
366*/
368{
369 if (fh || fd != -1)
370 return fh ? QT_FILENO(fh) : fd;
371 if (cachedFd != -1)
372 return cachedFd;
373
374 int flags = 0;
376 flags |= _O_APPEND;
378 flags |= _O_RDONLY;
379 cachedFd = _open_osfhandle((intptr_t) fileHandle, flags);
380 return cachedFd;
381}
382
383/*
384 \internal
385*/
387{
388 HANDLE handle = fileHandle;
389 if (fh || fd != -1)
390 handle = (HANDLE)_get_osfhandle(fh ? QT_FILENO(fh) : fd);
391 if (handle == INVALID_HANDLE_VALUE)
392 return false;
393
394 DWORD fileType = GetFileType(handle);
395 return (fileType == FILE_TYPE_CHAR)
396 || (fileType == FILE_TYPE_PIPE);
397}
398
399bool QFSFileEnginePrivate::nativeRenameOverwrite(const QFileSystemEntry &newEntry)
400{
401 if (fileHandle == INVALID_HANDLE_VALUE)
402 return false;
403 const QString newFilePath = newEntry.nativeFilePath();
404 const size_t nameByteLength = newFilePath.length() * sizeof(wchar_t);
405 if (nameByteLength + sizeof(wchar_t) > std::numeric_limits<DWORD>::max())
406 return false;
407
408 constexpr size_t RenameInfoSize = sizeof(FILE_RENAME_INFO);
409 const size_t renameDataSize = RenameInfoSize + nameByteLength + sizeof(wchar_t);
410 QVarLengthArray<char> v(qsizetype(renameDataSize), 0);
411
412 auto *renameInfo = q20::construct_at(reinterpret_cast<FILE_RENAME_INFO *>(v.data()));
413 auto renameInfoRAII = qScopeGuard([&] { std::destroy_at(renameInfo); });
414 renameInfo->ReplaceIfExists = TRUE;
415 renameInfo->RootDirectory = nullptr;
416 renameInfo->FileNameLength = DWORD(nameByteLength);
417 memcpy(renameInfo->FileName, newFilePath.data(), nameByteLength);
418
419 bool res = SetFileInformationByHandle(fileHandle, FileRenameInfo, renameInfo,
420 DWORD(renameDataSize));
421 if (!res) {
422 DWORD error = GetLastError();
423 q_func()->setError(QFile::RenameError, qt_error_string(int(error)));
424 }
425 return res;
426}
427
429{
430 return false;
431}
432
434{
435 QString ret;
436 //if filename is a drive: then get the pwd of that drive
437 if (fileName.length() >= 2 &&
438 fileName.at(0).isLetter() && fileName.at(1) == u':') {
439 int drv = fileName.toUpper().at(0).toLatin1() - 'A' + 1;
440 if (_getdrive() != drv) {
441 wchar_t buf[PATH_MAX];
442 ::_wgetdcwd(drv, buf, PATH_MAX);
444 }
445 }
446 if (ret.isEmpty()) {
447 //just the pwd
448 ret = QFileSystemEngine::currentPath().filePath();
449 }
450 if (ret.length() >= 2 && ret[1] == u':')
451 ret[0] = ret.at(0).toUpper(); // Force uppercase drive letters.
452 return ret;
453}
454
455// cf QStorageInfo::isReady
456static inline bool isDriveReady(const wchar_t *path)
457{
458 DWORD fileSystemFlags;
459 const UINT driveType = GetDriveType(path);
460 return (driveType != DRIVE_REMOVABLE && driveType != DRIVE_CDROM)
461 || GetVolumeInformation(path, nullptr, 0, nullptr, nullptr,
462 &fileSystemFlags, nullptr, 0) == TRUE;
463}
464
466{
468 const UINT oldErrorMode = ::SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
469 quint32 driveBits = (quint32) GetLogicalDrives() & 0x3ffffff;
470 wchar_t driveName[] = L"A:\\";
471
472 while (driveBits) {
473 if ((driveBits & 1) && isDriveReady(driveName))
474 ret.append(QFileInfo(QString::fromWCharArray(driveName)));
475 driveName[0]++;
476 driveBits = driveBits >> 1;
477 }
478 ::SetErrorMode(oldErrorMode);
479 return ret;
480}
481
482bool QFSFileEnginePrivate::doStat(QFileSystemMetaData::MetaDataFlags flags) const
483{
484 if (!tried_stat || !metaData.hasFlags(flags)) {
485 tried_stat = true;
486
487 int localFd = fd;
488 if (fh && fileEntry.isEmpty())
489 localFd = QT_FILENO(fh);
490 if (localFd != -1)
494 }
495
496 return metaData.exists();
497}
498
499// ### assume that they add .lnk to newName
500bool QFSFileEngine::link(const QString &newName)
501{
504 QFileSystemEntry(newName), error);
505 if (!ret)
506 setError(QFile::RenameError, error.toString());
507 return ret;
508}
509
513QAbstractFileEngine::FileFlags QFSFileEngine::fileFlags(QAbstractFileEngine::FileFlags type) const
514{
515 Q_D(const QFSFileEngine);
516
517 if (type & Refresh)
518 d->metaData.clear();
519
520 QAbstractFileEngine::FileFlags ret;
521
522 if (type & FlagsMask)
524
525 bool exists;
526 {
527 QFileSystemMetaData::MetaDataFlags queryFlags;
528
529 queryFlags |= QFileSystemMetaData::MetaDataFlags::fromInt(type.toInt())
531
532 // AliasType and BundleType are 0x0
533 if (type & TypesMask)
539
540 if (type & FlagsMask)
543
544 queryFlags |= QFileSystemMetaData::LinkType;
545
546 exists = d->doStat(queryFlags);
547 }
548
549 if (exists && (type & PermsMask))
550 ret |= FileFlags::fromInt(d->metaData.permissions().toInt());
551
552 if (type & TypesMask) {
553 if ((type & LinkType) && d->metaData.isLegacyLink())
554 ret |= LinkType;
555 if (d->metaData.isDirectory()) {
557 } else {
558 ret |= FileType;
559 }
560 }
561 if (type & FlagsMask) {
562 if (d->metaData.exists()) {
563 // if we succeeded in querying, then the file exists: a file on
564 // Windows cannot be deleted if we have an open handle to it
565 ret |= ExistsFlag;
566 if (d->fileEntry.isRoot())
567 ret |= RootFlag;
568 else if (d->metaData.isHidden())
569 ret |= HiddenFlag;
570 }
571 }
572 return ret;
573}
574
576{
577 Q_D(const QFSFileEngine);
578 HANDLE h = d->fileHandle;
579 if (h == INVALID_HANDLE_VALUE) {
580 int localFd = d->fd;
581 if (d->fh && d->fileEntry.isEmpty())
582 localFd = QT_FILENO(d->fh);
583 if (localFd != -1)
584 h = HANDLE(_get_osfhandle(localFd));
585 }
586 if (h != INVALID_HANDLE_VALUE)
587 return QFileSystemEngine::id(h);
588
589 // file is not open, try by path
590 return QFileSystemEngine::id(d->fileEntry);
591}
592
594{
595 Q_D(const QFSFileEngine);
596 switch (file) {
597 case BaseName:
598 return d->fileEntry.fileName();
599 case PathName:
600 return d->fileEntry.path();
601 case AbsoluteName:
602 case AbsolutePathName: {
603 QString ret = d->fileEntry.filePath();
604 if (isRelativePath()) {
606 } else if (ret.startsWith(u'/') // absolute path to the current drive, so \a.txt -> Z:\a.txt
607 || ret.size() == 2 // or a drive letter that needs to get a working dir appended
608 // or a drive-relative path, so Z:a.txt -> Z:\currentpath\a.txt
609 || (ret.size() > 2 && ret.at(2) != u'/')
610 || ret.contains(QStringView(u"/../"))
611 || ret.contains(QStringView(u"/./"))
612 || ret.endsWith(QStringView(u"/.."))
613 || ret.endsWith(QStringView(u"/."))) {
614 ret = QDir::fromNativeSeparators(QFileSystemEngine::nativeAbsoluteFilePath(ret));
615 }
616
617 // The path should be absolute at this point.
618 // From the docs :
619 // Absolute paths begin with the directory separator "/"
620 // (optionally preceded by a drive specification under Windows).
621 if (ret.at(0) != u'/') {
622 Q_ASSERT(ret.length() >= 2);
623 Q_ASSERT(ret.at(0).isLetter());
624 Q_ASSERT(ret.at(1) == u':');
625
626 // Force uppercase drive letters.
627 ret[0] = ret.at(0).toUpper();
628 }
629
630 if (file == AbsolutePathName) {
631 int slash = ret.lastIndexOf(u'/');
632 if (slash < 0)
633 return ret;
634 if (ret.at(0) != u'/' && slash == 2)
635 return ret.left(3); // include the slash
636 return ret.left(slash > 0 ? slash : 1);
637 }
638 return ret;
639 }
640 case CanonicalName:
641 case CanonicalPathName: {
643 return QString();
644 const QFileSystemEntry entry =
646
647 if (file == CanonicalPathName)
648 return entry.path();
649 return entry.filePath();
650 }
652 return QFileSystemEngine::getLinkTarget(d->fileEntry, d->metaData).filePath();
653 case RawLinkPath:
654 return QFileSystemEngine::getRawLinkPath(d->fileEntry, d->metaData).filePath();
655 case BundleName:
656 return QString();
657 case JunctionName:
658 return QFileSystemEngine::getJunctionTarget(d->fileEntry, d->metaData).filePath();
659 case DefaultName:
660 break;
661 case NFileNames:
662 Q_ASSERT(false);
663 break;
664 }
665 return d->fileEntry.filePath();
666}
667
669{
670 Q_D(const QFSFileEngine);
671 // drive, e.g. "a:", or UNC root, e.q. "//"
672 return d->fileEntry.isRelative();
673}
674
675uint QFSFileEngine::ownerId(FileOwner /*own*/) const
676{
677 static const uint nobodyID = (uint) -2;
678 return nobodyID;
679}
680
681QString QFSFileEngine::owner(FileOwner own) const
682{
683 Q_D(const QFSFileEngine);
684 return QFileSystemEngine::owner(d->fileEntry, own);
685}
686
688{
689 Q_D(QFSFileEngine);
691
692 // clear cached state (if any)
693 d->metaData.clearFlags(QFileSystemMetaData::Permissions);
694
695 bool ret = QFileSystemEngine::setPermissions(d->fileEntry, QFile::Permissions(perms), error);
696 if (!ret)
698 return ret;
699}
700
702{
703 Q_D(QFSFileEngine);
704
705 if (d->fileHandle != INVALID_HANDLE_VALUE || d->fd != -1 || d->fh) {
706 // resize open file
707 HANDLE fh = d->fileHandle;
708 if (fh == INVALID_HANDLE_VALUE) {
709 if (d->fh)
710 fh = (HANDLE)_get_osfhandle(QT_FILENO(d->fh));
711 else
712 fh = (HANDLE)_get_osfhandle(d->fd);
713 }
714 if (fh == INVALID_HANDLE_VALUE)
715 return false;
716 qint64 currentPos = pos();
717
718 if (seek(size) && SetEndOfFile(fh)) {
719 seek(qMin(currentPos, size));
720 return true;
721 }
722
723 seek(currentPos);
724 return false;
725 }
726
727 if (!d->fileEntry.isEmpty()) {
728 // resize file on disk
729 QFile file(d->fileEntry.filePath());
731 bool ret = file.resize(size);
732 if (!ret)
734 return ret;
735 }
736 }
737 return false;
738}
739
741{
742 Q_D(QFSFileEngine);
743
744 if (d->openMode == QFile::NotOpen) {
745 setError(QFile::PermissionsError, qt_error_string(ERROR_ACCESS_DENIED));
746 return false;
747 }
748
749 if (!newDate.isValid() || time == QFile::FileMetadataChangeTime) {
750 setError(QFile::UnspecifiedError, qt_error_string(ERROR_INVALID_PARAMETER));
751 return false;
752 }
753
754 HANDLE handle = d->fileHandle;
755 if (handle == INVALID_HANDLE_VALUE) {
756 if (d->fh)
757 handle = reinterpret_cast<HANDLE>(::_get_osfhandle(QT_FILENO(d->fh)));
758 else if (d->fd != -1)
759 handle = reinterpret_cast<HANDLE>(::_get_osfhandle(d->fd));
760 }
761
762 if (handle == INVALID_HANDLE_VALUE) {
763 setError(QFile::PermissionsError, qt_error_string(ERROR_ACCESS_DENIED));
764 return false;
765 }
766
770 return false;
771 }
772
773 d->metaData.clearFlags(QFileSystemMetaData::Times);
774 return true;
775}
776
778 QFile::MemoryMapFlags flags)
779{
780 Q_Q(QFSFileEngine);
782 if (openMode == QFile::NotOpen) {
783 q->setError(QFile::PermissionsError, qt_error_string(ERROR_ACCESS_DENIED));
784 return 0;
785 }
786 if (offset == 0 && size == 0) {
787 q->setError(QFile::UnspecifiedError, qt_error_string(ERROR_INVALID_PARAMETER));
788 return 0;
789 }
790
791 // check/setup args to map
792 DWORD access = 0;
794#ifdef FILE_MAP_COPY
795 access = FILE_MAP_COPY;
796#else
797 q->setError(QFile::UnspecifiedError, "MapPrivateOption unsupported");
798 return 0;
799#endif
800 } else if (openMode & QIODevice::WriteOnly) {
801 access = FILE_MAP_WRITE;
802 } else if (openMode & QIODevice::ReadOnly) {
803 access = FILE_MAP_READ;
804 }
805
806 if (mapHandle == NULL) {
807 // get handle to the file
808 HANDLE handle = fileHandle;
809
810 if (handle == INVALID_HANDLE_VALUE && fh)
811 handle = (HANDLE)::_get_osfhandle(QT_FILENO(fh));
812
813#ifdef Q_USE_DEPRECATED_MAP_API
814 nativeClose();
815 // handle automatically closed by kernel with mapHandle (below).
816 handle = ::CreateFileForMapping((const wchar_t*)fileEntry.nativeFilePath().utf16(),
817 GENERIC_READ | (openMode & QIODevice::WriteOnly ? GENERIC_WRITE : 0),
818 0,
819 NULL,
820 OPEN_EXISTING,
821 FILE_ATTRIBUTE_NORMAL,
822 NULL);
823 // Since this is a special case, we check if the return value was NULL and if so
824 // we change it to INVALID_HANDLE_VALUE to follow the logic inside this function.
825 if (!handle)
826 handle = INVALID_HANDLE_VALUE;
827#endif
828
829 if (handle == INVALID_HANDLE_VALUE) {
830 q->setError(QFile::PermissionsError, qt_error_string(ERROR_ACCESS_DENIED));
831 return 0;
832 }
833
834 // first create the file mapping handle
835 DWORD protection = (openMode & QIODevice::WriteOnly) ? PAGE_READWRITE : PAGE_READONLY;
836 mapHandle = ::CreateFileMapping(handle, 0, protection, 0, 0, 0);
837 if (mapHandle == NULL) {
839#ifdef Q_USE_DEPRECATED_MAP_API
840 ::CloseHandle(handle);
841#endif
842 return 0;
843 }
844 }
845
846 DWORD offsetHi = offset >> 32;
847 DWORD offsetLo = offset & Q_UINT64_C(0xffffffff);
848 SYSTEM_INFO sysinfo;
849 ::GetSystemInfo(&sysinfo);
850 DWORD mask = sysinfo.dwAllocationGranularity - 1;
851 DWORD extra = offset & mask;
852 if (extra)
853 offsetLo &= ~mask;
854
855 // attempt to create the map
856 LPVOID mapAddress = ::MapViewOfFile(mapHandle, access,
857 offsetHi, offsetLo, size + extra);
858 if (mapAddress) {
859 uchar *address = extra + static_cast<uchar*>(mapAddress);
860 maps[address] = extra;
861 return address;
862 }
863
864 switch(GetLastError()) {
865 case ERROR_ACCESS_DENIED:
867 break;
868 case ERROR_INVALID_PARAMETER:
869 // size are out of bounds
870 default:
872 }
873
874 ::CloseHandle(mapHandle);
875 mapHandle = NULL;
876 return 0;
877}
878
880{
881 Q_Q(QFSFileEngine);
882 const auto it = std::as_const(maps).find(ptr);
883 if (it == maps.cend()) {
884 q->setError(QFile::PermissionsError, qt_error_string(ERROR_ACCESS_DENIED));
885 return false;
886 }
887 uchar *start = ptr - *it;
888 if (!UnmapViewOfFile(start)) {
890 return false;
891 }
892
893 maps.erase(it);
894 if (maps.isEmpty()) {
895 ::CloseHandle(mapHandle);
896 mapHandle = NULL;
897 }
898
899 return true;
900}
901
906{
907 // There's some Windows Server 2016 API, but we won't
908 // bother with it.
910 return false;
911}
912
\inmodule QtCore \reentrant
void setError(QFile::FileError error, const QString &str)
Sets the error type to error, and the error string to errorString.
QFile::FileError error() const
Returns the QFile::FileError that resulted from the last failed operation.
\inmodule QtCore
Definition qbytearray.h:57
\inmodule QtCore\reentrant
Definition qdatetime.h:283
static QString fromNativeSeparators(const QString &pathName)
Definition qdir.cpp:962
static QString cleanPath(const QString &path)
Returns path with directory separators normalized (that is, platform-native separators converted to "...
Definition qdir.cpp:2398
static QString currentPath()
Returns the absolute path of the application's current directory.
Definition qdir.cpp:2054
qint64 nativeRead(char *data, qint64 maxlen)
qint64 readFdFh(char *data, qint64 maxlen)
QHash< uchar *, StartAndLength > maps
qint64 writeFdFh(const char *data, qint64 len)
QIODevice::OpenMode openMode
QFileSystemEntry fileEntry
bool doStat(QFileSystemMetaData::MetaDataFlags flags=QFileSystemMetaData::PosixStatFlags) const
bool nativeOpen(QIODevice::OpenMode openMode, std::optional< QFile::Permissions > permissions)
QFileSystemMetaData metaData
static bool openModeCanCreate(QIODevice::OpenMode openMode)
qint64 readLineFdFh(char *data, qint64 maxlen)
qint64 nativeWrite(const char *data, qint64 len)
uchar * map(qint64 offset, qint64 size, QFile::MemoryMapFlags flags)
qint64 nativeReadLine(char *data, qint64 maxlen)
\inmodule QtCore
static QFileInfoList drives()
For Windows, returns the list of drives in the file system as a list of QFileInfo objects.
QString fileName(FileName file) const override
\reimp
uint ownerId(FileOwner) const override
In Unix, if stat() is successful, the uid is returned if own is the owner.
bool setFileTime(const QDateTime &newDate, QFile::FileTime time) override
\reimp
static QString currentPath(const QString &path=QString())
For Unix, returns the current working directory for the file engine.
bool cloneTo(QAbstractFileEngine *target) override
\reimp
bool setSize(qint64 size) override
\reimp
bool setPermissions(uint perms) override
\reimp
qint64 pos() const override
\reimp
bool caseSensitive() const override
Returns false for Windows, true for Unix.
QByteArray id() const override
bool seek(qint64) override
\reimp
bool link(const QString &newName) override
Creates a link from the file currently specified by fileName() to newName.
bool isRelativePath() const override
\reimp
FileFlags fileFlags(FileFlags type) const override
\reimp
QString owner(FileOwner) const override
\reimp
bool flush() override
\reimp
@ FileMetadataChangeTime
Definition qfiledevice.h:60
static QFileSystemEntry getLinkTarget(const QFileSystemEntry &link, QFileSystemMetaData &data)
static QFileSystemEntry canonicalName(const QFileSystemEntry &entry, QFileSystemMetaData &data)
static QByteArray id(const QFileSystemEntry &entry)
static QFileSystemEntry getRawLinkPath(const QFileSystemEntry &link, QFileSystemMetaData &data)
static bool fillMetaData(const QFileSystemEntry &entry, QFileSystemMetaData &data, QFileSystemMetaData::MetaDataFlags what)
static bool createLink(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error)
static QFileSystemEntry getJunctionTarget(const QFileSystemEntry &link, QFileSystemMetaData &data)
static bool setPermissions(const QFileSystemEntry &entry, QFile::Permissions permissions, QSystemError &error, QFileSystemMetaData *data=nullptr)
static bool setFileTime(const QFileSystemEntry &entry, const QDateTime &newDate, QFile::FileTime whatTime, QSystemError &error)
static QFileSystemEntry currentPath()
Q_AUTOTEST_EXPORT NativePath nativeFilePath() const
Q_AUTOTEST_EXPORT bool isEmpty() const
bool hasFlags(MetaDataFlags flags) const
void clearFlags(MetaDataFlags flags=AllMetaDataFlags)
MetaDataFlags missingFlags(MetaDataFlags flags)
\inmodule QtCore
Definition qfile.h:93
QFILE_MAYBE_NODISCARD bool open(OpenMode flags) override
Opens the file using OpenMode mode, returning true if successful; otherwise false.
Definition qfile.cpp:904
bool resize(qint64 sz) override
\reimp
Definition qfile.cpp:1103
QString errorString() const
Returns a human-readable description of the last device error that occurred.
iterator find(const T &value)
Definition qset.h:159
\inmodule QtCore
Definition qstringview.h:78
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
static QString fromWCharArray(const wchar_t *string, qsizetype size=-1)
Definition qstring.h:1309
QString & append(QChar c)
Definition qstring.cpp:3252
QString & remove(qsizetype i, qsizetype len)
Removes n characters from the string, starting at the given position index, and returns a reference t...
Definition qstring.cpp:3466
qsizetype length() const noexcept
Returns the number of characters in this string.
Definition qstring.h:191
static Q_CORE_EXPORT QString stdString(int errorCode=-1)
QSet< QString >::iterator it
Combined button and popup list for selecting options.
void * HANDLE
T * construct_at(T *ptr, Args &&... args)
Definition q20memory.h:41
const int blockSize
DBusConnection const char DBusError * error
INT_PTR intptr_t
#define PATH_MAX
static bool isDriveReady(const wchar_t *path)
static bool isUncPath(const QString &path)
Q_DECL_COLD_FUNCTION Q_CORE_EXPORT QString qt_error_string(int errorCode=-1)
return ret
static ControlElement< T > * ptr(QWidget *widget)
constexpr const T & qMin(const T &a, const T &b)
Definition qminmax.h:40
GLenum GLsizei GLuint GLint * bytesWritten
GLsizei const GLfloat * v
[13]
GLuint64 GLenum void * handle
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum type
GLenum access
GLenum GLuint GLenum GLsizei const GLchar * buf
GLenum target
GLbitfield flags
GLuint start
GLenum GLuint GLintptr offset
GLuint64 GLenum GLint fd
GLint GLint GLint GLint GLint GLint GLint GLbitfield mask
GLfloat GLfloat GLfloat GLfloat h
GLuint res
GLuint entry
GLuint GLuint64EXT address
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
GLsizei const GLchar *const * path
GLenum GLsizei len
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
QScopeGuard< typename std::decay< F >::type > qScopeGuard(F &&f)
[qScopeGuard]
Definition qscopeguard.h:60
static FileType fileType(const QFileInfo &fi)
#define Q_UNUSED(x)
#define Q_UINT64_C(c)
Definition qtypes.h:58
unsigned int quint32
Definition qtypes.h:50
unsigned char uchar
Definition qtypes.h:32
ptrdiff_t qsizetype
Definition qtypes.h:165
unsigned int uint
Definition qtypes.h:34
long long qint64
Definition qtypes.h:60
QFile file
[0]