shell32 patch 23e
Martin Fuchs
martin-fuchs at gmx.net
Thu Mar 18 16:39:26 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()
- Remove unnecessary double quotation marks and command line arguments
- FIXME comment for len paramater in SHELL_ArgifyW()
Quotation mark handling is from Ge van Geldorp <ge at gse.nl>.
Index: shlexec.c
===================================================================
RCS file: /home/wine/wine/dlls/shell32/shlexec.c,v
retrieving revision 1.34
diff -u -p -d -r1.34 shlexec.c
--- shlexec.c 18 Mar 2004 04:04:29 -0000 1.34
+++ shlexec.c 18 Mar 2004 22:37:53 -0000
@@ -71,11 +71,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;
+ LPVOID pv;
+ PWSTR res = out;
+ PCWSTR cmd;
while (*fmt)
{
@@ -87,30 +92,82 @@ 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) == '"')
+ {
+ strcpyW(res, cmd);
+ res += strlenW(cmd);
+ }
+ 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 +178,9 @@ static BOOL SHELL_ArgifyW(WCHAR* res, in
else
*res++ = *fmt++;
}
+
*res = '\0';
+
return done;
}
@@ -332,7 +391,7 @@ static UINT SHELL_FindExecutableByOperat
* on the operation)
*/
static UINT SHELL_FindExecutable(LPCWSTR lpPath, LPCWSTR lpFile, LPCWSTR lpOperation,
- LPWSTR lpResult, LPWSTR key, void **env)
+ LPWSTR lpResult, int resultLen, LPWSTR key, void **env)
{
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};
@@ -477,8 +536,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 */
@@ -609,8 +680,10 @@ static unsigned dde_connect(WCHAR* key,
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;
}
@@ -706,7 +779,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);
TRACE("returning %s\n", debugstr_w(lpResult));
if (lpDirectory)
@@ -863,7 +936,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);
if (retval > 32) /* Found */
{
WCHAR wszQuotedCmd[MAX_PATH+2];
More information about the wine-patches
mailing list