Author: cwittich
Date: Thu May 22 18:53:44 2014
New Revision: 63414
URL:
http://svn.reactos.org/svn/reactos?rev=63414&view=rev
Log:
[shell32]
Import some changes from Wine to shlexec.cpp
patch by Ivan Rodionov see CORE-8196
Modified:
trunk/reactos/dll/win32/shell32/classes.cpp
trunk/reactos/dll/win32/shell32/shell32_main.cpp
trunk/reactos/dll/win32/shell32/shell32_main.h
trunk/reactos/dll/win32/shell32/shlexec.cpp
Modified: trunk/reactos/dll/win32/shell32/classes.cpp
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/shell32/classes.…
==============================================================================
--- trunk/reactos/dll/win32/shell32/classes.cpp [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/shell32/classes.cpp [iso-8859-1] Thu May 22 18:53:44 2014
@@ -34,7 +34,7 @@
/* added because we do not want to have double dots */
if (szExtension[0] == '.')
- bPrependDot = 0;
+ bPrependDot = FALSE;
if (bPrependDot)
szTemp[0] = '.';
@@ -66,7 +66,7 @@
/* added because we do not want to have double dots */
if (szExtension[0] == '.')
- bPrependDot = 0;
+ bPrependDot = FALSE;
if (bPrependDot)
szTemp[0] = '.';
@@ -109,7 +109,7 @@
TRACE("%p %s %p\n", hkeyClass, debugstr_w(szVerb), szDest);
- if (szVerb)
+ if (szVerb && *szVerb)
{
lstrcpynW(szDest, szVerb, len);
return TRUE;
@@ -173,7 +173,7 @@
return FALSE;
ret = FALSE;
- if (HCR_GetDefaultVerbW(hkeyClass, szVerb, sTempVerb, sizeof(sTempVerb)))
+ if (HCR_GetDefaultVerbW(hkeyClass, szVerb, sTempVerb,
sizeof(sTempVerb)/sizeof(sTempVerb[0])))
{
WCHAR sTemp[MAX_PATH];
wcscpy(sTemp, swShell);
@@ -420,7 +420,7 @@
}
}
- TRACE("-- %s\n", szDest);
+ TRACE("-- (%s)\n", szDest);
return ret;
}
Modified: trunk/reactos/dll/win32/shell32/shell32_main.cpp
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/shell32/shell32_…
==============================================================================
--- trunk/reactos/dll/win32/shell32/shell32_main.cpp [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/shell32/shell32_main.cpp [iso-8859-1] Thu May 22 18:53:44
2014
@@ -1075,7 +1075,7 @@
/*************************************************************************
* AboutDlgProc (internal)
*/
-INT_PTR CALLBACK AboutDlgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
+static INT_PTR CALLBACK AboutDlgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam
)
{
static DWORD cxLogoBmp;
static DWORD cyLogoBmp;
Modified: trunk/reactos/dll/win32/shell32/shell32_main.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/shell32/shell32_…
==============================================================================
--- trunk/reactos/dll/win32/shell32/shell32_main.h [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/shell32/shell32_main.h [iso-8859-1] Thu May 22 18:53:44 2014
@@ -53,7 +53,6 @@
BOOL HCR_GetClassNameA(REFIID riid, LPSTR szDest, DWORD len);
BOOL HCR_GetFolderAttributes(LPCITEMIDLIST pidlFolder, LPDWORD dwAttributes);
-INT_PTR CALLBACK AboutDlgProc(HWND,UINT,WPARAM,LPARAM);
DWORD WINAPI ParseFieldA(LPCSTR src, DWORD nField, LPSTR dst, DWORD len);
DWORD WINAPI ParseFieldW(LPCWSTR src, DWORD nField, LPWSTR dst, DWORD len);
@@ -173,11 +172,6 @@
#define HINSTANCE_32(h16) ((HINSTANCE)(ULONG_PTR)(h16))
#define HINSTANCE_16(h32) (LOWORD(h32))
-typedef UINT_PTR (*SHELL_ExecuteW32)(const WCHAR *lpCmd, WCHAR *env, BOOL shWait,
- const SHELLEXECUTEINFOW *sei, LPSHELLEXECUTEINFOW sei_out);
-
-BOOL SHELL_execute(LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc);
-
extern WCHAR swShell32Name[MAX_PATH];
BOOL UNIXFS_is_rooted_at_desktop(void);
Modified: trunk/reactos/dll/win32/shell32/shlexec.cpp
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/shell32/shlexec.…
==============================================================================
--- trunk/reactos/dll/win32/shell32/shlexec.cpp [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/shell32/shlexec.cpp [iso-8859-1] Thu May 22 18:53:44 2014
@@ -27,6 +27,9 @@
static const WCHAR wszExe[] = L".exe";
#define SEE_MASK_CLASSALL (SEE_MASK_CLASSNAME | SEE_MASK_CLASSKEY)
+
+typedef UINT_PTR (*SHELL_ExecuteW32)(const WCHAR *lpCmd, WCHAR *env, BOOL shWait,
+ const SHELLEXECUTEINFOW *sei, LPSHELLEXECUTEINFOW sei_out);
static void ParseNoTildeEffect(PWSTR &res, LPCWSTR &args, DWORD &len, DWORD
&used, int argNum)
{
@@ -382,7 +385,12 @@
}
}
- *res = '\0';
+ used++;
+ if (res - out < static_cast<int>(len))
+ *res = '\0';
+ else
+ out[len-1] = '\0';
+
TRACE("used %i of %i space\n", used, len);
if (out_len)
*out_len = used;
@@ -451,7 +459,7 @@
startup.dwFlags = STARTF_USESHOWWINDOW;
startup.wShowWindow = psei->nShow;
dwCreationFlags = CREATE_UNICODE_ENVIRONMENT;
- if (psei->fMask & SEE_MASK_NO_CONSOLE)
+ if (!(psei->fMask & SEE_MASK_NO_CONSOLE))
dwCreationFlags |= CREATE_NEW_CONSOLE;
startup.lpTitle = (LPWSTR)(psei->fMask & (SEE_MASK_HASLINKNAME |
SEE_MASK_HASTITLE) ? psei->lpClass : NULL);
@@ -589,28 +597,46 @@
return found;
}
-static UINT SHELL_FindExecutableByOperation(LPCWSTR lpOperation, LPWSTR key, LPWSTR
filetype, LPWSTR command, LONG commandlen)
+/*************************************************************************
+ * SHELL_FindExecutableByVerb [Internal]
+ *
+ * called from SHELL_FindExecutable or SHELL_execute_class
+ * in/out:
+ * classname a buffer, big enough, to get the key name to do actually the
+ * command "WordPad.Document.1\\shell\\open\\command"
+ * passed as "WordPad.Document.1"
+ * in:
+ * lpVerb the operation on it (open)
+ * commandlen the size of command buffer (in bytes)
+ * out:
+ * command a buffer, to store the command to do the
+ * operation on the file
+ * key a buffer, big enough, to get the key name to do actually the
+ * command "WordPad.Document.1\\shell\\open\\command"
+ * Can be NULL
+ */
+static UINT SHELL_FindExecutableByVerb(LPCWSTR lpVerb, LPWSTR key, LPWSTR classname,
LPWSTR command, LONG commandlen)
{
static const WCHAR wCommand[] = L"\\command";
HKEY hkeyClass;
WCHAR verb[MAX_PATH];
- if (RegOpenKeyExW(HKEY_CLASSES_ROOT, filetype, 0, 0x02000000, &hkeyClass))
+ if (RegOpenKeyExW(HKEY_CLASSES_ROOT, classname, 0, 0x02000000, &hkeyClass))
return SE_ERR_NOASSOC;
- if (!HCR_GetDefaultVerbW(hkeyClass, lpOperation, verb, sizeof(verb) /
sizeof(verb[0])))
+ if (!HCR_GetDefaultVerbW(hkeyClass, lpVerb, verb, sizeof(verb) / sizeof(verb[0])))
return SE_ERR_NOASSOC;
RegCloseKey(hkeyClass);
/* Looking for ...buffer\shell\<verb>\command */
- wcscat(filetype, L"\\shell\\");
- wcscat(filetype, verb);
- wcscat(filetype, wCommand);
-
- if (RegQueryValueW(HKEY_CLASSES_ROOT, filetype, command,
+ wcscat(classname, L"\\shell\\");
+ wcscat(classname, verb);
+ wcscat(classname, wCommand);
+
+ if (RegQueryValueW(HKEY_CLASSES_ROOT, classname, command,
&commandlen) == ERROR_SUCCESS)
{
commandlen /= sizeof(WCHAR);
- if (key) wcscpy(key, filetype);
+ if (key) wcscpy(key, classname);
#if 0
LPWSTR tmp;
WCHAR param[256];
@@ -624,10 +650,10 @@
*/
/* Get the parameters needed by the application
from the associated ddeexec key */
- tmp = strstrW(filetype, wCommand);
+ tmp = strstrW(classname, wCommand);
tmp[0] = '\0';
- wcscat(filetype, wDdeexec);
- if (RegQueryValueW(HKEY_CLASSES_ROOT, filetype, param,
+ wcscat(classname, wDdeexec);
+ if (RegQueryValueW(HKEY_CLASSES_ROOT, classname, param,
¶mlen) == ERROR_SUCCESS)
{
paramlen /= sizeof(WCHAR);
@@ -651,7 +677,7 @@
* Utility for code sharing between FindExecutable and ShellExecute
* in:
* lpFile the name of a file
- * lpOperation the operation on it (open)
+ * lpVerb the operation on it (open)
* out:
* lpResult a buffer, big enough :-(, to store the command to do the
* operation on the file
@@ -659,12 +685,12 @@
* command (it'll be used afterwards for more information
* on the operation)
*/
-static UINT SHELL_FindExecutable(LPCWSTR lpPath, LPCWSTR lpFile, LPCWSTR lpOperation,
+static UINT SHELL_FindExecutable(LPCWSTR lpPath, LPCWSTR lpFile, LPCWSTR lpVerb,
LPWSTR lpResult, DWORD resultLen, LPWSTR key, WCHAR
**env, LPITEMIDLIST pidl, LPCWSTR args)
{
WCHAR *extension = NULL; /* pointer to file extension */
- WCHAR filetype[256]; /* registry name for this filetype */
- LONG filetypelen = sizeof(filetype); /* length of above */
+ WCHAR classname[256]; /* registry name for this file type */
+ LONG classnamelen = sizeof(classname); /* length of above */
WCHAR command[1024]; /* command from registry */
WCHAR wBuffer[256]; /* Used to GetProfileString */
UINT retval = SE_ERR_NOASSOC;
@@ -699,7 +725,7 @@
{
TRACE("SearchPathW returned non-zero\n");
lpFile = xlpFile;
- /* Hey, isn't this value ignored? Why make this call? Shouldn't we
return here? --dank*/
+ /* The file was found in the application-supplied default directory (or the
system search path) */
}
else if (lpPath && SearchPathW(NULL, lpFile, wszExe,
sizeof(xlpFile)/sizeof(WCHAR), xlpFile, NULL))
{
@@ -711,8 +737,7 @@
attribs = GetFileAttributesW(lpFile);
if (attribs != INVALID_FILE_ATTRIBUTES && (attribs &
FILE_ATTRIBUTE_DIRECTORY))
{
- wcscpy(filetype, L"Folder");
- filetypelen = 6; /* strlen("Folder") */
+ wcscpy(classname, L"Folder");
}
else
{
@@ -736,7 +761,7 @@
/* Three places to check: */
/* 1. win.ini, [windows], programs (NB no leading '.') */
- /* 2. Registry, HKEY_CLASS_ROOT\<filetype>\shell\open\command */
+ /* 2. Registry, HKEY_CLASS_ROOT\<classname>\shell\open\command */
/* 3. win.ini, [extensions], extension (NB no leading '.' */
/* All I know of the order is that registry is checked before */
/* extensions; however, it'd make sense to check the programs */
@@ -773,28 +798,26 @@
}
/* Check registry */
- if (RegQueryValueW(HKEY_CLASSES_ROOT, extension, filetype,
- &filetypelen) == ERROR_SUCCESS)
- {
- filetypelen /= sizeof(WCHAR);
- if (filetypelen == sizeof(filetype) / sizeof(WCHAR))
- filetypelen--;
-
- filetype[filetypelen] = '\0';
- TRACE("File type: %s\n", debugstr_w(filetype));
+ if (RegQueryValueW(HKEY_CLASSES_ROOT, extension, classname,
+ &classnamelen) == ERROR_SUCCESS)
+ {
+ classnamelen /= sizeof(WCHAR);
+ if (classnamelen == sizeof(classname) / sizeof(WCHAR))
+ classnamelen--;
+
+ classname[classnamelen] = '\0';
+ TRACE("File type: %s\n", debugstr_w(classname));
}
else
{
- *filetype = '\0';
- filetypelen = 0;
- }
- }
-
- if (*filetype)
- {
- /* pass the operation string to SHELL_FindExecutableByOperation() */
- filetype[filetypelen] = '\0';
- retval = SHELL_FindExecutableByOperation(lpOperation, key, filetype, command,
sizeof(command));
+ *classname = '\0';
+ }
+ }
+
+ if (*classname)
+ {
+ /* pass the verb string to SHELL_FindExecutableByVerb() */
+ retval = SHELL_FindExecutableByVerb(lpVerb, key, classname, command,
sizeof(command));
if (retval > 32)
{
@@ -882,20 +905,34 @@
{
WCHAR regkey[256];
WCHAR * endkey = regkey + wcslen(key);
- WCHAR app[256], topic[256], ifexec[256], res[256];
+ WCHAR app[256], topic[256], ifexec[256], static_res[256];
+ WCHAR * dynamic_res=NULL;
+ WCHAR * res;
LONG applen, topiclen, ifexeclen;
WCHAR * exec;
DWORD ddeInst = 0;
DWORD tid;
- DWORD resultLen;
+ DWORD resultLen, endkeyLen;
HSZ hszApp, hszTopic;
HCONV hConv;
HDDEDATA hDdeData;
unsigned ret = SE_ERR_NOASSOC;
BOOL unicode = !(GetVersion() & 0x80000000);
+ if (strlenW(key) + 1 > sizeof(regkey) / sizeof(regkey[0]))
+ {
+ FIXME("input parameter %s larger than buffer\n", debugstr_w(key));
+ return 2;
+ }
wcscpy(regkey, key);
- wcscpy(endkey, L"\\application");
+ static const WCHAR wApplication[] = L"\\application";
+ endkeyLen = sizeof(regkey) / sizeof(regkey[0]) - (endkey - regkey);
+ if (strlenW(wApplication) + 1 > endkeyLen)
+ {
+ FIXME("endkey %s overruns buffer\n", debugstr_w(wApplication));
+ return 2;
+ }
+ wcscpy(endkey, wApplication);
applen = sizeof(app);
if (RegQueryValueW(HKEY_CLASSES_ROOT, regkey, app, &applen) != ERROR_SUCCESS)
{
@@ -908,6 +945,12 @@
/* Get application command from start string and find filename of application */
if (*start == '"')
{
+ if (strlenW(start + 1) + 1 > sizeof(command) / sizeof(command[0]))
+ {
+ FIXME("size of input parameter %s larger than buffer\n",
+ debugstr_w(start + 1));
+ return 2;
+ }
wcscpy(command, start + 1);
if ((ptr = wcschr(command, '"')))
* ptr = 0;
@@ -915,8 +958,9 @@
}
else
{
- LPWSTR p, space;
- for (p = (LPWSTR)start; (space = const_cast<LPWSTR>(strchrW(p, '
'))); p = space + 1)
+ LPCWSTR p;
+ LPWSTR space;
+ for (p = start; (space = const_cast<LPWSTR>(strchrW(p, ' ')));
p = space + 1)
{
int idx = space - start;
memcpy(command, start, idx * sizeof(WCHAR));
@@ -933,6 +977,11 @@
ERR("Unable to find application path for command %s\n",
debugstr_w(start));
return ERROR_ACCESS_DENIED;
}
+ if (strlenW(ptr) + 1 > sizeof(app) / sizeof(app[0]))
+ {
+ FIXME("size of found path %s larger than buffer\n",
debugstr_w(ptr));
+ return 2;
+ }
wcscpy(app, ptr);
/* Remove extensions (including .so) */
@@ -945,8 +994,14 @@
assert(ptr);
*ptr = 0;
}
-
- wcscpy(endkey, L"\\topic");
+
+ static const WCHAR wTopic[] = L"\\topic";
+ if (strlenW(wTopic) + 1 > endkeyLen)
+ {
+ FIXME("endkey %s overruns buffer\n", debugstr_w(wTopic));
+ return 2;
+ }
+ wcscpy(endkey, wTopic);
topiclen = sizeof(topic);
if (RegQueryValueW(HKEY_CLASSES_ROOT, regkey, topic, &topiclen) !=
ERROR_SUCCESS)
{
@@ -986,7 +1041,13 @@
SetLastError(ERROR_DDE_FAIL);
return 30; /* whatever */
}
- strcpyW(endkey, L"\\ifexec");
+ static const WCHAR wIfexec[] = L"\\ifexec";
+ if (strlenW(wIfexec) + 1 > endkeyLen)
+ {
+ FIXME("endkey %s overruns buffer\n", debugstr_w(wIfexec));
+ return 2;
+ }
+ strcpyW(endkey, wIfexec);
ifexeclen = sizeof(ifexec);
if (RegQueryValueW(HKEY_CLASSES_ROOT, regkey, ifexec, &ifexeclen) ==
ERROR_SUCCESS)
{
@@ -994,9 +1055,14 @@
}
}
- SHELL_ArgifyW(res, sizeof(res) / sizeof(WCHAR), exec, lpFile, pidl, szCommandline,
&resultLen);
- if (resultLen > sizeof(res) / sizeof(WCHAR))
- ERR("Argify buffer not large enough, truncated\n");
+ SHELL_ArgifyW(static_res, sizeof(static_res)/sizeof(WCHAR), exec, lpFile, pidl,
szCommandline, &resultLen);
+ if (resultLen > sizeof(static_res)/sizeof(WCHAR))
+ {
+ res = dynamic_res = static_cast<WCHAR *>(HeapAlloc(GetProcessHeap(), 0,
resultLen * sizeof(WCHAR)));
+ SHELL_ArgifyW(dynamic_res, resultLen, exec, lpFile, pidl, szCommandline, NULL);
+ }
+ else
+ res = static_res;
TRACE("%s %s => %s\n", debugstr_w(exec), debugstr_w(lpFile),
debugstr_w(res));
/* It's documented in the KB 330337 that IE has a bug and returns
@@ -1018,6 +1084,8 @@
else
WARN("DdeClientTransaction failed with error %04x\n",
DdeGetLastError(ddeInst));
ret = 33;
+
+ HeapFree(GetProcessHeap(), 0, dynamic_res);
DdeDisconnect(hConv);
@@ -1296,7 +1364,7 @@
memset(&ici, 0, sizeof ici);
ici.cbSize = sizeof ici;
- ici.fMask = CMIC_MASK_UNICODE | (sei->fMask & (SEE_MASK_NOASYNC |
SEE_MASK_ASYNCOK | SEE_MASK_FLAG_NO_UI));
+ ici.fMask = CMIC_MASK_UNICODE | (sei->fMask & (SEE_MASK_NO_CONSOLE |
SEE_MASK_NOASYNC | SEE_MASK_ASYNCOK | SEE_MASK_FLAG_NO_UI));
ici.nShow = sei->nShow;
ici.lpVerb = MAKEINTRESOURCEA(def);
ici.hwnd = sei->hwnd;
@@ -1411,34 +1479,61 @@
return r;
}
+static UINT_PTR SHELL_quote_and_execute(LPCWSTR wcmd, LPCWSTR wszParameters, LPCWSTR
lpstrProtocol, LPCWSTR wszApplicationName, LPWSTR env, LPSHELLEXECUTEINFOW psei,
LPSHELLEXECUTEINFOW psei_out, SHELL_ExecuteW32 execfunc);
+
static UINT_PTR SHELL_execute_class(LPCWSTR wszApplicationName, LPSHELLEXECUTEINFOW psei,
LPSHELLEXECUTEINFOW psei_out, SHELL_ExecuteW32 execfunc)
{
- WCHAR execCmd[1024], wcmd[1024];
+ WCHAR execCmd[1024], classname[1024];
/* launch a document by fileclass like 'WordPad.Document.1' */
/* the Commandline contains 'c:\Path\wordpad.exe "%1"' */
/* FIXME: wcmd should not be of a fixed size. Fixed to 1024, MAX_PATH is way too
short! */
ULONG cmask = (psei->fMask & SEE_MASK_CLASSALL);
DWORD resultLen;
BOOL done;
-
- HCR_GetExecuteCommandW((cmask == SEE_MASK_CLASSKEY) ? psei->hkeyClass : NULL,
- (cmask == SEE_MASK_CLASSNAME) ? psei->lpClass : NULL,
- psei->lpVerb,
- execCmd, sizeof(execCmd));
-
- /* FIXME: get the extension of lpFile, check if it fits to the lpClass */
- TRACE("SEE_MASK_CLASSNAME->%s, doc->%s\n", debugstr_w(execCmd),
debugstr_w(wszApplicationName));
-
- wcmd[0] = '\0';
- done = SHELL_ArgifyW(wcmd, sizeof(wcmd) / sizeof(WCHAR), execCmd, wszApplicationName,
(LPITEMIDLIST)psei->lpIDList, NULL, &resultLen);
- if (!done && wszApplicationName[0])
- {
- strcatW(wcmd, L" ");
- strcatW(wcmd, wszApplicationName);
- }
- if (resultLen > sizeof(wcmd) / sizeof(WCHAR))
- ERR("Argify buffer not large enough... truncating\n");
- return execfunc(wcmd, NULL, FALSE, psei, psei_out);
+ UINT_PTR rslt;
+
+ /* FIXME: remove following block when SHELL_quote_and_execute supports hkeyClass
parameter */
+ if (cmask != SEE_MASK_CLASSNAME)
+ {
+ WCHAR wcmd[1024];
+ HCR_GetExecuteCommandW((cmask == SEE_MASK_CLASSKEY) ? psei->hkeyClass : NULL,
+ (cmask == SEE_MASK_CLASSNAME) ? psei->lpClass : NULL,
+ psei->lpVerb,
+ execCmd, sizeof(execCmd));
+
+ /* FIXME: get the extension of lpFile, check if it fits to the lpClass */
+ TRACE("SEE_MASK_CLASSNAME->%s, doc->%s\n", debugstr_w(execCmd),
debugstr_w(wszApplicationName));
+
+ wcmd[0] = '\0';
+ done = SHELL_ArgifyW(wcmd, sizeof(wcmd) / sizeof(WCHAR), execCmd,
wszApplicationName, (LPITEMIDLIST)psei->lpIDList, NULL, &resultLen);
+ if (!done && wszApplicationName[0])
+ {
+ strcatW(wcmd, L" ");
+ if (*wszApplicationName != '"')
+ {
+ strcatW(wcmd, L"\"");
+ strcatW(wcmd, wszApplicationName);
+ strcatW(wcmd, L"\"");
+ }
+ else
+ strcatW(wcmd, wszApplicationName);
+ }
+ if (resultLen > sizeof(wcmd) / sizeof(WCHAR))
+ ERR("Argify buffer not large enough... truncating\n");
+ return execfunc(wcmd, NULL, FALSE, psei, psei_out);
+ }
+
+ strcpyW(classname, psei->lpClass);
+ rslt = SHELL_FindExecutableByVerb(psei->lpVerb, NULL, classname, execCmd,
sizeof(execCmd));
+
+ TRACE("SHELL_FindExecutableByVerb returned %u (%s, %s)\n", (unsigned
int)rslt, debugstr_w(classname), debugstr_w(execCmd));
+ if (33 > rslt)
+ return rslt;
+ rslt = SHELL_quote_and_execute( execCmd, L"", classname,
+ wszApplicationName, NULL, psei,
+ psei_out, execfunc );
+ return rslt;
+
}
static BOOL SHELL_translate_idlist(LPSHELLEXECUTEINFOW sei, LPWSTR wszParameters, DWORD
parametersLen, LPWSTR wszApplicationName, DWORD dwApplicationNameLen)
@@ -1448,7 +1543,7 @@
BOOL appKnownSingular = FALSE;
/* last chance to translate IDList: now also allow CLSID paths */
- if (SUCCEEDED(SHELL_GetPathFromIDListForExecuteW((LPCITEMIDLIST)sei->lpIDList,
buffer, sizeof(buffer)))) {
+ if (SUCCEEDED(SHELL_GetPathFromIDListForExecuteW((LPCITEMIDLIST)sei->lpIDList,
buffer, sizeof(buffer)/sizeof(WCHAR)))) {
if (buffer[0] == ':' && buffer[1] == ':') {
/* open shell folder for the specified class GUID */
if (strlenW(buffer) + 1 > parametersLen)
@@ -1487,7 +1582,7 @@
return appKnownSingular;
}
-static UINT_PTR SHELL_quote_and_execute(LPCWSTR wcmd, LPCWSTR wszParameters, LPCWSTR
lpstrProtocol, LPCWSTR wszApplicationName, LPWSTR env, LPSHELLEXECUTEINFOW psei,
LPSHELLEXECUTEINFOW psei_out, SHELL_ExecuteW32 execfunc)
+static UINT_PTR SHELL_quote_and_execute(LPCWSTR wcmd, LPCWSTR wszParameters, LPCWSTR
wszKeyname, LPCWSTR wszApplicationName, LPWSTR env, LPSHELLEXECUTEINFOW psei,
LPSHELLEXECUTEINFOW psei_out, SHELL_ExecuteW32 execfunc)
{
UINT_PTR retval;
DWORD len;
@@ -1513,17 +1608,17 @@
strcatW(wszQuotedCmd, wszParameters);
}
- TRACE("%s/%s => %s/%s\n", debugstr_w(wszApplicationName),
debugstr_w(psei->lpVerb), debugstr_w(wszQuotedCmd), debugstr_w(lpstrProtocol));
-
- if (*lpstrProtocol)
- retval = execute_from_key(lpstrProtocol, wszApplicationName, env,
psei->lpParameters, wcmd, execfunc, psei, psei_out);
+ TRACE("%s/%s => %s/%s\n", debugstr_w(wszApplicationName),
debugstr_w(psei->lpVerb), debugstr_w(wszQuotedCmd), debugstr_w(wszKeyname));
+
+ if (*wszKeyname)
+ retval = execute_from_key(wszKeyname, wszApplicationName, env,
psei->lpParameters, wcmd, execfunc, psei, psei_out);
else
retval = execfunc(wszQuotedCmd, env, FALSE, psei, psei_out);
HeapFree(GetProcessHeap(), 0, wszQuotedCmd);
return retval;
}
-static UINT_PTR SHELL_execute_url(LPCWSTR lpFile, LPCWSTR wFile, LPCWSTR wcmd,
LPSHELLEXECUTEINFOW psei, LPSHELLEXECUTEINFOW psei_out, SHELL_ExecuteW32 execfunc)
+static UINT_PTR SHELL_execute_url(LPCWSTR lpFile, LPCWSTR wcmd, LPSHELLEXECUTEINFOW psei,
LPSHELLEXECUTEINFOW psei_out, SHELL_ExecuteW32 execfunc)
{
static const WCHAR wShell[] = L"\\shell\\";
static const WCHAR wCommand[] = L"\\command";
@@ -1540,9 +1635,9 @@
iSize = strlenW(lpFile);
TRACE("Got URL: %s\n", debugstr_w(lpFile));
- /* Looking for ...protocol\shell\lpOperation\command */
+ /* Looking for ...<protocol>\shell\<lpVerb>\command */
len = iSize + lstrlenW(wShell) + lstrlenW(wCommand) + 1;
- if (psei->lpVerb)
+ if (psei->lpVerb && *psei->lpVerb)
len += lstrlenW(psei->lpVerb);
else
len += lstrlenW(wszOpen);
@@ -1550,23 +1645,16 @@
memcpy(lpstrProtocol, lpFile, iSize * sizeof(WCHAR));
lpstrProtocol[iSize] = '\0';
strcatW(lpstrProtocol, wShell);
- strcatW(lpstrProtocol, psei->lpVerb ? psei->lpVerb : wszOpen);
+ strcatW(lpstrProtocol, psei->lpVerb && *psei->lpVerb ? psei->lpVerb
: wszOpen);
strcatW(lpstrProtocol, wCommand);
- /* Remove File Protocol from lpFile */
- /* In the case file://path/file */
- if (!strncmpiW(lpFile, wFile, iSize))
- {
- lpFile += iSize;
- while (*lpFile == ':') lpFile++;
- }
retval = execute_from_key(lpstrProtocol, lpFile, NULL, psei->lpParameters,
wcmd, execfunc, psei, psei_out);
HeapFree(GetProcessHeap(), 0, lpstrProtocol);
return retval;
}
-void do_error_dialog(UINT_PTR retval, HWND hwnd, WCHAR* filename)
+static void do_error_dialog(UINT_PTR retval, HWND hwnd, WCHAR* filename)
{
WCHAR msg[2048];
DWORD_PTR msgArguments[3] = { (DWORD_PTR)filename, 0, 0 };
@@ -1591,7 +1679,7 @@
/*************************************************************************
* SHELL_execute [Internal]
*/
-BOOL SHELL_execute(LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc)
+static BOOL SHELL_execute(LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc)
{
static const DWORD unsupportedFlags =
SEE_MASK_INVOKEIDLIST | SEE_MASK_ICON | SEE_MASK_HOTKEY |
@@ -1608,7 +1696,7 @@
SHELLEXECUTEINFOW sei_tmp; /* modifiable copy of SHELLEXECUTEINFO struct */
WCHAR wfileName[MAX_PATH];
WCHAR *env;
- WCHAR lpstrProtocol[256];
+ WCHAR wszKeyname[256];
LPCWSTR lpFile;
UINT_PTR retval = SE_ERR_NOASSOC;
BOOL appKnownSingular = FALSE;
@@ -1766,36 +1854,40 @@
dwApplicationNameLen );
}
- /* expand environment strings */
- len = ExpandEnvironmentStringsW(sei_tmp.lpFile, NULL, 0);
- if (len > 0)
+ /* convert file URLs */
+ if (UrlIsFileUrlW(sei_tmp.lpFile))
{
LPWSTR buf;
- buf = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR));
-
- ExpandEnvironmentStringsW(sei_tmp.lpFile, buf, len + 1);
+ DWORD size;
+
+ size = MAX_PATH;
+ buf = static_cast<LPWSTR>(HeapAlloc(GetProcessHeap(), 0, size *
sizeof(WCHAR)));
+ if (!buf || FAILED(PathCreateFromUrlW(sei_tmp.lpFile, buf, &size, 0)))
+ {
+ HeapFree(GetProcessHeap(), 0, buf);
+ return SE_ERR_OOM;
+ }
+
HeapFree(GetProcessHeap(), 0, wszApplicationName);
- dwApplicationNameLen = len + 1;
+ dwApplicationNameLen = lstrlenW(buf) + 1;
wszApplicationName = buf;
- /* appKnownSingular unmodified */
-
sei_tmp.lpFile = wszApplicationName;
}
-
- if (*sei_tmp.lpParameters)
- {
- len = ExpandEnvironmentStringsW(sei_tmp.lpParameters, NULL, 0);
+ else /* or expand environment strings (not both!) */
+ {
+ len = ExpandEnvironmentStringsW(sei_tmp.lpFile, NULL, 0);
if (len > 0)
{
LPWSTR buf;
- len++;
- buf = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
- ExpandEnvironmentStringsW(sei_tmp.lpParameters, buf, len);
- if (wszParameters != parametersBuffer)
- HeapFree(GetProcessHeap(), 0, wszParameters);
- wszParameters = buf;
- parametersLen = len;
- sei_tmp.lpParameters = wszParameters;
+ buf = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR));
+
+ ExpandEnvironmentStringsW(sei_tmp.lpFile, buf, len + 1);
+ HeapFree(GetProcessHeap(), 0, wszApplicationName);
+ dwApplicationNameLen = len + 1;
+ wszApplicationName = buf;
+ /* appKnownSingular unmodified */
+
+ sei_tmp.lpFile = wszApplicationName;
}
}
@@ -1849,6 +1941,7 @@
/* terminate previous command string after the quote character */
*end = L'\0';
+ lpFile = wfileName;
}
else
{
@@ -1880,13 +1973,11 @@
}
}
- lstrcpynW(wfileName, sei_tmp.lpFile, sizeof(wfileName) / sizeof(WCHAR));
+ lpFile = sei_tmp.lpFile;
}
}
else
- lstrcpynW(wfileName, sei_tmp.lpFile, sizeof(wfileName) / sizeof(WCHAR));
-
- lpFile = wfileName;
+ lpFile = sei_tmp.lpFile;
wcmd = wcmdBuffer;
len = lstrlenW(wszApplicationName) + 3;
@@ -1919,10 +2010,10 @@
/* Else, try to find the executable */
wcmd[0] = L'\0';
- retval = SHELL_FindExecutable(sei_tmp.lpDirectory, lpFile, sei_tmp.lpVerb, wcmd,
wcmdLen, lpstrProtocol, &env, (LPITEMIDLIST)sei_tmp.lpIDList, sei_tmp.lpParameters);
+ retval = SHELL_FindExecutable(sei_tmp.lpDirectory, lpFile, sei_tmp.lpVerb, wcmd,
wcmdLen, wszKeyname, &env, (LPITEMIDLIST)sei_tmp.lpIDList, sei_tmp.lpParameters);
if (retval > 32) /* Found */
{
- retval = SHELL_quote_and_execute(wcmd, wszParameters, lpstrProtocol,
+ retval = SHELL_quote_and_execute(wcmd, wszParameters, wszKeyname,
wszApplicationName, env, &sei_tmp,
sei, execfunc);
HeapFree(GetProcessHeap(), 0, env);
@@ -1941,7 +2032,7 @@
{
swprintf(lpQuotedFile, L"\"%s\"", lpFile);
retval = SHELL_quote_and_execute(wExec, lpQuotedFile,
- lpstrProtocol,
+ wszKeyname,
wszApplicationName, env,
&sei_tmp, sei, execfunc);
HeapFree(GetProcessHeap(), 0, env);
@@ -1953,12 +2044,12 @@
}
else if (PathIsURLW(lpFile)) /* File not found, check for URL */
{
- retval = SHELL_execute_url(lpFile, L"file", wcmd, &sei_tmp, sei,
execfunc );
+ retval = SHELL_execute_url(lpFile, wcmd, &sei_tmp, sei, execfunc );
}
/* Check if file specified is in the form
www.??????.*** */
else if (!strncmpiW(lpFile, L"www", 3))
{
- /* if so, append lpFile http:// and call ShellExecute */
+ /* if so, prefix lpFile with http:// and call ShellExecute */
WCHAR lpstrTmpFile[256];
strcpyW(lpstrTmpFile, L"http://");
strcatW(lpstrTmpFile, lpFile);
@@ -1998,19 +2089,19 @@
/*************************************************************************
* ShellExecuteA [SHELL32.290]
*/
-HINSTANCE WINAPI ShellExecuteA(HWND hWnd, LPCSTR lpOperation, LPCSTR lpFile,
+HINSTANCE WINAPI ShellExecuteA(HWND hWnd, LPCSTR lpVerb, LPCSTR lpFile,
LPCSTR lpParameters, LPCSTR lpDirectory, INT iShowCmd)
{
SHELLEXECUTEINFOA sei;
TRACE("%p,%s,%s,%s,%s,%d\n",
- hWnd, debugstr_a(lpOperation), debugstr_a(lpFile),
+ hWnd, debugstr_a(lpVerb), debugstr_a(lpFile),
debugstr_a(lpParameters), debugstr_a(lpDirectory), iShowCmd);
sei.cbSize = sizeof(sei);
sei.fMask = SEE_MASK_FLAG_NO_UI;
sei.hwnd = hWnd;
- sei.lpVerb = lpOperation;
+ sei.lpVerb = lpVerb;
sei.lpFile = lpFile;
sei.lpParameters = lpParameters;
sei.lpDirectory = lpDirectory;
@@ -2090,10 +2181,10 @@
/*************************************************************************
* ShellExecuteW [SHELL32.294]
* from shellapi.h
- * WINSHELLAPI HINSTANCE APIENTRY ShellExecuteW(HWND hwnd, LPCWSTR lpOperation,
+ * WINSHELLAPI HINSTANCE APIENTRY ShellExecuteW(HWND hwnd, LPCWSTR lpVerb,
* LPCWSTR lpFile, LPCWSTR lpParameters, LPCWSTR lpDirectory, INT nShowCmd);
*/
-HINSTANCE WINAPI ShellExecuteW(HWND hwnd, LPCWSTR lpOperation, LPCWSTR lpFile,
+HINSTANCE WINAPI ShellExecuteW(HWND hwnd, LPCWSTR lpVerb, LPCWSTR lpFile,
LPCWSTR lpParameters, LPCWSTR lpDirectory, INT nShowCmd)
{
SHELLEXECUTEINFOW sei;
@@ -2102,7 +2193,7 @@
sei.cbSize = sizeof(sei);
sei.fMask = SEE_MASK_FLAG_NO_UI;
sei.hwnd = hwnd;
- sei.lpVerb = lpOperation;
+ sei.lpVerb = lpVerb;
sei.lpFile = lpFile;
sei.lpParameters = lpParameters;
sei.lpDirectory = lpDirectory;
@@ -2122,14 +2213,14 @@
*
* FIXME: the callback function most likely doesn't work the same way on Windows.
*/
-EXTERN_C HINSTANCE WINAPI WOWShellExecute(HWND hWnd, LPCSTR lpOperation, LPCSTR lpFile,
+EXTERN_C HINSTANCE WINAPI WOWShellExecute(HWND hWnd, LPCSTR lpVerb, LPCSTR lpFile,
LPCSTR lpParameters, LPCSTR lpDirectory, INT iShowCmd, void *callback)
{
SHELLEXECUTEINFOW seiW;
WCHAR *wVerb = NULL, *wFile = NULL, *wParameters = NULL, *wDirectory = NULL;
HANDLE hProcess = 0;
- seiW.lpVerb = lpOperation ? __SHCloneStrAtoW(&wVerb, lpOperation) : NULL;
+ seiW.lpVerb = lpVerb ? __SHCloneStrAtoW(&wVerb, lpVerb) : NULL;
seiW.lpFile = lpFile ? __SHCloneStrAtoW(&wFile, lpFile) : NULL;
seiW.lpParameters = lpParameters ? __SHCloneStrAtoW(&wParameters, lpParameters) :
NULL;
seiW.lpDirectory = lpDirectory ? __SHCloneStrAtoW(&wDirectory, lpDirectory) :
NULL;