diff --git a/dll/win32/shell32/CDefaultContextMenu.cpp b/dll/win32/shell32/CDefaultContextMenu.cpp index b7dd4eedf40..f55ed72dc3c 100644 --- a/dll/win32/shell32/CDefaultContextMenu.cpp +++ b/dll/win32/shell32/CDefaultContextMenu.cpp @@ -1302,8 +1302,7 @@ CDefaultContextMenu::TryToBrowse( HRESULT CDefaultContextMenu::InvokePidl(LPCMINVOKECOMMANDINFOEX lpcmi, LPCITEMIDLIST pidl, PStaticShellEntry pEntry) { - BOOL unicode = lpcmi->cbSize >= FIELD_OFFSET(CMINVOKECOMMANDINFOEX, ptInvoke) && - (lpcmi->fMask & CMIC_MASK_UNICODE); + const BOOL unicode = IsUnicode(*lpcmi); LPITEMIDLIST pidlFull = ILCombine(m_pidlFolder, pidl); if (pidlFull == NULL) @@ -1315,7 +1314,23 @@ CDefaultContextMenu::InvokePidl(LPCMINVOKECOMMANDINFOEX lpcmi, LPCITEMIDLIST pid BOOL bHasPath = SHGetPathFromIDListW(pidlFull, wszPath); WCHAR wszDir[MAX_PATH]; - if (bHasPath) + + SHELLEXECUTEINFOW sei = { sizeof(sei) }; + sei.fMask = SEE_MASK_CLASSKEY | SEE_MASK_IDLIST | (CmicFlagsToSeeFlags(lpcmi->fMask) & ~SEE_MASK_INVOKEIDLIST); + sei.hwnd = lpcmi->hwnd; + sei.nShow = lpcmi->nShow; + sei.lpVerb = pEntry->Verb; + sei.lpIDList = pidlFull; + sei.hkeyClass = pEntry->hkClass; + sei.dwHotKey = lpcmi->dwHotKey; + sei.hIcon = lpcmi->hIcon; + sei.lpDirectory = wszDir; + + if (unicode && !StrIsNullOrEmpty(lpcmi->lpDirectoryW)) + { + sei.lpDirectory = lpcmi->lpDirectoryW; + } + else if (bHasPath) { wcscpy(wszDir, wszPath); PathRemoveFileSpec(wszDir); @@ -1326,25 +1341,16 @@ CDefaultContextMenu::InvokePidl(LPCMINVOKECOMMANDINFOEX lpcmi, LPCITEMIDLIST pid *wszDir = UNICODE_NULL; } - CComHeapPtr pszParamsW; - SHELLEXECUTEINFOW sei = { sizeof(sei) }; - sei.hwnd = lpcmi->hwnd; - sei.nShow = SW_SHOWNORMAL; - sei.lpVerb = pEntry->Verb; - sei.lpDirectory = wszDir; - sei.lpIDList = pidlFull; - sei.hkeyClass = pEntry->hkClass; - sei.fMask = SEE_MASK_CLASSKEY | SEE_MASK_IDLIST; if (bHasPath) sei.lpFile = wszPath; + CComHeapPtr pszParamsW; if (unicode && !StrIsNullOrEmpty(lpcmi->lpParametersW)) sei.lpParameters = lpcmi->lpParametersW; else if (!StrIsNullOrEmpty(lpcmi->lpParameters) && __SHCloneStrAtoW(&pszParamsW, lpcmi->lpParameters)) sei.lpParameters = pszParamsW; ShellExecuteExW(&sei); - ILFree(pidlFull); return S_OK; diff --git a/dll/win32/shell32/CShellLink.cpp b/dll/win32/shell32/CShellLink.cpp index 218fa2a8825..5a73cb3fe49 100644 --- a/dll/win32/shell32/CShellLink.cpp +++ b/dll/win32/shell32/CShellLink.cpp @@ -2592,8 +2592,7 @@ HRESULT STDMETHODCALLTYPE CShellLink::InvokeCommand(LPCMINVOKECOMMANDINFO lpici) HRESULT CShellLink::DoOpen(LPCMINVOKECOMMANDINFO lpici) { - BOOL unicode = lpici->cbSize >= FIELD_OFFSET(CMINVOKECOMMANDINFOEX, ptInvoke) && - (lpici->fMask & CMIC_MASK_UNICODE); + const BOOL unicode = IsUnicode(*lpici); CStringW args; if (m_sArgs) diff --git a/dll/win32/shell32/precomp.h b/dll/win32/shell32/precomp.h index 5b319322af6..8389048af63 100644 --- a/dll/win32/shell32/precomp.h +++ b/dll/win32/shell32/precomp.h @@ -155,6 +155,15 @@ UINT GetDfmCmd(_In_ IContextMenu *pCM, _In_ LPCSTR verba); #define SHELL_ExecuteControlPanelCPL(hwnd, cpl) SHRunControlPanel((cpl), (hwnd)) +#define CmicFlagsToSeeFlags(flags) ((flags) & SEE_CMIC_COMMON_FLAGS) +static inline UINT SeeFlagsToCmicFlags(UINT flags) +{ + if (flags & SEE_MASK_CLASSNAME) + flags &= ~(SEE_MASK_HASLINKNAME | SEE_MASK_HASTITLE); + return flags & SEE_CMIC_COMMON_FLAGS; +} + + // CStubWindow32 --- The owner window of file property sheets. // This window hides taskbar button of property sheet. class CStubWindow32 : public CWindowImpl diff --git a/dll/win32/shell32/shlexec.cpp b/dll/win32/shell32/shlexec.cpp index a74e1ff0f44..00b29dc27b7 100644 --- a/dll/win32/shell32/shlexec.cpp +++ b/dll/win32/shell32/shlexec.cpp @@ -491,7 +491,7 @@ static UINT_PTR SHELL_ExecuteW(const WCHAR *lpCmd, WCHAR *env, BOOL shWait, /* make sure we don't fail the CreateProcess if the calling app passes in * a bad working directory */ - if (psei->lpDirectory && psei->lpDirectory[0]) + if (!StrIsNullOrEmpty(psei->lpDirectory)) { DWORD attr = GetFileAttributesW(psei->lpDirectory); if (attr != INVALID_FILE_ATTRIBUTES && attr & FILE_ATTRIBUTE_DIRECTORY) @@ -1559,9 +1559,9 @@ static HRESULT ShellExecute_ContextMenuVerb(LPSHELLEXECUTEINFOW sei) __SHCloneStrWtoA(&verb, sei->lpVerb); __SHCloneStrWtoA(¶meters, sei->lpParameters); - BOOL fDefault = !sei->lpVerb || !sei->lpVerb[0]; + BOOL fDefault = StrIsNullOrEmpty(sei->lpVerb); CMINVOKECOMMANDINFOEX ici = { sizeof(ici) }; - ici.fMask = (sei->fMask & (SEE_MASK_NO_CONSOLE | SEE_MASK_ASYNCOK | SEE_MASK_FLAG_NO_UI)) | CMIC_MASK_UNICODE; + ici.fMask = SeeFlagsToCmicFlags(sei->fMask) | CMIC_MASK_UNICODE; ici.nShow = sei->nShow; if (!fDefault) { @@ -1571,20 +1571,20 @@ static HRESULT ShellExecute_ContextMenuVerb(LPSHELLEXECUTEINFOW sei) ici.hwnd = sei->hwnd; ici.lpParameters = parameters; ici.lpParametersW = sei->lpParameters; - if ((sei->fMask & (SEE_MASK_HASLINKNAME | SEE_MASK_CLASSNAME)) == SEE_MASK_HASLINKNAME) - { - ici.fMask |= CMIC_MASK_HASLINKNAME; + ici.dwHotKey = sei->dwHotKey; + ici.hIcon = sei->hIcon; + if (ici.fMask & (CMIC_MASK_HASLINKNAME | CMIC_MASK_HASTITLE)) ici.lpTitleW = sei->lpClass; - } + enum { idFirst = 1, idLast = 0x7fff }; HMENU hMenu = CreatePopupMenu(); - hr = cm->QueryContextMenu(hMenu, 0, 1, 0x7fff, fDefault ? CMF_DEFAULTONLY : 0); + hr = cm->QueryContextMenu(hMenu, 0, idFirst, idLast, fDefault ? CMF_DEFAULTONLY : 0); if (!FAILED_UNEXPECTEDLY(hr)) { if (fDefault) { INT uDefault = GetMenuDefaultItem(hMenu, FALSE, 0); - uDefault = (uDefault != -1) ? uDefault - 1 : 0; + uDefault = (uDefault != -1) ? uDefault - idFirst : 0; ici.lpVerb = MAKEINTRESOURCEA(uDefault); ici.lpVerbW = MAKEINTRESOURCEW(uDefault); } @@ -1600,7 +1600,6 @@ static HRESULT ShellExecute_ContextMenuVerb(LPSHELLEXECUTEINFOW sei) } - /************************************************************************* * ShellExecute_FromContextMenu [Internal] */ @@ -1676,6 +1675,8 @@ static UINT_PTR SHELL_execute_class(LPCWSTR wszApplicationName, LPSHELLEXECUTEIN &resultLen, (psei->lpDirectory && *psei->lpDirectory) ? psei->lpDirectory : NULL); if (!done && wszApplicationName[0]) { +#if 0 // Given HKCR\.test=SZ:"test" and HKCR\test\shell\open\command=SZ:"cmd.exe /K echo.Hello", no filename is + // appended on Windows when there is no %1 nor %L when executed with: shlextdbg.exe /shellexec=c:\file.test /INVOKE strcatW(wcmd, L" "); if (*wszApplicationName != '"') { @@ -1685,6 +1686,7 @@ static UINT_PTR SHELL_execute_class(LPCWSTR wszApplicationName, LPSHELLEXECUTEIN } else strcatW(wcmd, wszApplicationName); +#endif } if (resultLen > ARRAY_SIZE(wcmd)) ERR("Argify buffer not large enough... truncating\n"); diff --git a/sdk/include/reactos/shellutils.h b/sdk/include/reactos/shellutils.h index 7487288cee1..17d7e0e74e7 100644 --- a/sdk/include/reactos/shellutils.h +++ b/sdk/include/reactos/shellutils.h @@ -609,6 +609,12 @@ struct CCoInit #define S_GREATERTHAN S_FALSE #define MAKE_COMPARE_HRESULT(x) ((x)>0 ? S_GREATERTHAN : ((x)<0 ? S_LESSTHAN : S_EQUAL)) +#define SEE_CMIC_COMMON_BASICFLAGS (SEE_MASK_NOASYNC | SEE_MASK_ASYNCOK | SEE_MASK_UNICODE | \ + SEE_MASK_NO_CONSOLE | SEE_MASK_FLAG_NO_UI | SEE_MASK_FLAG_SEPVDM | \ + SEE_MASK_FLAG_LOG_USAGE | SEE_MASK_NOZONECHECKS) +#define SEE_CMIC_COMMON_FLAGS (SEE_CMIC_COMMON_BASICFLAGS | SEE_MASK_HOTKEY | SEE_MASK_ICON | \ + SEE_MASK_HASLINKNAME | SEE_MASK_HASTITLE) + static inline BOOL ILIsSingle(LPCITEMIDLIST pidl) { return pidl == ILFindLastID(pidl); @@ -627,6 +633,19 @@ static inline PCUIDLIST_RELATIVE HIDA_GetPIDLItem(CIDA const* pida, SIZE_T i) #ifdef __cplusplus +#if defined(CMIC_MASK_UNICODE) && defined(SEE_MASK_UNICODE) +static inline bool IsUnicode(const CMINVOKECOMMANDINFOEX &ici) +{ + const UINT minsize = FIELD_OFFSET(CMINVOKECOMMANDINFOEX, ptInvoke); + return (ici.fMask & CMIC_MASK_UNICODE) && ici.cbSize >= minsize; +} + +static inline bool IsUnicode(const CMINVOKECOMMANDINFO &ici) +{ + return IsUnicode(*(CMINVOKECOMMANDINFOEX*)&ici); +} +#endif // CMIC_MASK_UNICODE + DECLSPEC_SELECTANY CLIPFORMAT g_cfHIDA = NULL; DECLSPEC_SELECTANY CLIPFORMAT g_cfShellIdListOffsets = NULL; @@ -784,7 +803,7 @@ DataObject_SetOffset(IDataObject* pDataObject, POINT* point) return DataObject_SetData(pDataObject, g_cfShellIdListOffsets, point, sizeof(point[0])); } -#endif +#endif // __cplusplus #ifdef __cplusplus struct SHELL_GetSettingImpl