Warning: That file was not part of the compilation database. It may have many parsing errors.
1 | /* This file is part of the KDE project |
---|---|
2 | |
3 | Copyright (C) 2006-2008 Ralf Habacker <ralf.habacker@freenet.de> |
4 | All rights reserved. |
5 | |
6 | This library is free software; you can redistribute it and/or |
7 | modify it under the terms of the GNU Library General Public |
8 | License as published by the Free Software Foundation; either |
9 | version 2 of the License, or (at your option) any later version. |
10 | |
11 | This library is distributed in the hope that it will be useful, |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
14 | Library General Public License for more details. |
15 | |
16 | You should have received a copy of the GNU Library General Public License |
17 | along with this library; see the file COPYING.LIB. If not, write to |
18 | the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
19 | Boston, MA 02110-1301, USA. |
20 | */ |
21 | #include "linkfile.h" |
22 | |
23 | #include <windows.h> |
24 | #include <windowsx.h> |
25 | #include <objbase.h> |
26 | #include <shlobj.h> |
27 | #include <shlwapi.h> |
28 | #include <initguid.h> |
29 | |
30 | #include <QDir> |
31 | #include <QFile> |
32 | |
33 | #include <KDebug> |
34 | #include <kstandarddirs.h> |
35 | #include <kservicegroup.h> |
36 | // required by kdesktopfile.h -> should be in kdesktopfile.h |
37 | #include <kconfiggroup.h> |
38 | #include <kdesktopfile.h> |
39 | |
40 | #if defined(_MSC_VER) |
41 | #define MY_CAST(a) a |
42 | #else |
43 | // mingw needs char cast |
44 | #define MY_CAST(a) (CHAR *)(a) |
45 | #endif |
46 | |
47 | /* |
48 | add correct prefix for win32 filesystem functions |
49 | described in msdn, but taken from Qt's qfsfileeninge_win.cpp |
50 | */ |
51 | static QString longFileName(const QString &path) |
52 | { |
53 | QString absPath = QDir::convertSeparators(path); |
54 | QString prefix = QLatin1String("\\\\?\\"); |
55 | if (path.startsWith("//") || path.startsWith( "\\\\")) { |
56 | prefix = QLatin1String("\\\\?\\UNC\\"); |
57 | absPath.remove(0, 2); |
58 | } |
59 | return prefix + absPath; |
60 | } |
61 | |
62 | bool LinkFile::read() |
63 | { |
64 | LPCWSTR szShortcutFile = (LPCWSTR)m_linkPath.utf16(); |
65 | WCHAR szTarget[MAX_PATH]; |
66 | WCHAR szWorkingDir[MAX_PATH]; |
67 | WCHAR szDescription[MAX_PATH]; |
68 | WCHAR szArguments[MAX_PATH]; |
69 | |
70 | IShellLink* psl = NULL; |
71 | IPersistFile* ppf = NULL; |
72 | bool bResult = false; |
73 | |
74 | # if !defined(UNICODE) |
75 | WCHAR wsz[MAX_PATH]; |
76 | if (0 == MultiByteToWideChar(CP_ACP, 0, MY_CAST(szShortcutFile), -1, wsz, MAX_PATH) ) |
77 | goto cleanup; |
78 | # else |
79 | LPCWSTR wsz = szShortcutFile; |
80 | # endif |
81 | |
82 | if (FAILED( CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void **) &psl) )) |
83 | goto cleanup; |
84 | |
85 | if (FAILED( psl->QueryInterface(IID_IPersistFile, (void **) &ppf) )) |
86 | goto cleanup; |
87 | |
88 | if (FAILED( ppf->Load(wsz, STGM_READ) )) |
89 | goto cleanup; |
90 | |
91 | if (NOERROR != psl->GetPath(MY_CAST(szTarget), MAX_PATH, NULL, 0) ) |
92 | goto cleanup; |
93 | m_execPath = QString::fromUtf16((const ushort*)szTarget); |
94 | |
95 | if (NOERROR != psl->GetWorkingDirectory(MY_CAST(szWorkingDir), MAX_PATH) ) |
96 | goto cleanup; |
97 | m_workingDir = QString::fromUtf16((const ushort*)szWorkingDir); |
98 | |
99 | if (NOERROR != psl->GetDescription(MY_CAST(szDescription), MAX_PATH) ) |
100 | goto cleanup; |
101 | m_description = QString::fromUtf16((const ushort*)szDescription); |
102 | |
103 | if (NOERROR != psl->GetArguments(MY_CAST(szArguments), MAX_PATH) ) |
104 | goto cleanup; |
105 | m_arguments = QString::fromUtf16((const ushort*)szArguments).split(QLatin1Char( |
106 | |
107 | bResult = true; |
108 | |
109 | cleanup: |
110 | if (ppf) ppf->Release(); |
111 | if (psl) psl->Release(); |
112 | return bResult; |
113 | } |
114 | |
115 | bool LinkFile::create() |
116 | { |
117 | HRESULT hres; |
118 | IShellLinkW* psl; |
119 | |
120 | QString linkName = longFileName(m_linkPath); |
121 | |
122 | LPCWSTR lpszPathObj = (LPCWSTR)m_execPath.utf16(); |
123 | LPCWSTR lpszPathLink = (LPCWSTR)m_linkPath.utf16(); |
124 | LPCWSTR lpszDesc = (LPCWSTR)m_description.utf16(); |
125 | LPCWSTR lpszWorkDir = (LPCWSTR)m_workingDir.utf16(); |
126 | // casting join directly results into a wrong lpszArguments |
127 | QString args = m_arguments.join(QLatin1String(" ")); |
128 | LPCWSTR lpszArguments = (LPCWSTR)args.utf16(); |
129 | |
130 | CoInitialize(NULL); |
131 | // Get a pointer to the IShellLink interface. |
132 | hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_ALL, IID_IShellLinkW, (LPVOID*)&psl); |
133 | |
134 | if (SUCCEEDED(hres)) |
135 | { |
136 | IPersistFile* ppf; |
137 | |
138 | // Set the path to the shortcut target and add the description. |
139 | if(!SUCCEEDED(psl->SetPath(lpszPathObj))) { |
140 | kDebug() << "error setting path for link to "<< m_execPath; |
141 | psl->Release(); |
142 | return false; |
143 | } |
144 | if(!SUCCEEDED(psl->SetDescription(lpszDesc))) { |
145 | kDebug() << "error setting description for link to "<< m_description; |
146 | psl->Release(); |
147 | return false; |
148 | } |
149 | if(!SUCCEEDED(psl->SetWorkingDirectory(lpszWorkDir))) { |
150 | kDebug() << "error setting working Directory for link to "<< m_workingDir; |
151 | psl->Release(); |
152 | return false; |
153 | } |
154 | if(!m_arguments.isEmpty() && !SUCCEEDED(psl->SetArguments(lpszArguments))) { |
155 | kDebug() << "error setting arguments for link to "<< m_arguments; |
156 | psl->Release(); |
157 | return false; |
158 | } |
159 | |
160 | // Query IShellLink for the IPersistFile interface for saving the |
161 | // shortcut in persistent storage. |
162 | hres = psl->QueryInterface(IID_IPersistFile, (LPVOID*)&ppf); |
163 | |
164 | if (SUCCEEDED(hres)) |
165 | { |
166 | hres = ppf->Save(lpszPathLink, TRUE); |
167 | // Save the link by calling IPersistFile::Save. |
168 | if(!SUCCEEDED(hres)) |
169 | kDebug() << "error saving link to "<< linkName; |
170 | |
171 | ppf->Release(); |
172 | } |
173 | psl->Release(); |
174 | } else { |
175 | kDebug() << "Error: Got no pointer to the IShellLink interface."; |
176 | } |
177 | CoUninitialize(); // cleanup COM after you're done using its services |
178 | return SUCCEEDED(hres) ? true : false; |
179 | } |
180 | |
181 | bool LinkFile::remove() |
182 | { |
183 | bool ret = QFile::remove(m_linkPath); |
184 | QFileInfo fi(m_linkPath); |
185 | QDir d; |
186 | d.rmpath(fi.absolutePath()); |
187 | return ret; |
188 | } |
189 | |
190 | bool LinkFile::exists() |
191 | { |
192 | return QFile::exists(m_linkPath); |
193 | } |
194 | |
195 | |
196 | bool LinkFiles::scan(QList <LinkFile> &files, const QString &path) |
197 | { |
198 | QDir aDir(path); |
199 | bool has_err = false; |
200 | if (aDir.exists())//QDir::NoDotAndDotDot |
201 | { |
202 | QFileInfoList entries = aDir.entryInfoList(QDir::NoDotAndDotDot | |
203 | QDir::Dirs | QDir::Files); |
204 | int count = entries.size(); |
205 | foreach(QFileInfo entryInfo, entries) |
206 | { |
207 | QString _path = entryInfo.absoluteFilePath(); |
208 | if (entryInfo.isDir()) |
209 | { |
210 | has_err = scan(files,_path); |
211 | } |
212 | else |
213 | { |
214 | if (_path.toLower().endsWith(".lnk")) |
215 | files.append(LinkFile("",_path, "", "")); |
216 | } |
217 | } |
218 | } |
219 | return has_err; |
220 | } |
221 | |
222 | bool LinkFiles::create(QList <LinkFile> &newFiles) |
223 | { |
224 | // create new link files |
225 | foreach(LinkFile linkFile, newFiles) |
226 | { |
227 | if (!linkFile.exists()) |
228 | { |
229 | if (linkFile.create()) |
230 | kDebug() << "created"<< linkFile; |
231 | else |
232 | kDebug() << "failed to create"<< linkFile; |
233 | } |
234 | } |
235 | return true; |
236 | } |
237 | |
238 | bool LinkFiles::cleanup(QList <LinkFile> &newFiles, QList <LinkFile> &oldFiles) |
239 | { |
240 | // delete not available linkfiles |
241 | foreach(LinkFile oldFile, oldFiles) |
242 | { |
243 | QString oldPath = QDir::fromNativeSeparators ( oldFile.linkPath().toLower() ); |
244 | bool found = false; |
245 | foreach(LinkFile newFile, newFiles) |
246 | { |
247 | QString newPath = QDir::fromNativeSeparators ( newFile.linkPath().toLower()); |
248 | if (newPath == oldPath) |
249 | { |
250 | found = true; |
251 | break; |
252 | } |
253 | } |
254 | if (!found) |
255 | { |
256 | kDebug() << "deleted"<< oldFile << oldFile.remove(); |
257 | } |
258 | } |
259 | return true; |
260 | } |
261 | |
262 | QDebug operator<<(QDebug out, const LinkFile &c) |
263 | { |
264 | out.space() << "LinkFile (" |
265 | << "linkPath"<< c.m_linkPath |
266 | << "execPath"<< c.m_execPath |
267 | << "arguments"<< c.m_arguments |
268 | << "workingDir"<< c.m_workingDir |
269 | << "description"<< c.m_description |
270 | << ")"; |
271 | return out; |
272 | } |
273 | |
274 | // vim: ts=4 sw=4 et |
275 |
Warning: That file was not part of the compilation database. It may have many parsing errors.