Francois Gouget : shell32: Fix computation of default verb.
Alexandre Julliard
julliard at wine.codeweavers.com
Mon Jun 26 07:12:21 CDT 2006
Module: wine
Branch: refs/heads/master
Commit: 9607151e38b4e6b24195907a664b2351919c2974
URL: http://source.winehq.org/git/?p=wine.git;a=commit;h=9607151e38b4e6b24195907a664b2351919c2974
Author: Francois Gouget <fgouget at 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);
More information about the wine-cvs
mailing list