mirror of
https://github.com/reactos/reactos.git
synced 2025-05-16 07:47:21 +00:00
- Call OpenWith dialog when no file association is found
- Partial wine syncAlexandre Julliard <julliard@winehq.org> shell32: Add implementation of WOWShellExecute. The callback is probably not fully compatible, but apps are not supposed to use that function anyway. Vincent Povirk <madewokherd+8cd9@gmail.com> shell32: Add a message for opening files with no association. Marcus Meissner <marcus@jet.franken.de> shell32: Fixed potential buffer overwrite in execute_from_key (Coverity). Vincent Povirk <vincent@codeweavers.com> shell32: Use the NO_UI flag in ShellExecute. In my testing on Windows, I wasn't able to make ShellExecute display any error dialogs. Paul Chitescu <paulc@voip.null.ro> shell32.dll: Return SE_ERR_FNF if file not found before checking for associations. svn path=/trunk/; revision=40666
This commit is contained in:
parent
c9234e9ca1
commit
c8b09007ed
4 changed files with 390 additions and 182 deletions
reactos/dll/win32/shell32
|
@ -213,7 +213,7 @@ static LPWSTR __inline __SHCloneStrAtoW(WCHAR ** target, const char * source)
|
||||||
#define HINSTANCE_16(h32) (LOWORD(h32))
|
#define HINSTANCE_16(h32) (LOWORD(h32))
|
||||||
|
|
||||||
typedef UINT_PTR (*SHELL_ExecuteW32)(const WCHAR *lpCmd, WCHAR *env, BOOL shWait,
|
typedef UINT_PTR (*SHELL_ExecuteW32)(const WCHAR *lpCmd, WCHAR *env, BOOL shWait,
|
||||||
LPSHELLEXECUTEINFOW sei, LPSHELLEXECUTEINFOW sei_out);
|
const SHELLEXECUTEINFOW *sei, LPSHELLEXECUTEINFOW sei_out);
|
||||||
|
|
||||||
BOOL SHELL_execute(LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc);
|
BOOL SHELL_execute(LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc);
|
||||||
|
|
||||||
|
|
|
@ -165,7 +165,7 @@ static BOOL SHELL_ArgifyW(WCHAR* out, int len, const WCHAR* fmt, const WCHAR* lp
|
||||||
case 'I':
|
case 'I':
|
||||||
if (pidl) {
|
if (pidl) {
|
||||||
INT chars = 0;
|
INT chars = 0;
|
||||||
/* %p should not exceed 8, maybe 16 when looking foward to 64bit.
|
/* %p should not exceed 8, maybe 16 when looking forward to 64bit.
|
||||||
* allowing a buffer of 100 should more than exceed all needs */
|
* allowing a buffer of 100 should more than exceed all needs */
|
||||||
WCHAR buf[100];
|
WCHAR buf[100];
|
||||||
LPVOID pv;
|
LPVOID pv;
|
||||||
|
@ -191,7 +191,7 @@ static BOOL SHELL_ArgifyW(WCHAR* out, int len, const WCHAR* fmt, const WCHAR* lp
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Make sure that we have at least one more %.*/
|
/* Make sure that we have at least one more %.*/
|
||||||
if (wcschr(fmt, '%'))
|
if (strchrW(fmt, '%'))
|
||||||
{
|
{
|
||||||
WCHAR tmpBuffer[1024];
|
WCHAR tmpBuffer[1024];
|
||||||
PWSTR tmpB = tmpBuffer;
|
PWSTR tmpB = tmpBuffer;
|
||||||
|
@ -275,7 +275,7 @@ static HRESULT SHELL_GetPathFromIDListForExecuteW(LPCITEMIDLIST pidl, LPWSTR psz
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static UINT_PTR SHELL_ExecuteW(const WCHAR *lpCmd, WCHAR *env, BOOL shWait,
|
static UINT_PTR SHELL_ExecuteW(const WCHAR *lpCmd, WCHAR *env, BOOL shWait,
|
||||||
LPSHELLEXECUTEINFOW psei, LPSHELLEXECUTEINFOW psei_out)
|
const SHELLEXECUTEINFOW *psei, LPSHELLEXECUTEINFOW psei_out)
|
||||||
{
|
{
|
||||||
STARTUPINFOW startup;
|
STARTUPINFOW startup;
|
||||||
PROCESS_INFORMATION info;
|
PROCESS_INFORMATION info;
|
||||||
|
@ -664,9 +664,7 @@ static UINT SHELL_FindExecutable(LPCWSTR lpPath, LPCWSTR lpFile, LPCWSTR lpOpera
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Truncate on first space, like Windows:
|
/* Truncate on first space */
|
||||||
* http://support.microsoft.com/?scid=kb%3Ben-us%3B140724
|
|
||||||
*/
|
|
||||||
WCHAR *p = lpResult;
|
WCHAR *p = lpResult;
|
||||||
while (*p != ' ' && *p != '\0')
|
while (*p != ' ' && *p != '\0')
|
||||||
p++;
|
p++;
|
||||||
|
@ -728,10 +726,10 @@ static HDDEDATA CALLBACK dde_cb(UINT uType, UINT uFmt, HCONV hConv,
|
||||||
* launching an application and trying (#2) to connect to it
|
* launching an application and trying (#2) to connect to it
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static unsigned dde_connect(WCHAR* key, const WCHAR* start, WCHAR* ddeexec,
|
static unsigned dde_connect(const WCHAR* key, const WCHAR* start, WCHAR* ddeexec,
|
||||||
const WCHAR* lpFile, WCHAR *env,
|
const WCHAR* lpFile, WCHAR *env,
|
||||||
LPCWSTR szCommandline, LPITEMIDLIST pidl, SHELL_ExecuteW32 execfunc,
|
LPCWSTR szCommandline, LPITEMIDLIST pidl, SHELL_ExecuteW32 execfunc,
|
||||||
LPSHELLEXECUTEINFOW psei, LPSHELLEXECUTEINFOW psei_out)
|
const SHELLEXECUTEINFOW *psei, LPSHELLEXECUTEINFOW psei_out)
|
||||||
{
|
{
|
||||||
static const WCHAR wApplication[] = {'\\','a','p','p','l','i','c','a','t','i','o','n',0};
|
static const WCHAR wApplication[] = {'\\','a','p','p','l','i','c','a','t','i','o','n',0};
|
||||||
static const WCHAR wTopic[] = {'\\','t','o','p','i','c',0};
|
static const WCHAR wTopic[] = {'\\','t','o','p','i','c',0};
|
||||||
|
@ -771,7 +769,7 @@ static unsigned dde_connect(WCHAR* key, const WCHAR* start, WCHAR* ddeexec,
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LPWSTR p,space;
|
LPWSTR p,space;
|
||||||
for (p=(LPWSTR)start; (space=wcschr(p, ' ')); p=space+1)
|
for (p=(LPWSTR)start; (space=strchrW(p, ' ')); p=space+1)
|
||||||
{
|
{
|
||||||
int idx = space-start;
|
int idx = space-start;
|
||||||
memcpy(command, start, idx*sizeof(WCHAR));
|
memcpy(command, start, idx*sizeof(WCHAR));
|
||||||
|
@ -796,7 +794,7 @@ static unsigned dde_connect(WCHAR* key, const WCHAR* start, WCHAR* ddeexec,
|
||||||
!wcscmp(ptr, wSo))
|
!wcscmp(ptr, wSo))
|
||||||
*ptr = 0;
|
*ptr = 0;
|
||||||
|
|
||||||
ptr = wcschr(app, '.');
|
ptr = strrchrW(app, '.');
|
||||||
assert(ptr);
|
assert(ptr);
|
||||||
*ptr = 0;
|
*ptr = 0;
|
||||||
}
|
}
|
||||||
|
@ -843,7 +841,7 @@ static unsigned dde_connect(WCHAR* key, const WCHAR* start, WCHAR* ddeexec,
|
||||||
SetLastError(ERROR_DDE_FAIL);
|
SetLastError(ERROR_DDE_FAIL);
|
||||||
return 30; /* whatever */
|
return 30; /* whatever */
|
||||||
}
|
}
|
||||||
wcscpy(endkey, wIfexec);
|
strcpyW(endkey, wIfexec);
|
||||||
ifexeclen = sizeof(ifexec);
|
ifexeclen = sizeof(ifexec);
|
||||||
if (RegQueryValueW(HKEY_CLASSES_ROOT, regkey, ifexec, &ifexeclen) == ERROR_SUCCESS)
|
if (RegQueryValueW(HKEY_CLASSES_ROOT, regkey, ifexec, &ifexeclen) == ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
|
@ -860,7 +858,7 @@ static unsigned dde_connect(WCHAR* key, const WCHAR* start, WCHAR* ddeexec,
|
||||||
* error DMLERR_NOTPROCESSED on XTYP_EXECUTE request.
|
* error DMLERR_NOTPROCESSED on XTYP_EXECUTE request.
|
||||||
*/
|
*/
|
||||||
if (unicode)
|
if (unicode)
|
||||||
hDdeData = DdeClientTransaction((LPBYTE)res, (wcslen(res) + 1) * sizeof(WCHAR), hConv, 0L, 0,
|
hDdeData = DdeClientTransaction((LPBYTE)res, (strlenW(res) + 1) * sizeof(WCHAR), hConv, 0L, 0,
|
||||||
XTYP_EXECUTE, 30000, &tid);
|
XTYP_EXECUTE, 30000, &tid);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -888,7 +886,7 @@ static unsigned dde_connect(WCHAR* key, const WCHAR* start, WCHAR* ddeexec,
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
* execute_from_key [Internal]
|
* execute_from_key [Internal]
|
||||||
*/
|
*/
|
||||||
static UINT_PTR execute_from_key(LPWSTR key, LPCWSTR lpFile, WCHAR *env, LPCWSTR szCommandline,
|
static UINT_PTR execute_from_key(LPCWSTR key, LPCWSTR lpFile, WCHAR *env, LPCWSTR szCommandline,
|
||||||
LPCWSTR executable_name,
|
LPCWSTR executable_name,
|
||||||
SHELL_ExecuteW32 execfunc,
|
SHELL_ExecuteW32 execfunc,
|
||||||
LPSHELLEXECUTEINFOW psei, LPSHELLEXECUTEINFOW psei_out)
|
LPSHELLEXECUTEINFOW psei, LPSHELLEXECUTEINFOW psei_out)
|
||||||
|
@ -914,8 +912,8 @@ static UINT_PTR execute_from_key(LPWSTR key, LPCWSTR lpFile, WCHAR *env, LPCWSTR
|
||||||
|
|
||||||
/* Is there a replace() function anywhere? */
|
/* Is there a replace() function anywhere? */
|
||||||
cmdlen /= sizeof(WCHAR);
|
cmdlen /= sizeof(WCHAR);
|
||||||
if (cmdlen >= sizeof(cmd)/sizeof(WCHAR))
|
if (cmdlen >= sizeof(cmd)/sizeof(WCHAR))
|
||||||
cmdlen = sizeof(cmd)/sizeof(WCHAR)-1;
|
cmdlen = sizeof(cmd)/sizeof(WCHAR)-1;
|
||||||
cmd[cmdlen] = '\0';
|
cmd[cmdlen] = '\0';
|
||||||
SHELL_ArgifyW(param, sizeof(param)/sizeof(WCHAR), cmd, lpFile, psei->lpIDList, szCommandline, &resultLen);
|
SHELL_ArgifyW(param, sizeof(param)/sizeof(WCHAR), cmd, lpFile, psei->lpIDList, szCommandline, &resultLen);
|
||||||
if (resultLen > sizeof(param)/sizeof(WCHAR))
|
if (resultLen > sizeof(param)/sizeof(WCHAR))
|
||||||
|
@ -924,14 +922,14 @@ static UINT_PTR execute_from_key(LPWSTR key, LPCWSTR lpFile, WCHAR *env, LPCWSTR
|
||||||
|
|
||||||
/* Get the parameters needed by the application
|
/* Get the parameters needed by the application
|
||||||
from the associated ddeexec key */
|
from the associated ddeexec key */
|
||||||
tmp = wcsstr(key, wCommand);
|
tmp = strstrW(key, wCommand);
|
||||||
assert(tmp);
|
assert(tmp);
|
||||||
wcscpy(tmp, wDdeexec);
|
wcscpy(tmp, wDdeexec);
|
||||||
|
|
||||||
if (RegQueryValueW(HKEY_CLASSES_ROOT, key, ddeexec, &ddeexeclen) == ERROR_SUCCESS)
|
if (RegQueryValueW(HKEY_CLASSES_ROOT, key, ddeexec, &ddeexeclen) == ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
TRACE("Got ddeexec %s => %s\n", debugstr_w(key), debugstr_w(ddeexec));
|
TRACE("Got ddeexec %s => %s\n", debugstr_w(key), debugstr_w(ddeexec));
|
||||||
if (!param[0]) wcscpy(param, executable_name);
|
if (!param[0]) strcpyW(param, executable_name);
|
||||||
retval = dde_connect(key, param, ddeexec, lpFile, env, szCommandline, psei->lpIDList, execfunc, psei, psei_out);
|
retval = dde_connect(key, param, ddeexec, lpFile, env, szCommandline, psei->lpIDList, execfunc, psei, psei_out);
|
||||||
}
|
}
|
||||||
else if (param[0])
|
else if (param[0])
|
||||||
|
@ -1017,7 +1015,7 @@ HINSTANCE WINAPI FindExecutableW(LPCWSTR lpFile, LPCWSTR lpDirectory, LPWSTR lpR
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME: is this already implemented somewhere else? */
|
/* FIXME: is this already implemented somewhere else? */
|
||||||
static HKEY ShellExecute_GetClassKey( LPSHELLEXECUTEINFOW sei )
|
static HKEY ShellExecute_GetClassKey( const SHELLEXECUTEINFOW *sei )
|
||||||
{
|
{
|
||||||
LPCWSTR ext = NULL, lpClass = NULL;
|
LPCWSTR ext = NULL, lpClass = NULL;
|
||||||
LPWSTR cls = NULL;
|
LPWSTR cls = NULL;
|
||||||
|
@ -1078,10 +1076,11 @@ static IDataObject *shellex_get_dataobj( LPSHELLEXECUTEINFOW sei )
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
WCHAR fullpath[MAX_PATH];
|
WCHAR fullpath[MAX_PATH];
|
||||||
|
BOOL ret;
|
||||||
|
|
||||||
fullpath[0] = 0;
|
fullpath[0] = 0;
|
||||||
r = GetFullPathNameW( sei->lpFile, MAX_PATH, fullpath, NULL );
|
ret = GetFullPathNameW( sei->lpFile, MAX_PATH, fullpath, NULL );
|
||||||
if (!r)
|
if (!ret)
|
||||||
goto end;
|
goto end;
|
||||||
|
|
||||||
pidl = ILCreateFromPathW( fullpath );
|
pidl = ILCreateFromPathW( fullpath );
|
||||||
|
@ -1272,25 +1271,196 @@ static LONG ShellExecute_FromContextMenu( LPSHELLEXECUTEINFOW sei )
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static UINT_PTR SHELL_execute_class( LPCWSTR wszApplicationName, LPSHELLEXECUTEINFOW psei, LPSHELLEXECUTEINFOW psei_out, SHELL_ExecuteW32 execfunc )
|
||||||
|
{
|
||||||
|
static const WCHAR wSpace[] = {' ',0};
|
||||||
|
WCHAR execCmd[1024], wcmd[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, psei->lpIDList, NULL, &resultLen);
|
||||||
|
if (!done && wszApplicationName[0])
|
||||||
|
{
|
||||||
|
strcatW(wcmd, wSpace);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL SHELL_translate_idlist( LPSHELLEXECUTEINFOW sei, LPWSTR wszParameters, DWORD parametersLen, LPWSTR wszApplicationName, DWORD dwApplicationNameLen )
|
||||||
|
{
|
||||||
|
static const WCHAR wExplorer[] = {'e','x','p','l','o','r','e','r','.','e','x','e',0};
|
||||||
|
WCHAR buffer[MAX_PATH];
|
||||||
|
BOOL appKnownSingular = FALSE;
|
||||||
|
|
||||||
|
/* last chance to translate IDList: now also allow CLSID paths */
|
||||||
|
if (SUCCEEDED(SHELL_GetPathFromIDListForExecuteW(sei->lpIDList, buffer, sizeof(buffer)))) {
|
||||||
|
if (buffer[0]==':' && buffer[1]==':') {
|
||||||
|
/* open shell folder for the specified class GUID */
|
||||||
|
if (strlenW(buffer) + 1 > parametersLen)
|
||||||
|
ERR("parameters len exceeds buffer size (%i > %i), truncating\n",
|
||||||
|
lstrlenW(buffer) + 1, parametersLen);
|
||||||
|
lstrcpynW(wszParameters, buffer, parametersLen);
|
||||||
|
if (strlenW(wExplorer) > dwApplicationNameLen)
|
||||||
|
ERR("application len exceeds buffer size (%i > %i), truncating\n",
|
||||||
|
lstrlenW(wExplorer) + 1, dwApplicationNameLen);
|
||||||
|
lstrcpynW(wszApplicationName, wExplorer, dwApplicationNameLen);
|
||||||
|
appKnownSingular = TRUE;
|
||||||
|
|
||||||
|
sei->fMask &= ~SEE_MASK_INVOKEIDLIST;
|
||||||
|
} else {
|
||||||
|
WCHAR target[MAX_PATH];
|
||||||
|
DWORD attribs;
|
||||||
|
DWORD resultLen;
|
||||||
|
/* Check if we're executing a directory and if so use the
|
||||||
|
handler for the Folder class */
|
||||||
|
strcpyW(target, buffer);
|
||||||
|
attribs = GetFileAttributesW(buffer);
|
||||||
|
if (attribs != INVALID_FILE_ATTRIBUTES &&
|
||||||
|
(attribs & FILE_ATTRIBUTE_DIRECTORY) &&
|
||||||
|
HCR_GetExecuteCommandW(0, wszFolder,
|
||||||
|
sei->lpVerb,
|
||||||
|
buffer, sizeof(buffer))) {
|
||||||
|
SHELL_ArgifyW(wszApplicationName, dwApplicationNameLen,
|
||||||
|
buffer, target, sei->lpIDList, NULL, &resultLen);
|
||||||
|
if (resultLen > dwApplicationNameLen)
|
||||||
|
ERR("Argify buffer not large enough... truncating\n");
|
||||||
|
appKnownSingular = FALSE;
|
||||||
|
}
|
||||||
|
sei->fMask &= ~SEE_MASK_INVOKEIDLIST;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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 const WCHAR wQuote[] = {'"',0};
|
||||||
|
static const WCHAR wSpace[] = {' ',0};
|
||||||
|
UINT_PTR retval;
|
||||||
|
DWORD len;
|
||||||
|
WCHAR *wszQuotedCmd;
|
||||||
|
|
||||||
|
/* Length of quotes plus length of command plus NULL terminator */
|
||||||
|
len = 2 + lstrlenW(wcmd) + 1;
|
||||||
|
if (wszParameters[0])
|
||||||
|
{
|
||||||
|
/* Length of space plus length of parameters */
|
||||||
|
len += 1 + lstrlenW(wszParameters);
|
||||||
|
}
|
||||||
|
wszQuotedCmd = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
|
||||||
|
/* Must quote to handle case where cmd contains spaces,
|
||||||
|
* else security hole if malicious user creates executable file "C:\\Program"
|
||||||
|
*/
|
||||||
|
strcpyW(wszQuotedCmd, wQuote);
|
||||||
|
strcatW(wszQuotedCmd, wcmd);
|
||||||
|
strcatW(wszQuotedCmd, wQuote);
|
||||||
|
if (wszParameters[0]) {
|
||||||
|
strcatW(wszQuotedCmd, wSpace);
|
||||||
|
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);
|
||||||
|
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 const WCHAR wShell[] = {'\\','s','h','e','l','l','\\',0};
|
||||||
|
static const WCHAR wCommand[] = {'\\','c','o','m','m','a','n','d',0};
|
||||||
|
UINT_PTR retval;
|
||||||
|
WCHAR *lpstrProtocol;
|
||||||
|
LPCWSTR lpstrRes;
|
||||||
|
INT iSize;
|
||||||
|
DWORD len;
|
||||||
|
|
||||||
|
lpstrRes = strchrW(lpFile, ':');
|
||||||
|
if (lpstrRes)
|
||||||
|
iSize = lpstrRes - lpFile;
|
||||||
|
else
|
||||||
|
iSize = strlenW(lpFile);
|
||||||
|
|
||||||
|
TRACE("Got URL: %s\n", debugstr_w(lpFile));
|
||||||
|
/* Looking for ...protocol\shell\lpOperation\command */
|
||||||
|
len = iSize + lstrlenW(wShell) + lstrlenW(wCommand) + 1;
|
||||||
|
if (psei->lpVerb)
|
||||||
|
len += lstrlenW(psei->lpVerb);
|
||||||
|
else
|
||||||
|
len += lstrlenW(wszOpen);
|
||||||
|
lpstrProtocol = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
|
||||||
|
memcpy(lpstrProtocol, lpFile, iSize*sizeof(WCHAR));
|
||||||
|
lpstrProtocol[iSize] = '\0';
|
||||||
|
strcatW(lpstrProtocol, wShell);
|
||||||
|
strcatW(lpstrProtocol, 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 msg[2048];
|
||||||
|
int error_code=GetLastError();
|
||||||
|
|
||||||
|
//FIXME
|
||||||
|
// call SHOpenWithDialog
|
||||||
|
if (retval == SE_ERR_NOASSOC)
|
||||||
|
LoadStringW(shell32_hInstance, IDS_SHLEXEC_NOASSOC, msg, sizeof(msg)/sizeof(WCHAR));
|
||||||
|
else
|
||||||
|
FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error_code, 0, msg, sizeof(msg)/sizeof(WCHAR), NULL);
|
||||||
|
|
||||||
|
MessageBoxW(hwnd, msg, NULL, MB_ICONERROR);
|
||||||
|
}
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
* SHELL_execute [Internal]
|
* SHELL_execute [Internal]
|
||||||
*/
|
*/
|
||||||
BOOL SHELL_execute( LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc )
|
BOOL SHELL_execute( LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc )
|
||||||
{
|
{
|
||||||
static const WCHAR wQuote[] = {'"',0};
|
|
||||||
static const WCHAR wSpace[] = {' ',0};
|
static const WCHAR wSpace[] = {' ',0};
|
||||||
static const WCHAR wWww[] = {'w','w','w',0};
|
static const WCHAR wWww[] = {'w','w','w',0};
|
||||||
static const WCHAR wFile[] = {'f','i','l','e',0};
|
static const WCHAR wFile[] = {'f','i','l','e',0};
|
||||||
static const WCHAR wHttp[] = {'h','t','t','p',':','/','/',0};
|
static const WCHAR wHttp[] = {'h','t','t','p',':','/','/',0};
|
||||||
static const WCHAR wExplorer[] = {'e','x','p','l','o','r','e','r','.','e','x','e',0};
|
|
||||||
//static const WCHAR wProperties[] = { 'p','r','o','p','e','r','t','i','e','s',0 };
|
|
||||||
static const DWORD unsupportedFlags =
|
static const DWORD unsupportedFlags =
|
||||||
SEE_MASK_INVOKEIDLIST | SEE_MASK_HOTKEY |
|
SEE_MASK_INVOKEIDLIST | SEE_MASK_ICON | SEE_MASK_HOTKEY |
|
||||||
SEE_MASK_CONNECTNETDRV | SEE_MASK_FLAG_DDEWAIT | SEE_MASK_FLAG_NO_UI |
|
SEE_MASK_CONNECTNETDRV | SEE_MASK_FLAG_DDEWAIT |
|
||||||
SEE_MASK_UNICODE | SEE_MASK_ASYNCOK | SEE_MASK_HMONITOR;
|
SEE_MASK_UNICODE | SEE_MASK_ASYNCOK | SEE_MASK_HMONITOR;
|
||||||
|
|
||||||
WCHAR *wszApplicationName, wszParameters[1024], wszDir[MAX_PATH];
|
WCHAR parametersBuffer[1024], dirBuffer[MAX_PATH], wcmdBuffer[1024];
|
||||||
|
WCHAR *wszApplicationName, *wszParameters, *wszDir, *wcmd;
|
||||||
DWORD dwApplicationNameLen = MAX_PATH+2;
|
DWORD dwApplicationNameLen = MAX_PATH+2;
|
||||||
|
DWORD parametersLen = sizeof(parametersBuffer) / sizeof(WCHAR);
|
||||||
|
DWORD dirLen = sizeof(dirBuffer) / sizeof(WCHAR);
|
||||||
|
DWORD wcmdLen = sizeof(wcmdBuffer) / sizeof(WCHAR);
|
||||||
DWORD len;
|
DWORD len;
|
||||||
SHELLEXECUTEINFOW sei_tmp; /* modifiable copy of SHELLEXECUTEINFO struct */
|
SHELLEXECUTEINFOW sei_tmp; /* modifiable copy of SHELLEXECUTEINFO struct */
|
||||||
WCHAR wfileName[MAX_PATH];
|
WCHAR wfileName[MAX_PATH];
|
||||||
|
@ -1298,13 +1468,10 @@ BOOL SHELL_execute( LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc )
|
||||||
WCHAR lpstrProtocol[256];
|
WCHAR lpstrProtocol[256];
|
||||||
LPCWSTR lpFile;
|
LPCWSTR lpFile;
|
||||||
UINT_PTR retval = SE_ERR_NOASSOC;
|
UINT_PTR retval = SE_ERR_NOASSOC;
|
||||||
WCHAR wcmd[1024];
|
|
||||||
WCHAR buffer[MAX_PATH];
|
|
||||||
BOOL done;
|
|
||||||
BOOL appKnownSingular = FALSE;
|
BOOL appKnownSingular = FALSE;
|
||||||
|
|
||||||
/* make a local copy of the LPSHELLEXECUTEINFO structure and work with this from now on */
|
/* make a local copy of the LPSHELLEXECUTEINFO structure and work with this from now on */
|
||||||
memcpy(&sei_tmp, sei, sizeof(sei_tmp));
|
sei_tmp = *sei;
|
||||||
|
|
||||||
TRACE("mask=0x%08x hwnd=%p verb=%s file=%s parm=%s dir=%s show=0x%08x class=%s\n",
|
TRACE("mask=0x%08x hwnd=%p verb=%s file=%s parm=%s dir=%s show=0x%08x class=%s\n",
|
||||||
sei_tmp.fMask, sei_tmp.hwnd, debugstr_w(sei_tmp.lpVerb),
|
sei_tmp.fMask, sei_tmp.hwnd, debugstr_w(sei_tmp.lpVerb),
|
||||||
|
@ -1323,7 +1490,7 @@ BOOL SHELL_execute( LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc )
|
||||||
}
|
}
|
||||||
else if (*sei_tmp.lpFile == '\"')
|
else if (*sei_tmp.lpFile == '\"')
|
||||||
{
|
{
|
||||||
DWORD l = wcslen(sei_tmp.lpFile+1);
|
DWORD l = strlenW(sei_tmp.lpFile+1);
|
||||||
if(l >= dwApplicationNameLen) dwApplicationNameLen = l+1;
|
if(l >= dwApplicationNameLen) dwApplicationNameLen = l+1;
|
||||||
wszApplicationName = HeapAlloc(GetProcessHeap(), 0, dwApplicationNameLen*sizeof(WCHAR));
|
wszApplicationName = HeapAlloc(GetProcessHeap(), 0, dwApplicationNameLen*sizeof(WCHAR));
|
||||||
memcpy(wszApplicationName, sei_tmp.lpFile+1, (l+1)*sizeof(WCHAR));
|
memcpy(wszApplicationName, sei_tmp.lpFile+1, (l+1)*sizeof(WCHAR));
|
||||||
|
@ -1332,19 +1499,37 @@ BOOL SHELL_execute( LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc )
|
||||||
appKnownSingular = TRUE;
|
appKnownSingular = TRUE;
|
||||||
TRACE("wszApplicationName=%s\n",debugstr_w(wszApplicationName));
|
TRACE("wszApplicationName=%s\n",debugstr_w(wszApplicationName));
|
||||||
} else {
|
} else {
|
||||||
DWORD l = wcslen(sei_tmp.lpFile)+1;
|
DWORD l = strlenW(sei_tmp.lpFile)+1;
|
||||||
if(l > dwApplicationNameLen) dwApplicationNameLen = l+1;
|
if(l > dwApplicationNameLen) dwApplicationNameLen = l+1;
|
||||||
wszApplicationName = HeapAlloc(GetProcessHeap(), 0, dwApplicationNameLen*sizeof(WCHAR));
|
wszApplicationName = HeapAlloc(GetProcessHeap(), 0, dwApplicationNameLen*sizeof(WCHAR));
|
||||||
memcpy(wszApplicationName, sei_tmp.lpFile, l*sizeof(WCHAR));
|
memcpy(wszApplicationName, sei_tmp.lpFile, l*sizeof(WCHAR));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wszParameters = parametersBuffer;
|
||||||
if (sei_tmp.lpParameters)
|
if (sei_tmp.lpParameters)
|
||||||
wcscpy(wszParameters, sei_tmp.lpParameters);
|
{
|
||||||
|
len = lstrlenW(sei_tmp.lpParameters) + 1;
|
||||||
|
if (len > parametersLen)
|
||||||
|
{
|
||||||
|
wszParameters = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
|
||||||
|
parametersLen = len;
|
||||||
|
}
|
||||||
|
strcpyW(wszParameters, sei_tmp.lpParameters);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
*wszParameters = '\0';
|
*wszParameters = '\0';
|
||||||
|
|
||||||
|
wszDir = dirBuffer;
|
||||||
if (sei_tmp.lpDirectory)
|
if (sei_tmp.lpDirectory)
|
||||||
wcscpy(wszDir, sei_tmp.lpDirectory);
|
{
|
||||||
|
len = lstrlenW(sei_tmp.lpDirectory) + 1;
|
||||||
|
if (len > dirLen)
|
||||||
|
{
|
||||||
|
wszDir = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
|
||||||
|
dirLen = len;
|
||||||
|
}
|
||||||
|
strcpyW(wszDir, sei_tmp.lpDirectory);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
*wszDir = '\0';
|
*wszDir = '\0';
|
||||||
|
|
||||||
|
@ -1367,12 +1552,16 @@ BOOL SHELL_execute( LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc )
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
hr = pSEH->lpVtbl->Execute(pSEH, &sei_tmp);
|
hr = IShellExecuteHookW_Execute(pSEH, &sei_tmp);
|
||||||
|
|
||||||
pSEH->lpVtbl->Release(pSEH);
|
IShellExecuteHookW_Release(pSEH);
|
||||||
|
|
||||||
if (hr == S_OK) {
|
if (hr == S_OK) {
|
||||||
HeapFree(GetProcessHeap(), 0, wszApplicationName);
|
HeapFree(GetProcessHeap(), 0, wszApplicationName);
|
||||||
|
if (wszParameters != parametersBuffer)
|
||||||
|
HeapFree(GetProcessHeap(), 0, wszParameters);
|
||||||
|
if (wszDir != dirBuffer)
|
||||||
|
HeapFree(GetProcessHeap(), 0, wszDir);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1386,80 +1575,48 @@ BOOL SHELL_execute( LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc )
|
||||||
{
|
{
|
||||||
sei->hInstApp = (HINSTANCE) 33;
|
sei->hInstApp = (HINSTANCE) 33;
|
||||||
HeapFree(GetProcessHeap(), 0, wszApplicationName);
|
HeapFree(GetProcessHeap(), 0, wszApplicationName);
|
||||||
|
if (wszParameters != parametersBuffer)
|
||||||
|
HeapFree(GetProcessHeap(), 0, wszParameters);
|
||||||
|
if (wszDir != dirBuffer)
|
||||||
|
HeapFree(GetProcessHeap(), 0, wszDir);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
#if 0
|
|
||||||
if (sei_tmp.lpVerb && !wcscmp(sei_tmp.lpVerb, wProperties))
|
|
||||||
{
|
|
||||||
SH_ShowPropertiesDialog(sei_tmp.lpFile);
|
|
||||||
sei->hInstApp = (HINSTANCE) 33;
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (sei_tmp.fMask & SEE_MASK_CLASSALL)
|
if (sei_tmp.fMask & SEE_MASK_CLASSALL)
|
||||||
{
|
{
|
||||||
/* launch a document by fileclass like 'WordPad.Document.1' */
|
retval = SHELL_execute_class( wszApplicationName, &sei_tmp, sei,
|
||||||
/* the Commandline contains 'c:\Path\wordpad.exe "%1"' */
|
execfunc );
|
||||||
/* FIXME: szCommandline should not be of a fixed size. Fixed to 1024, MAX_PATH is way too short! */
|
if (retval <= 32 && !(sei_tmp.fMask & SEE_MASK_FLAG_NO_UI))
|
||||||
ULONG cmask=(sei_tmp.fMask & SEE_MASK_CLASSALL);
|
|
||||||
DWORD resultLen;
|
|
||||||
HCR_GetExecuteCommandW((cmask == SEE_MASK_CLASSKEY) ? sei_tmp.hkeyClass : NULL,
|
|
||||||
(cmask == SEE_MASK_CLASSNAME) ? sei_tmp.lpClass: NULL,
|
|
||||||
sei_tmp.lpVerb,
|
|
||||||
wszParameters, sizeof(wszParameters)/sizeof(WCHAR));
|
|
||||||
|
|
||||||
/* FIXME: get the extension of lpFile, check if it fits to the lpClass */
|
|
||||||
TRACE("SEE_MASK_CLASSNAME->%s, doc->%s\n", debugstr_w(wszParameters), debugstr_w(wszApplicationName));
|
|
||||||
|
|
||||||
wcmd[0] = '\0';
|
|
||||||
done = SHELL_ArgifyW(wcmd, sizeof(wcmd)/sizeof(WCHAR), wszParameters, wszApplicationName, sei_tmp.lpIDList, NULL, &resultLen);
|
|
||||||
if (!done && wszApplicationName[0])
|
|
||||||
{
|
{
|
||||||
wcscat(wcmd, wSpace);
|
OPENASINFO Info;
|
||||||
wcscat(wcmd, wszApplicationName);
|
|
||||||
}
|
|
||||||
if (resultLen > sizeof(wcmd)/sizeof(WCHAR))
|
|
||||||
ERR("Argify buffer not large enough... truncating\n");
|
|
||||||
retval = execfunc(wcmd, NULL, FALSE, &sei_tmp, sei);
|
|
||||||
|
|
||||||
|
//FIXME
|
||||||
|
// need full path
|
||||||
|
|
||||||
|
Info.pcszFile = wszApplicationName;
|
||||||
|
Info.pcszClass = NULL;
|
||||||
|
Info.oaifInFlags = OAIF_ALLOW_REGISTRATION | OAIF_EXEC;
|
||||||
|
|
||||||
|
if (SHOpenWithDialog(sei_tmp.hwnd, &Info))
|
||||||
|
retval = 33; //FIXME
|
||||||
|
else
|
||||||
|
do_error_dialog(retval, sei_tmp.hwnd);
|
||||||
|
}
|
||||||
HeapFree(GetProcessHeap(), 0, wszApplicationName);
|
HeapFree(GetProcessHeap(), 0, wszApplicationName);
|
||||||
|
if (wszParameters != parametersBuffer)
|
||||||
|
HeapFree(GetProcessHeap(), 0, wszParameters);
|
||||||
|
if (wszDir != dirBuffer)
|
||||||
|
HeapFree(GetProcessHeap(), 0, wszDir);
|
||||||
return retval > 32;
|
return retval > 32;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Has the IDList not yet been translated? */
|
/* Has the IDList not yet been translated? */
|
||||||
if (sei_tmp.fMask & SEE_MASK_IDLIST)
|
if (sei_tmp.fMask & SEE_MASK_IDLIST)
|
||||||
{
|
{
|
||||||
/* last chance to translate IDList: now also allow CLSID paths */
|
appKnownSingular = SHELL_translate_idlist( &sei_tmp, wszParameters,
|
||||||
if (SUCCEEDED(SHELL_GetPathFromIDListForExecuteW(sei_tmp.lpIDList, buffer, sizeof(buffer)))) {
|
parametersLen,
|
||||||
if (buffer[0]==':' && buffer[1]==':') {
|
wszApplicationName,
|
||||||
/* open shell folder for the specified class GUID */
|
dwApplicationNameLen );
|
||||||
wcscpy(wszParameters, buffer);
|
|
||||||
wcscpy(wszApplicationName, wExplorer);
|
|
||||||
appKnownSingular = TRUE;
|
|
||||||
|
|
||||||
sei_tmp.fMask &= ~SEE_MASK_INVOKEIDLIST;
|
|
||||||
} else {
|
|
||||||
WCHAR target[MAX_PATH];
|
|
||||||
DWORD attribs;
|
|
||||||
DWORD resultLen;
|
|
||||||
/* Check if we're executing a directory and if so use the
|
|
||||||
handler for the Folder class */
|
|
||||||
wcscpy(target, buffer);
|
|
||||||
attribs = GetFileAttributesW(buffer);
|
|
||||||
if (attribs != INVALID_FILE_ATTRIBUTES &&
|
|
||||||
(attribs & FILE_ATTRIBUTE_DIRECTORY) &&
|
|
||||||
HCR_GetExecuteCommandW(0, wszFolder,
|
|
||||||
sei_tmp.lpVerb,
|
|
||||||
buffer, sizeof(buffer))) {
|
|
||||||
SHELL_ArgifyW(wszApplicationName, dwApplicationNameLen,
|
|
||||||
buffer, target, sei_tmp.lpIDList, NULL, &resultLen);
|
|
||||||
if (resultLen > dwApplicationNameLen)
|
|
||||||
ERR("Argify buffer not large enough... truncating\n");
|
|
||||||
appKnownSingular = FALSE;
|
|
||||||
}
|
|
||||||
sei_tmp.fMask &= ~SEE_MASK_INVOKEIDLIST;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* expand environment strings */
|
/* expand environment strings */
|
||||||
|
@ -1487,10 +1644,11 @@ BOOL SHELL_execute( LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc )
|
||||||
len++;
|
len++;
|
||||||
buf = HeapAlloc(GetProcessHeap(),0,len*sizeof(WCHAR));
|
buf = HeapAlloc(GetProcessHeap(),0,len*sizeof(WCHAR));
|
||||||
ExpandEnvironmentStringsW(sei_tmp.lpParameters, buf, len);
|
ExpandEnvironmentStringsW(sei_tmp.lpParameters, buf, len);
|
||||||
if (len > 1024)
|
if (wszParameters != parametersBuffer)
|
||||||
ERR("Parameters exceeds buffer size (%i > 1024)\n",len);
|
HeapFree(GetProcessHeap(), 0, wszParameters);
|
||||||
lstrcpynW(wszParameters, buf, min(1024,len));
|
wszParameters = buf;
|
||||||
HeapFree(GetProcessHeap(),0,buf);
|
parametersLen = len;
|
||||||
|
sei_tmp.lpParameters = wszParameters;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1503,10 +1661,10 @@ BOOL SHELL_execute( LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc )
|
||||||
len++;
|
len++;
|
||||||
buf = HeapAlloc(GetProcessHeap(),0,len*sizeof(WCHAR));
|
buf = HeapAlloc(GetProcessHeap(),0,len*sizeof(WCHAR));
|
||||||
ExpandEnvironmentStringsW(sei_tmp.lpDirectory, buf, len);
|
ExpandEnvironmentStringsW(sei_tmp.lpDirectory, buf, len);
|
||||||
if (len > 1024)
|
if (wszDir != dirBuffer)
|
||||||
ERR("Directory exceeds buffer size (%i > 1024)\n",len);
|
HeapFree(GetProcessHeap(), 0, wszDir);
|
||||||
lstrcpynW(wszDir, buf, min(1024,len));
|
wszDir = buf;
|
||||||
HeapFree(GetProcessHeap(),0,buf);
|
sei_tmp.lpDirectory = wszDir;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1536,7 +1694,7 @@ BOOL SHELL_execute( LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc )
|
||||||
end = src;
|
end = src;
|
||||||
|
|
||||||
/* copy the parameter string to 'wszParameters' */
|
/* copy the parameter string to 'wszParameters' */
|
||||||
wcscpy(wszParameters, src);
|
strcpyW(wszParameters, src);
|
||||||
|
|
||||||
/* terminate previous command string after the quote character */
|
/* terminate previous command string after the quote character */
|
||||||
*end = '\0';
|
*end = '\0';
|
||||||
|
@ -1549,114 +1707,142 @@ BOOL SHELL_execute( LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc )
|
||||||
LPWSTR space, s;
|
LPWSTR space, s;
|
||||||
|
|
||||||
LPWSTR beg = wszApplicationName/*sei_tmp.lpFile*/;
|
LPWSTR beg = wszApplicationName/*sei_tmp.lpFile*/;
|
||||||
for(s=beg; (space=wcschr(s, ' ')); s=space+1) {
|
for(s=beg; (space=strchrW(s, ' ')); s=space+1) {
|
||||||
int idx = space-sei_tmp.lpFile;
|
int idx = space-sei_tmp.lpFile;
|
||||||
memcpy(buffer, sei_tmp.lpFile, idx * sizeof(WCHAR));
|
memcpy(buffer, sei_tmp.lpFile, idx * sizeof(WCHAR));
|
||||||
buffer[idx] = '\0';
|
buffer[idx] = '\0';
|
||||||
|
|
||||||
/*FIXME This finds directory paths if the targeted file name contains spaces. */
|
/*FIXME This finds directory paths if the targeted file name contains spaces. */
|
||||||
if (SearchPathW(*sei_tmp.lpDirectory? sei_tmp.lpDirectory: NULL, buffer, wszExe, sizeof(xlpFile), xlpFile, NULL))
|
if (SearchPathW(*sei_tmp.lpDirectory? sei_tmp.lpDirectory: NULL, buffer, wszExe, sizeof(xlpFile)/sizeof(xlpFile[0]), xlpFile, NULL))
|
||||||
{
|
{
|
||||||
/* separate out command from parameter string */
|
/* separate out command from parameter string */
|
||||||
LPCWSTR p = space + 1;
|
LPCWSTR p = space + 1;
|
||||||
|
|
||||||
while(iswspace(*p))
|
while(isspaceW(*p))
|
||||||
++p;
|
++p;
|
||||||
|
|
||||||
wcscpy(wszParameters, p);
|
strcpyW(wszParameters, p);
|
||||||
*space = '\0';
|
*space = '\0';
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
wcscpy(wfileName, sei_tmp.lpFile);
|
lstrcpynW(wfileName, sei_tmp.lpFile,sizeof(wfileName)/sizeof(WCHAR));
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
wcscpy(wfileName, sei_tmp.lpFile);
|
lstrcpynW(wfileName, sei_tmp.lpFile,sizeof(wfileName)/sizeof(WCHAR));
|
||||||
|
|
||||||
lpFile = wfileName;
|
lpFile = wfileName;
|
||||||
|
|
||||||
wcscpy(wcmd, wszApplicationName);
|
wcmd = wcmdBuffer;
|
||||||
|
len = lstrlenW(wszApplicationName) + 1;
|
||||||
|
if (sei_tmp.lpParameters[0])
|
||||||
|
len += 1 + lstrlenW(wszParameters);
|
||||||
|
if (len > wcmdLen)
|
||||||
|
{
|
||||||
|
wcmd = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
|
||||||
|
wcmdLen = len;
|
||||||
|
}
|
||||||
|
strcpyW(wcmd, wszApplicationName);
|
||||||
if (sei_tmp.lpParameters[0]) {
|
if (sei_tmp.lpParameters[0]) {
|
||||||
wcscat(wcmd, wSpace);
|
strcatW(wcmd, wSpace);
|
||||||
wcscat(wcmd, wszParameters);
|
strcatW(wcmd, wszParameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
retval = execfunc(wcmd, NULL, FALSE, &sei_tmp, sei);
|
retval = execfunc(wcmd, NULL, FALSE, &sei_tmp, sei);
|
||||||
if (retval > 32) {
|
if (retval > 32) {
|
||||||
HeapFree(GetProcessHeap(), 0, wszApplicationName);
|
HeapFree(GetProcessHeap(), 0, wszApplicationName);
|
||||||
|
if (wszParameters != parametersBuffer)
|
||||||
|
HeapFree(GetProcessHeap(), 0, wszParameters);
|
||||||
|
if (wszDir != dirBuffer)
|
||||||
|
HeapFree(GetProcessHeap(), 0, wszDir);
|
||||||
|
if (wcmd != wcmdBuffer)
|
||||||
|
HeapFree(GetProcessHeap(), 0, wcmd);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Else, try to find the executable */
|
/* Else, try to find the executable */
|
||||||
wcmd[0] = '\0';
|
wcmd[0] = '\0';
|
||||||
retval = SHELL_FindExecutable(sei_tmp.lpDirectory, lpFile, sei_tmp.lpVerb, wcmd, 1024, lpstrProtocol, &env, sei_tmp.lpIDList, sei_tmp.lpParameters);
|
retval = SHELL_FindExecutable(sei_tmp.lpDirectory, lpFile, sei_tmp.lpVerb, wcmd, wcmdLen, lpstrProtocol, &env, sei_tmp.lpIDList, sei_tmp.lpParameters);
|
||||||
if (retval > 32) /* Found */
|
if (retval > 32) /* Found */
|
||||||
{
|
{
|
||||||
WCHAR wszQuotedCmd[MAX_PATH+2];
|
retval = SHELL_quote_and_execute( wcmd, wszParameters, lpstrProtocol,
|
||||||
/* Must quote to handle case where cmd contains spaces,
|
wszApplicationName, env, &sei_tmp,
|
||||||
* else security hole if malicious user creates executable file "C:\\Program"
|
sei, execfunc );
|
||||||
*/
|
|
||||||
wcscpy(wszQuotedCmd, wQuote);
|
|
||||||
wcscat(wszQuotedCmd, wcmd);
|
|
||||||
wcscat(wszQuotedCmd, wQuote);
|
|
||||||
if (wszParameters[0]) {
|
|
||||||
wcscat(wszQuotedCmd, wSpace);
|
|
||||||
wcscat(wszQuotedCmd, wszParameters);
|
|
||||||
}
|
|
||||||
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, sei_tmp.lpParameters, wcmd, execfunc, &sei_tmp, sei);
|
|
||||||
else
|
|
||||||
retval = execfunc(wszQuotedCmd, env, FALSE, &sei_tmp, sei);
|
|
||||||
HeapFree( GetProcessHeap(), 0, env );
|
HeapFree( GetProcessHeap(), 0, env );
|
||||||
}
|
}
|
||||||
|
else if (PathIsDirectoryW(lpFile))
|
||||||
|
{
|
||||||
|
static const WCHAR wExplorer[] = {'e','x','p','l','o','r','e','r',0};
|
||||||
|
static const WCHAR wQuote[] = {'"',0};
|
||||||
|
WCHAR wExec[MAX_PATH];
|
||||||
|
WCHAR * lpQuotedFile = HeapAlloc( GetProcessHeap(), 0, sizeof(WCHAR) * (strlenW(lpFile) + 3) );
|
||||||
|
|
||||||
|
if (lpQuotedFile)
|
||||||
|
{
|
||||||
|
retval = SHELL_FindExecutable( sei_tmp.lpDirectory, wExplorer,
|
||||||
|
wszOpen, wExec, MAX_PATH,
|
||||||
|
NULL, &env, NULL, NULL );
|
||||||
|
if (retval > 32)
|
||||||
|
{
|
||||||
|
strcpyW(lpQuotedFile, wQuote);
|
||||||
|
strcatW(lpQuotedFile, lpFile);
|
||||||
|
strcatW(lpQuotedFile, wQuote);
|
||||||
|
retval = SHELL_quote_and_execute( wExec, lpQuotedFile,
|
||||||
|
lpstrProtocol,
|
||||||
|
wszApplicationName, env,
|
||||||
|
&sei_tmp, sei, execfunc );
|
||||||
|
HeapFree( GetProcessHeap(), 0, env );
|
||||||
|
}
|
||||||
|
HeapFree( GetProcessHeap(), 0, lpQuotedFile );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
retval = 0; /* Out of memory */
|
||||||
|
}
|
||||||
else if (PathIsURLW(lpFile)) /* File not found, check for URL */
|
else if (PathIsURLW(lpFile)) /* File not found, check for URL */
|
||||||
{
|
{
|
||||||
static const WCHAR wShell[] = {'\\','s','h','e','l','l','\\',0};
|
retval = SHELL_execute_url( lpFile, wFile, wcmd, &sei_tmp, sei, execfunc );
|
||||||
static const WCHAR wCommand[] = {'\\','c','o','m','m','a','n','d',0};
|
|
||||||
LPWSTR lpstrRes;
|
|
||||||
INT iSize;
|
|
||||||
|
|
||||||
lpstrRes = wcschr(lpFile, ':');
|
|
||||||
if (lpstrRes)
|
|
||||||
iSize = lpstrRes - lpFile;
|
|
||||||
else
|
|
||||||
iSize = wcslen(lpFile);
|
|
||||||
|
|
||||||
TRACE("Got URL: %s\n", debugstr_w(lpFile));
|
|
||||||
/* Looking for ...protocol\shell\lpOperation\command */
|
|
||||||
memcpy(lpstrProtocol, lpFile, iSize*sizeof(WCHAR));
|
|
||||||
lpstrProtocol[iSize] = '\0';
|
|
||||||
wcscat(lpstrProtocol, wShell);
|
|
||||||
wcscat(lpstrProtocol, sei_tmp.lpVerb? sei_tmp.lpVerb: wszOpen);
|
|
||||||
wcscat(lpstrProtocol, wCommand);
|
|
||||||
|
|
||||||
/* Remove File Protocol from lpFile */
|
|
||||||
/* In the case file://path/file */
|
|
||||||
if (!_wcsnicmp(lpFile, wFile, iSize))
|
|
||||||
{
|
|
||||||
lpFile += iSize;
|
|
||||||
while (*lpFile == ':') lpFile++;
|
|
||||||
}
|
|
||||||
retval = execute_from_key(lpstrProtocol, lpFile, NULL, sei_tmp.lpParameters, wcmd, execfunc, &sei_tmp, sei);
|
|
||||||
}
|
}
|
||||||
/* Check if file specified is in the form www.??????.*** */
|
/* Check if file specified is in the form www.??????.*** */
|
||||||
else if (!_wcsnicmp(lpFile, wWww, 3))
|
else if (!strncmpiW(lpFile, wWww, 3))
|
||||||
{
|
{
|
||||||
/* if so, append lpFile http:// and call ShellExecute */
|
/* if so, append lpFile http:// and call ShellExecute */
|
||||||
WCHAR lpstrTmpFile[256];
|
WCHAR lpstrTmpFile[256];
|
||||||
wcscpy(lpstrTmpFile, wHttp);
|
strcpyW(lpstrTmpFile, wHttp);
|
||||||
wcscat(lpstrTmpFile, lpFile);
|
strcatW(lpstrTmpFile, lpFile);
|
||||||
retval = (UINT_PTR)ShellExecuteW(sei_tmp.hwnd, sei_tmp.lpVerb, lpstrTmpFile, NULL, NULL, 0);
|
retval = (UINT_PTR)ShellExecuteW(sei_tmp.hwnd, sei_tmp.lpVerb, lpstrTmpFile, NULL, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACE("retval %lu\n", retval);
|
TRACE("retval %lu\n", retval);
|
||||||
|
|
||||||
|
if (retval <= 32 && !(sei_tmp.fMask & SEE_MASK_FLAG_NO_UI))
|
||||||
|
{
|
||||||
|
OPENASINFO Info;
|
||||||
|
|
||||||
|
//FIXME
|
||||||
|
// need full path
|
||||||
|
|
||||||
|
Info.pcszFile = wszApplicationName;
|
||||||
|
Info.pcszClass = NULL;
|
||||||
|
Info.oaifInFlags = OAIF_ALLOW_REGISTRATION | OAIF_EXEC;
|
||||||
|
|
||||||
|
if (SHOpenWithDialog(sei_tmp.hwnd, &Info))
|
||||||
|
retval = 33; //FIXME
|
||||||
|
else
|
||||||
|
do_error_dialog(retval, sei_tmp.hwnd);
|
||||||
|
}
|
||||||
|
|
||||||
HeapFree(GetProcessHeap(), 0, wszApplicationName);
|
HeapFree(GetProcessHeap(), 0, wszApplicationName);
|
||||||
|
if (wszParameters != parametersBuffer)
|
||||||
|
HeapFree(GetProcessHeap(), 0, wszParameters);
|
||||||
|
if (wszDir != dirBuffer)
|
||||||
|
HeapFree(GetProcessHeap(), 0, wszDir);
|
||||||
|
if (wcmd != wcmdBuffer)
|
||||||
|
HeapFree(GetProcessHeap(), 0, wcmd);
|
||||||
|
|
||||||
sei->hInstApp = (HINSTANCE)(retval > 32 ? 33 : retval);
|
sei->hInstApp = (HINSTANCE)(retval > 32 ? 33 : retval);
|
||||||
|
|
||||||
return retval > 32;
|
return retval > 32;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1673,7 +1859,7 @@ HINSTANCE WINAPI ShellExecuteA(HWND hWnd, LPCSTR lpOperation,LPCSTR lpFile,
|
||||||
debugstr_a(lpParameters), debugstr_a(lpDirectory), iShowCmd);
|
debugstr_a(lpParameters), debugstr_a(lpDirectory), iShowCmd);
|
||||||
|
|
||||||
sei.cbSize = sizeof(sei);
|
sei.cbSize = sizeof(sei);
|
||||||
sei.fMask = 0;
|
sei.fMask = SEE_MASK_FLAG_NO_UI;
|
||||||
sei.hwnd = hWnd;
|
sei.hwnd = hWnd;
|
||||||
sei.lpVerb = lpOperation;
|
sei.lpVerb = lpOperation;
|
||||||
sei.lpFile = lpFile;
|
sei.lpFile = lpFile;
|
||||||
|
@ -1759,7 +1945,7 @@ HINSTANCE WINAPI ShellExecuteW(HWND hwnd, LPCWSTR lpOperation, LPCWSTR lpFile,
|
||||||
|
|
||||||
TRACE("\n");
|
TRACE("\n");
|
||||||
sei.cbSize = sizeof(sei);
|
sei.cbSize = sizeof(sei);
|
||||||
sei.fMask = 0;
|
sei.fMask = SEE_MASK_FLAG_NO_UI;
|
||||||
sei.hwnd = hwnd;
|
sei.hwnd = hwnd;
|
||||||
sei.lpVerb = lpOperation;
|
sei.lpVerb = lpOperation;
|
||||||
sei.lpFile = lpFile;
|
sei.lpFile = lpFile;
|
||||||
|
@ -1776,6 +1962,42 @@ HINSTANCE WINAPI ShellExecuteW(HWND hwnd, LPCWSTR lpOperation, LPCWSTR lpFile,
|
||||||
return sei.hInstApp;
|
return sei.hInstApp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
* WOWShellExecute [SHELL32.@]
|
||||||
|
*
|
||||||
|
* FIXME: the callback function most likely doesn't work the same way on Windows.
|
||||||
|
*/
|
||||||
|
HINSTANCE WINAPI WOWShellExecute(HWND hWnd, LPCSTR lpOperation,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.lpFile = lpFile ? __SHCloneStrAtoW(&wFile, lpFile) : NULL;
|
||||||
|
seiW.lpParameters = lpParameters ? __SHCloneStrAtoW(&wParameters, lpParameters) : NULL;
|
||||||
|
seiW.lpDirectory = lpDirectory ? __SHCloneStrAtoW(&wDirectory, lpDirectory) : NULL;
|
||||||
|
|
||||||
|
seiW.cbSize = sizeof(seiW);
|
||||||
|
seiW.fMask = 0;
|
||||||
|
seiW.hwnd = hWnd;
|
||||||
|
seiW.nShow = iShowCmd;
|
||||||
|
seiW.lpIDList = 0;
|
||||||
|
seiW.lpClass = 0;
|
||||||
|
seiW.hkeyClass = 0;
|
||||||
|
seiW.dwHotKey = 0;
|
||||||
|
seiW.hProcess = hProcess;
|
||||||
|
|
||||||
|
SHELL_execute( &seiW, callback );
|
||||||
|
|
||||||
|
SHFree(wVerb);
|
||||||
|
SHFree(wFile);
|
||||||
|
SHFree(wParameters);
|
||||||
|
SHFree(wDirectory);
|
||||||
|
return seiW.hInstApp;
|
||||||
|
}
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
* OpenAs_RunDLLA [SHELL32.@]
|
* OpenAs_RunDLLA [SHELL32.@]
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -135,6 +135,8 @@
|
||||||
#define IDS_LNK_FILE 170
|
#define IDS_LNK_FILE 170
|
||||||
#define IDS_SYS_FILE 171
|
#define IDS_SYS_FILE 171
|
||||||
#define IDS_EMPTY_BITBUCKET 172
|
#define IDS_EMPTY_BITBUCKET 172
|
||||||
|
#define IDS_SHLEXEC_NOASSOC 173
|
||||||
|
|
||||||
#define IDS_OPEN_VERB 300
|
#define IDS_OPEN_VERB 300
|
||||||
#define IDS_RUNAS_VERB 301
|
#define IDS_RUNAS_VERB 301
|
||||||
#define IDS_EDIT_VERB 302
|
#define IDS_EDIT_VERB 302
|
||||||
|
@ -165,6 +167,7 @@
|
||||||
#define IDS_FORMATDRIVE 327
|
#define IDS_FORMATDRIVE 327
|
||||||
#define IDS_RENAME 328
|
#define IDS_RENAME 328
|
||||||
#define IDS_INSERT 329
|
#define IDS_INSERT 329
|
||||||
|
#define IDS_DESCRIPTION 330
|
||||||
|
|
||||||
/* Note: this string is referenced from the registry */
|
/* Note: this string is referenced from the registry */
|
||||||
#define IDS_RECYCLEBIN_FOLDER_NAME 8964
|
#define IDS_RECYCLEBIN_FOLDER_NAME 8964
|
||||||
|
|
|
@ -411,23 +411,6 @@ RealDriveTypeFlags(INT iDrive, BOOL bUnknown)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Unimplemented
|
|
||||||
*/
|
|
||||||
HINSTANCE
|
|
||||||
WINAPI
|
|
||||||
WOWShellExecute(HWND hwnd,
|
|
||||||
LPCWSTR lpOperation,
|
|
||||||
LPCWSTR lpFile,
|
|
||||||
LPCWSTR lpParameters,
|
|
||||||
LPCWSTR lpDirectory,
|
|
||||||
INT nShowCmd,
|
|
||||||
void *lpfnCBWinExec)
|
|
||||||
{
|
|
||||||
FIXME("WOWShellExecute() stub\n");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Unimplemented
|
* Unimplemented
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in a new issue