1 /* This file is part of the KDE project
3 Copyright (C) 2006-2008 Ralf Habacker <ralf.habacker@freenet.de>
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.
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.
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.
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>
43 // mingw needs char cast
44 #define MY_CAST(a) (CHAR *)(a)
48 add correct prefix for win32 filesystem functions
49 described in msdn, but taken from Qt's qfsfileeninge_win.cpp
51 static QString
longFileName(const QString
&path
)
53 QString absPath
= QDir::convertSeparators(path
);
54 QString prefix
= QLatin1String("\\\\?\\");
55 if (path
.startsWith("//") || path
.startsWith("\\\\")) {
56 prefix
= QLatin1String("\\\\?\\UNC\\");
59 return prefix
+ absPath
;
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
];
70 IShellLink
* psl
= NULL
;
71 IPersistFile
* ppf
= NULL
;
74 # if !defined(UNICODE)
76 if (0 == MultiByteToWideChar(CP_ACP
, 0, MY_CAST(szShortcutFile
), -1, wsz
, MAX_PATH
) )
79 LPCWSTR wsz
= szShortcutFile
;
82 if (FAILED( CoCreateInstance(CLSID_ShellLink
, NULL
, CLSCTX_INPROC_SERVER
, IID_IShellLink
, (void **) &psl
) ))
85 if (FAILED( psl
->QueryInterface(IID_IPersistFile
, (void **) &ppf
) ))
88 if (FAILED( ppf
->Load(wsz
, STGM_READ
) ))
91 if (NOERROR
!= psl
->GetPath(MY_CAST(szTarget
), MAX_PATH
, NULL
, 0) )
93 m_execPath
= QString::fromUtf16((const ushort
*)szTarget
);
95 if (NOERROR
!= psl
->GetWorkingDirectory(MY_CAST(szWorkingDir
), MAX_PATH
) )
97 m_workingDir
= QString::fromUtf16((const ushort
*)szWorkingDir
);
99 if (NOERROR
!= psl
->GetDescription(MY_CAST(szDescription
), MAX_PATH
) )
101 m_description
= QString::fromUtf16((const ushort
*)szDescription
);
103 if (NOERROR
!= psl
->GetArguments(MY_CAST(szArguments
), MAX_PATH
) )
105 m_arguments
= QString::fromUtf16((const ushort
*)szArguments
).split(QLatin1Char(' '), QString::SkipEmptyParts
);
110 if (ppf
) ppf
->Release();
111 if (psl
) psl
->Release();
115 bool LinkFile::create()
120 QString linkName
= longFileName(m_linkPath
);
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();
131 // Get a pointer to the IShellLink interface.
132 hres
= CoCreateInstance(CLSID_ShellLink
, NULL
, CLSCTX_ALL
, IID_IShellLinkW
, (LPVOID
*)&psl
);
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
;
144 if(!SUCCEEDED(psl
->SetDescription(lpszDesc
))) {
145 kDebug() << "error setting description for link to " << m_description
;
149 if(!SUCCEEDED(psl
->SetWorkingDirectory(lpszWorkDir
))) {
150 kDebug() << "error setting working Directory for link to " << m_workingDir
;
154 if(!m_arguments
.isEmpty() && !SUCCEEDED(psl
->SetArguments(lpszArguments
))) {
155 kDebug() << "error setting arguments for link to " << m_arguments
;
160 // Query IShellLink for the IPersistFile interface for saving the
161 // shortcut in persistent storage.
162 hres
= psl
->QueryInterface(IID_IPersistFile
, (LPVOID
*)&ppf
);
166 hres
= ppf
->Save(lpszPathLink
, TRUE
);
167 // Save the link by calling IPersistFile::Save.
169 kDebug() << "error saving link to " << linkName
;
175 kDebug() << "Error: Got no pointer to the IShellLink interface.";
177 CoUninitialize(); // cleanup COM after you're done using its services
178 return SUCCEEDED(hres
) ? true : false;
181 bool LinkFile::remove()
183 bool ret
= QFile::remove(m_linkPath
);
184 QFileInfo
fi(m_linkPath
);
186 d
.rmpath(fi
.absolutePath());
190 bool LinkFile::exists()
192 return QFile::exists(m_linkPath
);
196 bool LinkFiles::scan(QList
<LinkFile
> &files
, const QString
&path
)
199 bool has_err
= false;
200 if (aDir
.exists())//QDir::NoDotAndDotDot
202 QFileInfoList entries
= aDir
.entryInfoList(QDir::NoDotAndDotDot
|
203 QDir::Dirs
| QDir::Files
);
204 int count
= entries
.size();
205 foreach(QFileInfo entryInfo
, entries
)
207 QString _path
= entryInfo
.absoluteFilePath();
208 if (entryInfo
.isDir())
210 has_err
= scan(files
,_path
);
214 if (_path
.toLower().endsWith(".lnk"))
215 files
.append(LinkFile("",_path
,"",""));
222 bool LinkFiles::create(QList
<LinkFile
> &newFiles
)
224 // create new link files
225 foreach(LinkFile linkFile
, newFiles
)
227 if (!linkFile
.exists())
229 if (linkFile
.create())
230 kDebug() << "created" << linkFile
;
232 kDebug() << "failed to create" << linkFile
;
238 bool LinkFiles::cleanup(QList
<LinkFile
> &newFiles
, QList
<LinkFile
> &oldFiles
)
240 // delete not available linkfiles
241 foreach(LinkFile oldFile
, oldFiles
)
243 QString oldPath
= QDir::fromNativeSeparators ( oldFile
.linkPath().toLower() );
245 foreach(LinkFile newFile
, newFiles
)
247 QString newPath
= QDir::fromNativeSeparators ( newFile
.linkPath().toLower());
248 if (newPath
== oldPath
)
256 kDebug() << "deleted" << oldFile
<< oldFile
.remove();
262 QDebug
operator<<(QDebug out
, const LinkFile
&c
)
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