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