Shell32 patch 9
Martin Fuchs
martin-fuchs at gmx.net
Sat Jan 17 10:06:48 CST 2004
Changelog:
- fix typos in shelllink.c header comment and a struct comment
- corrected SCF_UNICODE constant and use the value of SCF_UNC instead
- implemented IShellLink_ConstructFromFile() to read shell links from files
- call IShellLink_ConstructFromFile() in ISF_..._fnGetUIObjectOf() when being queried for IShellLink interface
Index: shell32_main.h
===================================================================
RCS file: /home/wine/wine/dlls/shell32/shell32_main.h,v
retrieving revision 1.77
diff -u -p -d -r1.77 shell32_main.h
--- shell32_main.h 16 Jan 2004 23:06:25 -0000 1.77
+++ shell32_main.h 17 Jan 2004 16:01:29 -0000
@@ -91,6 +91,7 @@ LPSHELLVIEW IShellView_Constructor(LPSHE
HRESULT WINAPI IFSFolder_Constructor(IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv);
HRESULT WINAPI IShellLink_Constructor(IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv);
+HRESULT WINAPI IShellLink_ConstructFromFile(IUnknown * pUnkOuter, REFIID riid, LPCITEMIDLIST pidl, LPVOID * ppv);
HRESULT WINAPI ISF_Desktop_Constructor(IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv);
HRESULT WINAPI ISF_MyComputer_Constructor(IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv);
HRESULT WINAPI IDropTargetHelper_Constructor (IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv);
Index: shelllink.c
===================================================================
RCS file: /home/wine/wine/dlls/shell32/shelllink.c,v
retrieving revision 1.59
diff -u -p -d -r1.59 shelllink.c
--- shelllink.c 17 Nov 2003 20:31:30 -0000 1.59
+++ shelllink.c 17 Jan 2004 16:01:29 -0000
@@ -19,7 +19,7 @@
*
* NOTES
* Nearly complete informations about the binary formats
- * of .lnk files avaiable at http://www.wotsit.org
+ * of .lnk files available at http://www.wotsit.org
*
*/
@@ -53,6 +53,7 @@
#include "pidl.h"
#include "shell32_main.h"
#include "shlguid.h"
+#include "shlwapi.h"
WINE_DEFAULT_DEBUG_CHANNEL(shell);
@@ -66,8 +67,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(shell);
#define SCF_WORKDIR 0x10
#define SCF_ARGS 0x20
#define SCF_CUSTOMICON 0x40
-#define SCF_UNC 0x80
-#define SCF_UNICODE 0x1000
+#define SCF_UNICODE 0x80
#include "pshpack1.h"
@@ -128,7 +128,7 @@ typedef struct
ICOM_VTABLE(IPersistFile)* lpvtblPersistFile;
ICOM_VTABLE(IPersistStream)* lpvtblPersistStream;
- /* data structures according to the informations in the lnk */
+ /* data structures according to the informations in the link */
LPITEMIDLIST pPidl;
WORD wHotKey;
SYSTEMTIME time1;
@@ -800,6 +800,134 @@ HRESULT WINAPI IShellLink_Constructor (
}
return S_OK;
+}
+
+
+static BOOL SHELL_ExistsFileW(LPCWSTR path)
+{
+ HANDLE hfile = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
+
+ if (hfile != INVALID_HANDLE_VALUE) {
+ CloseHandle(hfile);
+ return TRUE;
+ } else
+ return FALSE;
+}
+
+/**************************************************************************
+ * SHELL_ShellLink_UpdatePath
+ * update absolute path in sPath using relative path in sPathRel
+ */
+static HRESULT SHELL_ShellLink_UpdatePath(LPWSTR sPathRel, LPCWSTR path, LPCWSTR sWorkDir, LPWSTR* psPath)
+{
+ if (!path || !psPath)
+ return E_INVALIDARG;
+
+ if (!*psPath && sPathRel) {
+ WCHAR buffer[2*MAX_PATH], abs_path[2*MAX_PATH];
+
+ /* first try if [directory of link file] + [relative path] finds an existing file */
+ LPCWSTR src = path;
+ LPWSTR last_slash = NULL;
+ LPWSTR dest = buffer;
+ LPWSTR final;
+
+ /* copy path without file name to buffer */
+ while(*src) {
+ if (*src=='/' || *src=='\\')
+ last_slash = dest;
+
+ *dest++ = *src++;
+ }
+
+ lstrcpyW(last_slash? last_slash+1: buffer, sPathRel);
+
+ *abs_path = '\0';
+
+ if (SHELL_ExistsFileW(buffer)) {
+ if (!GetFullPathNameW(buffer, MAX_PATH, abs_path, &final))
+ lstrcpyW(abs_path, buffer);
+ } else {
+ /* try if [working directory] + [relative path] finds an existing file */
+ if (sWorkDir) {
+ lstrcpyW(buffer, sWorkDir);
+ lstrcpyW(PathAddBackslashW(buffer), sPathRel);
+
+ if (SHELL_ExistsFileW(buffer))
+ if (!GetFullPathNameW(buffer, MAX_PATH, abs_path, &final))
+ lstrcpyW(abs_path, buffer);
+ }
+ }
+
+ /* FIXME: This is even not enough - not all shell links can be resolved using this algorithm. */
+ if (!*abs_path)
+ lstrcpyW(abs_path, sPathRel);
+
+ *psPath = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(abs_path)+1)*sizeof(WCHAR));
+ if (!*psPath)
+ return E_OUTOFMEMORY;
+
+ lstrcpyW(*psPath, abs_path);
+ }
+
+ return S_OK;
+}
+
+/**************************************************************************
+ * IShellLink_ConstructFromFile
+ */
+HRESULT WINAPI IShellLink_ConstructFromFile (
+ IUnknown* pUnkOuter,
+ REFIID riid,
+ LPCITEMIDLIST pidl,
+ LPVOID* ppv
+)
+{
+ IShellLinkW* psl;
+
+ HRESULT hr = IShellLink_Constructor(NULL, riid, (LPVOID*)&psl);
+
+ if (SUCCEEDED(hr)) {
+ IPersistFile* ppf;
+
+ *ppv = NULL;
+
+ hr = IShellLinkW_QueryInterface(psl, &IID_IPersistFile, (LPVOID*)&ppf);
+
+ if (SUCCEEDED(hr)) {
+ WCHAR path[MAX_PATH];
+
+ if (SHGetPathFromIDListW(pidl, path)) {
+ hr = IPersistFile_Load(ppf, path, 0);
+
+ if (SUCCEEDED(hr)) {
+ *ppv = (IUnknown*) psl;
+
+ /*
+ The following code is here, not in IPersistStream_fnLoad() because
+ to be able to convert the relative path into the absolute path,
+ we need to know the path of the shell link file.
+ */
+ if (IsEqualIID(riid, &IID_IShellLinkW)) {
+ _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, psl);
+
+ hr = SHELL_ShellLink_UpdatePath(This->sPathRel, path, This->sWorkDir, &This->sPath);
+ } else {
+ ICOM_THIS(IShellLinkImpl, psl);
+
+ hr = SHELL_ShellLink_UpdatePath(This->sPathRel, path, This->sWorkDir, &This->sPath);
+ }
+ }
+ }
+
+ IPersistFile_Release(ppf);
+ }
+
+ if (!*ppv)
+ IShellLinkW_Release(psl);
+ }
+
+ return hr;
}
/**************************************************************************
Index: shfldr_desktop.c
===================================================================
RCS file: /home/wine/wine/dlls/shell32/shfldr_desktop.c,v
retrieving revision 1.14
diff -u -p -d -r1.14 shfldr_desktop.c
--- shfldr_desktop.c 30 Dec 2003 19:24:22 -0000 1.14
+++ shfldr_desktop.c 17 Jan 2004 16:01:29 -0000
@@ -430,6 +430,11 @@ static HRESULT WINAPI ISF_Desktop_fnGetU
hr = S_OK;
} else if (IsEqualIID (riid, &IID_IDropTarget) && (cidl >= 1)) {
hr = IShellFolder_QueryInterface (iface, &IID_IDropTarget, (LPVOID *) & pObj);
+ } else if ((IsEqualIID(riid,&IID_IShellLinkW) || IsEqualIID(riid,&IID_IShellLinkA))
+ && (cidl == 1)) {
+ pidl = ILCombine (This->pidlRoot, apidl[0]);
+ hr = IShellLink_ConstructFromFile(NULL, riid, pidl, (LPVOID*)&pObj);
+ SHFree (pidl);
} else {
hr = E_NOINTERFACE;
}
Index: shfldr_fs.c
===================================================================
RCS file: /home/wine/wine/dlls/shell32/shfldr_fs.c,v
retrieving revision 1.16
diff -u -p -d -r1.16 shfldr_fs.c
--- shfldr_fs.c 17 Sep 2003 04:17:33 -0000 1.16
+++ shfldr_fs.c 17 Jan 2004 16:01:30 -0000
@@ -574,6 +574,11 @@ IShellFolder_fnGetUIObjectOf (IShellFold
hr = S_OK;
} else if (IsEqualIID (riid, &IID_IDropTarget) && (cidl >= 1)) {
hr = IShellFolder_QueryInterface (iface, &IID_IDropTarget, (LPVOID *) & pObj);
+ } else if ((IsEqualIID(riid,&IID_IShellLinkW) || IsEqualIID(riid,&IID_IShellLinkA))
+ && (cidl == 1)) {
+ pidl = ILCombine (This->pidlRoot, apidl[0]);
+ hr = IShellLink_ConstructFromFile(NULL, riid, pidl, (LPVOID*)&pObj);
+ SHFree (pidl);
} else {
hr = E_NOINTERFACE;
}
Index: shfldr_mycomp.c
===================================================================
RCS file: /home/wine/wine/dlls/shell32/shfldr_mycomp.c,v
retrieving revision 1.11
diff -u -p -d -r1.11 shfldr_mycomp.c
--- shfldr_mycomp.c 30 Dec 2003 19:24:22 -0000 1.11
+++ shfldr_mycomp.c 17 Jan 2004 16:01:30 -0000
@@ -409,6 +409,11 @@ ISF_MyComputer_fnGetUIObjectOf (IShellFo
hr = S_OK;
} else if (IsEqualIID (riid, &IID_IDropTarget) && (cidl >= 1)) {
hr = IShellFolder_QueryInterface (iface, &IID_IDropTarget, (LPVOID *) & pObj);
+ } else if ((IsEqualIID(riid,&IID_IShellLinkW) || IsEqualIID(riid,&IID_IShellLinkA))
+ && (cidl == 1)) {
+ pidl = ILCombine (This->pidlRoot, apidl[0]);
+ hr = IShellLink_ConstructFromFile(NULL, riid, pidl, (LPVOID*)&pObj);
+ SHFree (pidl);
} else {
hr = E_NOINTERFACE;
}
More information about the wine-patches
mailing list