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*/
51static 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
62bool 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(' '), QString::SkipEmptyParts);
106
107 bResult = true;
108
109cleanup:
110 if (ppf) ppf->Release();
111 if (psl) psl->Release();
112 return bResult;
113}
114
115bool 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
181bool 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
190bool LinkFile::exists()
191{
192 return QFile::exists(m_linkPath);
193}
194
195
196bool 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
222bool 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
238bool 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
262QDebug 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.