#include <ctype.h>
#include <assert.h>
+#define COBJMACROS
+
#include "windef.h"
#include "winbase.h"
#include "winerror.h"
#include "winreg.h"
-#include "wownt32.h"
-#include "shellapi.h"
-#include "wingdi.h"
#include "winuser.h"
-#include "shlobj.h"
#include "shlwapi.h"
#include "ddeml.h"
#include "wine/winbase16.h"
#include "shell32_main.h"
-#include "undocshell.h"
#include "pidl.h"
#include "wine/debug.h"
static const WCHAR wszFolder[] = {'F','o','l','d','e','r',0};
static const WCHAR wszEmpty[] = {0};
+#define SEE_MASK_CLASSALL (SEE_MASK_CLASSNAME | SEE_MASK_CLASSKEY)
+
/***********************************************************************
* SHELL_ArgifyW [Internal]
* %* all following parameters (see batfile)
*
* FIXME: use 'len'
- * FIXME: Careful of going over string-boundries. No checking is done to 'res'...
+ * FIXME: Careful of going over string boundaries. No checking is done to 'res'...
*/
static BOOL SHELL_ArgifyW(WCHAR* out, int len, const WCHAR* fmt, const WCHAR* lpFile, LPITEMIDLIST pidl, LPCWSTR args)
{
WCHAR xlpFile[1024];
BOOL done = FALSE;
+ BOOL found_p1 = FALSE;
PWSTR res = out;
PCWSTR cmd;
LPVOID pv;
- WCHAR tmpBuffer[1024];
- PWSTR tmpB = tmpBuffer;
- WCHAR tmpEnvBuff[MAX_PATH];
- WCHAR* tmpE = tmpEnvBuff;
- DWORD envRet;
- static const WCHAR wszSPerc[] = {'%','s',0};
- static const WCHAR wszPerc[] = {'%',0};
TRACE("%p, %d, %s, %s, %p, %p\n", out, len, debugstr_w(fmt),
debugstr_w(lpFile), pidl, args);
else
cmd = lpFile;
- /* Add double quotation marks unless we already have them (e.g.: "file://%1" %* for exefile) */
- if (res == out || *(fmt + 1) != '"')
+ /* Add double quotation marks unless we already have them
+ (e.g.: "file://%1" %* for exefile) or unless the arg is already
+ enclosed in double quotation marks */
+ if ((res == out || *(fmt + 1) != '"') && *cmd != '"')
{
*res++ = '"';
strcpyW(res, cmd);
res += strlenW(cmd);
}
}
+ found_p1 = TRUE;
break;
/*
strcpyW(res, lpFile);
res += strlenW(lpFile);
}
+ found_p1 = TRUE;
break;
case 'i':
res += sprintfW(res, wszILPtr, pv);
SHUnlockShared(pv);
}
+ found_p1 = TRUE;
break;
- default:
- /*
- * Check if this is a env-variable here...
- */
-
- /* Make sure that we have at least one more %.*/
- if (strstrW(fmt, wszPerc))
- {
- while (*fmt != '%')
- *tmpB++ = *fmt++;
- *tmpB++ = 0;
-
- TRACE("Checking %s to be a env-var\n", debugstr_w(tmpBuffer));
+ default:
+ /*
+ * Check if this is an env-variable here...
+ */
- envRet = GetEnvironmentVariableW(tmpBuffer, tmpE, MAX_PATH);
- if (envRet == 0 || envRet > MAX_PATH)
- {
- TRACE("The env. var can't be found or is bigger than MAX_PATH => useless.");
- res += sprintfW(res, wszSPerc, tmpBuffer);
- }
- else
- {
- TRACE("Found it %s. Replacing... \n", debugstr_w(tmpEnvBuff));
- res += sprintfW(res, wszSPerc, tmpEnvBuff);
- }
- }
+ /* Make sure that we have at least one more %.*/
+ if (strchrW(fmt, '%'))
+ {
+ WCHAR tmpBuffer[1024];
+ PWSTR tmpB = tmpBuffer;
+ WCHAR tmpEnvBuff[MAX_PATH];
+ DWORD envRet;
- } /* switch */
+ while (*fmt != '%')
+ *tmpB++ = *fmt++;
+ *tmpB++ = 0;
+ TRACE("Checking %s to be an env-var\n", debugstr_w(tmpBuffer));
- fmt++;
- done = TRUE;
+ envRet = GetEnvironmentVariableW(tmpBuffer, tmpEnvBuff, MAX_PATH);
+ if (envRet == 0 || envRet > MAX_PATH)
+ strcpyW( res, tmpBuffer );
+ else
+ strcpyW( res, tmpEnvBuff );
+ res += strlenW(res);
+ }
+ done = TRUE;
+ break;
+ }
+ /* Don't skip past terminator (catch a single '%' at the end) */
+ if (*fmt != '\0')
+ {
+ fmt++;
+ }
}
else
*res++ = *fmt++;
*res = '\0';
- return done;
+ return found_p1;
}
HRESULT SHELL_GetPathFromIDListForExecuteA(LPCITEMIDLIST pidl, LPSTR pszPath, UINT uOutSize)
if (SUCCEEDED(hr) && *ppidl) {
/* We got a PIDL instead of a file system path - try to translate it. */
- if (SUCCEEDED(SHELL_GetPathFromIDListW(*ppidl, wcmd, MAX_PATH))) {
+ if (SHGetPathFromIDListW(*ppidl, wcmd)) {
SHFree(*ppidl);
*ppidl = NULL;
}
}
else if ((retval = GetLastError()) >= 32)
{
- FIXME("Strange error set by CreateProcess: %d\n", retval);
+ TRACE("CreateProcess returned error %d\n", retval);
retval = ERROR_BAD_FORMAT;
}
/******************************************************************
* dde_cb
*
- * callback for the DDE connection. not really usefull
+ * callback for the DDE connection. not really useful
*/
static HDDEDATA CALLBACK dde_cb(UINT uType, UINT uFmt, HCONV hConv,
HSZ hsz1, HSZ hsz2, HDDEDATA hData,
static const WCHAR wHttp[] = {'h','t','t','p',':','/','/',0};
static const WCHAR wExtLnk[] = {'.','l','n','k',0};
static const WCHAR wExplorer[] = {'e','x','p','l','o','r','e','r','.','e','x','e',0};
+ static const DWORD unsupportedFlags =
+ SEE_MASK_INVOKEIDLIST | SEE_MASK_ICON | SEE_MASK_HOTKEY |
+ SEE_MASK_CONNECTNETDRV | SEE_MASK_FLAG_DDEWAIT | SEE_MASK_FLAG_NO_UI |
+ SEE_MASK_UNICODE | SEE_MASK_NO_CONSOLE | SEE_MASK_ASYNCOK |
+ SEE_MASK_HMONITOR;
WCHAR wszApplicationName[MAX_PATH+2], wszParameters[1024], wszDir[MAX_PATH];
SHELLEXECUTEINFOW sei_tmp; /* modifiable copy of SHELLEXECUTEINFO struct */
sei_tmp.fMask, sei_tmp.hwnd, debugstr_w(sei_tmp.lpVerb),
debugstr_w(sei_tmp.lpFile), debugstr_w(sei_tmp.lpParameters),
debugstr_w(sei_tmp.lpDirectory), sei_tmp.nShow,
- (sei_tmp.fMask & SEE_MASK_CLASSNAME) ? debugstr_w(sei_tmp.lpClass) : "not used");
+ ((sei_tmp.fMask & SEE_MASK_CLASSALL) == SEE_MASK_CLASSNAME) ?
+ debugstr_w(sei_tmp.lpClass) : "not used");
sei->hProcess = NULL;
/* make copies of all path/command strings */
- if (sei_tmp.lpFile)
- strcpyW(wszApplicationName, sei_tmp.lpFile);
+ if (!sei_tmp.lpFile)
+ *wszApplicationName = '\0';
+ else if (*sei_tmp.lpFile == '\"')
+ {
+ UINT l;
+ strcpyW(wszApplicationName, sei_tmp.lpFile+1);
+ l=lstrlenW(wszApplicationName);
+ if (wszApplicationName[l-1] == '\"')
+ wszApplicationName[l-1] = '\0';
+ TRACE("wszApplicationName=%s\n",debugstr_w(wszApplicationName));
+ }
else
- *wszApplicationName = '\0';
+ strcpyW(wszApplicationName, sei_tmp.lpFile);
if (sei_tmp.lpParameters)
strcpyW(wszParameters, sei_tmp.lpParameters);
sei_tmp.lpParameters = wszParameters;
sei_tmp.lpDirectory = wszDir;
- if (sei_tmp.fMask & (SEE_MASK_INVOKEIDLIST | SEE_MASK_ICON | SEE_MASK_HOTKEY |
- SEE_MASK_CONNECTNETDRV | SEE_MASK_FLAG_DDEWAIT |
- SEE_MASK_DOENVSUBST | SEE_MASK_FLAG_NO_UI | SEE_MASK_UNICODE |
- SEE_MASK_NO_CONSOLE | SEE_MASK_ASYNCOK | SEE_MASK_HMONITOR ))
+ if (sei_tmp.fMask & unsupportedFlags)
{
- FIXME("flags ignored: 0x%08lx\n", sei_tmp.fMask);
+ FIXME("flags ignored: 0x%08lx\n", sei_tmp.fMask & unsupportedFlags);
}
/* process the IDList */
TRACE("-- idlist=%p (%s)\n", sei_tmp.lpIDList, debugstr_w(wszApplicationName));
}
- if (sei_tmp.fMask & (SEE_MASK_CLASSNAME | SEE_MASK_CLASSKEY))
+ 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! */
- HCR_GetExecuteCommandW((sei_tmp.fMask & SEE_MASK_CLASSKEY) ? sei_tmp.hkeyClass : NULL,
- (sei_tmp.fMask & SEE_MASK_CLASSNAME) ? sei_tmp.lpClass: NULL,
+ ULONG cmask=(sei_tmp.fMask & SEE_MASK_CLASSALL);
+ HCR_GetExecuteCommandW((cmask == SEE_MASK_CLASSKEY) ? sei_tmp.hkeyClass : NULL,
+ (cmask == SEE_MASK_CLASSNAME) ? sei_tmp.lpClass: NULL,
(sei_tmp.lpVerb) ? sei_tmp.lpVerb : wszOpen,
wszParameters, sizeof(wszParameters)/sizeof(WCHAR));
LPWSTR beg = wszApplicationName/*sei_tmp.lpFile*/;
for(s=beg; (space=strchrW(s, ' ')); s=space+1) {
int idx = space-sei_tmp.lpFile;
- strncpyW(buffer, sei_tmp.lpFile, idx);
+ memcpy(buffer, sei_tmp.lpFile, idx * sizeof(WCHAR));
buffer[idx] = '\0';
/*FIXME This finds directory paths if the targeted file name contains spaces. */
lpFile = wfileName;
+ strcpyW(wcmd, wszApplicationName);
if (sei_tmp.lpParameters[0]) {
- strcatW(wszApplicationName, wSpace);
- strcatW(wszApplicationName, wszParameters);
+ strcatW(wcmd, wSpace);
+ strcatW(wcmd, wszParameters);
}
/* We set the default to open, and that should generally work.
if (!sei_tmp.lpVerb)
sei_tmp.lpVerb = wszOpen;
- retval = execfunc(wszApplicationName, NULL, FALSE, &sei_tmp, sei);
+ retval = execfunc(wcmd, NULL, FALSE, &sei_tmp, sei);
if (retval > 32)
return TRUE;
retval = execute_from_key(lpstrProtocol, wszApplicationName, env, sei_tmp.lpParameters, execfunc, &sei_tmp, sei);
else
retval = execfunc(wszQuotedCmd, env, FALSE, &sei_tmp, sei);
- if (env) HeapFree( GetProcessHeap(), 0, env );
+ HeapFree( GetProcessHeap(), 0, env );
}
else if (PathIsURLW((LPWSTR)lpFile)) /* File not found, check for URL */
{
TRACE("Got URL: %s\n", debugstr_w(lpFile));
/* Looking for ...protocol\shell\lpOperation\command */
- strncpyW(lpstrProtocol, lpFile, iSize);
+ memcpy(lpstrProtocol, lpFile, iSize*sizeof(WCHAR));
lpstrProtocol[iSize] = '\0';
strcatW(lpstrProtocol, wShell);
strcatW(lpstrProtocol, sei_tmp.lpVerb? sei_tmp.lpVerb: wszOpen);
HANDLE hProcess = 0;
TRACE("%p,%s,%s,%s,%s,%d\n",
- hWnd, lpOperation, lpFile, lpParameters, lpDirectory, iShowCmd);
+ hWnd, debugstr_a(lpOperation), debugstr_a(lpFile),
+ debugstr_a(lpParameters), debugstr_a(lpDirectory), iShowCmd);
sei.cbSize = sizeof(sei);
sei.fMask = 0;
return sei.hInstApp;
}
-/*************************************************************************
- * ShellExecuteEx [SHELL32.291]
- *
- */
-BOOL WINAPI ShellExecuteExAW (LPVOID sei)
-{
- if (SHELL_OsIsUnicode())
- return ShellExecuteExW32 (sei, SHELL_ExecuteW);
- return ShellExecuteExA (sei);
-}
-
/*************************************************************************
* ShellExecuteExA [SHELL32.292]
*
if (sei->lpDirectory)
seiW.lpDirectory = __SHCloneStrAtoW(&wDirectory, sei->lpDirectory);
- if ((sei->fMask & SEE_MASK_CLASSNAME) && sei->lpClass)
+ if ((sei->fMask & SEE_MASK_CLASSALL) == SEE_MASK_CLASSNAME && sei->lpClass)
seiW.lpClass = __SHCloneStrAtoW(&wClass, sei->lpClass);
else
seiW.lpClass = NULL;
sei->hInstApp = seiW.hInstApp;
+ if (sei->fMask & SEE_MASK_NOCLOSEPROCESS)
+ sei->hProcess = seiW.hProcess;
+
if (wVerb) SHFree(wVerb);
if (wFile) SHFree(wFile);
if (wParameters) SHFree(wParameters);