Author: janderwald
Date: Thu Apr 23 16:39:11 2009
New Revision: 40666
URL:
http://svn.reactos.org/svn/reactos?rev=40666&view=rev
Log:
- Call OpenWith dialog when no file association is found
- Partial wine syncAlexandre Julliard <julliard(a)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(a)gmail.com>
shell32: Add a message for opening files with no association.
Marcus Meissner <marcus(a)jet.franken.de>
shell32: Fixed potential buffer overwrite in execute_from_key (Coverity).
Vincent Povirk <vincent(a)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(a)voip.null.ro>
shell32.dll: Return SE_ERR_FNF if file not found before checking for associations.
Modified:
trunk/reactos/dll/win32/shell32/shell32_main.h
trunk/reactos/dll/win32/shell32/shlexec.c
trunk/reactos/dll/win32/shell32/shresdef.h
trunk/reactos/dll/win32/shell32/stubs.c
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 Apr 23 16:39:11 2009
@@ -213,7 +213,7 @@
#define HINSTANCE_16(h32) (LOWORD(h32))
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);
Modified: trunk/reactos/dll/win32/shell32/shlexec.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/shell32/shlexec.…
==============================================================================
--- trunk/reactos/dll/win32/shell32/shlexec.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/shell32/shlexec.c [iso-8859-1] Thu Apr 23 16:39:11 2009
@@ -165,7 +165,7 @@
case 'I':
if (pidl) {
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 */
WCHAR buf[100];
LPVOID pv;
@@ -191,7 +191,7 @@
*/
/* Make sure that we have at least one more %.*/
- if (wcschr(fmt, '%'))
+ if (strchrW(fmt, '%'))
{
WCHAR tmpBuffer[1024];
PWSTR tmpB = tmpBuffer;
@@ -275,7 +275,7 @@
*
*/
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;
PROCESS_INFORMATION info;
@@ -664,9 +664,7 @@
}
else
{
- /* Truncate on first space, like Windows:
- *
http://support.microsoft.com/?scid=kb%3Ben-us%3B140724
- */
+ /* Truncate on first space */
WCHAR *p = lpResult;
while (*p != ' ' && *p != '\0')
p++;
@@ -728,10 +726,10 @@
* 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,
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 wTopic[] =
{'\\','t','o','p','i','c',0};
@@ -771,7 +769,7 @@
else
{
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;
memcpy(command, start, idx*sizeof(WCHAR));
@@ -796,7 +794,7 @@
!wcscmp(ptr, wSo))
*ptr = 0;
- ptr = wcschr(app, '.');
+ ptr = strrchrW(app, '.');
assert(ptr);
*ptr = 0;
}
@@ -843,7 +841,7 @@
SetLastError(ERROR_DDE_FAIL);
return 30; /* whatever */
}
- wcscpy(endkey, wIfexec);
+ strcpyW(endkey, wIfexec);
ifexeclen = sizeof(ifexec);
if (RegQueryValueW(HKEY_CLASSES_ROOT, regkey, ifexec, &ifexeclen) ==
ERROR_SUCCESS)
{
@@ -860,7 +858,7 @@
* error DMLERR_NOTPROCESSED on XTYP_EXECUTE request.
*/
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);
else
{
@@ -888,7 +886,7 @@
/*************************************************************************
* 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,
SHELL_ExecuteW32 execfunc,
LPSHELLEXECUTEINFOW psei, LPSHELLEXECUTEINFOW psei_out)
@@ -914,8 +912,8 @@
/* Is there a replace() function anywhere? */
cmdlen /= sizeof(WCHAR);
- if (cmdlen >= sizeof(cmd)/sizeof(WCHAR))
- cmdlen = sizeof(cmd)/sizeof(WCHAR)-1;
+ if (cmdlen >= sizeof(cmd)/sizeof(WCHAR))
+ cmdlen = sizeof(cmd)/sizeof(WCHAR)-1;
cmd[cmdlen] = '\0';
SHELL_ArgifyW(param, sizeof(param)/sizeof(WCHAR), cmd, lpFile, psei->lpIDList,
szCommandline, &resultLen);
if (resultLen > sizeof(param)/sizeof(WCHAR))
@@ -924,14 +922,14 @@
/* Get the parameters needed by the application
from the associated ddeexec key */
- tmp = wcsstr(key, wCommand);
+ tmp = strstrW(key, wCommand);
assert(tmp);
wcscpy(tmp, wDdeexec);
if (RegQueryValueW(HKEY_CLASSES_ROOT, key, ddeexec, &ddeexeclen) ==
ERROR_SUCCESS)
{
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);
}
else if (param[0])
@@ -1017,7 +1015,7 @@
}
/* 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;
LPWSTR cls = NULL;
@@ -1078,10 +1076,11 @@
else
{
WCHAR fullpath[MAX_PATH];
+ BOOL ret;
fullpath[0] = 0;
- r = GetFullPathNameW( sei->lpFile, MAX_PATH, fullpath, NULL );
- if (!r)
+ ret = GetFullPathNameW( sei->lpFile, MAX_PATH, fullpath, NULL );
+ if (!ret)
goto end;
pidl = ILCreateFromPathW( fullpath );
@@ -1272,25 +1271,196 @@
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]
*/
BOOL SHELL_execute( LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc )
{
- static const WCHAR wQuote[] = {'"',0};
static const WCHAR wSpace[] = {' ',0};
static const WCHAR wWww[] = {'w','w','w',0};
static const WCHAR wFile[] = {'f','i','l','e',0};
static const WCHAR wHttp[] =
{'h','t','t','p',':','/','/',0};
- static const WCHAR 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 =
- SEE_MASK_INVOKEIDLIST | SEE_MASK_HOTKEY |
- SEE_MASK_CONNECTNETDRV | SEE_MASK_FLAG_DDEWAIT | SEE_MASK_FLAG_NO_UI |
+ SEE_MASK_INVOKEIDLIST | SEE_MASK_ICON | SEE_MASK_HOTKEY |
+ SEE_MASK_CONNECTNETDRV | SEE_MASK_FLAG_DDEWAIT |
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 parametersLen = sizeof(parametersBuffer) / sizeof(WCHAR);
+ DWORD dirLen = sizeof(dirBuffer) / sizeof(WCHAR);
+ DWORD wcmdLen = sizeof(wcmdBuffer) / sizeof(WCHAR);
DWORD len;
SHELLEXECUTEINFOW sei_tmp; /* modifiable copy of SHELLEXECUTEINFO struct */
WCHAR wfileName[MAX_PATH];
@@ -1298,13 +1468,10 @@
WCHAR lpstrProtocol[256];
LPCWSTR lpFile;
UINT_PTR retval = SE_ERR_NOASSOC;
- WCHAR wcmd[1024];
- WCHAR buffer[MAX_PATH];
- BOOL done;
BOOL appKnownSingular = FALSE;
/* 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",
sei_tmp.fMask, sei_tmp.hwnd, debugstr_w(sei_tmp.lpVerb),
@@ -1323,7 +1490,7 @@
}
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;
wszApplicationName = HeapAlloc(GetProcessHeap(), 0,
dwApplicationNameLen*sizeof(WCHAR));
memcpy(wszApplicationName, sei_tmp.lpFile+1, (l+1)*sizeof(WCHAR));
@@ -1332,19 +1499,37 @@
appKnownSingular = TRUE;
TRACE("wszApplicationName=%s\n",debugstr_w(wszApplicationName));
} else {
- DWORD l = wcslen(sei_tmp.lpFile)+1;
+ DWORD l = strlenW(sei_tmp.lpFile)+1;
if(l > dwApplicationNameLen) dwApplicationNameLen = l+1;
wszApplicationName = HeapAlloc(GetProcessHeap(), 0,
dwApplicationNameLen*sizeof(WCHAR));
memcpy(wszApplicationName, sei_tmp.lpFile, l*sizeof(WCHAR));
}
+ wszParameters = parametersBuffer;
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
*wszParameters = '\0';
+ wszDir = dirBuffer;
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
*wszDir = '\0';
@@ -1367,12 +1552,16 @@
if (SUCCEEDED(hr))
{
- hr = pSEH->lpVtbl->Execute(pSEH, &sei_tmp);
-
- pSEH->lpVtbl->Release(pSEH);
+ hr = IShellExecuteHookW_Execute(pSEH, &sei_tmp);
+
+ IShellExecuteHookW_Release(pSEH);
if (hr == S_OK) {
HeapFree(GetProcessHeap(), 0, wszApplicationName);
+ if (wszParameters != parametersBuffer)
+ HeapFree(GetProcessHeap(), 0, wszParameters);
+ if (wszDir != dirBuffer)
+ HeapFree(GetProcessHeap(), 0, wszDir);
return TRUE;
}
}
@@ -1386,80 +1575,48 @@
{
sei->hInstApp = (HINSTANCE) 33;
HeapFree(GetProcessHeap(), 0, wszApplicationName);
+ if (wszParameters != parametersBuffer)
+ HeapFree(GetProcessHeap(), 0, wszParameters);
+ if (wszDir != dirBuffer)
+ HeapFree(GetProcessHeap(), 0, wszDir);
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)
{
- /* launch a document by fileclass like 'WordPad.Document.1' */
- /* the Commandline contains 'c:\Path\wordpad.exe "%1"' */
- /* FIXME: szCommandline should not be of a fixed size. Fixed to 1024, MAX_PATH is
way too short! */
- 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);
- 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);
-
+ retval = SHELL_execute_class( wszApplicationName, &sei_tmp, sei,
+ execfunc );
+ 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);
+ if (wszParameters != parametersBuffer)
+ HeapFree(GetProcessHeap(), 0, wszParameters);
+ if (wszDir != dirBuffer)
+ HeapFree(GetProcessHeap(), 0, wszDir);
return retval > 32;
}
/* Has the IDList not yet been translated? */
if (sei_tmp.fMask & SEE_MASK_IDLIST)
{
- /* last chance to translate IDList: now also allow CLSID paths */
- if (SUCCEEDED(SHELL_GetPathFromIDListForExecuteW(sei_tmp.lpIDList, buffer,
sizeof(buffer)))) {
- if (buffer[0]==':' && buffer[1]==':') {
- /* open shell folder for the specified class GUID */
- 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;
- }
- }
+ appKnownSingular = SHELL_translate_idlist( &sei_tmp, wszParameters,
+ parametersLen,
+ wszApplicationName,
+ dwApplicationNameLen );
}
/* expand environment strings */
@@ -1487,10 +1644,11 @@
len++;
buf = HeapAlloc(GetProcessHeap(),0,len*sizeof(WCHAR));
ExpandEnvironmentStringsW(sei_tmp.lpParameters, buf, len);
- if (len > 1024)
- ERR("Parameters exceeds buffer size (%i > 1024)\n",len);
- lstrcpynW(wszParameters, buf, min(1024,len));
- HeapFree(GetProcessHeap(),0,buf);
+ if (wszParameters != parametersBuffer)
+ HeapFree(GetProcessHeap(), 0, wszParameters);
+ wszParameters = buf;
+ parametersLen = len;
+ sei_tmp.lpParameters = wszParameters;
}
}
@@ -1503,10 +1661,10 @@
len++;
buf = HeapAlloc(GetProcessHeap(),0,len*sizeof(WCHAR));
ExpandEnvironmentStringsW(sei_tmp.lpDirectory, buf, len);
- if (len > 1024)
- ERR("Directory exceeds buffer size (%i > 1024)\n",len);
- lstrcpynW(wszDir, buf, min(1024,len));
- HeapFree(GetProcessHeap(),0,buf);
+ if (wszDir != dirBuffer)
+ HeapFree(GetProcessHeap(), 0, wszDir);
+ wszDir = buf;
+ sei_tmp.lpDirectory = wszDir;
}
}
@@ -1536,7 +1694,7 @@
end = src;
/* copy the parameter string to 'wszParameters' */
- wcscpy(wszParameters, src);
+ strcpyW(wszParameters, src);
/* terminate previous command string after the quote character */
*end = '\0';
@@ -1549,114 +1707,142 @@
LPWSTR space, s;
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;
memcpy(buffer, sei_tmp.lpFile, idx * sizeof(WCHAR));
buffer[idx] = '\0';
/*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 */
LPCWSTR p = space + 1;
- while(iswspace(*p))
+ while(isspaceW(*p))
++p;
- wcscpy(wszParameters, p);
+ strcpyW(wszParameters, p);
*space = '\0';
break;
}
}
- wcscpy(wfileName, sei_tmp.lpFile);
+ lstrcpynW(wfileName, sei_tmp.lpFile,sizeof(wfileName)/sizeof(WCHAR));
}
} else
- wcscpy(wfileName, sei_tmp.lpFile);
+ lstrcpynW(wfileName, sei_tmp.lpFile,sizeof(wfileName)/sizeof(WCHAR));
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]) {
- wcscat(wcmd, wSpace);
- wcscat(wcmd, wszParameters);
+ strcatW(wcmd, wSpace);
+ strcatW(wcmd, wszParameters);
}
retval = execfunc(wcmd, NULL, FALSE, &sei_tmp, sei);
if (retval > 32) {
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;
}
/* Else, try to find the executable */
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 */
{
- WCHAR wszQuotedCmd[MAX_PATH+2];
- /* Must quote to handle case where cmd contains spaces,
- * else security hole if malicious user creates executable file
"C:\\Program"
- */
- 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);
+ retval = SHELL_quote_and_execute( wcmd, wszParameters, lpstrProtocol,
+ wszApplicationName, env, &sei_tmp,
+ sei, execfunc );
+ 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 = execfunc(wszQuotedCmd, env, FALSE, &sei_tmp, sei);
- HeapFree( GetProcessHeap(), 0, env );
+ retval = 0; /* Out of memory */
}
else if (PathIsURLW(lpFile)) /* File not found, check for URL */
{
- static const WCHAR wShell[] =
{'\\','s','h','e','l','l','\\',0};
- 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);
+ retval = SHELL_execute_url( lpFile, wFile, wcmd, &sei_tmp, sei, execfunc );
}
/* 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 */
WCHAR lpstrTmpFile[256];
- wcscpy(lpstrTmpFile, wHttp);
- wcscat(lpstrTmpFile, lpFile);
+ strcpyW(lpstrTmpFile, wHttp);
+ strcatW(lpstrTmpFile, lpFile);
retval = (UINT_PTR)ShellExecuteW(sei_tmp.hwnd, sei_tmp.lpVerb, lpstrTmpFile,
NULL, NULL, 0);
}
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);
+ 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);
+
return retval > 32;
}
@@ -1673,7 +1859,7 @@
debugstr_a(lpParameters), debugstr_a(lpDirectory), iShowCmd);
sei.cbSize = sizeof(sei);
- sei.fMask = 0;
+ sei.fMask = SEE_MASK_FLAG_NO_UI;
sei.hwnd = hWnd;
sei.lpVerb = lpOperation;
sei.lpFile = lpFile;
@@ -1759,7 +1945,7 @@
TRACE("\n");
sei.cbSize = sizeof(sei);
- sei.fMask = 0;
+ sei.fMask = SEE_MASK_FLAG_NO_UI;
sei.hwnd = hwnd;
sei.lpVerb = lpOperation;
sei.lpFile = lpFile;
@@ -1777,6 +1963,42 @@
}
/*************************************************************************
+ * 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.@]
*/
void WINAPI OpenAs_RunDLLA(HWND hwnd, HINSTANCE hinst, LPCSTR cmdline, int cmdshow)
Modified: trunk/reactos/dll/win32/shell32/shresdef.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/shell32/shresdef…
==============================================================================
--- trunk/reactos/dll/win32/shell32/shresdef.h [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/shell32/shresdef.h [iso-8859-1] Thu Apr 23 16:39:11 2009
@@ -135,6 +135,8 @@
#define IDS_LNK_FILE 170
#define IDS_SYS_FILE 171
#define IDS_EMPTY_BITBUCKET 172
+#define IDS_SHLEXEC_NOASSOC 173
+
#define IDS_OPEN_VERB 300
#define IDS_RUNAS_VERB 301
#define IDS_EDIT_VERB 302
@@ -165,6 +167,7 @@
#define IDS_FORMATDRIVE 327
#define IDS_RENAME 328
#define IDS_INSERT 329
+#define IDS_DESCRIPTION 330
/* Note: this string is referenced from the registry */
#define IDS_RECYCLEBIN_FOLDER_NAME 8964
Modified: trunk/reactos/dll/win32/shell32/stubs.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/shell32/stubs.c?…
==============================================================================
--- trunk/reactos/dll/win32/shell32/stubs.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/shell32/stubs.c [iso-8859-1] Thu Apr 23 16:39:11 2009
@@ -409,23 +409,6 @@
{
FIXME("RealDriveTypeFlags() stub\n");
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;
}
/*