fixes for many ShellExecute() problems

svn path=/trunk/; revision=7560
This commit is contained in:
Martin Fuchs 2004-01-10 23:01:48 +00:00
parent ad5496bb9b
commit adfc55b3cf
3 changed files with 201 additions and 79 deletions

View file

@ -2110,8 +2110,8 @@ REFIID _ILGetGUIDPointer(LPCITEMIDLIST pidl)
} }
/************************************************************************** /**************************************************************************
* _ILGetTextPointer() * _ILGetCPanelPointer()
* gets a pointer to the long filename string stored in the pidl * gets a pointer to the control panel struct stored in the pidl
*/ */
PIDLCPanelStruct* _ILGetCPanelPointer(LPCITEMIDLIST pidl) PIDLCPanelStruct* _ILGetCPanelPointer(LPCITEMIDLIST pidl)
{ {

View file

@ -53,6 +53,7 @@
#include "pidl.h" #include "pidl.h"
#include "shell32_main.h" #include "shell32_main.h"
#include "shlguid.h" #include "shlguid.h"
#include "shlwapi.h"
WINE_DEFAULT_DEBUG_CHANNEL(shell); WINE_DEFAULT_DEBUG_CHANNEL(shell);
@ -822,17 +823,30 @@ HRESULT WINAPI IShellLink_Constructor (
return S_OK; 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;
}
/************************************************************************** /**************************************************************************
* _IShellLink_UpdatePath * SHELL_ShellLink_UpdatePath
* update absolute path in sPath using relative path in sPathRel * update absolute path in sPath using relative path in sPathRel
*/ */
static HRESULT _IShellLink_UpdatePath(LPWSTR sPathRel, LPCWSTR path, LPWSTR* psPath) static HRESULT SHELL_ShellLink_UpdatePath(LPWSTR sPathRel, LPCWSTR path, LPCWSTR sWorkDir, LPWSTR* psPath)
{ {
if (!path || !psPath) if (!path || !psPath)
return E_INVALIDARG; return E_INVALIDARG;
if (!*psPath && sPathRel) { if (!*psPath && sPathRel) {
WCHAR buffer[2*MAX_PATH], abs_path[2*MAX_PATH]; 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; LPCWSTR src = path;
LPWSTR last_slash = NULL; LPWSTR last_slash = NULL;
LPWSTR dest = buffer; LPWSTR dest = buffer;
@ -848,8 +862,26 @@ static HRESULT _IShellLink_UpdatePath(LPWSTR sPathRel, LPCWSTR path, LPWSTR* psP
lstrcpyW(last_slash? last_slash+1: buffer, sPathRel); lstrcpyW(last_slash? last_slash+1: buffer, sPathRel);
if (!GetFullPathNameW(buffer, MAX_PATH, abs_path, &final)) *abs_path = '\0';
lstrcpyW(abs_path, buffer);
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)); *psPath = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(abs_path)+1)*sizeof(WCHAR));
if (!*psPath) if (!*psPath)
@ -893,17 +925,17 @@ HRESULT WINAPI IShellLink_ConstructFromFile (
/* /*
The following code is here, not in IPersistStream_fnLoad() because The following code is here, not in IPersistStream_fnLoad() because
we need to know the path of the shell link file to convert the to be able to convert the relative path into the absolute path,
relative path into the absolute path. we need to know the path of the shell link file.
*/ */
if (IsEqualIID(riid, &IID_IShellLinkW)) { if (IsEqualIID(riid, &IID_IShellLinkW)) {
_ICOM_THIS_From_IShellLinkW(IShellLinkImpl, psl); _ICOM_THIS_From_IShellLinkW(IShellLinkImpl, psl);
hr = _IShellLink_UpdatePath(This->sPathRel, path, &This->sPath); hr = SHELL_ShellLink_UpdatePath(This->sPathRel, path, This->sWorkDir, &This->sPath);
} else { } else {
ICOM_THIS(IShellLinkImpl, psl); ICOM_THIS(IShellLinkImpl, psl);
hr = _IShellLink_UpdatePath(This->sPathRel, path, &This->sPath); hr = SHELL_ShellLink_UpdatePath(This->sPathRel, path, This->sWorkDir, &This->sPath);
} }
} }
} }
@ -1194,7 +1226,7 @@ static HRESULT WINAPI IShellLinkA_fnSetShowCmd(IShellLinkA * iface, INT iShowCmd
return NOERROR; return NOERROR;
} }
static HRESULT _PidlGeticonLocationA(IShellFolder* psf, LPITEMIDLIST pidl, LPSTR pszIconPath, int cchIconPath, int* piIcon) static HRESULT SHELL_PidlGeticonLocationA(IShellFolder* psf, LPITEMIDLIST pidl, LPSTR pszIconPath, int cchIconPath, int* piIcon)
{ {
LPCITEMIDLIST pidlLast; LPCITEMIDLIST pidlLast;
@ -1240,7 +1272,7 @@ static HRESULT WINAPI IShellLinkA_fnGetIconLocation(IShellLinkA * iface, LPSTR p
if (SUCCEEDED(hr)) { if (SUCCEEDED(hr)) {
/* first look for an icon using the PIDL (if present) */ /* first look for an icon using the PIDL (if present) */
if (This->pPidl) if (This->pPidl)
hr = _PidlGeticonLocationA(pdsk, This->pPidl, pszIconPath, cchIconPath, piIcon); hr = SHELL_PidlGeticonLocationA(pdsk, This->pPidl, pszIconPath, cchIconPath, piIcon);
else else
hr = E_FAIL; hr = E_FAIL;
@ -1251,7 +1283,7 @@ static HRESULT WINAPI IShellLinkA_fnGetIconLocation(IShellLinkA * iface, LPSTR p
hr = IShellFolder_ParseDisplayName(pdsk, 0, NULL, This->sPath, NULL, &pidl, NULL); hr = IShellFolder_ParseDisplayName(pdsk, 0, NULL, This->sPath, NULL, &pidl, NULL);
if (SUCCEEDED(hr)) { if (SUCCEEDED(hr)) {
hr = _PidlGeticonLocationA(pdsk, pidl, pszIconPath, cchIconPath, piIcon); hr = SHELL_PidlGeticonLocationA(pdsk, pidl, pszIconPath, cchIconPath, piIcon);
SHFree(pidl); SHFree(pidl);
} }
@ -1295,7 +1327,7 @@ static HRESULT WINAPI IShellLinkA_fnSetRelativePath(IShellLinkA * iface, LPCSTR
This->sPathRel = HEAP_strdupAtoW(GetProcessHeap(), 0, pszPathRel); This->sPathRel = HEAP_strdupAtoW(GetProcessHeap(), 0, pszPathRel);
This->bDirty = TRUE; This->bDirty = TRUE;
return _IShellLink_UpdatePath(This->sPathRel, This->sPath, &This->sPath); return SHELL_ShellLink_UpdatePath(This->sPathRel, This->sPath, This->sWorkDir, &This->sPath);
} }
static HRESULT WINAPI IShellLinkA_fnResolve(IShellLinkA * iface, HWND hwnd, DWORD fFlags) static HRESULT WINAPI IShellLinkA_fnResolve(IShellLinkA * iface, HWND hwnd, DWORD fFlags)
@ -1617,7 +1649,7 @@ static HRESULT WINAPI IShellLinkW_fnSetShowCmd(IShellLinkW * iface, INT iShowCmd
return S_OK; return S_OK;
} }
static HRESULT _PidlGeticonLocationW(IShellFolder* psf, LPITEMIDLIST pidl, LPWSTR pszIconPath, int cchIconPath, int* piIcon) static HRESULT SHELL_PidlGeticonLocationW(IShellFolder* psf, LPITEMIDLIST pidl, LPWSTR pszIconPath, int cchIconPath, int* piIcon)
{ {
LPCITEMIDLIST pidlLast; LPCITEMIDLIST pidlLast;
@ -1663,7 +1695,7 @@ static HRESULT WINAPI IShellLinkW_fnGetIconLocation(IShellLinkW * iface, LPWSTR
if (SUCCEEDED(hr)) { if (SUCCEEDED(hr)) {
/* first look for an icon using the PIDL (if present) */ /* first look for an icon using the PIDL (if present) */
if (This->pPidl) if (This->pPidl)
hr = _PidlGeticonLocationW(pdsk, This->pPidl, pszIconPath, cchIconPath, piIcon); hr = SHELL_PidlGeticonLocationW(pdsk, This->pPidl, pszIconPath, cchIconPath, piIcon);
else else
hr = E_FAIL; hr = E_FAIL;
@ -1674,7 +1706,7 @@ static HRESULT WINAPI IShellLinkW_fnGetIconLocation(IShellLinkW * iface, LPWSTR
hr = IShellFolder_ParseDisplayName(pdsk, 0, NULL, This->sPath, NULL, &pidl, NULL); hr = IShellFolder_ParseDisplayName(pdsk, 0, NULL, This->sPath, NULL, &pidl, NULL);
if (SUCCEEDED(hr)) { if (SUCCEEDED(hr)) {
hr = _PidlGeticonLocationW(pdsk, pidl, pszIconPath, cchIconPath, piIcon); hr = SHELL_PidlGeticonLocationW(pdsk, pidl, pszIconPath, cchIconPath, piIcon);
SHFree(pidl); SHFree(pidl);
} }
@ -1724,7 +1756,7 @@ static HRESULT WINAPI IShellLinkW_fnSetRelativePath(IShellLinkW * iface, LPCWSTR
lstrcpyW( This->sPathRel, pszPathRel ); lstrcpyW( This->sPathRel, pszPathRel );
This->bDirty = TRUE; This->bDirty = TRUE;
return _IShellLink_UpdatePath(This->sPathRel, This->sPath, &This->sPath); return SHELL_ShellLink_UpdatePath(This->sPathRel, This->sPath, This->sWorkDir, &This->sPath);
} }
static HRESULT WINAPI IShellLinkW_fnResolve(IShellLinkW * iface, HWND hwnd, DWORD fFlags) static HRESULT WINAPI IShellLinkW_fnResolve(IShellLinkW * iface, HWND hwnd, DWORD fFlags)

View file

@ -107,10 +107,10 @@ static BOOL argifyA(char* out, int len, const char* fmt, const char* lpFile, LPI
} }
else else
{ {
*res++ = '"'; /* *res++ = '"'; */
while(*args && !isspace(*args)) while(*args && !isspace(*args))
*res++ = *args++; *res++ = *args++;
*res++ = '"'; /* *res++ = '"'; */
while(isspace(*args)) while(isspace(*args))
++args; ++args;
@ -135,10 +135,10 @@ static BOOL argifyA(char* out, int len, const char* fmt, const char* lpFile, LPI
} }
else else
{ {
*res++ = '"'; /* *res++ = '"'; */
strcpy(res, cmd); strcpy(res, cmd);
res += strlen(cmd); res += strlen(cmd);
*res++ = '"'; /* *res++ = '"'; */
} }
} }
} }
@ -182,8 +182,47 @@ static BOOL argifyA(char* out, int len, const char* fmt, const char* lpFile, LPI
return done; return done;
} }
HRESULT SHELL_GetPathFromIDListForExecuteA(LPCITEMIDLIST pidl, LPSTR pszPath, UINT uOutSize)
{
STRRET strret;
IShellFolder* desktop;
HRESULT hr = SHGetDesktopFolder(&desktop);
if (SUCCEEDED(hr)) {
hr = IShellFolder_GetDisplayNameOf(desktop, pidl, SHGDN_FORPARSING, &strret);
if (SUCCEEDED(hr))
StrRetToStrNA(pszPath, uOutSize, &strret, pidl);
IShellFolder_Release(desktop);
}
return hr;
}
HRESULT SHELL_GetPathFromIDListForExecuteW(LPCITEMIDLIST pidl, LPWSTR pszPath, UINT uOutSize)
{
STRRET strret;
IShellFolder* desktop;
HRESULT hr = SHGetDesktopFolder(&desktop);
if (SUCCEEDED(hr)) {
hr = IShellFolder_GetDisplayNameOf(desktop, pidl, SHGDN_FORPARSING, &strret);
if (SUCCEEDED(hr))
StrRetToStrNW(pszPath, uOutSize, &strret, pidl);
IShellFolder_Release(desktop);
}
return hr;
}
/************************************************************************* /*************************************************************************
* SHELL_ResolveShortCutW [Internal] * SHELL_ResolveShortCutW [Internal]
* read shortcut file at 'wcmd' and fill psei with its content
*/ */
static HRESULT SHELL_ResolveShortCutW(LPWSTR wcmd, LPWSTR wargs, LPWSTR wdir, HWND hwnd, LPCWSTR lpVerb, int* pshowcmd, LPITEMIDLIST* ppidl) static HRESULT SHELL_ResolveShortCutW(LPWSTR wcmd, LPWSTR wargs, LPWSTR wdir, HWND hwnd, LPCWSTR lpVerb, int* pshowcmd, LPITEMIDLIST* ppidl)
{ {
@ -217,15 +256,9 @@ static HRESULT SHELL_ResolveShortCutW(LPWSTR wcmd, LPWSTR wargs, LPWSTR wdir, HW
if (SUCCEEDED(hr) && *ppidl) { if (SUCCEEDED(hr) && *ppidl) {
/* We got a PIDL instead of a file system path - try to translate it. */ /* We got a PIDL instead of a file system path - try to translate it. */
hr = SHELL_GetPathFromIDListW(*ppidl, wcmd, MAX_PATH); if (SUCCEEDED(SHELL_GetPathFromIDListW(*ppidl, wcmd, MAX_PATH))) {
if (SUCCEEDED(hr)) SHFree(*ppidl);
*ppidl = NULL; *ppidl = NULL;
if (wcmd[0]==':' && wcmd[1]==':') {
/* open shell folder for the specified class GUID */
strcpyW(wcmd, L"explorer.exe");
} else if (HCR_GetExecuteCommandW(L"Folder", lpVerb?lpVerb:L"open", wargs, MAX_PATH/*sizeof(szParameters)*/)) {
//FIXME@@ argifyW(wcmd, MAX_PATH/*sizeof(szApplicationName)*/, wargs, NULL, *ppidl, NULL);
} }
} }
} }
@ -253,6 +286,7 @@ static HRESULT SHELL_ResolveShortCutW(LPWSTR wcmd, LPWSTR wargs, LPWSTR wdir, HW
/************************************************************************* /*************************************************************************
* SHELL_ResolveShortCutA [Internal] * SHELL_ResolveShortCutA [Internal]
* read shortcut file at 'psei->lpFile' and fill psei with its content
*/ */
static HRESULT SHELL_ResolveShortCutA(LPSHELLEXECUTEINFOA psei) static HRESULT SHELL_ResolveShortCutA(LPSHELLEXECUTEINFOA psei)
{ {
@ -266,6 +300,9 @@ static HRESULT SHELL_ResolveShortCutA(LPSHELLEXECUTEINFOA psei)
hr = SHELL_ResolveShortCutW(wcmd, wargs, wdir, psei->hwnd, wverb, &psei->nShow, (LPITEMIDLIST*)&psei->lpIDList); hr = SHELL_ResolveShortCutW(wcmd, wargs, wdir, psei->hwnd, wverb, &psei->nShow, (LPITEMIDLIST*)&psei->lpIDList);
if (psei->lpIDList)
psei->fMask |= SEE_MASK_IDLIST;
if (SUCCEEDED(hr)) { if (SUCCEEDED(hr)) {
WideCharToMultiByte(CP_ACP, 0, wcmd, -1, (LPSTR)psei->lpFile, MAX_PATH/*sizeof(szApplicationName)*/, NULL, NULL); WideCharToMultiByte(CP_ACP, 0, wcmd, -1, (LPSTR)psei->lpFile, MAX_PATH/*sizeof(szApplicationName)*/, NULL, NULL);
WideCharToMultiByte(CP_ACP, 0, wdir, -1, (LPSTR)psei->lpDirectory, MAX_PATH/*sizeof(szDir)*/, NULL, NULL); WideCharToMultiByte(CP_ACP, 0, wdir, -1, (LPSTR)psei->lpDirectory, MAX_PATH/*sizeof(szDir)*/, NULL, NULL);
@ -388,7 +425,7 @@ static void *build_env( const char *path )
* On entry: szName is a filename (probably without path separators). * On entry: szName is a filename (probably without path separators).
* On exit: if szName found in "App Path", place full path in lpResult, and return true * On exit: if szName found in "App Path", place full path in lpResult, and return true
*/ */
static BOOL SHELL_TryAppPath( LPCSTR szName, LPSTR lpResult, void**env) static BOOL SHELL_TryAppPath(LPCSTR szName, LPSTR lpResult, void** env)
{ {
HKEY hkApp = 0; HKEY hkApp = 0;
char buffer[256]; char buffer[256];
@ -623,11 +660,11 @@ UINT SHELL_FindExecutable(LPCSTR lpPath, LPCSTR lpFile, LPCSTR lpOperation,
{ {
argifyA(lpResult, sizeof(lpResult), command, xlpFile, pidl, args); argifyA(lpResult, sizeof(lpResult), command, xlpFile, pidl, args);
/* Remove double quotation marks */ /* Remove double quotation marks and command line arguments */
if (*lpResult == '"') if (*lpResult == '"')
{ {
char *p = lpResult; char *p = lpResult;
while (*(p + 1) != '"' && *(p + 1) != ' ') while (*(p + 1) != '"')
{ {
*p = *(p + 1); *p = *(p + 1);
p++; p++;
@ -694,6 +731,7 @@ static unsigned dde_connect(char* key, char* start, char* ddeexec,
{ {
char* endkey = key + strlen(key); char* endkey = key + strlen(key);
char app[256], topic[256], ifexec[256]; char app[256], topic[256], ifexec[256];
char res[1024];
LONG applen, topiclen, ifexeclen; LONG applen, topiclen, ifexeclen;
char* exec; char* exec;
DWORD ddeInst = 0; DWORD ddeInst = 0;
@ -751,12 +789,10 @@ static unsigned dde_connect(char* key, char* start, char* ddeexec,
} }
} }
#if 0 /* argifyA has already been called. */
argifyA(res, sizeof(res), exec, lpFile, pidl, szCommandline); argifyA(res, sizeof(res), exec, lpFile, pidl, szCommandline);
TRACE("%s %s => %s\n", exec, lpFile, res); TRACE("%s %s => %s\n", exec, lpFile, res);
#endif
ret = (DdeClientTransaction((LPBYTE)szCommandline, strlen(szCommandline) + 1, hConv, 0L, 0, ret = (DdeClientTransaction((LPBYTE)res, strlen(res)+1, hConv, 0L, 0,
XTYP_EXECUTE, 10000, &tid) != DMLERR_NO_ERROR) ? 31 : 33; XTYP_EXECUTE, 10000, &tid) != DMLERR_NO_ERROR) ? 31 : 33;
DdeDisconnect(hConv); DdeDisconnect(hConv);
error: error:
@ -794,13 +830,10 @@ static UINT execute_from_key(LPSTR key, LPCSTR lpFile, void *env, LPCSTR szComma
} }
else else
{ {
#if 0 /* argifyA() has already been called. */
/* Is there a replace() function anywhere? */ /* Is there a replace() function anywhere? */
cmd[cmdlen] = '\0'; cmd[cmdlen] = '\0';
argifyA(param, sizeof(param), cmd, lpFile, psei->lpIDList, szCommandline); argifyA(param, sizeof(param), cmd, lpFile, psei->lpIDList, szCommandline);
#else
strcpy(param, szCommandline);
#endif
retval = SHELL_ExecuteA(param, env, FALSE, psei, psei_out); retval = SHELL_ExecuteA(param, env, FALSE, psei, psei_out);
} }
} }
@ -858,7 +891,7 @@ HINSTANCE WINAPI FindExecutableW(LPCWSTR lpFile, LPCWSTR lpDirectory, LPWSTR lpR
* FIXME: use PathProcessCommandA() to processes the command line string * FIXME: use PathProcessCommandA() to processes the command line string
* use PathResolveA() to search for the fully qualified executable path * use PathResolveA() to search for the fully qualified executable path
*/ */
BOOL WINAPI ShellExecuteExA32 (LPSHELLEXECUTEINFOA psei) BOOL WINAPI ShellExecuteExA32(LPSHELLEXECUTEINFOA psei)
{ {
CHAR szApplicationName[MAX_PATH+2], szParameters[MAX_PATH], fileName[MAX_PATH], szDir[MAX_PATH]; CHAR szApplicationName[MAX_PATH+2], szParameters[MAX_PATH], fileName[MAX_PATH], szDir[MAX_PATH];
SHELLEXECUTEINFOA sei_tmp; /* modifyable copy of SHELLEXECUTEINFO struct */ SHELLEXECUTEINFOA sei_tmp; /* modifyable copy of SHELLEXECUTEINFO struct */
@ -866,9 +899,8 @@ BOOL WINAPI ShellExecuteExA32 (LPSHELLEXECUTEINFOA psei)
char szProtocol[256]; char szProtocol[256];
LPCSTR lpFile; LPCSTR lpFile;
UINT retval = 31; UINT retval = 31;
char cmd[1024]; char buffer[1024];
const char* ext; const char* ext;
BOOL done;
memcpy(&sei_tmp, psei, sizeof(sei_tmp)); memcpy(&sei_tmp, psei, sizeof(sei_tmp));
@ -914,7 +946,8 @@ BOOL WINAPI ShellExecuteExA32 (LPSHELLEXECUTEINFOA psei)
HRESULT hr = SHBindToParent(sei_tmp.lpIDList, &IID_IShellExecuteHookA, (LPVOID*)&pSEH, NULL); HRESULT hr = SHBindToParent(sei_tmp.lpIDList, &IID_IShellExecuteHookA, (LPVOID*)&pSEH, NULL);
if (SUCCEEDED(hr)) { if (SUCCEEDED(hr))
{
hr = IShellExecuteHookA_Execute(pSEH, psei); hr = IShellExecuteHookA_Execute(pSEH, psei);
IShellExecuteHookA_Release(pSEH); IShellExecuteHookA_Release(pSEH);
@ -923,9 +956,12 @@ BOOL WINAPI ShellExecuteExA32 (LPSHELLEXECUTEINFOA psei)
return TRUE; return TRUE;
} }
/* translate PIDL into the corresponding file system path */ /* try to translate PIDL directly into the corresponding file system path */
if (FAILED(SHELL_GetPathFromIDListA(sei_tmp.lpIDList, szApplicationName/*sei_tmp.lpFile*/, sizeof(szApplicationName)))) if (SUCCEEDED(SHELL_GetPathFromIDListA(sei_tmp.lpIDList, szApplicationName/*sei_tmp.lpFile*/, sizeof(szApplicationName))))
return FALSE; {
sei_tmp.lpIDList = NULL;
sei_tmp.fMask &= ~SEE_MASK_INVOKEIDLIST;
}
TRACE("-- idlist=%p (%s)\n", sei_tmp.lpIDList, sei_tmp.lpFile); TRACE("-- idlist=%p (%s)\n", sei_tmp.lpIDList, sei_tmp.lpFile);
} }
@ -945,17 +981,17 @@ BOOL WINAPI ShellExecuteExA32 (LPSHELLEXECUTEINFOA psei)
szParameters/*sei_tmp.lpParameters*/, sizeof(szParameters)); szParameters/*sei_tmp.lpParameters*/, sizeof(szParameters));
/* FIXME: get the extension of lpFile, check if it fits to the lpClass */ /* FIXME: get the extension of lpFile, check if it fits to the lpClass */
TRACE("SEE_MASK_CLASSNAME->'%s', doc->'%s'\n", szParameters, sei_tmp.lpFile); TRACE("SEE_MASK_CLASSNAME->'%s', doc->'%s'\n", sei_tmp.lpParameters, sei_tmp.lpFile);
cmd[0] = '\0'; buffer[0] = '\0';
done = argifyA(cmd, sizeof(cmd), szParameters, sei_tmp.lpFile, sei_tmp.lpIDList, NULL);
if (!done && sei_tmp.lpFile[0]) if (!argifyA(buffer, sizeof(buffer), sei_tmp.lpParameters, sei_tmp.lpFile, sei_tmp.lpIDList, NULL) && sei_tmp.lpFile[0])
{ {
strcat(cmd, " "); strcat(buffer, " ");
strcat(cmd, sei_tmp.lpFile); strcat(buffer, sei_tmp.lpFile);
} }
retval = SHELL_ExecuteA(cmd, NULL, FALSE, &sei_tmp, psei); retval = SHELL_ExecuteA(buffer, NULL, FALSE, &sei_tmp, psei);
if (retval > 32) if (retval > 32)
return TRUE; return TRUE;
else else
@ -963,26 +999,75 @@ BOOL WINAPI ShellExecuteExA32 (LPSHELLEXECUTEINFOA psei)
} }
/* Else, try to execute the filename */ /* Else, try to execute the filename */
TRACE("execute:'%s','%s'\n", sei_tmp.lpFile, szParameters); TRACE("execute:'%s','%s'\n", sei_tmp.lpFile, sei_tmp.lpParameters);
/* resolve shell shortcuts */ /* resolve shell shortcuts */
ext = PathFindExtensionA(sei_tmp.lpFile); ext = PathFindExtensionA(sei_tmp.lpFile);
if (ext && !strcasecmp(ext, ".lnk")) /* or check for: shell_attribs & SFGAO_LINK */ if (ext && !strcasecmp(ext, ".lnk")) /* or check for: shell_attribs & SFGAO_LINK */
SHELL_ResolveShortCutA(&sei_tmp); {
if (SUCCEEDED(SHELL_ResolveShortCutA(&sei_tmp)))
{
/* repeat IDList processing if needed */
if (sei_tmp.fMask & SEE_MASK_IDLIST)
{
IShellExecuteHookA* pSEH;
HRESULT hr = SHBindToParent(sei_tmp.lpIDList, &IID_IShellExecuteHookA, (LPVOID*)&pSEH, NULL);
if (SUCCEEDED(hr))
{
hr = IShellExecuteHookA_Execute(pSEH, psei);
IShellExecuteHookA_Release(pSEH);
if (hr == S_OK)
return TRUE;
}
TRACE("-- idlist=%p (%s)\n", sei_tmp.lpIDList, sei_tmp.lpFile);
}
}
}
/* Has the IDList not yet been translated? */
if (sei_tmp.fMask & SEE_MASK_IDLIST)
{
/* last chance to translate IDList: now also allow CLSID paths */
if (SUCCEEDED(SHELL_GetPathFromIDListForExecuteA(sei_tmp.lpIDList, buffer, sizeof(buffer)))) {
if (buffer[0]==':' && buffer[1]==':') {
/* open shell folder for the specified class GUID */
strcpy(szParameters, buffer);
strcpy(szApplicationName, "explorer.exe");
sei_tmp.fMask &= ~SEE_MASK_INVOKEIDLIST;
} else if (HCR_GetExecuteCommandA("Folder", sei_tmp.lpVerb?sei_tmp.lpVerb:"open", buffer, sizeof(buffer))) {
argifyA(szApplicationName, sizeof(szApplicationName), buffer, NULL, sei_tmp.lpIDList, NULL);
sei_tmp.fMask &= ~SEE_MASK_INVOKEIDLIST;
}
}
}
/* expand environment strings */ /* expand environment strings */
if (ExpandEnvironmentStringsA(sei_tmp.lpFile, cmd, MAX_PATH))
lstrcpyA(szApplicationName/*sei_tmp.lpFile*/, cmd);
if (ExpandEnvironmentStringsA(sei_tmp.lpParameters, cmd, MAX_PATH)) if (ExpandEnvironmentStringsA(sei_tmp.lpFile, buffer, MAX_PATH))
lstrcpyA(szParameters/*sei_tmp.lpParameters*/, cmd); lstrcpyA(szApplicationName/*sei_tmp.lpFile*/, buffer);
if (*sei_tmp.lpParameters)
if (ExpandEnvironmentStringsA(sei_tmp.lpParameters, buffer, MAX_PATH))
lstrcpyA(szParameters/*sei_tmp.lpParameters*/, buffer);
if (*sei_tmp.lpDirectory)
if (ExpandEnvironmentStringsA(sei_tmp.lpDirectory, buffer, MAX_PATH))
lstrcpyA(szDir/*sei_tmp.lpDirectory*/, buffer);
if (ExpandEnvironmentStringsA(sei_tmp.lpDirectory, cmd, MAX_PATH))
lstrcpyA(szDir/*sei_tmp.lpDirectory*/, cmd);
/* separate out command line arguments from executable file name */ /* separate out command line arguments from executable file name */
if (!*szParameters) { if (!*sei_tmp.lpParameters) {
/* If the executable path is quoted, handle the rest of the command line as parameters. */ /* If the executable path is quoted, handle the rest of the command line as parameters. */
if (sei_tmp.lpFile[0] == '"') { if (sei_tmp.lpFile[0] == '"') {
LPSTR src = szApplicationName/*sei_tmp.lpFile*/ + 1; LPSTR src = szApplicationName/*sei_tmp.lpFile*/ + 1;
@ -1003,10 +1088,10 @@ BOOL WINAPI ShellExecuteExA32 (LPSHELLEXECUTEINFOA psei)
} else } else
end = src; end = src;
/* copy the paremeter string to 'szParameters' */ /* copy the parameter string to 'szParameters' */
strcpy(szParameters, src); strcpy(szParameters, src);
/* terminate 'sei_tmp.lpFile' after the quote character */ /* terminate previous command string after the quote character */
*end = '\0'; *end = '\0';
} }
else else
@ -1044,9 +1129,9 @@ BOOL WINAPI ShellExecuteExA32 (LPSHELLEXECUTEINFOA psei)
lpFile = fileName; lpFile = fileName;
if (szParameters[0]) { if (sei_tmp.lpParameters[0]) {
strcat(szApplicationName/*sei_tmp.lpFile*/, " "); strcat(szApplicationName/*sei_tmp.lpFile*/, " ");
strcat(szApplicationName/*sei_tmp.lpFile*/, szParameters); strcat(szApplicationName/*sei_tmp.lpFile*/, sei_tmp.lpParameters);
} }
retval = SHELL_ExecuteA(sei_tmp.lpFile, NULL, FALSE, &sei_tmp, psei); retval = SHELL_ExecuteA(sei_tmp.lpFile, NULL, FALSE, &sei_tmp, psei);
@ -1062,34 +1147,39 @@ BOOL WINAPI ShellExecuteExA32 (LPSHELLEXECUTEINFOA psei)
} }
/* Else, try to find the executable */ /* Else, try to find the executable */
cmd[0] = '\0'; buffer[0] = '\0';
retval = SHELL_FindExecutable(*sei_tmp.lpDirectory? sei_tmp.lpDirectory: NULL, lpFile, sei_tmp.lpVerb, cmd, szProtocol, &env, sei_tmp.lpIDList, szParameters); retval = SHELL_FindExecutable(*sei_tmp.lpDirectory? sei_tmp.lpDirectory: NULL, lpFile, sei_tmp.lpVerb, buffer, szProtocol, &env, sei_tmp.lpIDList, sei_tmp.lpParameters);
if (retval > 32) /* Found */ if (retval > 32) /* Found */
{ {
#if 0 /* SHELL_FindExecutable() already quoted by calling argifyA() */ {
#if 1 /* SHELL_FindExecutable() already quoted by calling argifyA() [not any more] */
CHAR szQuotedCmd[MAX_PATH+2]; CHAR szQuotedCmd[MAX_PATH+2];
/* Must quote to handle case where cmd contains spaces, /* Must quote to handle case where 'buffer' contains spaces,
* else security hole if malicious user creates executable file "C:\\Program" * else security hole if malicious user creates executable file "C:\\Program"
* *
* FIXME: If we don't have set explicitly command line arguments, we must first * FIXME: If we don't have set explicitly command line arguments, we must first
* split executable path from optional command line arguments. Otherwise we would quote * split executable path from optional command line arguments. Otherwise we would quote
* the complete string with executable path _and_ arguments, which is not what we want. * the complete string with executable path _and_ arguments, which is not what we want.
*/ */
if (szParameters[0]) if (sei_tmp.lpParameters[0])
sprintf(szQuotedCmd, "\"%s\" %s", cmd, szParameters); sprintf(szQuotedCmd, "\"%s\" %s", buffer, sei_tmp.lpParameters);
else else
sprintf(szQuotedCmd, "\"%s\"", cmd); sprintf(szQuotedCmd, "\"%s\"", buffer);
TRACE("%s/%s => %s/%s\n", sei_tmp.lpFile, sei_tmp.lpVerb?sei_tmp.lpVerb:"NULL", szQuotedCmd, szProtocol); TRACE("%s/%s => %s/%s\n", sei_tmp.lpFile, sei_tmp.lpVerb?sei_tmp.lpVerb:"NULL", szQuotedCmd, szProtocol);
if (*szProtocol) if (*szProtocol)
retval = execute_from_key(szProtocol, lpFile, env, sei, SHELL_ExecuteA, szParameters, &sei_tmp, psei); retval = execute_from_key(szProtocol, lpFile, env, sei_tmp.lpParameters, &sei_tmp, psei);
else else
retval = SHELL_ExecuteA(szQuotedCmd, env, sei_tmp.lpDirectory, sei, FALSE); retval = SHELL_ExecuteA(szQuotedCmd, env, FALSE, &sei_tmp, psei);
#else #else
if (*szProtocol) if (*szProtocol)
retval = execute_from_key(szProtocol, lpFile, env, cmd, &sei_tmp, psei); retval = execute_from_key(szProtocol, lpFile, env, buffer, &sei_tmp, psei);
else else
retval = SHELL_ExecuteA(cmd, env, FALSE, &sei_tmp, psei); retval = SHELL_ExecuteA(buffer, env, FALSE, &sei_tmp, psei);
#endif #endif
}
if (env) HeapFree( GetProcessHeap(), 0, env ); if (env) HeapFree( GetProcessHeap(), 0, env );
} }
else if (PathIsURLA((LPSTR)lpFile)) /* File not found, check for URL */ else if (PathIsURLA((LPSTR)lpFile)) /* File not found, check for URL */
@ -1119,7 +1209,7 @@ BOOL WINAPI ShellExecuteExA32 (LPSHELLEXECUTEINFOA psei)
while (*lpFile == ':') lpFile++; while (*lpFile == ':') lpFile++;
} }
retval = execute_from_key(szProtocol, lpFile, NULL, szParameters, &sei_tmp, psei); retval = execute_from_key(szProtocol, lpFile, NULL, sei_tmp.lpParameters, &sei_tmp, psei);
} }
/* Check if file specified is in the form www.??????.*** */ /* Check if file specified is in the form www.??????.*** */
else if (!strncasecmp(lpFile, "www", 3)) else if (!strncasecmp(lpFile, "www", 3))