mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 16:02:56 +00:00
[SHELL32][CMD][SHLWAPI] Use the openas verb when invoking unknown file types (#7981)
CORE-20184
This commit is contained in:
parent
6dd8e04438
commit
d663eb4466
11 changed files with 249 additions and 170 deletions
|
@ -266,10 +266,10 @@ typedef BOOL (WINAPI *MYEX)(LPSHELLEXECUTEINFO lpExecInfo);
|
||||||
HANDLE RunFile(DWORD flags, LPTSTR filename, LPTSTR params,
|
HANDLE RunFile(DWORD flags, LPTSTR filename, LPTSTR params,
|
||||||
LPTSTR directory, INT show)
|
LPTSTR directory, INT show)
|
||||||
{
|
{
|
||||||
SHELLEXECUTEINFO sei;
|
SHELLEXECUTEINFO sei = { sizeof(sei), flags | SEE_MASK_FLAG_DDEWAIT };
|
||||||
HMODULE hShell32;
|
HMODULE hShell32;
|
||||||
MYEX hShExt;
|
MYEX hShExt;
|
||||||
BOOL ret;
|
UINT err;
|
||||||
|
|
||||||
TRACE ("RunFile(%s)\n", debugstr_aw(filename));
|
TRACE ("RunFile(%s)\n", debugstr_aw(filename));
|
||||||
hShell32 = LoadLibrary(_T("SHELL32.DLL"));
|
hShell32 = LoadLibrary(_T("SHELL32.DLL"));
|
||||||
|
@ -289,19 +289,17 @@ HANDLE RunFile(DWORD flags, LPTSTR filename, LPTSTR params,
|
||||||
|
|
||||||
TRACE ("RunFile: ShellExecuteExA/W is at %x\n", hShExt);
|
TRACE ("RunFile: ShellExecuteExA/W is at %x\n", hShExt);
|
||||||
|
|
||||||
memset(&sei, 0, sizeof sei);
|
|
||||||
sei.cbSize = sizeof sei;
|
|
||||||
sei.fMask = flags;
|
|
||||||
sei.lpFile = filename;
|
sei.lpFile = filename;
|
||||||
sei.lpParameters = params;
|
sei.lpParameters = params;
|
||||||
sei.lpDirectory = directory;
|
sei.lpDirectory = directory;
|
||||||
sei.nShow = show;
|
sei.nShow = show;
|
||||||
ret = hShExt(&sei);
|
err = hShExt(&sei) ? ERROR_SUCCESS : GetLastError();
|
||||||
|
TRACE ("RunFile: ShellExecuteExA/W returned error %#x\n", err);
|
||||||
TRACE ("RunFile: ShellExecuteExA/W returned 0x%p\n", ret);
|
|
||||||
|
|
||||||
FreeLibrary(hShell32);
|
FreeLibrary(hShell32);
|
||||||
return ret ? sei.hProcess : NULL;
|
|
||||||
|
SetLastError(err);
|
||||||
|
return err ? NULL : sei.hProcess;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -431,6 +429,7 @@ Execute(LPTSTR Full, LPTSTR First, LPTSTR Rest, PARSED_COMMAND *Cmd)
|
||||||
/* exec the program */
|
/* exec the program */
|
||||||
PROCESS_INFORMATION prci;
|
PROCESS_INFORMATION prci;
|
||||||
STARTUPINFO stui;
|
STARTUPINFO stui;
|
||||||
|
UINT execerror = ERROR_FILE_NOT_FOUND;
|
||||||
|
|
||||||
/* build command line for CreateProcess(): FullName + " " + rest */
|
/* build command line for CreateProcess(): FullName + " " + rest */
|
||||||
BOOL quoted = !!_tcschr(First, _T(' '));
|
BOOL quoted = !!_tcschr(First, _T(' '));
|
||||||
|
@ -450,8 +449,8 @@ Execute(LPTSTR Full, LPTSTR First, LPTSTR Rest, PARSED_COMMAND *Cmd)
|
||||||
memset(&stui, 0, sizeof(stui));
|
memset(&stui, 0, sizeof(stui));
|
||||||
stui.cb = sizeof(stui);
|
stui.cb = sizeof(stui);
|
||||||
stui.lpTitle = Full;
|
stui.lpTitle = Full;
|
||||||
stui.dwFlags = STARTF_USESHOWWINDOW;
|
stui.dwFlags = 0;
|
||||||
stui.wShowWindow = SW_SHOWDEFAULT;
|
stui.wShowWindow = SW_SHOWNORMAL;
|
||||||
|
|
||||||
/* Set the console to standard mode */
|
/* Set the console to standard mode */
|
||||||
SetConsoleMode(ConStreamGetOSHandle(StdIn),
|
SetConsoleMode(ConStreamGetOSHandle(StdIn),
|
||||||
|
@ -470,14 +469,12 @@ Execute(LPTSTR Full, LPTSTR First, LPTSTR Rest, PARSED_COMMAND *Cmd)
|
||||||
{
|
{
|
||||||
CloseHandle(prci.hThread);
|
CloseHandle(prci.hThread);
|
||||||
}
|
}
|
||||||
else
|
else if (GetLastError() == ERROR_BAD_EXE_FORMAT)
|
||||||
{
|
{
|
||||||
// See if we can run this with ShellExecute() ie myfile.xls
|
// See if we can run this with ShellExecute() ie myfile.xls
|
||||||
prci.hProcess = RunFile(SEE_MASK_NOCLOSEPROCESS | SEE_MASK_NO_CONSOLE,
|
HANDLE hProcess = RunFile(SEE_MASK_NOCLOSEPROCESS | SEE_MASK_NO_CONSOLE,
|
||||||
szFullName,
|
szFullName, rest, NULL, SW_SHOWNORMAL);
|
||||||
rest,
|
execerror = hProcess ? ERROR_SUCCESS : GetLastError();
|
||||||
NULL,
|
|
||||||
SW_SHOWNORMAL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*FirstEnd = _T('\0');
|
*FirstEnd = _T('\0');
|
||||||
|
@ -499,10 +496,13 @@ Execute(LPTSTR Full, LPTSTR First, LPTSTR Rest, PARSED_COMMAND *Cmd)
|
||||||
}
|
}
|
||||||
CloseHandle(prci.hProcess);
|
CloseHandle(prci.hProcess);
|
||||||
}
|
}
|
||||||
else
|
else if (execerror)
|
||||||
{
|
{
|
||||||
TRACE ("[ShellExecute failed!: %s]\n", debugstr_aw(Full));
|
TRACE ("[ShellExecute failed!: %s]\n", debugstr_aw(Full));
|
||||||
error_bad_command(first);
|
if (execerror == ERROR_NO_ASSOCIATION)
|
||||||
|
error_cant_exec_program();
|
||||||
|
else
|
||||||
|
error_bad_command(first);
|
||||||
dwExitCode = 1;
|
dwExitCode = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -216,6 +216,7 @@ VOID error_parameter_format(TCHAR ch);
|
||||||
VOID error_invalid_switch(TCHAR ch);
|
VOID error_invalid_switch(TCHAR ch);
|
||||||
VOID error_invalid_parameter_format(PCTSTR s);
|
VOID error_invalid_parameter_format(PCTSTR s);
|
||||||
VOID error_out_of_memory(VOID);
|
VOID error_out_of_memory(VOID);
|
||||||
|
VOID error_cant_exec_program(VOID);
|
||||||
VOID error_syntax(PCTSTR s);
|
VOID error_syntax(PCTSTR s);
|
||||||
|
|
||||||
VOID msg_pause(VOID);
|
VOID msg_pause(VOID);
|
||||||
|
|
|
@ -141,6 +141,13 @@ VOID error_out_of_memory(VOID)
|
||||||
nErrorLevel = 1;
|
nErrorLevel = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VOID error_cant_exec_program(VOID)
|
||||||
|
{
|
||||||
|
/* TODO: Windows uses the custom string "The system cannot execute the specified program" here */
|
||||||
|
ErrorMessage(ERROR_NO_ASSOCIATION, NULL);
|
||||||
|
nErrorLevel = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
VOID error_invalid_parameter_format(PCWSTR s)
|
VOID error_invalid_parameter_format(PCWSTR s)
|
||||||
{
|
{
|
||||||
|
|
|
@ -5,8 +5,8 @@ Signature = "$Windows NT$"
|
||||||
HKLM,"SOFTWARE\Classes",,0x00000010
|
HKLM,"SOFTWARE\Classes",,0x00000010
|
||||||
|
|
||||||
; Default key
|
; Default key
|
||||||
HKCR,"*","",0x00000000,""
|
HKCR,"*","AlwaysShowExt",0x00000000,""
|
||||||
HKCR,"SystemFileAssociations","",0x00000000,""
|
HKCR,"SystemFileAssociations",,0x00000010
|
||||||
|
|
||||||
; Open With List
|
; Open With List
|
||||||
HKCR,"*\OpenWithList\excel.exe","",0x00000000,""
|
HKCR,"*\OpenWithList\excel.exe","",0x00000000,""
|
||||||
|
@ -16,6 +16,12 @@ HKCR,"*\OpenWithList\notepad.exe","",0x00000000,""
|
||||||
HKCR,"*\OpenWithList\winword.exe","",0x00000000,""
|
HKCR,"*\OpenWithList\winword.exe","",0x00000000,""
|
||||||
HKCR,"*\OpenWithList\wordpad.exe","",0x00000000,""
|
HKCR,"*\OpenWithList\wordpad.exe","",0x00000000,""
|
||||||
|
|
||||||
|
; Unknown
|
||||||
|
HKCR,"Unknown","AlwaysShowExt"
|
||||||
|
HKCR,"Unknown","QueryClassStore"
|
||||||
|
HKCR,"Unknown\shell","",,"openas"
|
||||||
|
HKCR,"Unknown\shell\openas\command","",0x00020000,"%SystemRoot%\system32\rundll32.exe %SystemRoot%\system32\shell32.dll,OpenAs_RunDLL %1"
|
||||||
|
|
||||||
; Folders
|
; Folders
|
||||||
HKCR,"Folder","",0x00000000,"Folder"
|
HKCR,"Folder","",0x00000000,"Folder"
|
||||||
;HKCR,"Folder\DefaultIcon","",0x00000000,"%SystemRoot%\system32\shell32.dll,-4"
|
;HKCR,"Folder\DefaultIcon","",0x00000000,"%SystemRoot%\system32\shell32.dll,-4"
|
||||||
|
|
|
@ -58,10 +58,10 @@ static const struct _StaticInvokeCommandMap_
|
||||||
SHORT DfmCmd;
|
SHORT DfmCmd;
|
||||||
} g_StaticInvokeCmdMap[] =
|
} g_StaticInvokeCmdMap[] =
|
||||||
{
|
{
|
||||||
{ "RunAs", 0 }, // Unimplemented
|
{ "runas", 0 }, // Unimplemented
|
||||||
{ "Print", 0 }, // Unimplemented
|
{ "print", 0 }, // Unimplemented
|
||||||
{ "Preview", 0 }, // Unimplemented
|
{ "preview", 0 }, // Unimplemented
|
||||||
{ "Open", FCIDM_SHVIEW_OPEN },
|
{ "open", FCIDM_SHVIEW_OPEN },
|
||||||
{ CMDSTR_NEWFOLDERA, FCIDM_SHVIEW_NEWFOLDER, (SHORT)DFM_CMD_NEWFOLDER },
|
{ CMDSTR_NEWFOLDERA, FCIDM_SHVIEW_NEWFOLDER, (SHORT)DFM_CMD_NEWFOLDER },
|
||||||
{ "cut", FCIDM_SHVIEW_CUT, /* ? */ },
|
{ "cut", FCIDM_SHVIEW_CUT, /* ? */ },
|
||||||
{ "copy", FCIDM_SHVIEW_COPY, (SHORT)DFM_CMD_COPY },
|
{ "copy", FCIDM_SHVIEW_COPY, (SHORT)DFM_CMD_COPY },
|
||||||
|
@ -139,6 +139,36 @@ EXTERN_C HRESULT SHELL32_EnumDefaultVerbList(LPCWSTR List, UINT Index, LPWSTR Ve
|
||||||
return HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS);
|
return HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static HRESULT GetFriendlyVerb(_In_ PCWSTR pszVerb, _Out_ PWSTR pszBuf, _In_ SIZE_T cchMax)
|
||||||
|
{
|
||||||
|
static const struct { PCWSTR pszVerb; WORD iResId; } map[] =
|
||||||
|
{
|
||||||
|
// { L"open", IDS_OPEN_VERB }, These two have already been handled
|
||||||
|
// { L"explore", IDS_EXPLORE_VERB },
|
||||||
|
{ L"edit", IDS_EDIT_VERB },
|
||||||
|
{ L"print", IDS_PRINT_VERB },
|
||||||
|
{ L"runas", IDS_RUNAS_VERB },
|
||||||
|
{ L"openas", IDS_OPEN_VERB },
|
||||||
|
{ L"find", IDS_FIND_VERB },
|
||||||
|
};
|
||||||
|
for (SIZE_T i = 0; i < _countof(map); ++i)
|
||||||
|
{
|
||||||
|
if (!_wcsicmp(pszVerb, map[i].pszVerb) &&
|
||||||
|
LoadStringW(shell32_hInstance, map[i].iResId, pszBuf, cchMax))
|
||||||
|
{
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to make a friendly verb based on the verb subkey
|
||||||
|
if (pszVerb[0] < 127 && !StrChrW(pszVerb, '&') && SUCCEEDED(StringCchCopyW(pszBuf + 1, --cchMax, pszVerb)))
|
||||||
|
{
|
||||||
|
*pszBuf = L'&';
|
||||||
|
return S_OK; // This can be changed to S_FALSE if the caller needs to know we faked it
|
||||||
|
}
|
||||||
|
return E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
class CDefaultContextMenu :
|
class CDefaultContextMenu :
|
||||||
public CComObjectRootEx<CComMultiThreadModelNoCS>,
|
public CComObjectRootEx<CComMultiThreadModelNoCS>,
|
||||||
public IContextMenu3,
|
public IContextMenu3,
|
||||||
|
@ -572,9 +602,8 @@ CDefaultContextMenu::AddStaticContextMenusToMenu(
|
||||||
{
|
{
|
||||||
UINT ntver = RosGetProcessEffectiveVersion();
|
UINT ntver = RosGetProcessEffectiveVersion();
|
||||||
MENUITEMINFOW mii = { sizeof(mii) };
|
MENUITEMINFOW mii = { sizeof(mii) };
|
||||||
UINT idResource;
|
|
||||||
WCHAR wszDispVerb[80]; // The limit on XP. If the friendly string is longer, it falls back to the verb key.
|
WCHAR wszDispVerb[80]; // The limit on XP. If the friendly string is longer, it falls back to the verb key.
|
||||||
UINT fState;
|
UINT fState, idVerbRes;
|
||||||
UINT cIds = 0, indexFirst = *pIndexMenu, indexDefault;
|
UINT cIds = 0, indexFirst = *pIndexMenu, indexDefault;
|
||||||
int iDefVerbIndex = -1;
|
int iDefVerbIndex = -1;
|
||||||
|
|
||||||
|
@ -587,6 +616,7 @@ CDefaultContextMenu::AddStaticContextMenusToMenu(
|
||||||
{
|
{
|
||||||
StaticShellEntry& info = m_StaticEntries.GetNext(it);
|
StaticShellEntry& info = m_StaticEntries.GetNext(it);
|
||||||
BOOL forceFirstPos = FALSE;
|
BOOL forceFirstPos = FALSE;
|
||||||
|
bool hide = false;
|
||||||
|
|
||||||
fState = MFS_ENABLED;
|
fState = MFS_ENABLED;
|
||||||
|
|
||||||
|
@ -599,86 +629,59 @@ CDefaultContextMenu::AddStaticContextMenusToMenu(
|
||||||
|
|
||||||
if (info.Verb.CompareNoCase(L"open") == 0)
|
if (info.Verb.CompareNoCase(L"open") == 0)
|
||||||
{
|
{
|
||||||
idResource = IDS_OPEN_VERB;
|
idVerbRes = IDS_OPEN_VERB; // TODO: This string should include '&'
|
||||||
fState |= MFS_DEFAULT; /* override default when open verb is found */
|
fState |= MFS_DEFAULT; /* override default when open verb is found */
|
||||||
forceFirstPos++;
|
forceFirstPos++;
|
||||||
}
|
}
|
||||||
else if (info.Verb.CompareNoCase(L"explore") == 0)
|
else if (info.Verb.CompareNoCase(L"explore") == 0)
|
||||||
{
|
{
|
||||||
idResource = IDS_EXPLORE_VERB;
|
idVerbRes = IDS_EXPLORE_VERB; // TODO: This string should include '&'
|
||||||
if (uFlags & CMF_EXPLORE)
|
if (uFlags & CMF_EXPLORE)
|
||||||
{
|
{
|
||||||
fState |= MFS_DEFAULT;
|
fState |= MFS_DEFAULT;
|
||||||
forceFirstPos++;
|
forceFirstPos++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (info.Verb.CompareNoCase(L"runas") == 0)
|
|
||||||
idResource = IDS_RUNAS_VERB;
|
|
||||||
else if (info.Verb.CompareNoCase(L"edit") == 0)
|
|
||||||
idResource = IDS_EDIT_VERB;
|
|
||||||
else if (info.Verb.CompareNoCase(L"find") == 0)
|
|
||||||
idResource = IDS_FIND_VERB;
|
|
||||||
else if (info.Verb.CompareNoCase(L"print") == 0)
|
|
||||||
idResource = IDS_PRINT_VERB;
|
|
||||||
else if (info.Verb.CompareNoCase(L"printto") == 0)
|
else if (info.Verb.CompareNoCase(L"printto") == 0)
|
||||||
continue;
|
hide = true;
|
||||||
else
|
else
|
||||||
idResource = 0;
|
idVerbRes = 0;
|
||||||
|
|
||||||
/* By default use verb for menu item name */
|
/* By default use verb for menu item name */
|
||||||
mii.dwTypeData = (LPWSTR)info.Verb.GetString();
|
mii.dwTypeData = (LPWSTR)info.Verb.GetString();
|
||||||
|
|
||||||
WCHAR wszKey[sizeof("shell\\") + MAX_VERB];
|
WCHAR wszKey[sizeof("shell\\") + MAX_VERB];
|
||||||
HRESULT hr;
|
HRESULT hr = StringCbPrintfW(wszKey, sizeof(wszKey), L"shell\\%s", info.Verb.GetString());
|
||||||
hr = StringCbPrintfW(wszKey, sizeof(wszKey), L"shell\\%s", info.Verb.GetString());
|
|
||||||
if (FAILED_UNEXPECTEDLY(hr))
|
if (FAILED_UNEXPECTEDLY(hr))
|
||||||
{
|
hide = true;
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
UINT cmdFlags = 0;
|
UINT cmdFlags = 0;
|
||||||
bool hide = false;
|
|
||||||
HKEY hkVerb;
|
HKEY hkVerb;
|
||||||
if (idResource > 0)
|
if (RegOpenKeyExW(info.hkClass, wszKey, 0, KEY_READ, &hkVerb) == ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
if (!(uFlags & CMF_OPTIMIZEFORINVOKE))
|
if (!(uFlags & CMF_OPTIMIZEFORINVOKE))
|
||||||
{
|
{
|
||||||
if (LoadStringW(shell32_hInstance, idResource, wszDispVerb, _countof(wszDispVerb)))
|
DWORD cbVerb = sizeof(wszDispVerb);
|
||||||
mii.dwTypeData = wszDispVerb; /* use translated verb */
|
LONG res = RegLoadMUIStringW(hkVerb, L"MUIVerb", wszDispVerb, cbVerb, NULL, 0, NULL);
|
||||||
else
|
if (res || !*wszDispVerb)
|
||||||
ERR("Failed to load string\n");
|
res = RegLoadMUIStringW(hkVerb, NULL, wszDispVerb, cbVerb, NULL, 0, NULL);
|
||||||
}
|
|
||||||
|
|
||||||
if (RegOpenKeyW(info.hkClass, wszKey, &hkVerb) != ERROR_SUCCESS)
|
if ((res == ERROR_SUCCESS && *wszDispVerb) ||
|
||||||
hkVerb = NULL;
|
(idVerbRes && LoadStringW(shell32_hInstance, idVerbRes, wszDispVerb, _countof(wszDispVerb))) ||
|
||||||
|
SUCCEEDED(GetFriendlyVerb(info.Verb, wszDispVerb, _countof(wszDispVerb))))
|
||||||
|
{
|
||||||
|
mii.dwTypeData = wszDispVerb;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (RegOpenKeyW(info.hkClass, wszKey, &hkVerb) == ERROR_SUCCESS)
|
hkVerb = NULL;
|
||||||
{
|
|
||||||
if (!(uFlags & CMF_OPTIMIZEFORINVOKE))
|
|
||||||
{
|
|
||||||
DWORD cbVerb = sizeof(wszDispVerb);
|
|
||||||
LONG res = RegLoadMUIStringW(hkVerb, L"MUIVerb", wszDispVerb, cbVerb, NULL, 0, NULL);
|
|
||||||
if (res || !*wszDispVerb)
|
|
||||||
res = RegLoadMUIStringW(hkVerb, NULL, wszDispVerb, cbVerb, NULL, 0, NULL);
|
|
||||||
|
|
||||||
if (res == ERROR_SUCCESS && *wszDispVerb)
|
|
||||||
{
|
|
||||||
/* use description for the menu entry */
|
|
||||||
mii.dwTypeData = wszDispVerb;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
hkVerb = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hkVerb)
|
if (hkVerb)
|
||||||
{
|
{
|
||||||
if (!(uFlags & CMF_EXTENDEDVERBS))
|
if (!hide && !(uFlags & CMF_EXTENDEDVERBS))
|
||||||
hide = RegValueExists(hkVerb, L"Extended");
|
hide = RegValueExists(hkVerb, L"Extended");
|
||||||
|
|
||||||
if (!hide)
|
if (!hide)
|
||||||
|
@ -687,6 +690,9 @@ CDefaultContextMenu::AddStaticContextMenusToMenu(
|
||||||
if (!hide && !(uFlags & CMF_DISABLEDVERBS))
|
if (!hide && !(uFlags & CMF_DISABLEDVERBS))
|
||||||
hide = RegValueExists(hkVerb, L"LegacyDisable");
|
hide = RegValueExists(hkVerb, L"LegacyDisable");
|
||||||
|
|
||||||
|
if (DWORD dwRest = (hide ? 0 : RegGetDword(hkVerb, NULL, L"SuppressionPolicy", 0)))
|
||||||
|
hide = SHRestricted((RESTRICTIONS)dwRest);
|
||||||
|
|
||||||
if (RegValueExists(hkVerb, L"NeverDefault"))
|
if (RegValueExists(hkVerb, L"NeverDefault"))
|
||||||
fState &= ~MFS_DEFAULT;
|
fState &= ~MFS_DEFAULT;
|
||||||
|
|
||||||
|
@ -924,6 +930,11 @@ CDefaultContextMenu::QueryContextMenu(
|
||||||
|
|
||||||
// TODO: DFM_MERGECONTEXTMENU_TOP
|
// TODO: DFM_MERGECONTEXTMENU_TOP
|
||||||
|
|
||||||
|
// TODO: Remove duplicate verbs. This will be easier when the static items handling
|
||||||
|
// has been moved to CLSID_ShellFileDefExt so we only have to deal with ShellEx.
|
||||||
|
// This is a Windows XP+ feature. On an unknown file type, Windows 2000 will
|
||||||
|
// display both "Open" (openas from Unknown) and "Open with..." (openas from *).
|
||||||
|
|
||||||
return MAKE_HRESULT(SEVERITY_SUCCESS, 0, cIds);
|
return MAKE_HRESULT(SEVERITY_SUCCESS, 0, cIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1278,8 +1289,6 @@ CDefaultContextMenu::BrowserFlagsFromVerb(LPCMINVOKECOMMANDINFOEX lpcmi, PStatic
|
||||||
LPCWSTR FlagsName;
|
LPCWSTR FlagsName;
|
||||||
WCHAR wszKey[sizeof("shell\\") + MAX_VERB];
|
WCHAR wszKey[sizeof("shell\\") + MAX_VERB];
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
DWORD wFlags;
|
|
||||||
DWORD cbVerb;
|
|
||||||
|
|
||||||
if (!m_site)
|
if (!m_site)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1306,14 +1315,7 @@ CDefaultContextMenu::BrowserFlagsFromVerb(LPCMINVOKECOMMANDINFOEX lpcmi, PStatic
|
||||||
hr = StringCbPrintfW(wszKey, sizeof(wszKey), L"shell\\%s", pEntry->Verb.GetString());
|
hr = StringCbPrintfW(wszKey, sizeof(wszKey), L"shell\\%s", pEntry->Verb.GetString());
|
||||||
if (FAILED_UNEXPECTEDLY(hr))
|
if (FAILED_UNEXPECTEDLY(hr))
|
||||||
return 0;
|
return 0;
|
||||||
|
return RegGetDword(pEntry->hkClass, wszKey, FlagsName, 0);
|
||||||
cbVerb = sizeof(wFlags);
|
|
||||||
if (RegGetValueW(pEntry->hkClass, wszKey, FlagsName, RRF_RT_REG_DWORD, NULL, &wFlags, &cbVerb) == ERROR_SUCCESS)
|
|
||||||
{
|
|
||||||
return wFlags;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT
|
HRESULT
|
||||||
|
|
|
@ -81,6 +81,67 @@ HRESULT SHELL32_GetDllFromRundll32CommandLine(LPCWSTR pszCmd, LPWSTR pszOut, SIZ
|
||||||
return HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW);
|
return HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static HRESULT SH32_EvaluateValidExecApp(_Inout_ PWSTR pszCmd, _In_ SIZE_T cchMax)
|
||||||
|
{
|
||||||
|
// FIXME: SHEvaluateSystemCommandTemplate is not implemented yet, using a minimal version.
|
||||||
|
if (!PathGetAppFromCommandLine(pszCmd, pszCmd, cchMax))
|
||||||
|
return E_FAIL;
|
||||||
|
|
||||||
|
UINT fPRF = PRF_VERIFYEXISTS | PRF_TRYPROGRAMEXTENSIONS | PRF_DONTFINDLNK;
|
||||||
|
WCHAR szCurrDir[MAX_PATH];
|
||||||
|
LPCWSTR pszDirsArr[2] = { szCurrDir, NULL }, *ppszDirs = NULL;
|
||||||
|
if (GetCurrentDirectoryW(_countof(szCurrDir), szCurrDir))
|
||||||
|
ppszDirs = pszDirsArr;
|
||||||
|
if (PathResolveW(pszCmd, ppszDirs, fPRF | (ppszDirs ? PRF_FIRSTDIRDEF : 0)))
|
||||||
|
return S_OK;
|
||||||
|
return E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT SH32_InvokeOpenWith(_In_ PCWSTR pszPath, _In_ LPCMINVOKECOMMANDINFO pici, _Out_ HANDLE *phProcess)
|
||||||
|
{
|
||||||
|
if (!pszPath || !pici)
|
||||||
|
return HResultFromWin32(ERROR_INVALID_PARAMETER);
|
||||||
|
|
||||||
|
HRESULT hr = HResultFromWin32(ERROR_NO_ASSOCIATION);
|
||||||
|
SHELLEXECUTEINFOW sei = { sizeof(sei), CmicFlagsToSeeFlags(pici->fMask), pici->hwnd };
|
||||||
|
sei.fMask |= SEE_MASK_CLASSKEY | SEE_MASK_NOZONECHECKS;
|
||||||
|
sei.lpFile = pszPath;
|
||||||
|
sei.nShow = pici->nShow;
|
||||||
|
if (phProcess)
|
||||||
|
{
|
||||||
|
sei.fMask |= SEE_MASK_NOCLOSEPROCESS;
|
||||||
|
sei.hProcess = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!RegOpenKeyExW(HKEY_CLASSES_ROOT, L"Unknown", 0, KEY_READ, &sei.hkeyClass))
|
||||||
|
{
|
||||||
|
// Use the internal dialog only if HKCR\Unknown\shell\openas\command exists but is invalid.
|
||||||
|
WCHAR szCmd[MAX_PATH * 2];
|
||||||
|
DWORD cch = _countof(szCmd);
|
||||||
|
hr = AssocQueryStringByKeyW(ASSOCF_NOTRUNCATE | ASSOCF_NOFIXUPS |
|
||||||
|
ASSOCF_IGNOREBASECLASS | ASSOCF_INIT_IGNOREUNKNOWN,
|
||||||
|
ASSOCSTR_COMMAND, sei.hkeyClass, NULL, szCmd, &cch);
|
||||||
|
if (SUCCEEDED(hr) && FAILED(SH32_EvaluateValidExecApp(szCmd, _countof(szCmd))))
|
||||||
|
{
|
||||||
|
OPENASINFO info = { pszPath, NULL, OAIF_EXEC | OAIF_REGISTER_EXT | OAIF_ALLOW_REGISTRATION };
|
||||||
|
hr = SHOpenWithDialog(sei.hwnd, &info);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hr = ShellExecuteExW(&sei) ? S_OK : HResultFromWin32(GetLastError());
|
||||||
|
}
|
||||||
|
RegCloseKey(sei.hkeyClass);
|
||||||
|
}
|
||||||
|
else if (!(pici->fMask & CMIC_MASK_FLAG_NO_UI))
|
||||||
|
{
|
||||||
|
SHELL_ErrorBox(sei.hwnd, hr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (phProcess)
|
||||||
|
*phProcess = sei.hProcess;
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
class COpenWithList
|
class COpenWithList
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -865,6 +926,7 @@ class COpenWithDialog
|
||||||
|
|
||||||
const OPENASINFO *m_pInfo;
|
const OPENASINFO *m_pInfo;
|
||||||
COpenWithList *m_pAppList;
|
COpenWithList *m_pAppList;
|
||||||
|
UINT m_InFlags;
|
||||||
BOOL m_bListAllocated;
|
BOOL m_bListAllocated;
|
||||||
HWND m_hDialog, m_hTreeView;
|
HWND m_hDialog, m_hTreeView;
|
||||||
HTREEITEM m_hRecommend;
|
HTREEITEM m_hRecommend;
|
||||||
|
@ -1031,13 +1093,22 @@ VOID COpenWithDialog::Init(HWND hwnd)
|
||||||
m_hDialog = hwnd;
|
m_hDialog = hwnd;
|
||||||
SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR)this);
|
SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR)this);
|
||||||
|
|
||||||
|
UINT fDisallow = 0;
|
||||||
|
PCWSTR pszExt = PathFindExtensionW(m_pInfo->pcszFile);
|
||||||
|
// Don't allow registration for "" nor "." nor ".exe" etc.
|
||||||
|
if (!pszExt || !pszExt[0] || !pszExt[1] || PathIsExeW(m_pInfo->pcszFile))
|
||||||
|
fDisallow |= OAIF_ALLOW_REGISTRATION | OAIF_FORCE_REGISTRATION;
|
||||||
|
if (SHRestricted(REST_NOFILEASSOCIATE))
|
||||||
|
fDisallow |= OAIF_ALLOW_REGISTRATION | OAIF_FORCE_REGISTRATION | OAIF_REGISTER_EXT;
|
||||||
|
|
||||||
/* Handle register checkbox */
|
/* Handle register checkbox */
|
||||||
|
m_InFlags = m_pInfo->oaifInFlags & ~fDisallow;
|
||||||
HWND hRegisterCheckbox = GetDlgItem(hwnd, 14003);
|
HWND hRegisterCheckbox = GetDlgItem(hwnd, 14003);
|
||||||
if (!(m_pInfo->oaifInFlags & OAIF_ALLOW_REGISTRATION))
|
if (!(m_InFlags & OAIF_ALLOW_REGISTRATION))
|
||||||
EnableWindow(hRegisterCheckbox, FALSE);
|
EnableWindow(hRegisterCheckbox, FALSE);
|
||||||
if (m_pInfo->oaifInFlags & OAIF_FORCE_REGISTRATION)
|
if (m_InFlags & OAIF_FORCE_REGISTRATION)
|
||||||
SendMessage(hRegisterCheckbox, BM_SETCHECK, BST_CHECKED, 0);
|
SendMessage(hRegisterCheckbox, BM_SETCHECK, BST_CHECKED, 0);
|
||||||
if (m_pInfo->oaifInFlags & OAIF_HIDE_REGISTRATION)
|
if (m_InFlags & OAIF_HIDE_REGISTRATION)
|
||||||
ShowWindow(hRegisterCheckbox, SW_HIDE);
|
ShowWindow(hRegisterCheckbox, SW_HIDE);
|
||||||
|
|
||||||
if (m_pInfo->pcszFile)
|
if (m_pInfo->pcszFile)
|
||||||
|
@ -1111,7 +1182,7 @@ VOID COpenWithDialog::Accept()
|
||||||
if (pApp)
|
if (pApp)
|
||||||
{
|
{
|
||||||
/* Set programm as default handler */
|
/* Set programm as default handler */
|
||||||
if (IsDlgButtonChecked(m_hDialog, 14003) == BST_CHECKED)
|
if (IsDlgButtonChecked(m_hDialog, 14003) == BST_CHECKED && (m_InFlags & OAIF_REGISTER_EXT))
|
||||||
{
|
{
|
||||||
m_pAppList->SetDefaultHandler(pApp, m_pInfo->pcszFile);
|
m_pAppList->SetDefaultHandler(pApp, m_pInfo->pcszFile);
|
||||||
// FIXME: Update DefaultIcon registry
|
// FIXME: Update DefaultIcon registry
|
||||||
|
@ -1119,7 +1190,7 @@ VOID COpenWithDialog::Accept()
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Execute program */
|
/* Execute program */
|
||||||
if (m_pInfo->oaifInFlags & OAIF_EXEC)
|
if (m_InFlags & OAIF_EXEC)
|
||||||
m_pAppList->Execute(pApp, m_pInfo->pcszFile);
|
m_pAppList->Execute(pApp, m_pInfo->pcszFile);
|
||||||
|
|
||||||
EndDialog(m_hDialog, 1);
|
EndDialog(m_hDialog, 1);
|
||||||
|
@ -1394,15 +1465,7 @@ COpenWithMenu::InvokeCommand(LPCMINVOKECOMMANDINFO lpici)
|
||||||
if (m_idCmdFirst + LOWORD(lpici->lpVerb) == idChooseApp)
|
if (m_idCmdFirst + LOWORD(lpici->lpVerb) == idChooseApp)
|
||||||
{
|
{
|
||||||
DoChooseApp:
|
DoChooseApp:
|
||||||
OPENASINFO info;
|
hr = SH32_InvokeOpenWith(m_wszPath, lpici, NULL);
|
||||||
LPCWSTR pwszExt = PathFindExtensionW(m_wszPath);
|
|
||||||
|
|
||||||
info.pcszFile = m_wszPath;
|
|
||||||
info.oaifInFlags = OAIF_EXEC;
|
|
||||||
if (pwszExt[0])
|
|
||||||
info.oaifInFlags |= OAIF_REGISTER_EXT | OAIF_ALLOW_REGISTRATION;
|
|
||||||
info.pcszClass = NULL;
|
|
||||||
hr = SHOpenWithDialog(lpici->hwnd, &info);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -591,7 +591,7 @@ HRESULT CQueryAssociations::GetValue(HKEY hkey, const WCHAR *name, void **data,
|
||||||
DWORD size;
|
DWORD size;
|
||||||
LONG ret;
|
LONG ret;
|
||||||
|
|
||||||
ret = RegQueryValueExW(hkey, name, 0, NULL, NULL, &size);
|
ret = SHQueryValueExW(hkey, name, 0, NULL, NULL, &size);
|
||||||
if (ret != ERROR_SUCCESS)
|
if (ret != ERROR_SUCCESS)
|
||||||
return HRESULT_FROM_WIN32(ret);
|
return HRESULT_FROM_WIN32(ret);
|
||||||
|
|
||||||
|
@ -602,7 +602,7 @@ HRESULT CQueryAssociations::GetValue(HKEY hkey, const WCHAR *name, void **data,
|
||||||
if (!*data)
|
if (!*data)
|
||||||
return E_OUTOFMEMORY;
|
return E_OUTOFMEMORY;
|
||||||
|
|
||||||
ret = RegQueryValueExW(hkey, name, 0, NULL, (LPBYTE)*data, &size);
|
ret = SHQueryValueExW(hkey, name, 0, NULL, (LPBYTE)*data, &size);
|
||||||
if (ret != ERROR_SUCCESS)
|
if (ret != ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
HeapFree(GetProcessHeap(), 0, *data);
|
HeapFree(GetProcessHeap(), 0, *data);
|
||||||
|
|
|
@ -1480,6 +1480,7 @@ BOOL SHELL_FS_HideExtension(LPCWSTR szPath)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// TODO: else if "AlwaysShowExt"
|
||||||
|
|
||||||
return doHide;
|
return doHide;
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,6 +47,19 @@ static BOOL SHELL_InRunDllProcess(VOID)
|
||||||
return s_bInDllProcess;
|
return s_bInDllProcess;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static UINT_PTR InvokeOpenWith(HWND hWndOwner, SHELLEXECUTEINFOW &sei)
|
||||||
|
{
|
||||||
|
extern HRESULT SH32_InvokeOpenWith(PCWSTR, LPCMINVOKECOMMANDINFO, HANDLE *);
|
||||||
|
|
||||||
|
HANDLE *phProc = (sei.fMask & SEE_MASK_NOCLOSEPROCESS) ? &sei.hProcess : NULL;
|
||||||
|
UINT fCmic = (sei.fMask & SEE_CMIC_COMMON_BASICFLAGS) | CMIC_MASK_FLAG_NO_UI;
|
||||||
|
CMINVOKECOMMANDINFO ici = { sizeof(ici), fCmic, hWndOwner };
|
||||||
|
ici.nShow = SW_SHOW;
|
||||||
|
HRESULT hr = SH32_InvokeOpenWith(sei.lpFile, &ici, phProc);
|
||||||
|
SetLastError(ERROR_NO_ASSOCIATION);
|
||||||
|
return SUCCEEDED(hr) ? 42 : SE_ERR_NOASSOC;
|
||||||
|
}
|
||||||
|
|
||||||
static void ParseNoTildeEffect(PWSTR &res, LPCWSTR &args, DWORD &len, DWORD &used, int argNum)
|
static void ParseNoTildeEffect(PWSTR &res, LPCWSTR &args, DWORD &len, DWORD &used, int argNum)
|
||||||
{
|
{
|
||||||
bool firstCharQuote = false;
|
bool firstCharQuote = false;
|
||||||
|
@ -697,14 +710,14 @@ static UINT SHELL_FindExecutableByVerb(LPCWSTR lpVerb, LPWSTR key, LPWSTR classn
|
||||||
HKEY hkeyClass;
|
HKEY hkeyClass;
|
||||||
WCHAR verb[MAX_PATH];
|
WCHAR verb[MAX_PATH];
|
||||||
|
|
||||||
if (RegOpenKeyExW(HKEY_CLASSES_ROOT, classname, 0, 0x02000000, &hkeyClass))
|
if (RegOpenKeyExW(HKEY_CLASSES_ROOT, classname, 0, KEY_READ, &hkeyClass))
|
||||||
return SE_ERR_NOASSOC;
|
return SE_ERR_NOASSOC;
|
||||||
if (!HCR_GetDefaultVerbW(hkeyClass, lpVerb, verb, ARRAY_SIZE(verb)))
|
if (!HCR_GetDefaultVerbW(hkeyClass, lpVerb, verb, ARRAY_SIZE(verb)))
|
||||||
return SE_ERR_NOASSOC;
|
return SE_ERR_NOASSOC;
|
||||||
RegCloseKey(hkeyClass);
|
RegCloseKey(hkeyClass);
|
||||||
|
|
||||||
/* Looking for ...buffer\shell\<verb>\command */
|
/* Looking for ...buffer\shell\<verb>\command */
|
||||||
wcscat(classname, L"\\shell\\");
|
wcscat(classname, L"\\shell\\"); // FIXME: Use HCR_GetExecuteCommandW or AssocAPI
|
||||||
wcscat(classname, verb);
|
wcscat(classname, verb);
|
||||||
wcscat(classname, L"\\command");
|
wcscat(classname, L"\\command");
|
||||||
|
|
||||||
|
@ -1361,48 +1374,21 @@ HINSTANCE WINAPI FindExecutableW(LPCWSTR lpFile, LPCWSTR lpDirectory, LPWSTR lpR
|
||||||
/* FIXME: is this already implemented somewhere else? */
|
/* FIXME: is this already implemented somewhere else? */
|
||||||
static HKEY ShellExecute_GetClassKey(const SHELLEXECUTEINFOW *sei)
|
static HKEY ShellExecute_GetClassKey(const SHELLEXECUTEINFOW *sei)
|
||||||
{
|
{
|
||||||
LPCWSTR ext = NULL, lpClass = NULL;
|
if ((sei->fMask & SEE_MASK_CLASSALL) == SEE_MASK_CLASSKEY)
|
||||||
CHeapPtr<WCHAR, CLocalAllocator> cls;
|
|
||||||
DWORD type = 0, sz = 0;
|
|
||||||
HKEY hkey = 0;
|
|
||||||
LONG r;
|
|
||||||
|
|
||||||
if (sei->fMask & SEE_MASK_CLASSALL)
|
|
||||||
return sei->hkeyClass;
|
return sei->hkeyClass;
|
||||||
|
|
||||||
|
HKEY hKey = NULL;
|
||||||
if (sei->fMask & SEE_MASK_CLASSNAME)
|
if (sei->fMask & SEE_MASK_CLASSNAME)
|
||||||
lpClass = sei->lpClass;
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
ext = PathFindExtensionW(sei->lpFile);
|
TRACE("class = %s\n", debugstr_w(sei->lpClass));
|
||||||
TRACE("ext = %s\n", debugstr_w(ext));
|
RegOpenKeyExW(HKEY_CLASSES_ROOT, sei->lpClass, 0, KEY_READ, &hKey);
|
||||||
if (!ext)
|
return hKey;
|
||||||
return hkey;
|
|
||||||
|
|
||||||
r = RegOpenKeyW(HKEY_CLASSES_ROOT, ext, &hkey);
|
|
||||||
if (r != ERROR_SUCCESS)
|
|
||||||
return hkey;
|
|
||||||
|
|
||||||
r = RegQueryValueExW(hkey, NULL, 0, &type, NULL, &sz);
|
|
||||||
if (r == ERROR_SUCCESS && type == REG_SZ)
|
|
||||||
{
|
|
||||||
sz += sizeof (WCHAR);
|
|
||||||
cls.Allocate(sz / sizeof(WCHAR));
|
|
||||||
cls[0] = 0;
|
|
||||||
RegQueryValueExW(hkey, NULL, 0, &type, (LPBYTE)(LPWSTR)cls, &sz);
|
|
||||||
}
|
|
||||||
|
|
||||||
RegCloseKey( hkey );
|
|
||||||
lpClass = cls;
|
|
||||||
}
|
}
|
||||||
|
PCWSTR ext = PathFindExtensionW(sei->lpFile);
|
||||||
TRACE("class = %s\n", debugstr_w(lpClass));
|
TRACE("ext = %s\n", debugstr_w(ext));
|
||||||
|
if (!StrIsNullOrEmpty(ext) && SUCCEEDED(HCR_GetProgIdKeyOfExtension(ext, &hKey, FALSE)))
|
||||||
hkey = 0;
|
return hKey;
|
||||||
if (lpClass)
|
return NULL;
|
||||||
RegOpenKeyW( HKEY_CLASSES_ROOT, lpClass, &hkey);
|
|
||||||
|
|
||||||
return hkey;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT shellex_get_dataobj( LPSHELLEXECUTEINFOW sei, CComPtr<IDataObject>& dataObj)
|
static HRESULT shellex_get_dataobj( LPSHELLEXECUTEINFOW sei, CComPtr<IDataObject>& dataObj)
|
||||||
|
@ -1410,7 +1396,7 @@ static HRESULT shellex_get_dataobj( LPSHELLEXECUTEINFOW sei, CComPtr<IDataObject
|
||||||
CComHeapPtr<ITEMIDLIST> allocatedPidl;
|
CComHeapPtr<ITEMIDLIST> allocatedPidl;
|
||||||
LPITEMIDLIST pidl = NULL;
|
LPITEMIDLIST pidl = NULL;
|
||||||
|
|
||||||
if (sei->fMask & SEE_MASK_CLASSALL)
|
if (sei->fMask & SEE_MASK_CLASSALL) // FIXME: This makes no sense? SEE_MASK_IDLIST?
|
||||||
{
|
{
|
||||||
pidl = (LPITEMIDLIST)sei->lpIDList;
|
pidl = (LPITEMIDLIST)sei->lpIDList;
|
||||||
}
|
}
|
||||||
|
@ -1680,7 +1666,7 @@ static LONG ShellExecute_FromContextMenuHandlers( LPSHELLEXECUTEINFOW sei )
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static UINT_PTR SHELL_quote_and_execute(LPCWSTR wcmd, LPCWSTR wszParameters, LPCWSTR lpstrProtocol, LPCWSTR wszApplicationName, LPWSTR env, LPSHELLEXECUTEINFOW psei, LPSHELLEXECUTEINFOW psei_out, SHELL_ExecuteW32 execfunc);
|
static UINT_PTR SHELL_quote_and_execute(LPCWSTR wcmd, LPCWSTR wszParameters, LPCWSTR wszKeyname, LPCWSTR wszApplicationName, LPWSTR env, LPSHELLEXECUTEINFOW psei, LPSHELLEXECUTEINFOW psei_out, SHELL_ExecuteW32 execfunc);
|
||||||
|
|
||||||
static UINT_PTR SHELL_execute_class(LPCWSTR wszApplicationName, LPSHELLEXECUTEINFOW psei, LPSHELLEXECUTEINFOW psei_out, SHELL_ExecuteW32 execfunc)
|
static UINT_PTR SHELL_execute_class(LPCWSTR wszApplicationName, LPSHELLEXECUTEINFOW psei, LPSHELLEXECUTEINFOW psei_out, SHELL_ExecuteW32 execfunc)
|
||||||
{
|
{
|
||||||
|
@ -1905,7 +1891,7 @@ static UINT_PTR SHELL_execute_url(LPCWSTR lpFile, LPCWSTR wcmd, LPSHELLEXECUTEIN
|
||||||
if (psei->lpVerb && *psei->lpVerb)
|
if (psei->lpVerb && *psei->lpVerb)
|
||||||
len += lstrlenW(psei->lpVerb);
|
len += lstrlenW(psei->lpVerb);
|
||||||
else
|
else
|
||||||
len += lstrlenW(L"open");
|
len += lstrlenW(L"open"); // FIXME: Use HCR_GetExecuteCommandW or AssocAPI
|
||||||
lpstrProtocol.Allocate(len);
|
lpstrProtocol.Allocate(len);
|
||||||
memcpy(lpstrProtocol, lpFile, iSize * sizeof(WCHAR));
|
memcpy(lpstrProtocol, lpFile, iSize * sizeof(WCHAR));
|
||||||
lpstrProtocol[iSize] = '\0';
|
lpstrProtocol[iSize] = '\0';
|
||||||
|
@ -1919,13 +1905,12 @@ static UINT_PTR SHELL_execute_url(LPCWSTR lpFile, LPCWSTR wcmd, LPSHELLEXECUTEIN
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void do_error_dialog(UINT_PTR retval, HWND hwnd, WCHAR* filename)
|
static void do_error_dialog(UINT_PTR retval, HWND hwnd, PCWSTR filename)
|
||||||
{
|
{
|
||||||
WCHAR msg[2048];
|
WCHAR msg[2048];
|
||||||
DWORD_PTR msgArguments[3] = { (DWORD_PTR)filename, 0, 0 };
|
DWORD_PTR msgArguments[3] = { (DWORD_PTR)filename, 0, 0 };
|
||||||
DWORD error_code;
|
const DWORD error_code = GetLastError();
|
||||||
|
|
||||||
error_code = GetLastError();
|
|
||||||
if (retval == SE_ERR_NOASSOC)
|
if (retval == SE_ERR_NOASSOC)
|
||||||
LoadStringW(shell32_hInstance, IDS_SHLEXEC_NOASSOC, msg, ARRAY_SIZE(msg));
|
LoadStringW(shell32_hInstance, IDS_SHLEXEC_NOASSOC, msg, ARRAY_SIZE(msg));
|
||||||
else
|
else
|
||||||
|
@ -1938,6 +1923,7 @@ static void do_error_dialog(UINT_PTR retval, HWND hwnd, WCHAR* filename)
|
||||||
(va_list*)msgArguments);
|
(va_list*)msgArguments);
|
||||||
|
|
||||||
MessageBoxW(hwnd, msg, NULL, MB_ICONERROR);
|
MessageBoxW(hwnd, msg, NULL, MB_ICONERROR);
|
||||||
|
SetLastError(error_code); // Restore
|
||||||
}
|
}
|
||||||
|
|
||||||
static WCHAR *expand_environment( const WCHAR *str )
|
static WCHAR *expand_environment( const WCHAR *str )
|
||||||
|
@ -1971,6 +1957,7 @@ static BOOL SHELL_execute(LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc)
|
||||||
BOOL appKnownSingular = FALSE;
|
BOOL appKnownSingular = FALSE;
|
||||||
|
|
||||||
/* make a local copy of the LPSHELLEXECUTEINFO structure and work with this from now on */
|
/* make a local copy of the LPSHELLEXECUTEINFO structure and work with this from now on */
|
||||||
|
sei->hProcess = NULL;
|
||||||
SHELLEXECUTEINFOW sei_tmp = *sei;
|
SHELLEXECUTEINFOW sei_tmp = *sei;
|
||||||
|
|
||||||
TRACE("mask=0x%08x hwnd=%p verb=%s file=%s parm=%s dir=%s show=0x%08x class=%s\n",
|
TRACE("mask=0x%08x hwnd=%p verb=%s file=%s parm=%s dir=%s show=0x%08x class=%s\n",
|
||||||
|
@ -1980,8 +1967,6 @@ static BOOL SHELL_execute(LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc)
|
||||||
((sei_tmp.fMask & SEE_MASK_CLASSALL) == SEE_MASK_CLASSNAME) ?
|
((sei_tmp.fMask & SEE_MASK_CLASSALL) == SEE_MASK_CLASSNAME) ?
|
||||||
debugstr_w(sei_tmp.lpClass) : "not used");
|
debugstr_w(sei_tmp.lpClass) : "not used");
|
||||||
|
|
||||||
sei->hProcess = NULL;
|
|
||||||
|
|
||||||
/* make copies of all path/command strings */
|
/* make copies of all path/command strings */
|
||||||
CHeapPtr<WCHAR, CLocalAllocator> wszApplicationName;
|
CHeapPtr<WCHAR, CLocalAllocator> wszApplicationName;
|
||||||
DWORD dwApplicationNameLen = MAX_PATH + 2;
|
DWORD dwApplicationNameLen = MAX_PATH + 2;
|
||||||
|
@ -2330,7 +2315,8 @@ static BOOL SHELL_execute(LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc)
|
||||||
/* if so, prefix lpFile with http:// and call ShellExecute */
|
/* if so, prefix lpFile with http:// and call ShellExecute */
|
||||||
WCHAR lpstrTmpFile[256];
|
WCHAR lpstrTmpFile[256];
|
||||||
strcpyW(lpstrTmpFile, L"http://");
|
strcpyW(lpstrTmpFile, L"http://");
|
||||||
strcatW(lpstrTmpFile, lpFile);
|
strcatW(lpstrTmpFile, lpFile); // FIXME: Possible buffer overflow
|
||||||
|
// FIXME: This will not correctly return the hProcess to the caller
|
||||||
retval = (UINT_PTR)ShellExecuteW(sei_tmp.hwnd, sei_tmp.lpVerb, lpstrTmpFile, NULL, NULL, 0);
|
retval = (UINT_PTR)ShellExecuteW(sei_tmp.hwnd, sei_tmp.lpVerb, lpstrTmpFile, NULL, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2338,18 +2324,10 @@ static BOOL SHELL_execute(LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc)
|
||||||
|
|
||||||
if (retval <= 32 && !(sei_tmp.fMask & SEE_MASK_FLAG_NO_UI))
|
if (retval <= 32 && !(sei_tmp.fMask & SEE_MASK_FLAG_NO_UI))
|
||||||
{
|
{
|
||||||
OPENASINFO Info;
|
if (retval == SE_ERR_NOASSOC && !(sei->fMask & SEE_MASK_CLASSALL))
|
||||||
|
retval = InvokeOpenWith(sei_tmp.hwnd, *sei);
|
||||||
//FIXME
|
if (retval <= 32)
|
||||||
// need full path
|
do_error_dialog(retval, sei_tmp.hwnd, lpFile);
|
||||||
|
|
||||||
Info.pcszFile = wszApplicationName;
|
|
||||||
Info.pcszClass = NULL;
|
|
||||||
Info.oaifInFlags = OAIF_ALLOW_REGISTRATION | OAIF_EXEC;
|
|
||||||
|
|
||||||
//if (SHOpenWithDialog(sei_tmp.hwnd, &Info) != S_OK)
|
|
||||||
DBG_UNREFERENCED_LOCAL_VARIABLE(Info);
|
|
||||||
do_error_dialog(retval, sei_tmp.hwnd, wszApplicationName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sei->hInstApp = (HINSTANCE)(retval > 32 ? 33 : retval);
|
sei->hInstApp = (HINSTANCE)(retval > 32 ? 33 : retval);
|
||||||
|
@ -2393,7 +2371,11 @@ static DWORD
|
||||||
ShellExecute_Normal(_Inout_ LPSHELLEXECUTEINFOW sei)
|
ShellExecute_Normal(_Inout_ LPSHELLEXECUTEINFOW sei)
|
||||||
{
|
{
|
||||||
// FIXME
|
// FIXME
|
||||||
return SHELL_execute(sei, SHELL_ExecuteW) ? ERROR_SUCCESS : ERROR_FILE_NOT_FOUND;
|
if (SHELL_execute(sei, SHELL_ExecuteW))
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
DWORD err = GetLastError();
|
||||||
|
assert(err);
|
||||||
|
return err ? err : ERROR_FILE_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
static VOID
|
static VOID
|
||||||
|
@ -2592,14 +2574,8 @@ EXTERN_C HINSTANCE WINAPI WOWShellExecute(HWND hWnd, LPCSTR lpVerb, LPCSTR lpFil
|
||||||
EXTERN_C void WINAPI
|
EXTERN_C void WINAPI
|
||||||
OpenAs_RunDLLW(HWND hwnd, HINSTANCE hinst, LPCWSTR cmdline, int cmdshow)
|
OpenAs_RunDLLW(HWND hwnd, HINSTANCE hinst, LPCWSTR cmdline, int cmdshow)
|
||||||
{
|
{
|
||||||
OPENASINFO info;
|
OPENASINFO info = { cmdline, NULL, OAIF_ALLOW_REGISTRATION | OAIF_REGISTER_EXT | OAIF_EXEC };
|
||||||
TRACE("%p, %p, %s, %d\n", hwnd, hinst, debugstr_w(cmdline), cmdshow);
|
TRACE("%p, %p, %s, %d\n", hwnd, hinst, debugstr_w(cmdline), cmdshow);
|
||||||
|
|
||||||
ZeroMemory(&info, sizeof(info));
|
|
||||||
info.pcszFile = cmdline;
|
|
||||||
info.pcszClass = NULL;
|
|
||||||
info.oaifInFlags = OAIF_ALLOW_REGISTRATION | OAIF_REGISTER_EXT | OAIF_EXEC;
|
|
||||||
|
|
||||||
SHOpenWithDialog(hwnd, &info);
|
SHOpenWithDialog(hwnd, &info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2700,7 +2676,7 @@ HRESULT WINAPI ShellExecCmdLine(
|
||||||
if (dwSeclFlags & SECL_RUNAS)
|
if (dwSeclFlags & SECL_RUNAS)
|
||||||
{
|
{
|
||||||
dwSize = 0;
|
dwSize = 0;
|
||||||
hr = AssocQueryStringW(ASSOCF_NONE, ASSOCSTR_COMMAND, lpCommand, L"RunAs", NULL, &dwSize);
|
hr = AssocQueryStringW(ASSOCF_NONE, ASSOCSTR_COMMAND, lpCommand, L"runas", NULL, &dwSize);
|
||||||
if (SUCCEEDED(hr) && dwSize != 0)
|
if (SUCCEEDED(hr) && dwSize != 0)
|
||||||
{
|
{
|
||||||
pszVerb = L"runas";
|
pszVerb = L"runas";
|
||||||
|
|
|
@ -54,6 +54,20 @@ RegKeyExists(HKEY hKey, LPCWSTR Path)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline UINT
|
||||||
|
RegQueryDword(HKEY hKey, PCWSTR pszPath, PCWSTR pszName, DWORD *pnVal)
|
||||||
|
{
|
||||||
|
DWORD cb = sizeof(*pnVal);
|
||||||
|
return RegGetValueW(hKey, pszPath, pszName, RRF_RT_REG_DWORD, NULL, pnVal, &cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline DWORD
|
||||||
|
RegGetDword(HKEY hKey, PCWSTR pszPath, PCWSTR pszName, DWORD nDefVal)
|
||||||
|
{
|
||||||
|
DWORD nVal;
|
||||||
|
return RegQueryDword(hKey, pszPath, pszName, &nVal) == ERROR_SUCCESS ? nVal : nDefVal;
|
||||||
|
}
|
||||||
|
|
||||||
inline DWORD
|
inline DWORD
|
||||||
RegSetOrDelete(HKEY hKey, LPCWSTR Name, DWORD Type, LPCVOID Data, DWORD Size)
|
RegSetOrDelete(HKEY hKey, LPCWSTR Name, DWORD Type, LPCVOID Data, DWORD Size)
|
||||||
{
|
{
|
||||||
|
|
|
@ -40,7 +40,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(shell);
|
||||||
/* Default IQueryAssociations::Init() flags */
|
/* Default IQueryAssociations::Init() flags */
|
||||||
#ifdef __REACTOS__
|
#ifdef __REACTOS__
|
||||||
#define SHLWAPI_DEF_ASSOCF (ASSOCF_INIT_BYEXENAME | ASSOCF_INIT_DEFAULTTOSTAR | \
|
#define SHLWAPI_DEF_ASSOCF (ASSOCF_INIT_BYEXENAME | ASSOCF_INIT_DEFAULTTOSTAR | \
|
||||||
ASSOCF_INIT_DEFAULTTOFOLDER | ASSOCF_INIT_NOREMAPCLSID)
|
ASSOCF_INIT_DEFAULTTOFOLDER | ASSOCF_INIT_NOREMAPCLSID | \
|
||||||
|
ASSOCF_INIT_IGNOREUNKNOWN)
|
||||||
#else
|
#else
|
||||||
#define SHLWAPI_DEF_ASSOCF (ASSOCF_INIT_BYEXENAME|ASSOCF_INIT_DEFAULTTOSTAR| \
|
#define SHLWAPI_DEF_ASSOCF (ASSOCF_INIT_BYEXENAME|ASSOCF_INIT_DEFAULTTOSTAR| \
|
||||||
ASSOCF_INIT_DEFAULTTOFOLDER)
|
ASSOCF_INIT_DEFAULTTOFOLDER)
|
||||||
|
@ -377,8 +378,12 @@ HRESULT WINAPI AssocQueryKeyW(ASSOCF cfFlags, ASSOCKEY assockey, LPCWSTR pszAsso
|
||||||
hRet = AssocCreate( CLSID_QueryAssociations, &IID_IQueryAssociations, (void **)&lpAssoc );
|
hRet = AssocCreate( CLSID_QueryAssociations, &IID_IQueryAssociations, (void **)&lpAssoc );
|
||||||
if (FAILED(hRet)) return hRet;
|
if (FAILED(hRet)) return hRet;
|
||||||
|
|
||||||
|
#ifdef __REACTOS__
|
||||||
|
hRet = IQueryAssociations_Init(lpAssoc, cfFlags & SHLWAPI_DEF_ASSOCF, pszAssoc, NULL, NULL);
|
||||||
|
#else
|
||||||
cfFlags &= SHLWAPI_DEF_ASSOCF;
|
cfFlags &= SHLWAPI_DEF_ASSOCF;
|
||||||
hRet = IQueryAssociations_Init(lpAssoc, cfFlags, pszAssoc, NULL, NULL);
|
hRet = IQueryAssociations_Init(lpAssoc, cfFlags, pszAssoc, NULL, NULL);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (SUCCEEDED(hRet))
|
if (SUCCEEDED(hRet))
|
||||||
hRet = IQueryAssociations_GetKey(lpAssoc, cfFlags, assockey, pszExtra, phkeyOut);
|
hRet = IQueryAssociations_GetKey(lpAssoc, cfFlags, assockey, pszExtra, phkeyOut);
|
||||||
|
@ -542,8 +547,12 @@ HRESULT WINAPI AssocQueryStringByKeyW(ASSOCF cfFlags, ASSOCSTR str, HKEY hkAssoc
|
||||||
hRet = AssocCreate( CLSID_QueryAssociations, &IID_IQueryAssociations, (void **)&lpAssoc );
|
hRet = AssocCreate( CLSID_QueryAssociations, &IID_IQueryAssociations, (void **)&lpAssoc );
|
||||||
if (FAILED(hRet)) return hRet;
|
if (FAILED(hRet)) return hRet;
|
||||||
|
|
||||||
|
#ifdef __REACTOS__
|
||||||
|
hRet = IQueryAssociations_Init(lpAssoc, cfFlags & SHLWAPI_DEF_ASSOCF, 0, hkAssoc, NULL);
|
||||||
|
#else
|
||||||
cfFlags &= SHLWAPI_DEF_ASSOCF;
|
cfFlags &= SHLWAPI_DEF_ASSOCF;
|
||||||
hRet = IQueryAssociations_Init(lpAssoc, cfFlags, 0, hkAssoc, NULL);
|
hRet = IQueryAssociations_Init(lpAssoc, cfFlags, 0, hkAssoc, NULL);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (SUCCEEDED(hRet))
|
if (SUCCEEDED(hRet))
|
||||||
hRet = IQueryAssociations_GetString(lpAssoc, cfFlags, str, pszExtra,
|
hRet = IQueryAssociations_GetString(lpAssoc, cfFlags, str, pszExtra,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue