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