[EXPLORER][BROWSEUI][SHLWAPI][BOOTDATA][WIN32K] Support AppKeys and more WM_APPCOMMANDs (#7879)

Implements a couple of extra commands in IShellBrowser and adds support for the AppKeys fallback registry key (used when the foreground application does not handle the command).
This commit is contained in:
Whindmar Saksit 2025-04-18 18:35:30 +02:00 committed by GitHub
parent 2e85425c53
commit 5a10ec60be
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 219 additions and 61 deletions

View file

@ -20,6 +20,8 @@
#include "precomp.h" #include "precomp.h"
#include <commoncontrols.h> #include <commoncontrols.h>
#include <regstr.h>
#include <shlwapi_undoc.h>
/* Set DUMP_TASKS to 1 to enable a dump of the tasks and task groups every /* Set DUMP_TASKS to 1 to enable a dump of the tasks and task groups every
5 seconds */ 5 seconds */
@ -1476,25 +1478,60 @@ public:
::SendMessage(hwndTray, TWM_PULSE, bDelete, (LPARAM)hwndActive); ::SendMessage(hwndTray, TWM_PULSE, bDelete, (LPARAM)hwndActive);
} }
static BOOL InvokeRegistryAppKeyCommand(UINT uAppCmd)
{
BOOL bResult = FALSE;
WCHAR szBuf[MAX_PATH * 2];
wsprintfW(szBuf, L"%s\\AppKey\\%u", REGSTR_PATH_EXPLORER, uAppCmd);
HUSKEY hKey;
if (SHRegOpenUSKeyW(szBuf, KEY_READ, NULL, &hKey, FALSE) != ERROR_SUCCESS)
return bResult;
DWORD cb = sizeof(szBuf);
if (!bResult && SHRegQueryUSValueW(hKey, L"ShellExecute", NULL, szBuf, &cb, FALSE, NULL, 0) == ERROR_SUCCESS)
{
bResult = TRUE;
}
cb = sizeof(szBuf);
if (!bResult && SHRegQueryUSValueW(hKey, L"Association", NULL, szBuf, &cb, FALSE, NULL, 0) == ERROR_SUCCESS)
{
bResult = TRUE;
cb = _countof(szBuf);
if (AssocQueryString(ASSOCF_NOTRUNCATE, ASSOCSTR_EXECUTABLE, szBuf, NULL, szBuf, &cb) != S_OK)
*szBuf = UNICODE_NULL;
}
cb = sizeof(szBuf);
if (!bResult && SHRegQueryUSValueW(hKey, L"RegisteredApp", NULL, szBuf, &cb, FALSE, NULL, 0) == ERROR_SUCCESS)
{
bResult = TRUE;
SHRunIndirectRegClientCommand(NULL, szBuf);
*szBuf = UNICODE_NULL; // Don't execute again
}
SHRegCloseUSKey(hKey);
// Note: Tweak UI uses an empty string for its "Do nothing" option.
if (bResult && *szBuf)
ShellExec_RunDLLW(NULL, NULL, szBuf, SW_SHOW);
return bResult;
}
BOOL HandleAppCommand(IN WPARAM wParam, IN LPARAM lParam) BOOL HandleAppCommand(IN WPARAM wParam, IN LPARAM lParam)
{ {
BOOL Ret = FALSE; const UINT uAppCmd = GET_APPCOMMAND_LPARAM(lParam);
if (InvokeRegistryAppKeyCommand(uAppCmd))
switch (GET_APPCOMMAND_LPARAM(lParam)) return TRUE;
switch (uAppCmd)
{ {
case APPCOMMAND_BROWSER_SEARCH: case APPCOMMAND_VOLUME_MUTE:
Ret = SHFindFiles(NULL, case APPCOMMAND_VOLUME_DOWN:
NULL); case APPCOMMAND_VOLUME_UP:
break; // TODO: Try IMMDeviceEnumerator::GetDefaultAudioEndpoint first and then fall back to mixer.
FIXME("Call the mixer API to change the global volume\n");
case APPCOMMAND_BROWSER_HOME: return TRUE;
case APPCOMMAND_LAUNCH_MAIL: case APPCOMMAND_BROWSER_SEARCH:
default: return SHFindFiles(NULL, NULL);
TRACE("Shell app command %d unhandled!\n", (INT) GET_APPCOMMAND_LPARAM(lParam));
break;
} }
return FALSE;
return Ret;
} }
LRESULT OnShellHook(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) LRESULT OnShellHook(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
@ -1513,7 +1550,7 @@ public:
switch ((INT) wParam) switch ((INT) wParam)
{ {
case HSHELL_APPCOMMAND: case HSHELL_APPCOMMAND:
Ret = HandleAppCommand(wParam, lParam); Ret = HandleAppCommand(0, lParam);
break; break;
case HSHELL_WINDOWCREATED: case HSHELL_WINDOWCREATED:

View file

@ -104,20 +104,20 @@ HKLM,"SOFTWARE\Classes\Applications\mplay32.exe\SupportedTypes",".avi",0x0000000
HKLM,"SOFTWARE\Classes\ftp","",0x00000000,"URL:File Transfer Protocol" HKLM,"SOFTWARE\Classes\ftp","",0x00000000,"URL:File Transfer Protocol"
HKLM,"SOFTWARE\Classes\ftp\Source Filter","",0x00000000,"{E436EBB6-524F-11CE-9F53-0020AF0BA770}" HKLM,"SOFTWARE\Classes\ftp\Source Filter","",0x00000000,"{E436EBB6-524F-11CE-9F53-0020AF0BA770}"
HKLM,"SOFTWARE\Classes\ftp","URL Protocol",0x00000000,"" HKLM,"SOFTWARE\Classes\ftp","URL Protocol",0x00000000,""
HKLM,"SOFTWARE\Classes\ftp\shell\open\command","",0x00000000,"""%programfiles%\Internet Explorer\iexplore.exe"" ""%1""" HKLM,"SOFTWARE\Classes\ftp\shell\open\command","",0x00020000,"""%programfiles%\Internet Explorer\iexplore.exe"" ""%1"""
HKLM,"SOFTWARE\Classes\gopher","",0x00000000,"URL:Gopher Protocol" HKLM,"SOFTWARE\Classes\gopher","",0x00000000,"URL:Gopher Protocol"
HKLM,"SOFTWARE\Classes\gopher\Source Filter","",0x00000000,"{E436EBB6-524F-11CE-9F53-0020AF0BA770}" HKLM,"SOFTWARE\Classes\gopher\Source Filter","",0x00000000,"{E436EBB6-524F-11CE-9F53-0020AF0BA770}"
HKLM,"SOFTWARE\Classes\gopher","URL Protocol",0x00000000,"" HKLM,"SOFTWARE\Classes\gopher","URL Protocol",0x00000000,""
;see http ;see http
;HKLM,"SOFTWARE\Classes\gopher\shell\open\command","",0x00000000,"""%programfiles%\Internet Explorer\iexplore.exe"" -nohome" ;HKLM,"SOFTWARE\Classes\gopher\shell\open\command","",0x00020000,"""%programfiles%\Internet Explorer\iexplore.exe"" -nohome"
HKLM,"SOFTWARE\Classes\gopher\shell\open\command","",0x00000000,"""%programfiles%\Internet Explorer\iexplore.exe"" ""%1""" HKLM,"SOFTWARE\Classes\gopher\shell\open\command","",0x00020000,"""%programfiles%\Internet Explorer\iexplore.exe"" ""%1"""
HKLM,"SOFTWARE\Classes\http","",0x00000000,"URL:HyperText Transfer Protocol" HKLM,"SOFTWARE\Classes\http","",0x00000000,"URL:HyperText Transfer Protocol"
HKLM,"SOFTWARE\Classes\http\DefaultIcon","",0x00000000,"%SystemRoot%\system32\url.dll,0" HKLM,"SOFTWARE\Classes\http\DefaultIcon","",0x00020000,"%SystemRoot%\system32\url.dll,0"
HKLM,"SOFTWARE\Classes\http\Source Filter","",0x00000000,"{E436EBB6-524F-11CE-9F53-0020AF0BA770}" HKLM,"SOFTWARE\Classes\http\Source Filter","",0x00000000,"{E436EBB6-524F-11CE-9F53-0020AF0BA770}"
HKLM,"SOFTWARE\Classes\http","URL Protocol",0x00000000,"" HKLM,"SOFTWARE\Classes\http","URL Protocol",0x00000000,""
HKLM,"SOFTWARE\Classes\http\shell\open\command","",0x00000000,"""%programfiles%\Internet Explorer\iexplore.exe"" ""%1""" HKLM,"SOFTWARE\Classes\http\shell\open\command","",0x00020000,"""%programfiles%\Internet Explorer\iexplore.exe"" ""%1"""
;TODO : iexplore should use DDE ;TODO : iexplore should use DDE
;HKLM,"SOFTWARE\Classes\http\shell\open\ddeexec","",0x00000000,"""%1"",,-1,0,,,," ;HKLM,"SOFTWARE\Classes\http\shell\open\ddeexec","",0x00000000,"""%1"",,-1,0,,,,"
;HKLM,"SOFTWARE\Classes\http\shell\open\ddeexec","NoActivateHandler",0x00000000,"" ;HKLM,"SOFTWARE\Classes\http\shell\open\ddeexec","NoActivateHandler",0x00000000,""
@ -129,14 +129,14 @@ HKLM,"SOFTWARE\Classes\https\DefaultIcon","",0x00000000,"%SystemRoot%\system32\u
HKLM,"SOFTWARE\Classes\https\Source Filter","",0x00000000,"{E436EBB6-524F-11CE-9F53-0020AF0BA770}" HKLM,"SOFTWARE\Classes\https\Source Filter","",0x00000000,"{E436EBB6-524F-11CE-9F53-0020AF0BA770}"
HKLM,"SOFTWARE\Classes\https","URL Protocol",0x00000000,"" HKLM,"SOFTWARE\Classes\https","URL Protocol",0x00000000,""
;see http ;see http
;HKLM,"SOFTWARE\Classes\https\shell\open\command","",0x00000000,"""%programfiles%\Internet Explorer\iexplore.exe"" -nohome" ;HKLM,"SOFTWARE\Classes\https\shell\open\command","",0x00020000,"""%programfiles%\Internet Explorer\iexplore.exe"" -nohome"
HKLM,"SOFTWARE\Classes\https\shell\open\command","",0x00000000,"""%programfiles%\Internet Explorer\iexplore.exe"" ""%1""" HKLM,"SOFTWARE\Classes\https\shell\open\command","",0x00020000,"""%programfiles%\Internet Explorer\iexplore.exe"" ""%1"""
; Register system default web browser ; Register system default web browser
HKLM,"SOFTWARE\Clients\StartMenuInternet","",0x00000000,"IEXPLORE.EXE" HKLM,"SOFTWARE\Clients\StartMenuInternet","",0x00000000,"IEXPLORE.EXE"
HKLM,"SOFTWARE\Clients\StartMenuInternet\IEXPLORE.EXE","",0x00000000,"Internet Explorer" HKLM,"SOFTWARE\Clients\StartMenuInternet\IEXPLORE.EXE","",0x00000000,"Internet Explorer"
HKLM,"SOFTWARE\Clients\StartMenuInternet\IEXPLORE.EXE\DefaultIcon","",0x00000000,"%programfiles%\Internet Explorer\iexplore.exe,-7" HKLM,"SOFTWARE\Clients\StartMenuInternet\IEXPLORE.EXE\DefaultIcon","",0x00020000,"%programfiles%\Internet Explorer\iexplore.exe,-7"
HKLM,"SOFTWARE\Clients\StartMenuInternet\IEXPLORE.EXE\shell\open\command","",0x00000000,"%programfiles%\Internet Explorer\iexplore.exe" HKLM,"SOFTWARE\Clients\StartMenuInternet\IEXPLORE.EXE\shell\open\command","",0x00020000,"%programfiles%\Internet Explorer\iexplore.exe"
; CTF ; CTF
HKLM,"SOFTWARE\Microsoft\CTF\SystemShared",,0x00000012 HKLM,"SOFTWARE\Microsoft\CTF\SystemShared",,0x00000012

View file

@ -64,6 +64,7 @@
#define IDM_BAND_MENU 269 #define IDM_BAND_MENU 269
#define IDM_BAND_TITLE 0xA200 #define IDM_BAND_TITLE 0xA200
#define IDM_BAND_CLOSE 0xA201 #define IDM_BAND_CLOSE 0xA201
#define FCIDM_BROWSER_STOP 0xA21A
#define FCIDM_BROWSER_TOGGLEFULLSCREEN 0xA21B #define FCIDM_BROWSER_TOGGLEFULLSCREEN 0xA21B
#define IDM_POPUPMENU 2001 #define IDM_POPUPMENU 2001

View file

@ -4182,20 +4182,22 @@ LRESULT CShellBrowser::OnGetSettingsPtr(UINT uMsg, WPARAM wParam, LPARAM lParam,
// WM_APPCOMMAND // WM_APPCOMMAND
LRESULT CShellBrowser::OnAppCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) LRESULT CShellBrowser::OnAppCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{ {
UINT uCmd = GET_APPCOMMAND_LPARAM(lParam); UINT uCmd = GET_APPCOMMAND_LPARAM(lParam), uExecCmd = 0;
switch (uCmd) switch (uCmd)
{ {
case APPCOMMAND_BROWSER_BACKWARD: case APPCOMMAND_BROWSER_BACKWARD: uExecCmd = IDM_GOTO_BACK; break;
GoBack(); case APPCOMMAND_BROWSER_FORWARD: uExecCmd = IDM_GOTO_FORWARD; break;
break; case APPCOMMAND_BROWSER_REFRESH: uExecCmd = IDM_VIEW_REFRESH; break;
case APPCOMMAND_BROWSER_STOP: uExecCmd = FCIDM_BROWSER_STOP; break; // TODO: Handle Stop()
case APPCOMMAND_BROWSER_FORWARD: case APPCOMMAND_BROWSER_SEARCH: uExecCmd = IDM_EXPLORERBAR_SEARCH; break;
GoForward(); case APPCOMMAND_BROWSER_FAVORITES: uExecCmd = IDM_EXPLORERBAR_FAVORITES; break;
break; case APPCOMMAND_BROWSER_HOME: uExecCmd = IDM_GOTO_HOMEPAGE; break;
}
default: if (uExecCmd)
FIXME("uCmd: %u\n", uCmd); {
break; SendMessage(WM_COMMAND, uExecCmd, 0);
bHandled = TRUE;
return TRUE;
} }
return 0; return 0;
} }

View file

@ -0,0 +1,26 @@
HKLM
{
NoRemove Software
{
NoRemove Microsoft
{
NoRemove Windows
{
NoRemove CurrentVersion
{
NoRemove Explorer
{
ForceRemove AppKey
{
7 { val Association = s 'http' }
15 { val Association = s 'mailto' }
16 { val Association = s '.mp3' }
17 { val ShellExecute = s '::{20D04FE0-3AEA-1069-A2D8-08002B30309D}' }
18 { val ShellExecute = s 'calc.exe' }
}
}
}
}
}
}
}

View file

@ -34,3 +34,4 @@ IDR_COPYASPATHMENU REGISTRY "res/rgs/copyaspathmenu.rgs"
IDR_COPYTOMENU REGISTRY "res/rgs/copytomenu.rgs" IDR_COPYTOMENU REGISTRY "res/rgs/copytomenu.rgs"
IDR_MOVETOMENU REGISTRY "res/rgs/movetomenu.rgs" IDR_MOVETOMENU REGISTRY "res/rgs/movetomenu.rgs"
IDR_RECYCLEBINCLEANER REGISTRY "res/rgs/recyclebincleaner.rgs" IDR_RECYCLEBINCLEANER REGISTRY "res/rgs/recyclebincleaner.rgs"
IDR_EXPLORER REGISTRY "res/rgs/explorer.rgs"

View file

@ -426,6 +426,19 @@ STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
return hResult; return hResult;
} }
static HRESULT UpdateRegistryFromResource(BOOL Register)
{
static const BYTE resid[] =
{
IDR_FOLDEROPTIONS,
IDR_EXPLORER,
};
HRESULT hr = S_OK;
for (SIZE_T i = 0; i < _countof(resid) && SUCCEEDED(hr); ++i)
hr = gModule.UpdateRegistryFromResource(resid[i], Register, NULL);
return hr;
}
/*********************************************************************** /***********************************************************************
* DllRegisterServer (SHELL32.@) * DllRegisterServer (SHELL32.@)
*/ */
@ -437,8 +450,7 @@ STDAPI DllRegisterServer()
if (FAILED(hr)) if (FAILED(hr))
return hr; return hr;
hr = gModule.UpdateRegistryFromResource(IDR_FOLDEROPTIONS, TRUE, NULL); if (FAILED(hr = UpdateRegistryFromResource(TRUE)))
if (FAILED(hr))
return hr; return hr;
hr = SHELL_RegisterShellFolders(); hr = SHELL_RegisterShellFolders();
@ -459,8 +471,7 @@ STDAPI DllUnregisterServer()
if (FAILED(hr)) if (FAILED(hr))
return hr; return hr;
hr = gModule.UpdateRegistryFromResource(IDR_FOLDEROPTIONS, FALSE, NULL); if (FAILED(hr = UpdateRegistryFromResource(FALSE)))
if (FAILED(hr))
return hr; return hr;
return S_OK; return S_OK;

View file

@ -2656,7 +2656,7 @@ HRESULT WINAPI ShellExecCmdLine(
DWORD dwSeclFlags) DWORD dwSeclFlags)
{ {
SHELLEXECUTEINFOW info; SHELLEXECUTEINFOW info;
DWORD dwSize, dwError, dwType, dwFlags = SEE_MASK_DOENVSUBST | SEE_MASK_NOASYNC; DWORD dwSize, dwType, dwFlags = SEE_MASK_DOENVSUBST | SEE_MASK_NOASYNC;
LPCWSTR pszVerb = NULL; LPCWSTR pszVerb = NULL;
WCHAR szFile[MAX_PATH], szFile2[MAX_PATH]; WCHAR szFile[MAX_PATH], szFile2[MAX_PATH];
HRESULT hr; HRESULT hr;
@ -2765,21 +2765,9 @@ HRESULT WINAPI ShellExecCmdLine(
info.lpParameters = (pchParams && *pchParams) ? pchParams : NULL; info.lpParameters = (pchParams && *pchParams) ? pchParams : NULL;
info.lpDirectory = pwszStartDir; info.lpDirectory = pwszStartDir;
info.nShow = nShow; info.nShow = nShow;
if (ShellExecuteExW(&info)) UINT error = ShellExecuteExW(&info) ? ERROR_SUCCESS : GetLastError();
{
if (info.lpIDList)
CoTaskMemFree(info.lpIDList);
SHFree(lpCommand);
return S_OK;
}
dwError = GetLastError();
SHFree(lpCommand); SHFree(lpCommand);
return HRESULT_FROM_WIN32(error);
return HRESULT_FROM_WIN32(dwError);
} }
/************************************************************************* /*************************************************************************

View file

@ -941,3 +941,4 @@
#define IDR_MOVETOMENU 160 #define IDR_MOVETOMENU 160
#define IDR_COPYASPATHMENU 161 #define IDR_COPYASPATHMENU 161
#define IDR_RECYCLEBINCLEANER 162 #define IDR_RECYCLEBINCLEANER 162
#define IDR_EXPLORER 163

View file

@ -464,9 +464,9 @@
464 stdcall -noname SHExpandEnvironmentStringsForUserW(ptr wstr ptr long) userenv.ExpandEnvironmentStringsForUserW 464 stdcall -noname SHExpandEnvironmentStringsForUserW(ptr wstr ptr long) userenv.ExpandEnvironmentStringsForUserW
465 stub -noname PathUnExpandEnvStringsForUserA 465 stub -noname PathUnExpandEnvStringsForUserA
466 stdcall -stub -noname PathUnExpandEnvStringsForUserW(ptr wstr ptr long) 466 stdcall -stub -noname PathUnExpandEnvStringsForUserW(ptr wstr ptr long)
467 stub -ordinal SHRunIndirectRegClientCommand 467 stdcall -ordinal SHRunIndirectRegClientCommand(ptr wstr) # Exported by name in Vista+
468 stub -noname RunIndirectRegCommand 468 stdcall -noname RunIndirectRegCommand(ptr ptr wstr wstr)
469 stub -noname RunRegCommand 469 stdcall -noname RunRegCommand(ptr ptr wstr)
470 stub -noname IUnknown_ProfferServiceOld 470 stub -noname IUnknown_ProfferServiceOld
471 stdcall -noname SHCreatePropertyBagOnRegKey(ptr wstr long ptr ptr) 471 stdcall -noname SHCreatePropertyBagOnRegKey(ptr wstr long ptr ptr)
472 stdcall -noname SHCreatePropertyBagOnProfileSection(wstr wstr long ptr ptr) 472 stdcall -noname SHCreatePropertyBagOnProfileSection(wstr wstr long ptr ptr)

View file

@ -32,6 +32,8 @@
WINE_DEFAULT_DEBUG_CHANNEL(shell); WINE_DEFAULT_DEBUG_CHANNEL(shell);
EXTERN_C LSTATUS WINAPI RegGetValueW(HKEY, LPCWSTR, LPCWSTR, DWORD, LPDWORD, PVOID, LPDWORD);
static inline WORD static inline WORD
GetVersionMajorMinor() GetVersionMajorMinor()
{ {
@ -203,6 +205,89 @@ IContextMenu_Invoke(
return !FAILED_UNEXPECTEDLY(hr); return !FAILED_UNEXPECTEDLY(hr);
} }
/*************************************************************************
* ShellExecuteCommand [INTERNAL]
*/
static HRESULT
ShellExecuteCommand(_In_opt_ HWND hWnd, _In_ PCWSTR Command, _In_opt_ UINT Flags)
{
WCHAR szCmd[MAX_PATH * 2];
int len = PathProcessCommand(Command, szCmd, _countof(szCmd), PPCF_ADDARGUMENTS | PPCF_FORCEQUALIFY);
if (len <= 0) // Could not resolve the command, just use the input
{
HRESULT hr = StringCchCopyW(szCmd, _countof(szCmd), Command);
if (FAILED(hr))
return hr;
}
PWSTR pszArgs = PathGetArgsW(szCmd);
PathRemoveArgsW(szCmd);
PathUnquoteSpacesW(szCmd);
SHELLEXECUTEINFOW sei = { sizeof(sei), Flags, hWnd, NULL, szCmd, pszArgs };
sei.nShow = SW_SHOW;
UINT error = ShellExecuteExW(&sei) ? ERROR_SUCCESS : GetLastError();
return HRESULT_FROM_WIN32(error);
}
/*************************************************************************
* RunRegCommand [SHLWAPI.469]
*/
EXTERN_C HRESULT WINAPI
RunRegCommand(_In_opt_ HWND hWnd, _In_ HKEY hKey, _In_opt_ PCWSTR pszSubKey)
{
WCHAR szCmd[MAX_PATH * 2];
DWORD cb = sizeof(szCmd);
DWORD error = RegGetValueW(hKey, pszSubKey, NULL, RRF_RT_REG_SZ, NULL, szCmd, &cb);
if (error)
return HRESULT_FROM_WIN32(error);
return ShellExecuteCommand(hWnd, szCmd, SEE_MASK_FLAG_LOG_USAGE);
}
/*************************************************************************
* RunIndirectRegCommand [SHLWAPI.468]
*/
EXTERN_C HRESULT WINAPI
RunIndirectRegCommand(_In_opt_ HWND hWnd, _In_ HKEY hKey, _In_opt_ PCWSTR pszSubKey, _In_ PCWSTR pszVerb)
{
WCHAR szKey[MAX_PATH];
HRESULT hr;
if (pszSubKey)
hr = StringCchPrintfW(szKey, _countof(szKey), L"%s\\shell\\%s\\command", pszSubKey, pszVerb);
else
hr = StringCchPrintfW(szKey, _countof(szKey), L"shell\\%s\\command", pszVerb);
return SUCCEEDED(hr) ? RunRegCommand(hWnd, hKey, szKey) : hr;
}
/*************************************************************************
* SHRunIndirectRegClientCommand [SHLWAPI.467]
*/
EXTERN_C HRESULT WINAPI
SHRunIndirectRegClientCommand(_In_opt_ HWND hWnd, _In_ PCWSTR pszClientType)
{
WCHAR szKey[MAX_PATH], szClient[MAX_PATH];
HRESULT hr = StringCchPrintfW(szKey, _countof(szKey), L"Software\\Clients\\%s", pszClientType);
if (FAILED(hr))
return hr;
// Find the default client
DWORD error, cb;
cb = sizeof(szClient);
error = RegGetValueW(HKEY_CURRENT_USER, szKey, NULL, RRF_RT_REG_SZ, NULL, szClient, &cb);
if (error)
{
cb = sizeof(szClient);
if (error != ERROR_MORE_DATA && error != ERROR_BUFFER_OVERFLOW)
error = RegGetValueW(HKEY_LOCAL_MACHINE, szKey, NULL, RRF_RT_REG_SZ, NULL, szClient, &cb);
if (error)
return HRESULT_FROM_WIN32(error);
}
hr = StringCchPrintfW(szKey, _countof(szKey), L"Software\\Clients\\%s\\%s", pszClientType, szClient);
if (SUCCEEDED(hr))
hr = RunIndirectRegCommand(hWnd, HKEY_LOCAL_MACHINE, szKey, L"open");
return hr;
}
/************************************************************************* /*************************************************************************
* PathFileExistsDefExtAndAttributesW [SHLWAPI.511] * PathFileExistsDefExtAndAttributesW [SHLWAPI.511]
* *

View file

@ -371,6 +371,10 @@ IContextMenu_Invoke(
_In_ LPCSTR lpVerb, _In_ LPCSTR lpVerb,
_In_ UINT uFlags); _In_ UINT uFlags);
HRESULT WINAPI RunRegCommand(_In_opt_ HWND hWnd, _In_ HKEY hKey, _In_opt_ PCWSTR pszSubKey);
HRESULT WINAPI RunIndirectRegCommand(_In_opt_ HWND hWnd, _In_ HKEY hKey, _In_opt_ PCWSTR pszSubKey, _In_ PCWSTR pszVerb);
HRESULT WINAPI SHRunIndirectRegClientCommand(_In_ HWND hWnd, _In_ PCWSTR pszClientType);
DWORD WINAPI SHGetObjectCompatFlags(IUnknown *pUnk, const CLSID *clsid); DWORD WINAPI SHGetObjectCompatFlags(IUnknown *pUnk, const CLSID *clsid);
#define SHACF_WIN95SHLEXEC 0x00000200 /* Geoff Chappell */ #define SHACF_WIN95SHLEXEC 0x00000200 /* Geoff Chappell */

View file

@ -1735,6 +1735,8 @@ VOID co_IntShellHookNotify(WPARAM Message, WPARAM wParam, LPARAM lParam)
if (HwndList) if (HwndList)
{ {
HWND* cursor = HwndList; HWND* cursor = HwndList;
LPARAM shellhookparam = (Message == HSHELL_LANGUAGE || Message == HSHELL_APPCOMMAND)
? lParam : (LPARAM)wParam;
for (; *cursor; cursor++) for (; *cursor; cursor++)
{ {
@ -1742,11 +1744,11 @@ VOID co_IntShellHookNotify(WPARAM Message, WPARAM wParam, LPARAM lParam)
UserPostMessage(*cursor, UserPostMessage(*cursor,
gpsi->uiShellMsg, gpsi->uiShellMsg,
Message, Message,
(Message == HSHELL_LANGUAGE ? lParam : (LPARAM)wParam) ); shellhookparam);
/* co_IntPostOrSendMessage(*cursor, /* co_IntPostOrSendMessage(*cursor,
gpsi->uiShellMsg, gpsi->uiShellMsg,
Message, Message,
(Message == HSHELL_LANGUAGE ? lParam : (LPARAM)wParam) );*/ shellhookparam);*/
} }
ExFreePoolWithTag(HwndList, USERTAG_WINDOWLIST); ExFreePoolWithTag(HwndList, USERTAG_WINDOWLIST);