Warning: That file was not part of the compilation database. It may have many parsing errors.

1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtCore module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include "qstandardpaths.h"
41
42#include <qdir.h>
43#include <private/qsystemlibrary_p.h>
44#include <qstringlist.h>
45
46#ifndef QT_BOOTSTRAPPED
47#include <qcoreapplication.h>
48#endif
49
50#include <qt_windows.h>
51#include <shlobj.h>
52#include <intshcut.h>
53
54#ifndef QT_NO_STANDARDPATHS
55
56QT_BEGIN_NAMESPACE
57
58static QString convertCharArray(const wchar_t *path)
59{
60 return QDir::fromNativeSeparators(QString::fromWCharArray(path));
61}
62
63static inline bool isGenericConfigLocation(QStandardPaths::StandardLocation type)
64{
65 return type == QStandardPaths::GenericConfigLocation || type == QStandardPaths::GenericDataLocation;
66}
67
68static inline bool isConfigLocation(QStandardPaths::StandardLocation type)
69{
70 return type == QStandardPaths::ConfigLocation || type == QStandardPaths::AppConfigLocation
71 || type == QStandardPaths::AppDataLocation || type == QStandardPaths::AppLocalDataLocation
72 || isGenericConfigLocation(type);
73}
74
75static void appendOrganizationAndApp(QString &path) // Courtesy qstandardpaths_unix.cpp
76{
77#ifndef QT_BOOTSTRAPPED
78 const QString &org = QCoreApplication::organizationName();
79 if (!org.isEmpty())
80 path += QLatin1Char('/') + org;
81 const QString &appName = QCoreApplication::applicationName();
82 if (!appName.isEmpty())
83 path += QLatin1Char('/') + appName;
84#else // !QT_BOOTSTRAPPED
85 Q_UNUSED(path)
86#endif
87}
88
89static inline void appendTestMode(QString &path)
90{
91 if (QStandardPaths::isTestModeEnabled())
92 path += QLatin1String("/qttest");
93}
94
95// Map QStandardPaths::StandardLocation to KNOWNFOLDERID of SHGetKnownFolderPath()
96static GUID writableSpecialFolderId(QStandardPaths::StandardLocation type)
97{
98 static const GUID folderIds[] = {
99 FOLDERID_Desktop, // DesktopLocation
100 FOLDERID_Documents, // DocumentsLocation
101 FOLDERID_Fonts, // FontsLocation
102 FOLDERID_Programs, // ApplicationsLocation
103 FOLDERID_Music, // MusicLocation
104 FOLDERID_Videos, // MoviesLocation
105 FOLDERID_Pictures, // PicturesLocation
106 GUID(), GUID(), // TempLocation/HomeLocation
107 FOLDERID_LocalAppData, // AppLocalDataLocation ("Local" path), AppLocalDataLocation = DataLocation
108 GUID(), // CacheLocation
109 FOLDERID_LocalAppData, // GenericDataLocation ("Local" path)
110 GUID(), // RuntimeLocation
111 FOLDERID_LocalAppData, // ConfigLocation ("Local" path)
112 GUID(), GUID(), // DownloadLocation/GenericCacheLocation
113 FOLDERID_LocalAppData, // GenericConfigLocation ("Local" path)
114 FOLDERID_RoamingAppData,// AppDataLocation ("Roaming" path)
115 FOLDERID_LocalAppData, // AppConfigLocation ("Local" path)
116 };
117
118 Q_STATIC_ASSERT(sizeof(folderIds) / sizeof(folderIds[0]) == size_t(QStandardPaths::AppConfigLocation + 1));
119 return size_t(type) < sizeof(folderIds) / sizeof(folderIds[0]) ? folderIds[type] : GUID();
120}
121
122// Convenience for SHGetKnownFolderPath().
123static QString sHGetKnownFolderPath(const GUID &clsid)
124{
125 QString result;
126 typedef HRESULT (WINAPI *GetKnownFolderPath)(const GUID&, DWORD, HANDLE, LPWSTR*);
127
128 static const GetKnownFolderPath sHGetKnownFolderPath = // Vista onwards.
129 reinterpret_cast<GetKnownFolderPath>(QSystemLibrary::resolve(QLatin1String("shell32"), "SHGetKnownFolderPath"));
130
131 LPWSTR path;
132 if (Q_LIKELY(sHGetKnownFolderPath && SUCCEEDED(sHGetKnownFolderPath(clsid, KF_FLAG_DONT_VERIFY, 0, &path)))) {
133 result = convertCharArray(path);
134 CoTaskMemFree(path);
135 }
136 return result;
137}
138
139QString QStandardPaths::writableLocation(StandardLocation type)
140{
141 QString result;
142 switch (type) {
143 case DownloadLocation:
144 result = sHGetKnownFolderPath(FOLDERID_Downloads);
145 if (result.isEmpty())
146 result = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
147 break;
148
149 case CacheLocation:
150 // Although Microsoft has a Cache key it is a pointer to IE's cache, not a cache
151 // location for everyone. Most applications seem to be using a
152 // cache directory located in their AppData directory
153 result = sHGetKnownFolderPath(writableSpecialFolderId(AppLocalDataLocation));
154 if (!result.isEmpty()) {
155 appendTestMode(result);
156 appendOrganizationAndApp(result);
157 result += QLatin1String("/cache");
158 }
159 break;
160
161 case GenericCacheLocation:
162 result = sHGetKnownFolderPath(writableSpecialFolderId(GenericDataLocation));
163 if (!result.isEmpty()) {
164 appendTestMode(result);
165 result += QLatin1String("/cache");
166 }
167 break;
168
169 case RuntimeLocation:
170 case HomeLocation:
171 result = QDir::homePath();
172 break;
173
174 case TempLocation:
175 result = QDir::tempPath();
176 break;
177
178 default:
179 result = sHGetKnownFolderPath(writableSpecialFolderId(type));
180 if (!result.isEmpty() && isConfigLocation(type)) {
181 appendTestMode(result);
182 if (!isGenericConfigLocation(type))
183 appendOrganizationAndApp(result);
184 }
185 break;
186 }
187 return result;
188}
189
190#ifndef QT_BOOTSTRAPPED
191extern QString qAppFileName();
192#endif
193
194QStringList QStandardPaths::standardLocations(StandardLocation type)
195{
196 QStringList dirs;
197 const QString localDir = writableLocation(type);
198 if (!localDir.isEmpty())
199 dirs.append(localDir);
200
201 // type-specific handling goes here
202 if (isConfigLocation(type)) {
203 QString programData = sHGetKnownFolderPath(FOLDERID_ProgramData);
204 if (!programData.isEmpty()) {
205 if (!isGenericConfigLocation(type))
206 appendOrganizationAndApp(programData);
207 dirs.append(programData);
208 }
209#ifndef QT_BOOTSTRAPPED
210 // Note: QCoreApplication::applicationDirPath(), while static, requires
211 // an application instance. But we might need to resolve the standard
212 // locations earlier than that, so we fall back to qAppFileName().
213 QString applicationDirPath = qApp ? QCoreApplication::applicationDirPath()
214 : QFileInfo(qAppFileName()).path();
215 dirs.append(applicationDirPath);
216 const QString dataDir = applicationDirPath + QLatin1String("/data");
217 dirs.append(dataDir);
218
219 if (!isGenericConfigLocation(type)) {
220 QString appDataDir = dataDir;
221 appendOrganizationAndApp(appDataDir);
222 if (appDataDir != dataDir)
223 dirs.append(appDataDir);
224 }
225#endif // !QT_BOOTSTRAPPED
226 } // isConfigLocation()
227
228 return dirs;
229}
230
231QT_END_NAMESPACE
232
233#endif // QT_NO_STANDARDPATHS
234

Warning: That file was not part of the compilation database. It may have many parsing errors.