shell32 patch 23e
Martin Fuchs
martin-fuchs at gmx.net
Thu Mar 25 14:27:37 CST 2004
Changelog:
- fix handling of %2, %3, ... and lower case format characters in SHELL_ArgifyW()
- move "%I" expansion from ShellExecuteEx() into common function SHELL_ArgifyW()
- pass buffer length to SHELL_FindExecutable()
- FIXME comment for len paramater in SHELL_ArgifyW()
Quotation mark handling is from Ge van Geldorp <ge at gse.nl>:
- Add double quotation marks unless we already have them (e.g.: "%1" %* for exefile)
- Remove unnecessary double quotation marks and command line arguments
Index: shell32_main.h
===================================================================
RCS file: /home/wine/wine/dlls/shell32/shell32_main.h,v
retrieving revision 1.83
diff -u -p -d -r1.83 shell32_main.h
--- shell32_main.h 22 Mar 2004 20:43:07 -0000 1.83
+++ shell32_main.h 25 Mar 2004 20:56:09 -0000
@@ -233,6 +233,9 @@ typedef UINT (*SHELL_ExecuteW32)(const W
BOOL WINAPI ShellExecuteExW32(LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc);
+UINT SHELL_FindExecutable(LPCWSTR lpPath, LPCWSTR lpFile, LPCWSTR lpOperation,
+ LPWSTR lpResult, int resultLen, LPWSTR key, void **env, LPITEMIDLIST pidl, LPCWSTR args);
+
extern WCHAR swShell32Name[MAX_PATH];
#endif
Index: shelllink.c
===================================================================
RCS file: /home/wine/wine/dlls/shell32/shelllink.c,v
retrieving revision 1.62
diff -u -p -d -r1.62 shelllink.c
--- shelllink.c 22 Mar 2004 22:58:37 -0000 1.62
+++ shelllink.c 25 Mar 2004 20:56:10 -0000
@@ -652,20 +652,29 @@ static HRESULT WINAPI IPersistStream_fnS
IStream* stm,
BOOL fClearDirty)
{
+ static const WCHAR wOpen[] = {'o','p','e','n',0};
+
LINK_HEADER header;
- ULONG count;
- HRESULT r;
+ WCHAR exePath[MAX_PATH];
+ ULONG count;
+ HRESULT r;
- _ICOM_THIS_From_IPersistStream(IShellLinkImpl, iface);
+ _ICOM_THIS_From_IPersistStream(IShellLinkImpl, iface);
TRACE("(%p) %p %x\n", This, stm, fClearDirty);
+ *exePath = '\0';
+
+ if (This->sPath)
+ SHELL_FindExecutable(NULL, This->sPath, wOpen, exePath, MAX_PATH, NULL, NULL, NULL, NULL);
+
/* if there's no PIDL, generate one */
if( ! This->pPidl )
{
- if( ! This->sPath )
+ if( !*exePath )
return E_FAIL;
- This->pPidl = ILCreateFromPathW( This->sPath );
+
+ This->pPidl = ILCreateFromPathW(exePath);
}
memset(&header, 0, sizeof(header));
@@ -712,10 +721,7 @@ static HRESULT WINAPI IPersistStream_fnS
}
}
- TRACE("Path = %s\n", debugstr_w(This->sPath));
- if( ! This->sPath )
- return E_FAIL;
- Stream_WriteLocationInfo( stm, This->sPath );
+ Stream_WriteLocationInfo( stm, exePath );
TRACE("Description = %s\n", debugstr_w(This->sDescription));
if( This->sDescription )
Index: shlexec.c
===================================================================
RCS file: /home/wine/wine/dlls/shell32/shlexec.c,v
retrieving revision 1.35
diff -u -p -d -r1.35 shlexec.c
--- shlexec.c 19 Mar 2004 01:52:30 -0000 1.35
+++ shlexec.c 25 Mar 2004 20:56:10 -0000
@@ -54,6 +54,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(exec);
static const WCHAR wszOpen[] = {'o','p','e','n',0};
static const WCHAR wszExe[] = {'.','e','x','e',0};
+static const WCHAR wszILPtr[] = {':','%','p',0};
static const WCHAR wszShell[] = {'\\','s','h','e','l','l','\\',0};
@@ -71,11 +72,16 @@ static const WCHAR wszShell[] = {'\\','s
* %L seems to be %1 as long filename followed by the 8+3 variation
* %S ???
* %* all following parameters (see batfile)
+ *
+ * FIXME: use 'len'
*/
-static BOOL SHELL_ArgifyW(WCHAR* res, int len, const WCHAR* fmt, const WCHAR* lpFile)
+static BOOL SHELL_ArgifyW(WCHAR* out, int len, const WCHAR* fmt, const WCHAR* lpFile, LPITEMIDLIST pidl, LPCWSTR args)
{
- WCHAR xlpFile[1024];
- BOOL done = FALSE;
+ WCHAR xlpFile[1024];
+ BOOL done = FALSE;
+ PWSTR res = out;
+ PCWSTR cmd;
+ LPVOID pv;
while (*fmt)
{
@@ -87,30 +93,84 @@ static BOOL SHELL_ArgifyW(WCHAR* res, in
case '%':
*res++ = '%';
break;
- case '1':
- case '*':
- if (!done || (*fmt == '1'))
- {
- if (SearchPathW(NULL, lpFile, wszExe, sizeof(xlpFile)/sizeof(WCHAR), xlpFile, NULL))
- {
- strcpyW(res, xlpFile);
- res += strlenW(xlpFile);
- }
- else
- {
- strcpyW(res, lpFile);
- res += strlenW(lpFile);
- }
- }
+
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case '0':
+ case '*':
+ if (args)
+ {
+ if (*fmt == '*')
+ {
+ *res++ = '"';
+ while(*args)
+ *res++ = *args++;
+ *res++ = '"';
+ }
+ else
+ {
+ while(*args && !isspace(*args))
+ *res++ = *args++;
+
+ while(isspace(*args))
+ ++args;
+ }
+ }
+ else
+ {
+ case '1':
+ if (!done || (*fmt == '1'))
+ {
+ /*FIXME Is the call to SearchPathW() really needed? We already have separated out the parameter string in args. */
+ if (SearchPathW(NULL, lpFile, wszExe, sizeof(xlpFile)/sizeof(WCHAR), xlpFile, NULL))
+ cmd = xlpFile;
+ else
+ cmd = lpFile;
+
+ /* Add double quotation marks unless we already have them (e.g.: "%1" %* for exefile) */
+ if (res==out || res[-1]!='"')
+ {
+ *res++ = '"';
+ strcpyW(res, cmd);
+ res += strlenW(cmd);
+ *res++ = '"';
+ }
+ else
+ {
+ strcpyW(res, cmd);
+ res += strlenW(cmd);
+ }
+ }
+ }
break;
+
/*
* IE uses this alot for activating things such as windows media
* player. This is not verified to be fully correct but it appears
* to work just fine.
*/
- case 'L':
- strcpyW(res,lpFile);
- res += strlenW(lpFile);
+ case 'l':
+ case 'L':
+ if (lpFile) {
+ strcpyW(res, lpFile);
+ res += strlenW(lpFile);
+ }
+ break;
+
+ case 'i':
+ case 'I':
+ if (pidl) {
+ HGLOBAL hmem = SHAllocShared(pidl, ILGetSize(pidl), 0);
+ pv = SHLockShared(hmem, 0);
+ res += sprintfW(res, wszILPtr, pv);
+ SHUnlockShared(pv);
+ }
break;
default: FIXME("Unknown escape sequence %%%c\n", *fmt);
@@ -121,7 +181,9 @@ static BOOL SHELL_ArgifyW(WCHAR* res, in
else
*res++ = *fmt++;
}
+
*res = '\0';
+
return done;
}
@@ -343,8 +405,8 @@ static UINT SHELL_FindExecutableByOperat
* command (it'll be used afterwards for more information
* on the operation)
*/
-static UINT SHELL_FindExecutable(LPCWSTR lpPath, LPCWSTR lpFile, LPCWSTR lpOperation,
- LPWSTR lpResult, LPWSTR key, void **env)
+UINT SHELL_FindExecutable(LPCWSTR lpPath, LPCWSTR lpFile, LPCWSTR lpOperation,
+ LPWSTR lpResult, int resultLen, LPWSTR key, void **env, LPITEMIDLIST pidl, LPCWSTR args)
{
static const WCHAR wWindows[] = {'w','i','n','d','o','w','s',0};
static const WCHAR wPrograms[] = {'p','r','o','g','r','a','m','s',0};
@@ -489,8 +551,20 @@ static UINT SHELL_FindExecutable(LPCWSTR
}
if (retval > 32)
- {
- SHELL_ArgifyW(lpResult, 1024 /*FIXME*/, command, xlpFile);
+ {
+ SHELL_ArgifyW(lpResult, resultLen, command, xlpFile, pidl, args);
+
+ /* Remove double quotation marks and command line arguments */
+ if (*lpResult == '"')
+ {
+ WCHAR *p = lpResult;
+ while (*(p + 1) != '"')
+ {
+ *p = *(p + 1);
+ p++;
+ }
+ *p = '\0';
+ }
}
}
else /* Check win.ini */
@@ -548,7 +622,7 @@ static HDDEDATA CALLBACK dde_cb(UINT uTy
*/
static unsigned dde_connect(WCHAR* key, WCHAR* start, WCHAR* ddeexec,
const WCHAR* lpFile, void *env,
- SHELL_ExecuteW32 execfunc,
+ LPCWSTR szCommandline, LPITEMIDLIST pidl, SHELL_ExecuteW32 execfunc,
LPSHELLEXECUTEINFOW psei, LPSHELLEXECUTEINFOW psei_out)
{
static const WCHAR wApplication[] = {'\\','a','p','p','l','i','c','a','t','i','o','n',0};
@@ -615,21 +689,23 @@ static unsigned dde_connect(WCHAR* key,
}
}
- SHELL_ArgifyW(res, sizeof(res)/sizeof(WCHAR), exec, lpFile);
+ SHELL_ArgifyW(res, sizeof(res)/sizeof(WCHAR), exec, lpFile, pidl, szCommandline);
TRACE("%s %s => %s\n", debugstr_w(exec), debugstr_w(lpFile), debugstr_w(res));
ret = (DdeClientTransaction((LPBYTE)res, (strlenW(res) + 1) * sizeof(WCHAR), hConv, 0L, 0,
XTYP_EXECUTE, 10000, &tid) != DMLERR_NO_ERROR) ? 31 : 33;
DdeDisconnect(hConv);
+
error:
DdeUninitialize(ddeInst);
+
return ret;
}
/*************************************************************************
* execute_from_key [Internal]
*/
-static UINT execute_from_key(LPWSTR key, LPCWSTR lpFile, void *env,
+static UINT execute_from_key(LPWSTR key, LPCWSTR lpFile, void *env, LPCWSTR szCommandline,
SHELL_ExecuteW32 execfunc,
LPSHELLEXECUTEINFOW psei, LPSHELLEXECUTEINFOW psei_out)
{
@@ -655,14 +731,14 @@ static UINT execute_from_key(LPWSTR key,
if (RegQueryValueW(HKEY_CLASSES_ROOT, key, param, ¶mlen) == ERROR_SUCCESS)
{
TRACE("Got ddeexec %s => %s\n", debugstr_w(key), debugstr_w(param));
- retval = dde_connect(key, cmd, param, lpFile, env, execfunc, psei, psei_out);
+ retval = dde_connect(key, cmd, param, lpFile, env, szCommandline, psei->lpIDList, execfunc, psei, psei_out);
}
else
{
/* Is there a replace() function anywhere? */
cmdlen /= sizeof(WCHAR);
cmd[cmdlen] = '\0';
- SHELL_ArgifyW(param, sizeof(param)/sizeof(WCHAR), cmd, lpFile);
+ SHELL_ArgifyW(param, sizeof(param)/sizeof(WCHAR), cmd, lpFile, psei->lpIDList, szCommandline);
retval = execfunc(param, env, FALSE, psei, psei_out);
}
}
@@ -718,7 +794,7 @@ HINSTANCE WINAPI FindExecutableW(LPCWSTR
SetCurrentDirectoryW(lpDirectory);
}
- retval = SHELL_FindExecutable(lpDirectory, lpFile, wszOpen, lpResult, NULL, NULL);
+ retval = SHELL_FindExecutable(lpDirectory, lpFile, wszOpen, lpResult, MAX_PATH, NULL, NULL, NULL, NULL);
TRACE("returning %s\n", debugstr_w(lpResult));
if (lpDirectory)
@@ -739,10 +815,8 @@ BOOL WINAPI ShellExecuteExW32 (LPSHELLEX
WCHAR wszApplicationName[MAX_PATH+2], wszCommandline[1024], wszDir[MAX_PATH];
SHELLEXECUTEINFOW sei_tmp; /* modifyable copy of SHELLEXECUTEINFO struct */
- WCHAR wszPidl[20], wfileName[MAX_PATH];
- LPWSTR pos;
+ WCHAR wfileName[MAX_PATH];
void *env;
- int gap, len;
WCHAR lpstrProtocol[256];
LPCWSTR lpFile;
UINT retval = 31;
@@ -798,27 +872,6 @@ BOOL WINAPI ShellExecuteExW32 (LPSHELLEX
strcatW(wszApplicationName, wQuote);
TRACE("-- idlist=%p (%s)\n", sei_tmp.lpIDList, debugstr_w(wszApplicationName));
}
- else
- {
- if (sei_tmp.fMask & SEE_MASK_IDLIST)
- {
- static const WCHAR wI[] = {'%','I',0}, wP[] = {':','%','p',0};
- pos = strstrW(wszCommandline, wI);
- if (pos)
- {
- LPVOID pv;
- HGLOBAL hmem = SHAllocShared(sei_tmp.lpIDList, ILGetSize(sei_tmp.lpIDList), 0);
- pv = SHLockShared(hmem,0);
- sprintfW(wszPidl,wP,pv );
- SHUnlockShared(pv);
-
- gap = strlenW(wszPidl);
- len = strlenW(pos)-2;
- memmove(pos+gap,pos+2,len*sizeof(WCHAR));
- memcpy(pos,wszPidl,gap*sizeof(WCHAR));
- }
- }
- }
if (sei_tmp.fMask & (SEE_MASK_CLASSNAME | SEE_MASK_CLASSKEY))
{
@@ -834,7 +887,7 @@ BOOL WINAPI ShellExecuteExW32 (LPSHELLEX
TRACE("SEE_MASK_CLASSNAME->'%s', doc->'%s'\n", debugstr_w(wszCommandline), debugstr_w(wszApplicationName));
wcmd[0] = '\0';
- done = SHELL_ArgifyW(wcmd, sizeof(wcmd)/sizeof(WCHAR), wszCommandline, wszApplicationName);
+ done = SHELL_ArgifyW(wcmd, sizeof(wcmd)/sizeof(WCHAR), wszCommandline, wszApplicationName, sei_tmp.lpIDList, NULL);
if (!done && wszApplicationName[0])
{
strcatW(wcmd, wSpace);
@@ -875,7 +928,7 @@ BOOL WINAPI ShellExecuteExW32 (LPSHELLEX
/* Else, try to find the executable */
wcmd[0] = '\0';
- retval = SHELL_FindExecutable(sei_tmp.lpDirectory, lpFile, sei_tmp.lpVerb, wcmd, lpstrProtocol, &env);
+ retval = SHELL_FindExecutable(sei_tmp.lpDirectory, lpFile, sei_tmp.lpVerb, wcmd, 1024, lpstrProtocol, &env, sei_tmp.lpIDList, sei_tmp.lpParameters);
if (retval > 32) /* Found */
{
WCHAR wszQuotedCmd[MAX_PATH+2];
@@ -891,7 +944,7 @@ BOOL WINAPI ShellExecuteExW32 (LPSHELLEX
}
TRACE("%s/%s => %s/%s\n", debugstr_w(wszApplicationName), debugstr_w(sei_tmp.lpVerb), debugstr_w(wszQuotedCmd), debugstr_w(lpstrProtocol));
if (*lpstrProtocol)
- retval = execute_from_key(lpstrProtocol, wszApplicationName, env, execfunc, &sei_tmp, sei);
+ retval = execute_from_key(lpstrProtocol, wszApplicationName, env, sei_tmp.lpParameters, execfunc, &sei_tmp, sei);
else
retval = execfunc(wszQuotedCmd, env, FALSE, &sei_tmp, sei);
if (env) HeapFree( GetProcessHeap(), 0, env );
@@ -924,7 +977,7 @@ BOOL WINAPI ShellExecuteExW32 (LPSHELLEX
lpFile += iSize;
while (*lpFile == ':') lpFile++;
}
- retval = execute_from_key(lpstrProtocol, lpFile, NULL, execfunc, &sei_tmp, sei);
+ retval = execute_from_key(lpstrProtocol, lpFile, NULL, sei_tmp.lpParameters, execfunc, &sei_tmp, sei);
}
/* Check if file specified is in the form www.??????.*** */
else if (!strncmpiW(lpFile, wWww, 3))
More information about the wine-patches
mailing list