mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 14:53:40 +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,
|
||||
LPTSTR directory, INT show)
|
||||
{
|
||||
SHELLEXECUTEINFO sei;
|
||||
SHELLEXECUTEINFO sei = { sizeof(sei), flags | SEE_MASK_FLAG_DDEWAIT };
|
||||
HMODULE hShell32;
|
||||
MYEX hShExt;
|
||||
BOOL ret;
|
||||
UINT err;
|
||||
|
||||
TRACE ("RunFile(%s)\n", debugstr_aw(filename));
|
||||
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);
|
||||
|
||||
memset(&sei, 0, sizeof sei);
|
||||
sei.cbSize = sizeof sei;
|
||||
sei.fMask = flags;
|
||||
sei.lpFile = filename;
|
||||
sei.lpParameters = params;
|
||||
sei.lpDirectory = directory;
|
||||
sei.nShow = show;
|
||||
ret = hShExt(&sei);
|
||||
|
||||
TRACE ("RunFile: ShellExecuteExA/W returned 0x%p\n", ret);
|
||||
err = hShExt(&sei) ? ERROR_SUCCESS : GetLastError();
|
||||
TRACE ("RunFile: ShellExecuteExA/W returned error %#x\n", err);
|
||||
|
||||
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 */
|
||||
PROCESS_INFORMATION prci;
|
||||
STARTUPINFO stui;
|
||||
UINT execerror = ERROR_FILE_NOT_FOUND;
|
||||
|
||||
/* build command line for CreateProcess(): FullName + " " + rest */
|
||||
BOOL quoted = !!_tcschr(First, _T(' '));
|
||||
|
@ -450,8 +449,8 @@ Execute(LPTSTR Full, LPTSTR First, LPTSTR Rest, PARSED_COMMAND *Cmd)
|
|||
memset(&stui, 0, sizeof(stui));
|
||||
stui.cb = sizeof(stui);
|
||||
stui.lpTitle = Full;
|
||||
stui.dwFlags = STARTF_USESHOWWINDOW;
|
||||
stui.wShowWindow = SW_SHOWDEFAULT;
|
||||
stui.dwFlags = 0;
|
||||
stui.wShowWindow = SW_SHOWNORMAL;
|
||||
|
||||
/* Set the console to standard mode */
|
||||
SetConsoleMode(ConStreamGetOSHandle(StdIn),
|
||||
|
@ -470,14 +469,12 @@ Execute(LPTSTR Full, LPTSTR First, LPTSTR Rest, PARSED_COMMAND *Cmd)
|
|||
{
|
||||
CloseHandle(prci.hThread);
|
||||
}
|
||||
else
|
||||
else if (GetLastError() == ERROR_BAD_EXE_FORMAT)
|
||||
{
|
||||
// See if we can run this with ShellExecute() ie myfile.xls
|
||||
prci.hProcess = RunFile(SEE_MASK_NOCLOSEPROCESS | SEE_MASK_NO_CONSOLE,
|
||||
szFullName,
|
||||
rest,
|
||||
NULL,
|
||||
SW_SHOWNORMAL);
|
||||
HANDLE hProcess = RunFile(SEE_MASK_NOCLOSEPROCESS | SEE_MASK_NO_CONSOLE,
|
||||
szFullName, rest, NULL, SW_SHOWNORMAL);
|
||||
execerror = hProcess ? ERROR_SUCCESS : GetLastError();
|
||||
}
|
||||
|
||||
*FirstEnd = _T('\0');
|
||||
|
@ -499,10 +496,13 @@ Execute(LPTSTR Full, LPTSTR First, LPTSTR Rest, PARSED_COMMAND *Cmd)
|
|||
}
|
||||
CloseHandle(prci.hProcess);
|
||||
}
|
||||
else
|
||||
else if (execerror)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -216,6 +216,7 @@ VOID error_parameter_format(TCHAR ch);
|
|||
VOID error_invalid_switch(TCHAR ch);
|
||||
VOID error_invalid_parameter_format(PCTSTR s);
|
||||
VOID error_out_of_memory(VOID);
|
||||
VOID error_cant_exec_program(VOID);
|
||||
VOID error_syntax(PCTSTR s);
|
||||
|
||||
VOID msg_pause(VOID);
|
||||
|
|
|
@ -141,6 +141,13 @@ VOID error_out_of_memory(VOID)
|
|||
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)
|
||||
{
|
||||
|
|
|
@ -5,8 +5,8 @@ Signature = "$Windows NT$"
|
|||
HKLM,"SOFTWARE\Classes",,0x00000010
|
||||
|
||||
; Default key
|
||||
HKCR,"*","",0x00000000,""
|
||||
HKCR,"SystemFileAssociations","",0x00000000,""
|
||||
HKCR,"*","AlwaysShowExt",0x00000000,""
|
||||
HKCR,"SystemFileAssociations",,0x00000010
|
||||
|
||||
; Open With List
|
||||
HKCR,"*\OpenWithList\excel.exe","",0x00000000,""
|
||||
|
@ -16,6 +16,12 @@ HKCR,"*\OpenWithList\notepad.exe","",0x00000000,""
|
|||
HKCR,"*\OpenWithList\winword.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
|
||||
HKCR,"Folder","",0x00000000,"Folder"
|
||||
;HKCR,"Folder\DefaultIcon","",0x00000000,"%SystemRoot%\system32\shell32.dll,-4"
|
||||
|
|
|
@ -58,10 +58,10 @@ static const struct _StaticInvokeCommandMap_
|
|||
SHORT DfmCmd;
|
||||
} g_StaticInvokeCmdMap[] =
|
||||
{
|
||||
{ "RunAs", 0 }, // Unimplemented
|
||||
{ "Print", 0 }, // Unimplemented
|
||||
{ "Preview", 0 }, // Unimplemented
|
||||
{ "Open", FCIDM_SHVIEW_OPEN },
|
||||
{ "runas", 0 }, // Unimplemented
|
||||
{ "print", 0 }, // Unimplemented
|
||||
{ "preview", 0 }, // Unimplemented
|
||||
{ "open", FCIDM_SHVIEW_OPEN },
|
||||
{ CMDSTR_NEWFOLDERA, FCIDM_SHVIEW_NEWFOLDER, (SHORT)DFM_CMD_NEWFOLDER },
|
||||
{ "cut", FCIDM_SHVIEW_CUT, /* ? */ },
|
||||
{ "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);
|
||||
}
|
||||
|
||||
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 :
|
||||
public CComObjectRootEx<CComMultiThreadModelNoCS>,
|
||||
public IContextMenu3,
|
||||
|
@ -572,9 +602,8 @@ CDefaultContextMenu::AddStaticContextMenusToMenu(
|
|||
{
|
||||
UINT ntver = RosGetProcessEffectiveVersion();
|
||||
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.
|
||||
UINT fState;
|
||||
UINT fState, idVerbRes;
|
||||
UINT cIds = 0, indexFirst = *pIndexMenu, indexDefault;
|
||||
int iDefVerbIndex = -1;
|
||||
|
||||
|
@ -587,6 +616,7 @@ CDefaultContextMenu::AddStaticContextMenusToMenu(
|
|||
{
|
||||
StaticShellEntry& info = m_StaticEntries.GetNext(it);
|
||||
BOOL forceFirstPos = FALSE;
|
||||
bool hide = false;
|
||||
|
||||
fState = MFS_ENABLED;
|
||||
|
||||
|
@ -599,86 +629,59 @@ CDefaultContextMenu::AddStaticContextMenusToMenu(
|
|||
|
||||
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 */
|
||||
forceFirstPos++;
|
||||
}
|
||||
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)
|
||||
{
|
||||
fState |= MFS_DEFAULT;
|
||||
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)
|
||||
continue;
|
||||
hide = true;
|
||||
else
|
||||
idResource = 0;
|
||||
idVerbRes = 0;
|
||||
|
||||
/* By default use verb for menu item name */
|
||||
mii.dwTypeData = (LPWSTR)info.Verb.GetString();
|
||||
|
||||
WCHAR wszKey[sizeof("shell\\") + MAX_VERB];
|
||||
HRESULT hr;
|
||||
hr = StringCbPrintfW(wszKey, sizeof(wszKey), L"shell\\%s", info.Verb.GetString());
|
||||
HRESULT hr = StringCbPrintfW(wszKey, sizeof(wszKey), L"shell\\%s", info.Verb.GetString());
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
hide = true;
|
||||
|
||||
UINT cmdFlags = 0;
|
||||
bool hide = false;
|
||||
HKEY hkVerb;
|
||||
if (idResource > 0)
|
||||
if (RegOpenKeyExW(info.hkClass, wszKey, 0, KEY_READ, &hkVerb) == ERROR_SUCCESS)
|
||||
{
|
||||
if (!(uFlags & CMF_OPTIMIZEFORINVOKE))
|
||||
{
|
||||
if (LoadStringW(shell32_hInstance, idResource, wszDispVerb, _countof(wszDispVerb)))
|
||||
mii.dwTypeData = wszDispVerb; /* use translated verb */
|
||||
else
|
||||
ERR("Failed to load string\n");
|
||||
}
|
||||
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 (RegOpenKeyW(info.hkClass, wszKey, &hkVerb) != ERROR_SUCCESS)
|
||||
hkVerb = NULL;
|
||||
if ((res == ERROR_SUCCESS && *wszDispVerb) ||
|
||||
(idVerbRes && LoadStringW(shell32_hInstance, idVerbRes, wszDispVerb, _countof(wszDispVerb))) ||
|
||||
SUCCEEDED(GetFriendlyVerb(info.Verb, wszDispVerb, _countof(wszDispVerb))))
|
||||
{
|
||||
mii.dwTypeData = wszDispVerb;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (RegOpenKeyW(info.hkClass, wszKey, &hkVerb) == ERROR_SUCCESS)
|
||||
{
|
||||
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;
|
||||
}
|
||||
hkVerb = NULL;
|
||||
}
|
||||
|
||||
if (hkVerb)
|
||||
{
|
||||
if (!(uFlags & CMF_EXTENDEDVERBS))
|
||||
if (!hide && !(uFlags & CMF_EXTENDEDVERBS))
|
||||
hide = RegValueExists(hkVerb, L"Extended");
|
||||
|
||||
if (!hide)
|
||||
|
@ -687,6 +690,9 @@ CDefaultContextMenu::AddStaticContextMenusToMenu(
|
|||
if (!hide && !(uFlags & CMF_DISABLEDVERBS))
|
||||
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"))
|
||||
fState &= ~MFS_DEFAULT;
|
||||
|
||||
|
@ -924,6 +930,11 @@ CDefaultContextMenu::QueryContextMenu(
|
|||
|
||||
// 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);
|
||||
}
|
||||
|
||||
|
@ -1278,8 +1289,6 @@ CDefaultContextMenu::BrowserFlagsFromVerb(LPCMINVOKECOMMANDINFOEX lpcmi, PStatic
|
|||
LPCWSTR FlagsName;
|
||||
WCHAR wszKey[sizeof("shell\\") + MAX_VERB];
|
||||
HRESULT hr;
|
||||
DWORD wFlags;
|
||||
DWORD cbVerb;
|
||||
|
||||
if (!m_site)
|
||||
return 0;
|
||||
|
@ -1306,14 +1315,7 @@ CDefaultContextMenu::BrowserFlagsFromVerb(LPCMINVOKECOMMANDINFOEX lpcmi, PStatic
|
|||
hr = StringCbPrintfW(wszKey, sizeof(wszKey), L"shell\\%s", pEntry->Verb.GetString());
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return 0;
|
||||
|
||||
cbVerb = sizeof(wFlags);
|
||||
if (RegGetValueW(pEntry->hkClass, wszKey, FlagsName, RRF_RT_REG_DWORD, NULL, &wFlags, &cbVerb) == ERROR_SUCCESS)
|
||||
{
|
||||
return wFlags;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return RegGetDword(pEntry->hkClass, wszKey, FlagsName, 0);
|
||||
}
|
||||
|
||||
HRESULT
|
||||
|
|
|
@ -81,6 +81,67 @@ HRESULT SHELL32_GetDllFromRundll32CommandLine(LPCWSTR pszCmd, LPWSTR pszOut, SIZ
|
|||
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
|
||||
{
|
||||
public:
|
||||
|
@ -865,6 +926,7 @@ class COpenWithDialog
|
|||
|
||||
const OPENASINFO *m_pInfo;
|
||||
COpenWithList *m_pAppList;
|
||||
UINT m_InFlags;
|
||||
BOOL m_bListAllocated;
|
||||
HWND m_hDialog, m_hTreeView;
|
||||
HTREEITEM m_hRecommend;
|
||||
|
@ -1031,13 +1093,22 @@ VOID COpenWithDialog::Init(HWND hwnd)
|
|||
m_hDialog = hwnd;
|
||||
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 */
|
||||
m_InFlags = m_pInfo->oaifInFlags & ~fDisallow;
|
||||
HWND hRegisterCheckbox = GetDlgItem(hwnd, 14003);
|
||||
if (!(m_pInfo->oaifInFlags & OAIF_ALLOW_REGISTRATION))
|
||||
if (!(m_InFlags & OAIF_ALLOW_REGISTRATION))
|
||||
EnableWindow(hRegisterCheckbox, FALSE);
|
||||
if (m_pInfo->oaifInFlags & OAIF_FORCE_REGISTRATION)
|
||||
if (m_InFlags & OAIF_FORCE_REGISTRATION)
|
||||
SendMessage(hRegisterCheckbox, BM_SETCHECK, BST_CHECKED, 0);
|
||||
if (m_pInfo->oaifInFlags & OAIF_HIDE_REGISTRATION)
|
||||
if (m_InFlags & OAIF_HIDE_REGISTRATION)
|
||||
ShowWindow(hRegisterCheckbox, SW_HIDE);
|
||||
|
||||
if (m_pInfo->pcszFile)
|
||||
|
@ -1111,7 +1182,7 @@ VOID COpenWithDialog::Accept()
|
|||
if (pApp)
|
||||
{
|
||||
/* 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);
|
||||
// FIXME: Update DefaultIcon registry
|
||||
|
@ -1119,7 +1190,7 @@ VOID COpenWithDialog::Accept()
|
|||
}
|
||||
|
||||
/* Execute program */
|
||||
if (m_pInfo->oaifInFlags & OAIF_EXEC)
|
||||
if (m_InFlags & OAIF_EXEC)
|
||||
m_pAppList->Execute(pApp, m_pInfo->pcszFile);
|
||||
|
||||
EndDialog(m_hDialog, 1);
|
||||
|
@ -1394,15 +1465,7 @@ COpenWithMenu::InvokeCommand(LPCMINVOKECOMMANDINFO lpici)
|
|||
if (m_idCmdFirst + LOWORD(lpici->lpVerb) == idChooseApp)
|
||||
{
|
||||
DoChooseApp:
|
||||
OPENASINFO info;
|
||||
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);
|
||||
hr = SH32_InvokeOpenWith(m_wszPath, lpici, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -591,7 +591,7 @@ HRESULT CQueryAssociations::GetValue(HKEY hkey, const WCHAR *name, void **data,
|
|||
DWORD size;
|
||||
LONG ret;
|
||||
|
||||
ret = RegQueryValueExW(hkey, name, 0, NULL, NULL, &size);
|
||||
ret = SHQueryValueExW(hkey, name, 0, NULL, NULL, &size);
|
||||
if (ret != ERROR_SUCCESS)
|
||||
return HRESULT_FROM_WIN32(ret);
|
||||
|
||||
|
@ -602,7 +602,7 @@ HRESULT CQueryAssociations::GetValue(HKEY hkey, const WCHAR *name, void **data,
|
|||
if (!*data)
|
||||
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)
|
||||
{
|
||||
HeapFree(GetProcessHeap(), 0, *data);
|
||||
|
|
|
@ -1480,6 +1480,7 @@ BOOL SHELL_FS_HideExtension(LPCWSTR szPath)
|
|||
}
|
||||
}
|
||||
}
|
||||
// TODO: else if "AlwaysShowExt"
|
||||
|
||||
return doHide;
|
||||
}
|
||||
|
|
|
@ -47,6 +47,19 @@ static BOOL SHELL_InRunDllProcess(VOID)
|
|||
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)
|
||||
{
|
||||
bool firstCharQuote = false;
|
||||
|
@ -697,14 +710,14 @@ static UINT SHELL_FindExecutableByVerb(LPCWSTR lpVerb, LPWSTR key, LPWSTR classn
|
|||
HKEY hkeyClass;
|
||||
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;
|
||||
if (!HCR_GetDefaultVerbW(hkeyClass, lpVerb, verb, ARRAY_SIZE(verb)))
|
||||
return SE_ERR_NOASSOC;
|
||||
RegCloseKey(hkeyClass);
|
||||
|
||||
/* 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, L"\\command");
|
||||
|
||||
|
@ -1361,48 +1374,21 @@ HINSTANCE WINAPI FindExecutableW(LPCWSTR lpFile, LPCWSTR lpDirectory, LPWSTR lpR
|
|||
/* FIXME: is this already implemented somewhere else? */
|
||||
static HKEY ShellExecute_GetClassKey(const SHELLEXECUTEINFOW *sei)
|
||||
{
|
||||
LPCWSTR ext = NULL, lpClass = NULL;
|
||||
CHeapPtr<WCHAR, CLocalAllocator> cls;
|
||||
DWORD type = 0, sz = 0;
|
||||
HKEY hkey = 0;
|
||||
LONG r;
|
||||
|
||||
if (sei->fMask & SEE_MASK_CLASSALL)
|
||||
if ((sei->fMask & SEE_MASK_CLASSALL) == SEE_MASK_CLASSKEY)
|
||||
return sei->hkeyClass;
|
||||
|
||||
HKEY hKey = NULL;
|
||||
if (sei->fMask & SEE_MASK_CLASSNAME)
|
||||
lpClass = sei->lpClass;
|
||||
else
|
||||
{
|
||||
ext = PathFindExtensionW(sei->lpFile);
|
||||
TRACE("ext = %s\n", debugstr_w(ext));
|
||||
if (!ext)
|
||||
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;
|
||||
TRACE("class = %s\n", debugstr_w(sei->lpClass));
|
||||
RegOpenKeyExW(HKEY_CLASSES_ROOT, sei->lpClass, 0, KEY_READ, &hKey);
|
||||
return hKey;
|
||||
}
|
||||
|
||||
TRACE("class = %s\n", debugstr_w(lpClass));
|
||||
|
||||
hkey = 0;
|
||||
if (lpClass)
|
||||
RegOpenKeyW( HKEY_CLASSES_ROOT, lpClass, &hkey);
|
||||
|
||||
return hkey;
|
||||
PCWSTR ext = PathFindExtensionW(sei->lpFile);
|
||||
TRACE("ext = %s\n", debugstr_w(ext));
|
||||
if (!StrIsNullOrEmpty(ext) && SUCCEEDED(HCR_GetProgIdKeyOfExtension(ext, &hKey, FALSE)))
|
||||
return hKey;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
@ -1680,7 +1666,7 @@ static LONG ShellExecute_FromContextMenuHandlers( LPSHELLEXECUTEINFOW sei )
|
|||
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)
|
||||
{
|
||||
|
@ -1905,7 +1891,7 @@ static UINT_PTR SHELL_execute_url(LPCWSTR lpFile, LPCWSTR wcmd, LPSHELLEXECUTEIN
|
|||
if (psei->lpVerb && *psei->lpVerb)
|
||||
len += lstrlenW(psei->lpVerb);
|
||||
else
|
||||
len += lstrlenW(L"open");
|
||||
len += lstrlenW(L"open"); // FIXME: Use HCR_GetExecuteCommandW or AssocAPI
|
||||
lpstrProtocol.Allocate(len);
|
||||
memcpy(lpstrProtocol, lpFile, iSize * sizeof(WCHAR));
|
||||
lpstrProtocol[iSize] = '\0';
|
||||
|
@ -1919,13 +1905,12 @@ static UINT_PTR SHELL_execute_url(LPCWSTR lpFile, LPCWSTR wcmd, LPSHELLEXECUTEIN
|
|||
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];
|
||||
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)
|
||||
LoadStringW(shell32_hInstance, IDS_SHLEXEC_NOASSOC, msg, ARRAY_SIZE(msg));
|
||||
else
|
||||
|
@ -1938,6 +1923,7 @@ static void do_error_dialog(UINT_PTR retval, HWND hwnd, WCHAR* filename)
|
|||
(va_list*)msgArguments);
|
||||
|
||||
MessageBoxW(hwnd, msg, NULL, MB_ICONERROR);
|
||||
SetLastError(error_code); // Restore
|
||||
}
|
||||
|
||||
static WCHAR *expand_environment( const WCHAR *str )
|
||||
|
@ -1971,6 +1957,7 @@ static BOOL SHELL_execute(LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc)
|
|||
BOOL appKnownSingular = FALSE;
|
||||
|
||||
/* make a local copy of the LPSHELLEXECUTEINFO structure and work with this from now on */
|
||||
sei->hProcess = NULL;
|
||||
SHELLEXECUTEINFOW sei_tmp = *sei;
|
||||
|
||||
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) ?
|
||||
debugstr_w(sei_tmp.lpClass) : "not used");
|
||||
|
||||
sei->hProcess = NULL;
|
||||
|
||||
/* make copies of all path/command strings */
|
||||
CHeapPtr<WCHAR, CLocalAllocator> wszApplicationName;
|
||||
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 */
|
||||
WCHAR lpstrTmpFile[256];
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -2338,18 +2324,10 @@ static BOOL SHELL_execute(LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc)
|
|||
|
||||
if (retval <= 32 && !(sei_tmp.fMask & SEE_MASK_FLAG_NO_UI))
|
||||
{
|
||||
OPENASINFO Info;
|
||||
|
||||
//FIXME
|
||||
// need full path
|
||||
|
||||
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);
|
||||
if (retval == SE_ERR_NOASSOC && !(sei->fMask & SEE_MASK_CLASSALL))
|
||||
retval = InvokeOpenWith(sei_tmp.hwnd, *sei);
|
||||
if (retval <= 32)
|
||||
do_error_dialog(retval, sei_tmp.hwnd, lpFile);
|
||||
}
|
||||
|
||||
sei->hInstApp = (HINSTANCE)(retval > 32 ? 33 : retval);
|
||||
|
@ -2393,7 +2371,11 @@ static DWORD
|
|||
ShellExecute_Normal(_Inout_ LPSHELLEXECUTEINFOW sei)
|
||||
{
|
||||
// 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
|
||||
|
@ -2592,14 +2574,8 @@ EXTERN_C HINSTANCE WINAPI WOWShellExecute(HWND hWnd, LPCSTR lpVerb, LPCSTR lpFil
|
|||
EXTERN_C void WINAPI
|
||||
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);
|
||||
|
||||
ZeroMemory(&info, sizeof(info));
|
||||
info.pcszFile = cmdline;
|
||||
info.pcszClass = NULL;
|
||||
info.oaifInFlags = OAIF_ALLOW_REGISTRATION | OAIF_REGISTER_EXT | OAIF_EXEC;
|
||||
|
||||
SHOpenWithDialog(hwnd, &info);
|
||||
}
|
||||
|
||||
|
@ -2700,7 +2676,7 @@ HRESULT WINAPI ShellExecCmdLine(
|
|||
if (dwSeclFlags & SECL_RUNAS)
|
||||
{
|
||||
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)
|
||||
{
|
||||
pszVerb = L"runas";
|
||||
|
|
|
@ -54,6 +54,20 @@ RegKeyExists(HKEY hKey, LPCWSTR Path)
|
|||
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
|
||||
RegSetOrDelete(HKEY hKey, LPCWSTR Name, DWORD Type, LPCVOID Data, DWORD Size)
|
||||
{
|
||||
|
|
|
@ -40,7 +40,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(shell);
|
|||
/* Default IQueryAssociations::Init() flags */
|
||||
#ifdef __REACTOS__
|
||||
#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
|
||||
#define SHLWAPI_DEF_ASSOCF (ASSOCF_INIT_BYEXENAME|ASSOCF_INIT_DEFAULTTOSTAR| \
|
||||
ASSOCF_INIT_DEFAULTTOFOLDER)
|
||||
|
@ -377,8 +378,12 @@ HRESULT WINAPI AssocQueryKeyW(ASSOCF cfFlags, ASSOCKEY assockey, LPCWSTR pszAsso
|
|||
hRet = AssocCreate( CLSID_QueryAssociations, &IID_IQueryAssociations, (void **)&lpAssoc );
|
||||
if (FAILED(hRet)) return hRet;
|
||||
|
||||
#ifdef __REACTOS__
|
||||
hRet = IQueryAssociations_Init(lpAssoc, cfFlags & SHLWAPI_DEF_ASSOCF, pszAssoc, NULL, NULL);
|
||||
#else
|
||||
cfFlags &= SHLWAPI_DEF_ASSOCF;
|
||||
hRet = IQueryAssociations_Init(lpAssoc, cfFlags, pszAssoc, NULL, NULL);
|
||||
#endif
|
||||
|
||||
if (SUCCEEDED(hRet))
|
||||
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 );
|
||||
if (FAILED(hRet)) return hRet;
|
||||
|
||||
#ifdef __REACTOS__
|
||||
hRet = IQueryAssociations_Init(lpAssoc, cfFlags & SHLWAPI_DEF_ASSOCF, 0, hkAssoc, NULL);
|
||||
#else
|
||||
cfFlags &= SHLWAPI_DEF_ASSOCF;
|
||||
hRet = IQueryAssociations_Init(lpAssoc, cfFlags, 0, hkAssoc, NULL);
|
||||
#endif
|
||||
|
||||
if (SUCCEEDED(hRet))
|
||||
hRet = IQueryAssociations_GetString(lpAssoc, cfFlags, str, pszExtra,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue