From e44ed31434a4768e797d8097406c9b8283e76049 Mon Sep 17 00:00:00 2001 From: Roshni-P <58657076+Roshni-P@users.noreply.github.com> Date: Fri, 4 Sep 2020 07:25:48 +0530 Subject: [PATCH] Add the ability to open the target file of a Shortcut (.lnk) Fix #8483, close #8810 --- PowerEditor/gcc/makefile | 2 +- PowerEditor/src/NppIO.cpp | 63 ++++++++++++++++++++++++++++++++------- 2 files changed, 54 insertions(+), 11 deletions(-) diff --git a/PowerEditor/gcc/makefile b/PowerEditor/gcc/makefile index c8729bf38..a8418f0d1 100644 --- a/PowerEditor/gcc/makefile +++ b/PowerEditor/gcc/makefile @@ -250,7 +250,7 @@ CXX = $(CROSS_COMPILE)g++ CXXFLAGS = $(INCLUDESPECIAL) -DTIXML_USE_STL -DTIXMLA_USE_STL $(UNICODE) -std=c++17 -fpermissive INCLUDES = $(patsubst %,-I%,$(DIRS)) -I./include LDFLAGS = -Wl,--subsystem,windows -municode -mwindows -LIBS = -lcomdlg32 -lcomctl32 -lgdi32 -lole32 -loleacc -lshell32 -lshlwapi -ldbghelp -lversion -lcrypt32 -lsensapi -lwintrust -lwinmm +LIBS = -lcomdlg32 -lcomctl32 -lgdi32 -lole32 -loleacc -lshell32 -lshlwapi -ldbghelp -lversion -lcrypt32 -lsensapi -lwintrust -lwinmm -luuid RC = $(CROSS_COMPILE)windres diff --git a/PowerEditor/src/NppIO.cpp b/PowerEditor/src/NppIO.cpp index 960ee751a..e46fdd8c8 100644 --- a/PowerEditor/src/NppIO.cpp +++ b/PowerEditor/src/NppIO.cpp @@ -130,12 +130,55 @@ DWORD WINAPI Notepad_plus::monitorFileOnChange(void * params) return EXIT_SUCCESS; } +void resolveLinkFile(generic_string& linkFilePath) +{ + IShellLink* psl; + WCHAR targetFilePath[MAX_PATH]; + WIN32_FIND_DATA wfd; + + HRESULT hres = CoInitialize(NULL); + if (SUCCEEDED(hres)) + { + hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*)&psl); + if (SUCCEEDED(hres)) + { + IPersistFile* ppf; + hres = psl->QueryInterface(IID_IPersistFile, (void**)&ppf); + if (SUCCEEDED(hres)) + { + // Load the shortcut. + hres = ppf->Load(linkFilePath.c_str(), STGM_READ); + if (SUCCEEDED(hres) && hres != S_FALSE) + { + // Resolve the link. + hres = psl->Resolve(NULL, 0); + if (SUCCEEDED(hres) && hres != S_FALSE) + { + // Get the path to the link target. + hres = psl->GetPath(targetFilePath, MAX_PATH, (WIN32_FIND_DATA*)&wfd, SLGP_SHORTPATH); + if (SUCCEEDED(hres) && hres != S_FALSE) + { + linkFilePath = targetFilePath; + } + } + } + ppf->Release(); + } + psl->Release(); + } + CoUninitialize(); + } +} + BufferID Notepad_plus::doOpen(const generic_string& fileName, bool isRecursive, bool isReadOnly, int encoding, const TCHAR *backupFileName, FILETIME fileNameTimestamp) { const rsize_t longFileNameBufferSize = MAX_PATH; // TODO stop using fixed-size buffer if (fileName.size() >= longFileNameBufferSize - 1) // issue with all other sub-routines return BUFFER_INVALID; + generic_string targetFileName = fileName; + resolveLinkFile(targetFileName); + //If [GetFullPathName] succeeds, the return value is the length, in TCHARs, of the string copied to lpBuffer, not including the terminating null character. //If the lpBuffer buffer is too small to contain the path, the return value [of GetFullPathName] is the size, in TCHARs, of the buffer that is required to hold the path and the terminating null character. //If [GetFullPathName] fails for any other reason, the return value is zero. @@ -143,7 +186,7 @@ BufferID Notepad_plus::doOpen(const generic_string& fileName, bool isRecursive, NppParameters& nppParam = NppParameters::getInstance(); TCHAR longFileName[longFileNameBufferSize]; - const DWORD getFullPathNameResult = ::GetFullPathName(fileName.c_str(), longFileNameBufferSize, longFileName, NULL); + const DWORD getFullPathNameResult = ::GetFullPathName(targetFileName.c_str(), longFileNameBufferSize, longFileName, NULL); if (getFullPathNameResult == 0) { return BUFFER_INVALID; @@ -163,12 +206,12 @@ BufferID Notepad_plus::doOpen(const generic_string& fileName, bool isRecursive, bool isSnapshotMode = backupFileName != NULL && PathFileExists(backupFileName); if (isSnapshotMode && !PathFileExists(longFileName)) // UNTITLED { - wcscpy_s(longFileName, fileName.c_str()); + wcscpy_s(longFileName, targetFileName.c_str()); } _lastRecentFileList.remove(longFileName); generic_string fileName2Find; - generic_string gs_fileName{ fileName }; + generic_string gs_fileName{ targetFileName }; // "fileName" could be: @@ -177,7 +220,7 @@ BufferID Notepad_plus::doOpen(const generic_string& fileName, bool isRecursive, // 3. a file name with relative path to open or create // Search case 1 & 2 firstly - BufferID foundBufID = MainFileManager.getBufferFromName(fileName.c_str()); + BufferID foundBufID = MainFileManager.getBufferFromName(targetFileName.c_str()); if (foundBufID == BUFFER_INVALID) fileName2Find = longFileName; @@ -364,19 +407,19 @@ BufferID Notepad_plus::doOpen(const generic_string& fileName, bool isRecursive, } else { - if (globbing || ::PathIsDirectory(fileName.c_str())) + if (globbing || ::PathIsDirectory(targetFileName.c_str())) { vector fileNames; vector patterns; if (globbing) { - const TCHAR * substring = wcsrchr(fileName.c_str(), TCHAR('\\')); + const TCHAR * substring = wcsrchr(targetFileName.c_str(), TCHAR('\\')); if (substring) { - size_t pos = substring - fileName.c_str(); + size_t pos = substring - targetFileName.c_str(); patterns.push_back(substring + 1); - generic_string dir(fileName.c_str(), pos + 1); // use char * to evoke: + generic_string dir(targetFileName.c_str(), pos + 1); // use char * to evoke: // string (const char* s, size_t n); // and avoid to call (if pass string) : // string (const string& str, size_t pos, size_t len = npos); @@ -386,8 +429,8 @@ BufferID Notepad_plus::doOpen(const generic_string& fileName, bool isRecursive, } else { - generic_string fileNameStr = fileName; - if (fileName[fileName.size() - 1] != '\\') + generic_string fileNameStr = targetFileName; + if (targetFileName[targetFileName.size() - 1] != '\\') fileNameStr += TEXT("\\"); patterns.push_back(TEXT("*"));