shell32 patch 23h
Martin Fuchs
martin-fuchs at gmx.net
Sat Apr 3 04:09:31 CST 2004
Changelog:
resolve shell shortcuts and process ID lists in ShellExecute() functions
Index: shlexec.c
===================================================================
RCS file: /home/wine/wine/dlls/shell32/shlexec.c,v
retrieving revision 1.38
diff -u -p -d -r1.38 shlexec.c
--- shlexec.c 1 Apr 2004 21:00:23 -0000 1.38
+++ shlexec.c 3 Apr 2004 10:06:28 -0000
@@ -47,6 +47,7 @@
#include "wine/winbase16.h"
#include "shell32_main.h"
#include "undocshell.h"
+#include "pidl.h"
#include "wine/debug.h"
@@ -56,6 +57,8 @@ static const WCHAR wszOpen[] = {'o','p',
static const WCHAR wszExe[] = {'.','e','x','e',0};
static const WCHAR wszILPtr[] = {':','%','p',0};
static const WCHAR wszShell[] = {'\\','s','h','e','l','l','\\',0};
+static const WCHAR wszFolder[] = {'F','o','l','d','e','r',0};
+static const WCHAR wszEmpty[] = {0};
/***********************************************************************
@@ -186,6 +189,108 @@ static BOOL SHELL_ArgifyW(WCHAR* out, in
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]
+ * read shortcut file at 'wcmd'
+ */
+static HRESULT SHELL_ResolveShortCutW(LPWSTR wcmd, LPWSTR wargs, LPWSTR wdir, HWND hwnd, LPCWSTR lpVerb, int* pshowcmd, LPITEMIDLIST* ppidl)
+{
+ IShellFolder* psf;
+
+ HRESULT hr = SHGetDesktopFolder(&psf);
+
+ *ppidl = NULL;
+
+ if (SUCCEEDED(hr)) {
+ LPITEMIDLIST pidl;
+ ULONG l;
+
+ hr = IShellFolder_ParseDisplayName(psf, 0, 0, wcmd, &l, &pidl, 0);
+
+ if (SUCCEEDED(hr)) {
+ IShellLinkW* psl;
+
+ hr = IShellFolder_GetUIObjectOf(psf, NULL, 1, (LPCITEMIDLIST*)&pidl, &IID_IShellLinkW, NULL, (LPVOID*)&psl);
+
+ if (SUCCEEDED(hr)) {
+ hr = IShellLinkW_Resolve(psl, hwnd, 0);
+
+ if (SUCCEEDED(hr)) {
+ hr = IShellLinkW_GetPath(psl, wcmd, MAX_PATH, NULL, SLGP_UNCPRIORITY);
+
+ if (SUCCEEDED(hr)) {
+ if (!*wcmd) {
+ /* We could not translate the PIDL in the shell link into a valid file system path - so return the PIDL instead. */
+ hr = IShellLinkW_GetIDList(psl, ppidl);
+
+ if (SUCCEEDED(hr) && *ppidl) {
+ /* We got a PIDL instead of a file system path - try to translate it. */
+ if (SUCCEEDED(SHELL_GetPathFromIDListW(*ppidl, wcmd, MAX_PATH))) {
+ SHFree(*ppidl);
+ *ppidl = NULL;
+ }
+ }
+ }
+
+ if (SUCCEEDED(hr)) {
+ /* get command line arguments, working directory and display mode if available */
+ IShellLinkW_GetWorkingDirectory(psl, wdir, MAX_PATH);
+ IShellLinkW_GetArguments(psl, wargs, MAX_PATH);
+ IShellLinkW_GetShowCmd(psl, pshowcmd);
+ }
+ }
+ }
+
+ IShellLinkW_Release(psl);
+ }
+
+ SHFree(pidl);
+ }
+
+ IShellFolder_Release(psf);
+ }
+
+ return hr;
+}
+
/*************************************************************************
* SHELL_ExecuteW [Internal]
*
@@ -569,11 +674,10 @@ UINT SHELL_FindExecutable(LPCWSTR lpPath
else /* Check win.ini */
{
static const WCHAR wExtensions[] = {'e','x','t','e','n','s','i','o','n','s',0};
- static const WCHAR wEmpty[] = {0};
/* Toss the leading dot */
extension++;
- if (GetProfileStringW(wExtensions, extension, wEmpty, command, sizeof(command)/sizeof(WCHAR)) > 0)
+ if (GetProfileStringW(wExtensions, extension, wszEmpty, command, sizeof(command)/sizeof(WCHAR)) > 0)
{
if (strlenW(command) != 0)
{
@@ -811,6 +915,8 @@ BOOL WINAPI ShellExecuteExW32 (LPSHELLEX
static const WCHAR wWww[] = {'w','w','w',0};
static const WCHAR wFile[] = {'f','i','l','e',0};
static const WCHAR wHttp[] = {'h','t','t','p',':','/','/',0};
+ static const WCHAR wExtLnk[] = {'.','l','n','k',0};
+ static const WCHAR wExplorer[] = {'e','x','p','l','o','r','e','r','.','e','x','e',0};
WCHAR wszApplicationName[MAX_PATH+2], wszCommandline[1024], wszDir[MAX_PATH];
SHELLEXECUTEINFOW sei_tmp; /* modifyable copy of SHELLEXECUTEINFO struct */
@@ -821,6 +927,7 @@ BOOL WINAPI ShellExecuteExW32 (LPSHELLEX
UINT retval = 31;
WCHAR wcmd[1024];
WCHAR buffer[MAX_PATH];
+ const WCHAR* ext;
BOOL done;
/* make a local copy of the LPSHELLEXECUTEINFO structure and work with this from now on */
@@ -912,6 +1019,73 @@ BOOL WINAPI ShellExecuteExW32 (LPSHELLEX
else
return FALSE;
}
+
+
+ /* resolve shell shortcuts */
+ ext = PathFindExtensionW(sei_tmp.lpFile);
+
+ if (ext && !strcmpiW(ext, wExtLnk)) /* or check for: shell_attribs & SFGAO_LINK */
+ {
+ HRESULT hr;
+
+ /* expand paths before reading shell link */
+ if (ExpandEnvironmentStringsW(sei_tmp.lpFile, buffer, MAX_PATH))
+ lstrcpyW(wszApplicationName/*sei_tmp.lpFile*/, buffer);
+
+ if (*sei_tmp.lpParameters)
+ if (ExpandEnvironmentStringsW(sei_tmp.lpParameters, buffer, MAX_PATH))
+ lstrcpyW(wszCommandline/*sei_tmp.lpParameters*/, buffer);
+
+ hr = SHELL_ResolveShortCutW((LPWSTR)sei_tmp.lpFile, (LPWSTR)sei_tmp.lpParameters, (LPWSTR)sei_tmp.lpDirectory,
+ sei_tmp.hwnd, sei_tmp.lpVerb?sei_tmp.lpVerb:wszEmpty, &sei_tmp.nShow, (LPITEMIDLIST*)&sei_tmp.lpIDList);
+
+ if (sei->lpIDList)
+ sei->fMask |= SEE_MASK_IDLIST;
+
+ if (SUCCEEDED(hr))
+ {
+ /* repeat IDList processing if needed */
+ if (sei_tmp.fMask & SEE_MASK_IDLIST)
+ {
+ IShellExecuteHookW* pSEH;
+
+ HRESULT hr = SHBindToParent(sei_tmp.lpIDList, &IID_IShellExecuteHookW, (LPVOID*)&pSEH, NULL);
+
+ if (SUCCEEDED(hr))
+ {
+ hr = IShellExecuteHookW_Execute(pSEH, sei);
+
+ IShellExecuteHookW_Release(pSEH);
+
+ if (hr == S_OK)
+ return TRUE;
+ }
+
+ TRACE("-- idlist=%p (%s)\n", debugstr_w(sei_tmp.lpIDList), debugstr_w(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_GetPathFromIDListForExecuteW(sei_tmp.lpIDList, buffer, sizeof(buffer)))) {
+ if (buffer[0]==':' && buffer[1]==':') {
+ /* open shell folder for the specified class GUID */
+ strcpyW(wszCommandline, buffer);
+ strcpyW(wszApplicationName, wExplorer);
+
+ sei_tmp.fMask &= ~SEE_MASK_INVOKEIDLIST;
+ } else if (HCR_GetExecuteCommandW(0, wszFolder, sei_tmp.lpVerb?sei_tmp.lpVerb:wszOpen, buffer, sizeof(buffer))) {
+ SHELL_ArgifyW(wszApplicationName, sizeof(wszApplicationName)/sizeof(WCHAR), buffer, NULL, sei_tmp.lpIDList, NULL);
+
+ sei_tmp.fMask &= ~SEE_MASK_INVOKEIDLIST;
+ }
+ }
+ }
+
/* expand environment strings */
if (ExpandEnvironmentStringsW(sei_tmp.lpFile, buffer, MAX_PATH))
More information about the wine-patches
mailing list