Module: wine Branch: refs/heads/master Commit: 9607151e38b4e6b24195907a664b2351919c2974 URL: http://source.winehq.org/git/?p=wine.git;a=commit;h=9607151e38b4e6b24195907a...
Author: Francois Gouget fgouget@codeweavers.com Date: Fri Jun 23 18:32:38 2006 +0200
shell32: Fix computation of default verb.
Compute the default verb as documented on MSDN instead of blindly assuming it is 'open'. This fixes the WordViewer association in some cases.
---
dlls/shell32/classes.c | 88 +++++++++++++++++++++++++++++++++++-------- dlls/shell32/shell32_main.h | 1 dlls/shell32/shlexec.c | 25 +++++++----- 3 files changed, 87 insertions(+), 27 deletions(-)
diff --git a/dlls/shell32/classes.c b/dlls/shell32/classes.c index eb9d9e9..f6db0dc 100644 --- a/dlls/shell32/classes.c +++ b/dlls/shell32/classes.c @@ -117,30 +117,86 @@ BOOL HCR_MapTypeToValueA(LPCSTR szExtens return TRUE; }
+static const WCHAR swShell[] = {'s','h','e','l','l','\',0}; +static const WCHAR swOpen[] = {'o','p','e','n',0}; +static const WCHAR swCommand[] = {'\','c','o','m','m','a','n','d',0}; + +BOOL HCR_GetDefaultVerbW( HKEY hkeyClass, LPCWSTR szVerb, LPWSTR szDest, DWORD len ) +{ + WCHAR sTemp[MAX_PATH]; + LONG size; + HKEY hkey; + + TRACE("%p %s %p\n", hkeyClass, debugstr_w(szVerb), szDest); + + if (szVerb) + { + lstrcpynW(szDest, szVerb, len); + return TRUE; + } + + size=len; + *szDest='\0'; + if (!RegQueryValueW(hkeyClass, swShell, szDest, &size) && *szDest) + { + /* The MSDN says to first try the default verb */ + lstrcpyW(sTemp, swShell); + lstrcatW(sTemp, szDest); + lstrcatW(sTemp, swCommand); + if (!RegOpenKeyExW(hkeyClass, sTemp, 0, 0, &hkey)) + { + RegCloseKey(hkey); + TRACE("default verb=%s\n", debugstr_w(szDest)); + return TRUE; + } + } + + /* then fallback to 'open' */ + lstrcpyW(sTemp, swShell); + lstrcatW(sTemp, swOpen); + lstrcatW(sTemp, swCommand); + if (!RegOpenKeyExW(hkeyClass, sTemp, 0, 0, &hkey)) + { + RegCloseKey(hkey); + lstrcpynW(szDest, swOpen, len); + TRACE("default verb=open\n"); + return TRUE; + } + + /* and then just use the first verb on Windows >= 2000 */ + if (!RegEnumKeyW(hkeyClass, 0, szDest, len) && *szDest) + { + TRACE("default verb=first verb=%s\n", debugstr_w(szDest)); + return TRUE; + } + + TRACE("no default verb!\n"); + return FALSE; +}
BOOL HCR_GetExecuteCommandW( HKEY hkeyClass, LPCWSTR szClass, LPCWSTR szVerb, LPWSTR szDest, DWORD len ) { - static const WCHAR swShell[] = {'s','h','e','l','l','\',0}; - static const WCHAR swCommand[] = {'\','c','o','m','m','a','n','d',0}; - BOOL ret = FALSE; + WCHAR sTempVerb[MAX_PATH]; + BOOL ret;
TRACE("%p %s %s %p\n", hkeyClass, debugstr_w(szClass), debugstr_w(szVerb), szDest);
if (szClass) RegOpenKeyExW(HKEY_CLASSES_ROOT, szClass, 0, 0x02000000, &hkeyClass); - - if (hkeyClass) - { - WCHAR sTemp[MAX_PATH]; - lstrcpyW(sTemp, swShell); - lstrcatW(sTemp, szVerb); - lstrcatW(sTemp, swCommand); - - ret = (ERROR_SUCCESS == SHGetValueW(hkeyClass, sTemp, NULL, NULL, szDest, &len)); - - if (szClass) - RegCloseKey(hkeyClass); - } + if (!hkeyClass) + return FALSE; + ret = FALSE; + + if (HCR_GetDefaultVerbW(hkeyClass, szVerb, sTempVerb, sizeof(sTempVerb))) + { + WCHAR sTemp[MAX_PATH]; + lstrcpyW(sTemp, swShell); + lstrcatW(sTemp, sTempVerb); + lstrcatW(sTemp, swCommand); + ret = (ERROR_SUCCESS == SHGetValueW(hkeyClass, sTemp, NULL, NULL, szDest, &len)); + } + if (szClass) + RegCloseKey(hkeyClass);
TRACE("-- %s\n", debugstr_w(szDest) ); return ret; diff --git a/dlls/shell32/shell32_main.h b/dlls/shell32/shell32_main.h index 32d002f..e13c850 100644 --- a/dlls/shell32/shell32_main.h +++ b/dlls/shell32/shell32_main.h @@ -57,6 +57,7 @@ INT SIC_GetIconIndex (LPCWSTR sSourceFil
/* Classes Root */ BOOL HCR_MapTypeToValueW(LPCWSTR szExtension, LPWSTR szFileType, LONG len, BOOL bPrependDot); +BOOL HCR_GetDefaultVerbW( HKEY hkeyClass, LPCWSTR szVerb, LPWSTR szDest, DWORD len ); BOOL HCR_GetExecuteCommandW( HKEY hkeyClass, LPCWSTR szClass, LPCWSTR szVerb, LPWSTR szDest, DWORD len ); BOOL HCR_GetDefaultIconW(LPCWSTR szClass, LPWSTR szDest, DWORD len, int* picon_idx); BOOL HCR_GetDefaultIconFromGUIDW(REFIID riid, LPWSTR szDest, DWORD len, int* picon_idx); diff --git a/dlls/shell32/shlexec.c b/dlls/shell32/shlexec.c index f626b1d..955f323 100644 --- a/dlls/shell32/shlexec.c +++ b/dlls/shell32/shlexec.c @@ -426,10 +426,18 @@ end: static UINT SHELL_FindExecutableByOperation(LPCWSTR lpPath, LPCWSTR lpFile, LPCWSTR lpOperation, LPWSTR key, LPWSTR filetype, LPWSTR command, LONG commandlen) { static const WCHAR wCommand[] = {'\','c','o','m','m','a','n','d',0}; + HKEY hkeyClass; + WCHAR verb[MAX_PATH]; + + if (RegOpenKeyExW(HKEY_CLASSES_ROOT, filetype, 0, 0x02000000, &hkeyClass)) + return 31; /* default - 'No association was found' */ + if (!HCR_GetDefaultVerbW(hkeyClass, lpOperation, verb, sizeof(verb))) + return 31; /* default - 'No association was found' */ + RegCloseKey(hkeyClass);
/* Looking for ...buffer\shell<verb>\command */ strcatW(filetype, wszShell); - strcatW(filetype, lpOperation); + strcatW(filetype, verb); strcatW(filetype, wCommand);
if (RegQueryValueW(HKEY_CLASSES_ROOT, filetype, command, @@ -508,10 +516,10 @@ UINT SHELL_FindExecutable(LPCWSTR lpPath if (key) *key = '\0';
/* trap NULL parameters on entry */ - if ((lpFile == NULL) || (lpResult == NULL) || (lpOperation == NULL)) + if ((lpFile == NULL) || (lpResult == NULL)) { - WARN("(lpFile=%s,lpResult=%s,lpOperation=%s): NULL parameter\n", - debugstr_w(lpFile), debugstr_w(lpOperation), debugstr_w(lpResult)); + WARN("(lpFile=%s,lpResult=%s): NULL parameter\n", + debugstr_w(lpFile), debugstr_w(lpResult)); return 2; /* File not found. Close enough, I guess. */ }
@@ -1292,7 +1300,7 @@ BOOL SHELL_execute( LPSHELLEXECUTEINFOW ULONG cmask=(sei_tmp.fMask & SEE_MASK_CLASSALL); HCR_GetExecuteCommandW((cmask == SEE_MASK_CLASSKEY) ? sei_tmp.hkeyClass : NULL, (cmask == SEE_MASK_CLASSNAME) ? sei_tmp.lpClass: NULL, - (sei_tmp.lpVerb) ? sei_tmp.lpVerb : wszOpen, + sei_tmp.lpVerb, wszParameters, sizeof(wszParameters)/sizeof(WCHAR));
/* FIXME: get the extension of lpFile, check if it fits to the lpClass */ @@ -1332,7 +1340,7 @@ BOOL SHELL_execute( LPSHELLEXECUTEINFOW if (attribs != INVALID_FILE_ATTRIBUTES && (attribs & FILE_ATTRIBUTE_DIRECTORY) && HCR_GetExecuteCommandW(0, wszFolder, - sei_tmp.lpVerb?sei_tmp.lpVerb:wszOpen, + sei_tmp.lpVerb, buffer, sizeof(buffer))) { SHELL_ArgifyW(wszApplicationName, dwApplicationNameLen, buffer, target, sei_tmp.lpIDList, NULL); @@ -1427,11 +1435,6 @@ BOOL SHELL_execute( LPSHELLEXECUTEINFOW strcatW(wcmd, wszParameters); }
- /* We set the default to open, and that should generally work. - But that is not really the way the MS docs say to do it. */ - if (!sei_tmp.lpVerb) - sei_tmp.lpVerb = wszOpen; - retval = execfunc(wcmd, NULL, FALSE, &sei_tmp, sei); if (retval > 32) { HeapFree(GetProcessHeap(), 0, wszApplicationName);