Home » U++ Library support » U++ Core » Symlink/Shortcut support
Symlink/Shortcut support [message #24830] |
Mon, 01 February 2010 08:02  |
 |
koldo
Messages: 3432 Registered: August 2008
|
Senior Veteran |
|
|
Hello all
Now symlinks-shortcuts are supported in Core only in Linux with:
It would be good to have a wider support in Linux and Windows.
The proposal is to add IsSymlink() for both OS and a new function like bool GetSymLinkPath(const char *linkPath, String &filePath); to get the real path of the symlink.
The implementation could be (some parts has been borrowed from U++):
bool IsSymLink(const char *path) {
#ifdef PLATFORM_WIN32
return GetFileExt(path) == ".lnk";
#else
struct stat stf;
lstat(path, &stf);
return S_ISLNK(stf.st_mode);
#endif
}
bool GetSymLinkPath(const char *linkPath, String &filePath)
{
#ifdef PLATFORM_WIN32
HRESULT hres;
IShellLink* psl;
IPersistFile* ppf;
CoInitialize(NULL);
hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink,
(PVOID *) &psl);
if(SUCCEEDED(hres)) {
hres = psl->QueryInterface(IID_IPersistFile, (PVOID *) &ppf);
if(SUCCEEDED(hres)) {
hres = ppf->Load(ToSystemCharsetW(linkPath), STGM_READ);
if(SUCCEEDED(hres)) {
char fileW[_MAX_PATH] = {0};
psl->GetPath(fileW, _MAX_PATH, NULL, 0);
filePath = FromSystemCharset(fileW);
} else
return false;
ppf->Release();
} else
return false;
psl->Release();
} else
return false;
CoUninitialize();
return true;
#else
char buff[_MAX_PATH + 1];
bool ret;
int len = readlink(linkPath, buff, _MAX_PATH);
if (ret = (len > 0 && len < _MAX_PATH))
buff[len] = '\0';
else
*buff = '\0';
filePath = buff;
return ret;
#endif
}
Best regards
Iñaki
|
|
|
|
|
|
|
Re: Symlink/Shortcut support [message #24860 is a reply to message #24830] |
Mon, 01 February 2010 21:40   |
 |
fudadmin
Messages: 1321 Registered: November 2005 Location: Kaunas, Lithuania
|
Ultimate Contributor Administrator |
|
|
Hi guys, sorry for big breaks but life sometimes make crude corrections... But I've never stopped working on u++. Hopefully I'll to start posting my contributions if... ok, we will see. And, sorry, I've had symlink in my u++ version for windows for some time.
Some of my code if that helps:
bool FindFile::IsShellLinkDir() const //aris002 wrong name? tmp
{
if (!GetName().EndsWith(".lnk")) //aris002 shell we check ext somewhere outside?
return false;
// char linkpath[MAX_PATH];
LPCSTR linkpath=~path;
LLOG("IsShellLinkDir getname="<<GetName());
char szGotPath[MAX_PATH];
char szDescription[MAX_PATH];
// WIN32_FIND_DATA wfd;
HRESULT hres;
IShellLink* psl;
CoInitialize(NULL);
hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
IID_IShellLink, (LPVOID *) &psl);
if(SUCCEEDED(hres)) {
IPersistFile* ppf;
psl->QueryInterface(IID_IPersistFile, (void**)&ppf);
if(SUCCEEDED(hres)) {
WCHAR szPath[_MAX_PATH] = { 0 };
MultiByteToWideChar(CP_ACP, 0, linkpath, (int)strlen(linkpath), szPath, _MAX_PATH);
//not correct? - might be links with diffrerent extensions
//get shortcuts extension from registry? how?
hres = ppf->Load(szPath, STGM_READ); //Load the shortcut.
if (SUCCEEDED(hres)) {
// LLOG("ppf->Load ok!! "<<linkpath);
hres = psl->GetPath((LPSTR)szGotPath, MAX_PATH,
NULL, SLGP_UNCPRIORITY );
LLOG("name "<<GetName()<<" target "<<szGotPath);
// if(SUCCEEDED(hres))
// LLOG("SUCCEEDED link ");
ppf->Release();
}
psl->Release();
}
}
CoUninitialize();
if(SUCCEEDED(hres)) {
LLOG("SUCCEEDED2 link ");
return true;
}
else
return false;
//return SUCCEEDED(hres);
}
bool ResolveShellLink(const String& path, String& linked) //aris002
{
// char linkpath[MAX_PATH];
LPCSTR linkpath=path;
LLOG("IsShellLinkDir getname="<<path);
char szGotPath[MAX_PATH];
HRESULT hres;
IShellLink* psl;
CoInitialize(NULL);
hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
IID_IShellLink, (LPVOID *) &psl);
if(SUCCEEDED(hres)) {
IPersistFile* ppf;
psl->QueryInterface(IID_IPersistFile, (void**)&ppf);
if(SUCCEEDED(hres)) {
WCHAR szPath[_MAX_PATH] = { 0 };
MultiByteToWideChar(CP_ACP, 0, linkpath, (int)strlen(linkpath), szPath, _MAX_PATH);
//not correct? - might be links with diffrerent extensions
//get shortcuts extension from registry? how?
hres = ppf->Load(szPath, STGM_READ); //Load the shortcut.
if (SUCCEEDED(hres)) {
// LLOG("ppf->Load ok!! "<<linkpath);
hres = psl->GetPath((LPSTR)szGotPath, MAX_PATH,
NULL, SLGP_UNCPRIORITY );
LLOG("name "<<linkpath<<" target "<<szGotPath);
linked=szGotPath;
// if(SUCCEEDED(hres))
// LLOG("SUCCEEDED link ");
ppf->Release();
}
psl->Release();
}
}
CoUninitialize();
if(SUCCEEDED(hres)) {
LLOG("SUCCEEDED2 RESOLVED link ");
return true;
}
else
return false;
//return SUCCEEDED(hres);
}
they are not optimal and might need above or somewhere else switching off the check of target existance if I can remember.
Below the whole files attached.
P.S I've got also adapted for older version of FileSel for those with icon overlays. And, sorry i don't use svn because because that's too dificult for me, esp, merging.
Huge thanks to all of you!
-
Attachment: Path.h
(Size: 8.85KB, Downloaded 353 times)
-
Attachment: Path.cpp
(Size: 29.86KB, Downloaded 291 times)
|
|
|
|
|
Re: Symlink/Shortcut support [message #24939 is a reply to message #24938] |
Fri, 05 February 2010 10:25   |
 |
mirek
Messages: 14256 Registered: November 2005
|
Ultimate Member |
|
|
Please check my altered version:
String GetSymLinkPath(const char *linkpath)
{
#ifdef PLATFORM_WIN32
String path;
HRESULT hres;
IShellLink* psl;
IPersistFile* ppf;
CoInitialize(NULL);
hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink,
(PVOID *) &psl);
if(SUCCEEDED(hres)) {
hres = psl->QueryInterface(IID_IPersistFile, (PVOID *) &ppf);
if(SUCCEEDED(hres)) {
hres = ppf->Load(ToSystemCharsetW(linkPath), STGM_READ);
if(SUCCEEDED(hres)) {
char fileW[_MAX_PATH] = {0};
psl->GetPath(fileW, _MAX_PATH, NULL, 0);
path = FromSystemCharset(fileW);
}
ppf->Release();
}
psl->Release();
}
CoUninitialize();
return path;
#else
char buff[_MAX_PATH + 1];
bool ret;
int len = readlink(linkPath, buff, _MAX_PATH);
if(len > 0 && len < _MAX_PATH)
return String(buff, len);
return Null;
#endif
}
(now in U++, thanks).
|
|
|
|
|
|
|
|
|
Re: Symlink/Shortcut support [message #24997 is a reply to message #24995] |
Sat, 06 February 2010 23:19   |
 |
mirek
Messages: 14256 Registered: November 2005
|
Ultimate Member |
|
|
koldo wrote on Sat, 06 February 2010 17:13 |
luzr wrote on Sat, 06 February 2010 19:40 |
koldo wrote on Sat, 06 February 2010 08:30 |
luzr wrote on Sat, 06 February 2010 13:20 | Like this:
bool FindFile::IsSymLink() const
{
String name = GetName();
if(GetFileExt(name) != ".lnk")
return false;
return !IsNull(GetSymLinkPath(AppendFileName(path, name)));
}
Mirek
|
Well. It is not the most efficient possible but it is very valid.
|
Why? System calls appear to be equivalent for the test and for obtaining the path.
Mirek
|
Hello Mirek
Being punctilious these is not necessary:
char fileW[_MAX_PATH] = {0};
psl->GetPath(fileW, _MAX_PATH, NULL, 0);
path = FromSystemCharset(fileW);
|
I have to admit I have only considered fudadmin code.
OK, I will change it...
Mirek
|
|
|
|
Goto Forum:
Current Time: Sat May 03 01:31:48 CEST 2025
Total time taken to generate the page: 0.00873 seconds
|