- 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
This commit is contained in:
Martin Fuchs 2004-01-20 01:37:24 +00:00 committed by Alexandre Julliard
parent a34dc5b53a
commit eae9444bc8
5 changed files with 148 additions and 4 deletions

View File

@ -91,6 +91,7 @@ LPSHELLVIEW IShellView_Constructor(LPSHELLFOLDER);
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);

View File

@ -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;
@ -802,6 +802,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;
}
/**************************************************************************
* IShellLinkA_QueryInterface
*/

View File

@ -430,6 +430,11 @@ static HRESULT WINAPI ISF_Desktop_fnGetUIObjectOf (IShellFolder2 * iface,
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;
}

View File

@ -574,6 +574,11 @@ IShellFolder_fnGetUIObjectOf (IShellFolder2 * iface,
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;
}

View File

@ -409,6 +409,11 @@ ISF_MyComputer_fnGetUIObjectOf (IShellFolder2 * iface,
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;
}