Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qsharedmemory_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// Qt-Security score:significant reason:default
4
8#include <qdebug.h>
9#include <qt_windows.h>
10
12
13using namespace Qt::StringLiterals;
14
15#if QT_CONFIG(sharedmemory)
16
17void QSharedMemoryPrivate::setWindowsErrorString(QLatin1StringView function)
18{
19 DWORD windowsError = GetLastError();
20 if (windowsError == 0)
21 return;
22 switch (windowsError) {
23 case ERROR_ALREADY_EXISTS:
24 error = QSharedMemory::AlreadyExists;
25 errorString = QSharedMemory::tr("%1: already exists").arg(function);
26 break;
27 case ERROR_FILE_NOT_FOUND:
28 error = QSharedMemory::NotFound;
29 errorString = QSharedMemory::tr("%1: doesn't exist").arg(function);
30 break;
31 case ERROR_COMMITMENT_LIMIT:
32 error = QSharedMemory::InvalidSize;
33 errorString = QSharedMemory::tr("%1: invalid size").arg(function);
34 break;
35 case ERROR_NO_SYSTEM_RESOURCES:
36 case ERROR_NOT_ENOUGH_MEMORY:
37 error = QSharedMemory::OutOfResources;
38 errorString = QSharedMemory::tr("%1: out of resources").arg(function);
39 break;
40 case ERROR_ACCESS_DENIED:
41 error = QSharedMemory::PermissionDenied;
42 errorString = QSharedMemory::tr("%1: permission denied").arg(function);
43 break;
44 default:
45 errorString = QSharedMemory::tr("%1: unknown error: %2")
46 .arg(function, qt_error_string(windowsError));
47 error = QSharedMemory::UnknownError;
48#if defined QSHAREDMEMORY_DEBUG
49 qDebug() << errorString << "key" << key;
50#endif
51 }
52}
53
54HANDLE QSharedMemoryWin32::handle(QSharedMemoryPrivate *self)
55{
56 if (!hand) {
57 const auto function = "QSharedMemory::handle"_L1;
58 if (self->nativeKey.isEmpty()) {
59 self->setError(QSharedMemory::KeyError,
60 QSharedMemory::tr("%1: unable to make key").arg(function));
61 return 0;
62 }
63 hand = OpenFileMapping(FILE_MAP_ALL_ACCESS, false,
64 reinterpret_cast<const wchar_t *>(self->nativeKey.nativeKey().utf16()));
65 if (!hand) {
66 self->setWindowsErrorString(function);
67 return 0;
68 }
69 }
70 return hand;
71}
72
73bool QSharedMemoryWin32::cleanHandle(QSharedMemoryPrivate *)
74{
75 if (hand != 0 && !CloseHandle(hand)) {
76 hand = 0;
77 return false;
78 }
79 hand = 0;
80 return true;
81}
82
83bool QSharedMemoryWin32::create(QSharedMemoryPrivate *self, qsizetype size)
84{
85 const auto function = "QSharedMemory::create"_L1;
86 if (self->nativeKey.isEmpty()) {
87 self->setError(QSharedMemory::KeyError,
88 QSharedMemory::tr("%1: key error").arg(function));
89 return false;
90 }
91
92 // Create the file mapping.
93 DWORD high, low;
94 if constexpr (sizeof(qsizetype) == 8)
95 high = DWORD(quint64(size) >> 32);
96 else
97 high = 0;
98 low = DWORD(size_t(size) & 0xffffffff);
99 hand = CreateFileMapping(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, high, low,
100 reinterpret_cast<const wchar_t *>(self->nativeKey.nativeKey().utf16()));
101 self->setWindowsErrorString(function);
102
103 // hand is valid when it already exists unlike unix so explicitly check
104 return self->error != QSharedMemory::AlreadyExists && hand;
105}
106
107bool QSharedMemoryWin32::attach(QSharedMemoryPrivate *self, QSharedMemory::AccessMode mode)
108{
109 // Grab a pointer to the memory block
110 int permissions = (mode == QSharedMemory::ReadOnly ? FILE_MAP_READ : FILE_MAP_ALL_ACCESS);
111 self->memory = (void *)MapViewOfFile(handle(self), permissions, 0, 0, 0);
112 if (!self->memory) {
113 self->setWindowsErrorString("QSharedMemory::attach"_L1);
114 cleanHandle(self);
115 return false;
116 }
117
118 // Grab the size of the memory we have been given (a multiple of 4K on windows)
119 MEMORY_BASIC_INFORMATION info;
120 if (!VirtualQuery(self->memory, &info, sizeof(info))) {
121 // Windows doesn't set an error code on this one,
122 // it should only be a kernel memory error.
123 self->setError(QSharedMemory::UnknownError,
124 QSharedMemory::tr("%1: size query failed")
125 .arg("QSharedMemory::attach: "_L1));
126 return false;
127 }
128 self->size = qsizetype(info.RegionSize);
129
130 return true;
131}
132
133bool QSharedMemoryWin32::detach(QSharedMemoryPrivate *self)
134{
135 // umap memory
136 if (!UnmapViewOfFile(self->memory)) {
137 self->setWindowsErrorString("QSharedMemory::detach"_L1);
138 return false;
139 }
140 self->memory = 0;
141 self->size = 0;
142
143 // close handle
144 return cleanHandle(self);
145}
146
147#endif // QT_CONFIG(sharedmemory)
148
149QT_END_NAMESPACE
Combined button and popup list for selecting options.