📄 shlexec.c
字号:
/* make copies of all path/command strings */
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
strcpyW(wszApplicationName, sei_tmp.lpFile);
if (sei_tmp.lpParameters)
strcpyW(wszParameters, sei_tmp.lpParameters);
else
*wszParameters = '\0';
if (sei_tmp.lpDirectory)
strcpyW(wszDir, sei_tmp.lpDirectory);
else
*wszDir = '\0';
/* adjust string pointers to point to the new buffers */
sei_tmp.lpFile = wszApplicationName;
sei_tmp.lpParameters = wszParameters;
sei_tmp.lpDirectory = wszDir;
if (sei_tmp.fMask & unsupportedFlags)
{
FIXME("flags ignored: 0x%08lx\n", sei_tmp.fMask & unsupportedFlags);
}
/* process the IDList */
if (sei_tmp.fMask & SEE_MASK_IDLIST)
{
IShellExecuteHookW* pSEH;
HRESULT hr = SHBindToParent(sei_tmp.lpIDList, &IID_IShellExecuteHookW, (LPVOID*)&pSEH, NULL);
if (SUCCEEDED(hr))
{
hr = IShellExecuteHookW_Execute(pSEH, &sei_tmp);
IShellExecuteHookW_Release(pSEH);
if (hr == S_OK)
return TRUE;
}
SHGetPathFromIDListW(sei_tmp.lpIDList, wszApplicationName);
TRACE("-- idlist=%p (%s)\n", sei_tmp.lpIDList, debugstr_w(wszApplicationName));
}
if ( ERROR_SUCCESS == ShellExecute_FromContextMenu( &sei_tmp ) )
{
sei->hInstApp = (HINSTANCE) 33;
return TRUE;
}
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);
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));
/* 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);
if (!done && wszApplicationName[0])
{
strcatW(wcmd, wSpace);
strcatW(wcmd, wszApplicationName);
}
retval = execfunc(wcmd, NULL, FALSE, &sei_tmp, sei);
if (retval > 32)
return TRUE;
else
return FALSE;
}
/* 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 */
strcpyW(wszParameters, buffer);
strcpyW(wszApplicationName, wExplorer);
sei_tmp.fMask &= ~SEE_MASK_INVOKEIDLIST;
} else {
/* 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 &&
0 != (attribs & FILE_ATTRIBUTE_DIRECTORY) &&
HCR_GetExecuteCommandW(0, wszFolder,
sei_tmp.lpVerb?sei_tmp.lpVerb:wszOpen,
buffer, sizeof(buffer))) {
SHELL_ArgifyW(wszApplicationName,
sizeof(wszApplicationName)/sizeof(WCHAR),
buffer, target, sei_tmp.lpIDList, NULL);
}
sei_tmp.fMask &= ~SEE_MASK_INVOKEIDLIST;
}
}
}
/* expand environment strings */
if (ExpandEnvironmentStringsW(sei_tmp.lpFile, buffer, MAX_PATH))
lstrcpyW(wszApplicationName, buffer);
if (*sei_tmp.lpParameters)
if (ExpandEnvironmentStringsW(sei_tmp.lpParameters, buffer, MAX_PATH))
lstrcpyW(wszParameters, buffer);
if (*sei_tmp.lpDirectory)
if (ExpandEnvironmentStringsW(sei_tmp.lpDirectory, buffer, MAX_PATH))
lstrcpyW(wszDir, buffer);
/* Else, try to execute the filename */
TRACE("execute:%s,%s,%s\n", debugstr_w(wszApplicationName), debugstr_w(wszParameters), debugstr_w(wszDir));
/* separate out command line arguments from executable file name */
if (!*sei_tmp.lpParameters) {
/* If the executable path is quoted, handle the rest of the command line as parameters. */
if (sei_tmp.lpFile[0] == '"') {
LPWSTR src = wszApplicationName/*sei_tmp.lpFile*/ + 1;
LPWSTR dst = wfileName;
LPWSTR end;
/* copy the unquoted executable path to 'wfileName' */
while(*src && *src!='"')
*dst++ = *src++;
*dst = '\0';
if (*src == '"') {
end = ++src;
while(isspace(*src))
++src;
} else
end = src;
/* copy the parameter string to 'wszParameters' */
strcpyW(wszParameters, src);
/* terminate previous command string after the quote character */
*end = '\0';
}
else
{
/* If the executable name is not quoted, we have to use this search loop here,
that in CreateProcess() is not sufficient because it does not handle shell links. */
WCHAR buffer[MAX_PATH], xlpFile[MAX_PATH];
LPWSTR space, s;
LPWSTR beg = wszApplicationName/*sei_tmp.lpFile*/;
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))
{
/* separate out command from parameter string */
LPCWSTR p = space + 1;
while(isspaceW(*p))
++p;
strcpyW(wszParameters, p);
*space = '\0';
break;
}
}
strcpyW(wfileName, sei_tmp.lpFile);
}
} else
strcpyW(wfileName, sei_tmp.lpFile);
lpFile = wfileName;
strcpyW(wcmd, wszApplicationName);
if (sei_tmp.lpParameters[0]) {
strcatW(wcmd, wSpace);
strcatW(wcmd, wszParameters);
}
/* We set the default to open, and that should generally work.
But that is not really the way the MS docs say to do it. */
if (!sei_tmp.lpVerb)
sei_tmp.lpVerb = wszOpen;
retval = execfunc(wcmd, NULL, FALSE, &sei_tmp, sei);
if (retval > 32)
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);
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"
*/
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(sei_tmp.lpVerb), debugstr_w(wszQuotedCmd), debugstr_w(lpstrProtocol));
if (*lpstrProtocol)
retval = execute_from_key(lpstrProtocol, wszApplicationName, env, sei_tmp.lpParameters, execfunc, &sei_tmp, sei);
else
retval = execfunc(wszQuotedCmd, env, FALSE, &sei_tmp, sei);
HeapFree( GetProcessHeap(), 0, env );
}
else if (PathIsURLW((LPWSTR)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 = 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 */
memcpy(lpstrProtocol, lpFile, iSize*sizeof(WCHAR));
lpstrProtocol[iSize] = '\0';
strcatW(lpstrProtocol, wShell);
strcatW(lpstrProtocol, sei_tmp.lpVerb? sei_tmp.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, sei_tmp.lpParameters, execfunc, &sei_tmp, sei);
}
/* Check if file specified is in the form www.??????.*** */
else if (!strncmpiW(lpFile, wWww, 3))
{
/* if so, append lpFile http:// and call ShellExecute */
WCHAR lpstrTmpFile[256];
strcpyW(lpstrTmpFile, wHttp);
strcatW(lpstrTmpFile, lpFile);
retval = (UINT_PTR)ShellExecuteW(sei_tmp.hwnd, sei_tmp.lpVerb, lpstrTmpFile, NULL, NULL, 0);
}
TRACE("retval %u\n", retval);
if (retval <= 32)
{
sei->hInstApp = (HINSTANCE)retval;
return FALSE;
}
sei->hInstApp = (HINSTANCE)33;
return TRUE;
}
/*************************************************************************
* ShellExecuteA [SHELL32.290]
*/
HINSTANCE WINAPI ShellExecuteA(HWND hWnd, LPCSTR lpOperation,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),
debugstr_a(lpParameters), debugstr_a(lpDirectory), iShowCmd);
sei.cbSize = sizeof(sei);
sei.fMask = 0;
sei.hwnd = hWnd;
sei.lpVerb = lpOperation;
sei.lpFile = lpFile;
sei.lpParameters = lpParameters;
sei.lpDirectory = lpDirectory;
sei.nShow = iShowCmd;
sei.lpIDList = 0;
sei.lpClass = 0;
sei.hkeyClass = 0;
sei.dwHotKey = 0;
sei.hProcess = 0;
ShellExecuteExA (&sei);
return sei.hInstApp;
}
/*************************************************************************
* ShellExecuteExA [SHELL32.292]
*
*/
BOOL WINAPI ShellExecuteExA (LPSHELLEXECUTEINFOA sei)
{
SHELLEXECUTEINFOW seiW;
BOOL ret;
WCHAR *wVerb = NULL, *wFile = NULL, *wParameters = NULL, *wDirectory = NULL, *wClass = NULL;
TRACE("%p\n", sei);
memcpy(&seiW, sei, sizeof(SHELLEXECUTEINFOW));
if (sei->lpVerb)
seiW.lpVerb = __SHCloneStrAtoW(&wVerb, sei->lpVerb);
if (sei->lpFile)
seiW.lpFile = __SHCloneStrAtoW(&wFile, sei->lpFile);
if (sei->lpParameters)
seiW.lpParameters = __SHCloneStrAtoW(&wParameters, sei->lpParameters);
if (sei->lpDirectory)
seiW.lpDirectory = __SHCloneStrAtoW(&wDirectory, sei->lpDirectory);
if ((sei->fMask & SEE_MASK_CLASSALL) == SEE_MASK_CLASSNAME && sei->lpClass)
seiW.lpClass = __SHCloneStrAtoW(&wClass, sei->lpClass);
else
seiW.lpClass = NULL;
ret = SHELL_execute( &seiW, SHELL_ExecuteW );
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);
if (wDirectory) SHFree(wDirectory);
if (wClass) SHFree(wClass);
return ret;
}
/*************************************************************************
* ShellExecuteExW [SHELL32.293]
*
*/
BOOL WINAPI ShellExecuteExW (LPSHELLEXECUTEINFOW sei)
{
return SHELL_execute( sei, SHELL_ExecuteW );
}
/*************************************************************************
* ShellExecuteW [SHELL32.294]
* from shellapi.h
* WINSHELLAPI HINSTANCE APIENTRY ShellExecuteW(HWND hwnd, LPCWSTR lpOperation,
* LPCWSTR lpFile, LPCWSTR lpParameters, LPCWSTR lpDirectory, INT nShowCmd);
*/
HINSTANCE WINAPI ShellExecuteW(HWND hwnd, LPCWSTR lpOperation, LPCWSTR lpFile,
LPCWSTR lpParameters, LPCWSTR lpDirectory, INT nShowCmd)
{
SHELLEXECUTEINFOW sei;
TRACE("\n");
sei.cbSize = sizeof(sei);
sei.fMask = 0;
sei.hwnd = hwnd;
sei.lpVerb = lpOperation;
sei.lpFile = lpFile;
sei.lpParameters = lpParameters;
sei.lpDirectory = lpDirectory;
sei.nShow = nShowCmd;
sei.lpIDList = 0;
sei.lpClass = 0;
sei.hkeyClass = 0;
sei.dwHotKey = 0;
sei.hProcess = 0;
SHELL_execute( &sei, SHELL_ExecuteW );
return sei.hInstApp;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -