mirror of
https://github.com/reactos/reactos.git
synced 2025-08-06 09:13:00 +00:00
[SHELL32] Fix IShellExecuteHookW (#8097)
This commit is contained in:
parent
c0b4a2cab0
commit
a3b032b118
12 changed files with 150 additions and 49 deletions
|
@ -672,6 +672,7 @@ HRESULT WINAPI CNetConUiObject::InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi)
|
|||
}
|
||||
case IDS_NET_STATUS:
|
||||
{
|
||||
// TODO: Windows does not display this with an owner window
|
||||
return ShowNetConnectionStatus(m_lpOleCmd, m_pidl, lpcmi->hwnd);
|
||||
}
|
||||
case IDS_NET_REPAIR:
|
||||
|
@ -837,27 +838,6 @@ HRESULT WINAPI CNetworkConnections::GetCurFolder(PIDLIST_ABSOLUTE *pidl)
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* ISF_NetConnect_ShellExecuteHookW_Execute
|
||||
*/
|
||||
HRESULT WINAPI CNetworkConnections::Execute(LPSHELLEXECUTEINFOW pei)
|
||||
{
|
||||
PCUITEMID_CHILD pidl = ILFindLastID((ITEMIDLIST*)pei->lpIDList);
|
||||
PNETCONIDSTRUCT pdata = ILGetConnData(pidl);
|
||||
if (!pdata)
|
||||
{
|
||||
ERR("Got invalid pidl\n");
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
if (pdata->Status == NCS_CONNECTED)
|
||||
{
|
||||
return ShowNetConnectionStatus(m_lpOleCmd, pidl, pei->hwnd);
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT WINAPI CNetworkConnections::Initialize(PCIDLIST_ABSOLUTE pidlFolder, IDataObject *pdtobj, HKEY hkeyProgID)
|
||||
{
|
||||
FIXME("CNetworkConnections::Initialize()\n");
|
||||
|
|
|
@ -14,8 +14,7 @@ class CNetworkConnections:
|
|||
public IShellExtInit,
|
||||
public IShellFolder2,
|
||||
public IOleCommandTarget,
|
||||
public IShellFolderViewCB,
|
||||
public IShellExecuteHookW
|
||||
public IShellFolderViewCB
|
||||
{
|
||||
public:
|
||||
CNetworkConnections();
|
||||
|
@ -57,9 +56,6 @@ class CNetworkConnections:
|
|||
// IShellFolderViewCB
|
||||
STDMETHOD(MessageSFVCB)(UINT uMsg, WPARAM wParam, LPARAM lParam) override;
|
||||
|
||||
// IShellExecuteHookW
|
||||
STDMETHOD(Execute)(LPSHELLEXECUTEINFOW pei) override;
|
||||
|
||||
private:
|
||||
|
||||
/* both paths are parsible from the desktop */
|
||||
|
@ -77,7 +73,6 @@ class CNetworkConnections:
|
|||
COM_INTERFACE_ENTRY_IID(IID_IShellExtInit, IShellExtInit)
|
||||
COM_INTERFACE_ENTRY_IID(IID_IOleCommandTarget, IOleCommandTarget)
|
||||
COM_INTERFACE_ENTRY_IID(IID_IShellFolderViewCB, IShellFolderViewCB)
|
||||
COM_INTERFACE_ENTRY_IID(IID_IShellExecuteHookW, IShellExecuteHookW)
|
||||
END_COM_MAP()
|
||||
|
||||
DECLARE_NO_REGISTRY()
|
||||
|
|
|
@ -1397,10 +1397,9 @@ CDefaultContextMenu::InvokePidl(LPCMINVOKECOMMANDINFOEX lpcmi, LPCITEMIDLIST pid
|
|||
if (!sei.lpClass && (lpcmi->fMask & (CMIC_MASK_HASLINKNAME | CMIC_MASK_HASTITLE)) && unicode)
|
||||
sei.lpClass = lpcmi->lpTitleW; // Forward .lnk path from CShellLink::DoOpen (for consrv STARTF_TITLEISLINKNAME)
|
||||
|
||||
ShellExecuteExW(&sei);
|
||||
HRESULT hr = ShellExecuteExW(&sei) ? S_OK : HResultFromWin32(GetLastError());
|
||||
ILFree(pidlFull);
|
||||
|
||||
return S_OK;
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
|
|
|
@ -27,7 +27,7 @@ SHELL_InitializeExtension(REFCLSID clsid, PCIDLIST_ABSOLUTE pidlFolder, IDataObj
|
|||
{
|
||||
*ppv = NULL;
|
||||
IUnknown *pUnk;
|
||||
HRESULT hr = SHCoCreateInstance(NULL, &clsid, NULL, riid, (void**)&pUnk);
|
||||
HRESULT hr = SHExtCoCreateInstance(NULL, &clsid, NULL, riid, (void**)&pUnk);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
CComPtr<IShellExtInit> Init;
|
||||
|
|
|
@ -98,7 +98,7 @@
|
|||
99 stdcall -noname SetAppStartingCursor(long long)
|
||||
100 stdcall SHRestricted(long)
|
||||
101 stdcall OpenAs_RunDLLA(long long str long)
|
||||
102 stdcall SHCoCreateInstance(wstr ptr long ptr ptr)
|
||||
102 stdcall SHCoCreateInstance(wstr ptr ptr ptr ptr)
|
||||
103 stdcall SignalFileOpen(ptr)
|
||||
104 stdcall OpenAs_RunDLLW(long long wstr long)
|
||||
105 stdcall Activate_RunDLL(ptr ptr wstr long)
|
||||
|
@ -467,3 +467,4 @@
|
|||
755 stdcall -noname PathIsEqualOrSubFolder(wstr wstr)
|
||||
756 stub -noname DeleteFileThumbnail
|
||||
757 stdcall -version=0x600+ DisplayNameOfW(ptr ptr long ptr long)
|
||||
866 stdcall -version=0x600+ SHExtCoCreateInstance(wstr ptr ptr ptr ptr)
|
||||
|
|
|
@ -33,6 +33,42 @@ EXTERN_C BOOL PathIsExeW(LPCWSTR lpszPath);
|
|||
typedef UINT_PTR (*SHELL_ExecuteW32)(const WCHAR *lpCmd, WCHAR *env, BOOL shWait,
|
||||
const SHELLEXECUTEINFOW *sei, LPSHELLEXECUTEINFOW sei_out);
|
||||
|
||||
static int Win32ErrFromHInst(HINSTANCE hInst)
|
||||
{
|
||||
if ((SIZE_T)hInst > 32)
|
||||
return ERROR_SUCCESS;
|
||||
switch ((SIZE_T)hInst)
|
||||
{
|
||||
case SE_ERR_FNF:
|
||||
case SE_ERR_PNF:
|
||||
case SE_ERR_ACCESSDENIED:
|
||||
case SE_ERR_OOM:
|
||||
return (UINT)(SIZE_T)hInst;
|
||||
case SE_ERR_SHARE:
|
||||
return ERROR_SHARING_VIOLATION;
|
||||
case SE_ERR_DDETIMEOUT:
|
||||
case SE_ERR_DDEFAIL:
|
||||
case SE_ERR_DDEBUSY:
|
||||
return ERROR_DDE_FAIL;
|
||||
case SE_ERR_DLLNOTFOUND:
|
||||
return ERROR_DLL_NOT_FOUND;
|
||||
//case SE_ERR_ASSOCINCOMPLETE: Note: Windows treats this as a success code
|
||||
case SE_ERR_NOASSOC:
|
||||
return ERROR_NO_ASSOCIATION;
|
||||
case 10:
|
||||
return ERROR_OLD_WIN_VERSION;
|
||||
case 12:
|
||||
return ERROR_APP_WRONG_OS;
|
||||
case 15:
|
||||
return ERROR_RMODE_APP;
|
||||
case 16:
|
||||
return ERROR_SINGLE_INSTANCE_APP;
|
||||
case 20:
|
||||
return ERROR_INVALID_DLL;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Is the current process a rundll32.exe?
|
||||
static BOOL SHELL_InRunDllProcess(VOID)
|
||||
{
|
||||
|
@ -60,6 +96,57 @@ static UINT_PTR InvokeOpenWith(HWND hWndOwner, SHELLEXECUTEINFOW &sei)
|
|||
return SUCCEEDED(hr) ? 42 : SE_ERR_NOASSOC;
|
||||
}
|
||||
|
||||
static HRESULT InvokeShellExecuteHook(PCWSTR pszClsid, LPSHELLEXECUTEINFOW pSEI)
|
||||
{
|
||||
CComPtr<IUnknown> pUnk;
|
||||
if (FAILED(SHExtCoCreateInstance(pszClsid, NULL, NULL, IID_PPV_ARG(IUnknown, &pUnk))))
|
||||
return S_FALSE;
|
||||
CComPtr<IShellExecuteHookW> pWide;
|
||||
if (SUCCEEDED(pUnk->QueryInterface(IID_PPV_ARG(IShellExecuteHookW, &pWide))))
|
||||
return pWide->Execute(pSEI);
|
||||
HRESULT hr = S_FALSE;
|
||||
#if 0 // TODO
|
||||
CComPtr<IShellExecuteHookA> pAnsi;
|
||||
if (SUCCEEDED(pUnk->QueryInterface(IID_PPV_ARG(IShellExecuteHookA, &pAnsi))))
|
||||
{
|
||||
SHELLEXECUTEINFOA sei = *(SHELLEXECUTEINFOA*)pSEI;
|
||||
// TODO: Convert the strings
|
||||
hr = pAnsi->Execute(sei);
|
||||
pSEI->hProcess = sei.hProcess;
|
||||
pSEI->hInstApp = sei.hInstApp;
|
||||
}
|
||||
#endif
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT TryShellExecuteHooks(LPSHELLEXECUTEINFOW pSEI)
|
||||
{
|
||||
// https://devblogs.microsoft.com/oldnewthing/20080910-00/?p=20933 claims hooks
|
||||
// were removed in Vista but this is incorrect, they are disabled by default.
|
||||
// https://groups.google.com/g/microsoft.public.platformsdk.shell/c/ixdOX1--IKk
|
||||
// says they are now controlled by the EnableShellExecuteHooks policy.
|
||||
if (pSEI->fMask & SEE_MASK_NO_HOOKS)
|
||||
return S_FALSE;
|
||||
if (LOBYTE(GetVersion()) >= 6 && !SH32_InternalRestricted(REST_SH32_ENABLESHELLEXECUTEHOOKS))
|
||||
return S_FALSE;
|
||||
|
||||
HRESULT hr = S_FALSE;
|
||||
HKEY hKey;
|
||||
LRESULT res = RegOpenKeyExW(HKEY_LOCAL_MACHINE, REGSTR_PATH_EXPLORER L"\\ShellExecuteHooks", 0, KEY_READ, &hKey);
|
||||
if (res != ERROR_SUCCESS)
|
||||
return S_FALSE;
|
||||
for (UINT i = 0; hr == S_FALSE; ++i)
|
||||
{
|
||||
WCHAR szClsid[42];
|
||||
DWORD cch = _countof(szClsid);
|
||||
if (RegEnumValueW(hKey, i, szClsid, &cch, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
|
||||
break;
|
||||
hr = InvokeShellExecuteHook(szClsid, pSEI);
|
||||
}
|
||||
RegCloseKey(hKey);
|
||||
return hr;
|
||||
}
|
||||
|
||||
static void ParseNoTildeEffect(PWSTR &res, LPCWSTR &args, DWORD &len, DWORD &used, int argNum)
|
||||
{
|
||||
bool firstCharQuote = false;
|
||||
|
@ -1968,6 +2055,20 @@ static BOOL SHELL_execute(LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc)
|
|||
((sei_tmp.fMask & SEE_MASK_CLASSALL) == SEE_MASK_CLASSNAME) ?
|
||||
debugstr_w(sei_tmp.lpClass) : "not used");
|
||||
|
||||
// Call hooks before expanding and resolving strings
|
||||
HRESULT hr = TryShellExecuteHooks(sei);
|
||||
if (hr != S_FALSE)
|
||||
{
|
||||
int err = Win32ErrFromHInst(sei->hInstApp);
|
||||
if (err <= 0)
|
||||
{
|
||||
sei->hInstApp = (HINSTANCE)UlongToHandle(42);
|
||||
return TRUE;
|
||||
}
|
||||
SetLastError(err);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* make copies of all path/command strings */
|
||||
CHeapPtr<WCHAR, CLocalAllocator> wszApplicationName;
|
||||
DWORD dwApplicationNameLen = MAX_PATH + 2;
|
||||
|
@ -2083,16 +2184,6 @@ static BOOL SHELL_execute(LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc)
|
|||
(sei_tmp.fMask & SEE_MASK_INVOKEIDLIST) != SEE_MASK_INVOKEIDLIST)
|
||||
{
|
||||
LPCITEMIDLIST pidl = (LPCITEMIDLIST)sei_tmp.lpIDList;
|
||||
|
||||
CComPtr<IShellExecuteHookW> pSEH;
|
||||
HRESULT hr = SHBindToParent(pidl, IID_PPV_ARG(IShellExecuteHookW, &pSEH), NULL);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = pSEH->Execute(&sei_tmp);
|
||||
if (hr == S_OK)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
hr = SHGetNameAndFlagsW(pidl, SHGDN_FORPARSING, wszApplicationName, dwApplicationNameLen, NULL);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
|
@ -2117,7 +2208,7 @@ static BOOL SHELL_execute(LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc)
|
|||
|
||||
if ((sei_tmp.fMask & SEE_MASK_INVOKEIDLIST) == SEE_MASK_INVOKEIDLIST)
|
||||
{
|
||||
HRESULT hr = ShellExecute_ContextMenuVerb(&sei_tmp);
|
||||
hr = ShellExecute_ContextMenuVerb(&sei_tmp);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
sei->hInstApp = (HINSTANCE)42;
|
||||
|
@ -2157,7 +2248,7 @@ static BOOL SHELL_execute(LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc)
|
|||
StrCmpNW(sei_tmp.lpFile, L"::{", 3) == 0))
|
||||
{
|
||||
CComHeapPtr<ITEMIDLIST> pidlParsed;
|
||||
HRESULT hr = SHParseDisplayName(sei_tmp.lpFile, NULL, &pidlParsed, 0, NULL);
|
||||
hr = SHParseDisplayName(sei_tmp.lpFile, NULL, &pidlParsed, 0, NULL);
|
||||
if (SUCCEEDED(hr) && SHELL_InvokePidl(&sei_tmp, pidlParsed))
|
||||
{
|
||||
sei_tmp.hInstApp = (HINSTANCE)UlongToHandle(42);
|
||||
|
@ -2352,7 +2443,7 @@ HINSTANCE WINAPI ShellExecuteA(HWND hWnd, LPCSTR lpVerb, LPCSTR lpFile,
|
|||
debugstr_a(lpParameters), debugstr_a(lpDirectory), iShowCmd);
|
||||
|
||||
sei.cbSize = sizeof(sei);
|
||||
sei.fMask = SEE_MASK_FLAG_NO_UI;
|
||||
sei.fMask = SEE_MASK_FLAG_NO_UI | SEE_MASK_UNKNOWN_0x1000;
|
||||
sei.hwnd = hWnd;
|
||||
sei.lpVerb = lpVerb;
|
||||
sei.lpFile = lpFile;
|
||||
|
@ -2520,7 +2611,7 @@ HINSTANCE WINAPI ShellExecuteW(HWND hwnd, LPCWSTR lpVerb, LPCWSTR lpFile,
|
|||
|
||||
TRACE("\n");
|
||||
sei.cbSize = sizeof(sei);
|
||||
sei.fMask = SEE_MASK_FLAG_NO_UI;
|
||||
sei.fMask = SEE_MASK_FLAG_NO_UI | SEE_MASK_UNKNOWN_0x1000;
|
||||
sei.hwnd = hwnd;
|
||||
sei.lpVerb = lpVerb;
|
||||
sei.lpFile = lpFile;
|
||||
|
|
|
@ -305,3 +305,8 @@ DEFINE_POLICY( REST_USEDESKTOPINICACHE, "Explorer", "UseDesk
|
|||
|
||||
// NOTE: This is a SHDOCVW-only policy.
|
||||
// DEFINE_POLICY( 0x50000024, "Explorer", "NoFileUrl" ),
|
||||
|
||||
#if defined(__REACTOS__) && defined(_SHELL32_)
|
||||
// Internal SHELL32 policies (keep these at the end of the list)
|
||||
DEFINE_POLICY( REST_SH32_ENABLESHELLEXECUTEHOOKS, "Explorer", "EnableShellExecuteHooks" ),
|
||||
#endif
|
||||
|
|
|
@ -37,7 +37,10 @@ extern HMODULE huser32 DECLSPEC_HIDDEN;
|
|||
extern HINSTANCE shell32_hInstance DECLSPEC_HIDDEN;
|
||||
extern int (WINAPI* SHELL_StrCmpLogical)(PCWSTR s1, PCWSTR s2);
|
||||
|
||||
BOOL WINAPI Shell_GetImageLists(HIMAGELIST * lpBigList, HIMAGELIST * lpSmallList);
|
||||
enum {
|
||||
REST_SH32_ENABLESHELLEXECUTEHOOKS = 0x00060001, // POLID_EnableShellExecuteHooks
|
||||
};
|
||||
DWORD SH32_InternalRestricted(DWORD rest);
|
||||
|
||||
/* Iconcache */
|
||||
#define INVALID_INDEX -1
|
||||
|
@ -48,6 +51,7 @@ INT SIC_GetIconIndex (LPCWSTR sSourceFile, INT dwSourceIndex, DWORD dwFlags ) DE
|
|||
extern INT ShellLargeIconSize;
|
||||
extern INT ShellSmallIconSize;
|
||||
extern INT ShellIconBPP;
|
||||
BOOL WINAPI Shell_GetImageLists(HIMAGELIST * lpBigList, HIMAGELIST * lpSmallList);
|
||||
|
||||
/* Classes Root */
|
||||
HRESULT HCR_GetProgIdKeyOfExtension(PCWSTR szExtension, PHKEY phKey, BOOL AllowFallback);
|
||||
|
|
|
@ -193,6 +193,17 @@ end:
|
|||
return hres;
|
||||
}
|
||||
|
||||
HRESULT WINAPI SHExtCoCreateInstance(
|
||||
_In_opt_ LPCWSTR aclsid,
|
||||
_In_opt_ const CLSID *clsid,
|
||||
_In_opt_ LPUNKNOWN pUnkOuter,
|
||||
_In_ REFIID refiid,
|
||||
_Out_ LPVOID *ppv)
|
||||
{
|
||||
// TODO: Verify that this CLSID is allowed if REST_ENFORCESHELLEXTSECURITY is active
|
||||
return SHCoCreateInstance(aclsid, clsid, pUnkOuter, refiid, ppv);
|
||||
}
|
||||
|
||||
#ifndef __REACTOS__
|
||||
/*************************************************************************
|
||||
* DllGetClassObject [SHELL32.@]
|
||||
|
|
|
@ -163,7 +163,7 @@ static BOOL SHELL_QueryRestrictionsChanged(VOID)
|
|||
* b: 98Lite 2.0 (which uses many of these policy keys) http://www.98lite.net/
|
||||
* c: 'The Windows 95 Registry', by John Woram, 1996 MIS: Press
|
||||
*/
|
||||
DWORD WINAPI SHRestricted (RESTRICTIONS rest)
|
||||
DWORD WINAPI SHRestricted(RESTRICTIONS rest)
|
||||
{
|
||||
TRACE("(0x%08lX)\n", rest);
|
||||
|
||||
|
@ -177,6 +177,12 @@ DWORD WINAPI SHRestricted (RESTRICTIONS rest)
|
|||
return SHRestrictionLookup(rest, NULL, s_PolicyTable, g_RestValues);
|
||||
}
|
||||
|
||||
DWORD SH32_InternalRestricted(DWORD rest)
|
||||
{
|
||||
/* assert((rest & 0x00060000) == 0x00060000) */
|
||||
return SHRestricted(rest);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* SHSettingsChanged [SHELL32.244]
|
||||
*
|
||||
|
|
|
@ -670,7 +670,7 @@ public:
|
|||
#define CmicFlagsToSeeFlags(flags) ((flags) & SEE_CMIC_COMMON_FLAGS)
|
||||
static inline UINT SeeFlagsToCmicFlags(UINT flags)
|
||||
{
|
||||
if (flags & SEE_MASK_CLASSNAME)
|
||||
if ((flags & (SEE_MASK_CLASSNAME | SEE_MASK_CLASSKEY)) == SEE_MASK_CLASSNAME)
|
||||
flags &= ~(SEE_MASK_HASLINKNAME | SEE_MASK_HASTITLE);
|
||||
return flags & SEE_CMIC_COMMON_FLAGS;
|
||||
}
|
||||
|
|
|
@ -678,10 +678,12 @@ HRESULT WINAPI ShellExecCmdLine(
|
|||
* CMINVOKECOMMANDINFOEX structure.
|
||||
*/
|
||||
#define SEE_MASK_UNKNOWN_0x1000 0x00001000 // FIXME: Name
|
||||
#define SEE_MASK_NO_HOOKS 0x00002000 // https://www.yisu.com/ask/30968554.html
|
||||
#define SEE_MASK_HASLINKNAME 0x00010000
|
||||
#define SEE_MASK_FLAG_SEPVDM 0x00020000
|
||||
#define SEE_MASK_USE_RESERVED 0x00040000
|
||||
#define SEE_MASK_HASTITLE 0x00080000
|
||||
#define SEE_MASK_FILEANDURL 0x00400000 // https://textslashplain.com/2019/09/25/web-to-app-communication-directinvoke/
|
||||
|
||||
HINSTANCE WINAPI
|
||||
RealShellExecuteA(
|
||||
|
@ -783,6 +785,13 @@ HRESULT WINAPI SHCreateDefClassObject(
|
|||
|
||||
void WINAPI SHFreeUnusedLibraries(void);
|
||||
|
||||
HRESULT WINAPI SHExtCoCreateInstance(
|
||||
_In_opt_ LPCWSTR aclsid,
|
||||
_In_opt_ const CLSID *clsid,
|
||||
_In_opt_ LPUNKNOWN pUnkOuter,
|
||||
_In_ REFIID refiid,
|
||||
_Out_ LPVOID *ppv);
|
||||
|
||||
/* SHCreateLinks flags */
|
||||
#define SHCLF_PREFIXNAME 0x01
|
||||
#define SHCLF_CREATEONDESKTOP 0x02
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue