Commit 9607151e authored by Francois Gouget's avatar Francois Gouget Committed by Alexandre Julliard

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.
parent 21668ad7
...@@ -117,30 +117,86 @@ BOOL HCR_MapTypeToValueA(LPCSTR szExtension, LPSTR szFileType, LONG len, BOOL bP ...@@ -117,30 +117,86 @@ BOOL HCR_MapTypeToValueA(LPCSTR szExtension, LPSTR szFileType, LONG len, BOOL bP
return TRUE; 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 ) BOOL HCR_GetExecuteCommandW( HKEY hkeyClass, LPCWSTR szClass, LPCWSTR szVerb, LPWSTR szDest, DWORD len )
{ {
static const WCHAR swShell[] = {'s','h','e','l','l','\\',0}; WCHAR sTempVerb[MAX_PATH];
static const WCHAR swCommand[] = {'\\','c','o','m','m','a','n','d',0}; BOOL ret;
BOOL ret = FALSE;
TRACE("%p %s %s %p\n", hkeyClass, debugstr_w(szClass), debugstr_w(szVerb), szDest); TRACE("%p %s %s %p\n", hkeyClass, debugstr_w(szClass), debugstr_w(szVerb), szDest);
if (szClass) if (szClass)
RegOpenKeyExW(HKEY_CLASSES_ROOT, szClass, 0, 0x02000000, &hkeyClass); RegOpenKeyExW(HKEY_CLASSES_ROOT, szClass, 0, 0x02000000, &hkeyClass);
if (!hkeyClass)
return FALSE;
ret = FALSE;
if (hkeyClass) if (HCR_GetDefaultVerbW(hkeyClass, szVerb, sTempVerb, sizeof(sTempVerb)))
{ {
WCHAR sTemp[MAX_PATH]; WCHAR sTemp[MAX_PATH];
lstrcpyW(sTemp, swShell); lstrcpyW(sTemp, swShell);
lstrcatW(sTemp, szVerb); lstrcatW(sTemp, sTempVerb);
lstrcatW(sTemp, swCommand); lstrcatW(sTemp, swCommand);
ret = (ERROR_SUCCESS == SHGetValueW(hkeyClass, sTemp, NULL, NULL, szDest, &len)); ret = (ERROR_SUCCESS == SHGetValueW(hkeyClass, sTemp, NULL, NULL, szDest, &len));
}
if (szClass) if (szClass)
RegCloseKey(hkeyClass); RegCloseKey(hkeyClass);
}
TRACE("-- %s\n", debugstr_w(szDest) ); TRACE("-- %s\n", debugstr_w(szDest) );
return ret; return ret;
......
...@@ -57,6 +57,7 @@ INT SIC_GetIconIndex (LPCWSTR sSourceFile, INT dwSourceIndex, DWORD dwFlags ); ...@@ -57,6 +57,7 @@ INT SIC_GetIconIndex (LPCWSTR sSourceFile, INT dwSourceIndex, DWORD dwFlags );
/* Classes Root */ /* Classes Root */
BOOL HCR_MapTypeToValueW(LPCWSTR szExtension, LPWSTR szFileType, LONG len, BOOL bPrependDot); 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_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_GetDefaultIconW(LPCWSTR szClass, LPWSTR szDest, DWORD len, int* picon_idx);
BOOL HCR_GetDefaultIconFromGUIDW(REFIID riid, LPWSTR szDest, DWORD len, int* picon_idx); BOOL HCR_GetDefaultIconFromGUIDW(REFIID riid, LPWSTR szDest, DWORD len, int* picon_idx);
......
...@@ -426,10 +426,18 @@ end: ...@@ -426,10 +426,18 @@ end:
static UINT SHELL_FindExecutableByOperation(LPCWSTR lpPath, LPCWSTR lpFile, LPCWSTR lpOperation, LPWSTR key, LPWSTR filetype, LPWSTR command, LONG commandlen) 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}; 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 */ /* Looking for ...buffer\shell\<verb>\command */
strcatW(filetype, wszShell); strcatW(filetype, wszShell);
strcatW(filetype, lpOperation); strcatW(filetype, verb);
strcatW(filetype, wCommand); strcatW(filetype, wCommand);
if (RegQueryValueW(HKEY_CLASSES_ROOT, filetype, command, if (RegQueryValueW(HKEY_CLASSES_ROOT, filetype, command,
...@@ -508,10 +516,10 @@ UINT SHELL_FindExecutable(LPCWSTR lpPath, LPCWSTR lpFile, LPCWSTR lpOperation, ...@@ -508,10 +516,10 @@ UINT SHELL_FindExecutable(LPCWSTR lpPath, LPCWSTR lpFile, LPCWSTR lpOperation,
if (key) *key = '\0'; if (key) *key = '\0';
/* trap NULL parameters on entry */ /* 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", WARN("(lpFile=%s,lpResult=%s): NULL parameter\n",
debugstr_w(lpFile), debugstr_w(lpOperation), debugstr_w(lpResult)); debugstr_w(lpFile), debugstr_w(lpResult));
return 2; /* File not found. Close enough, I guess. */ return 2; /* File not found. Close enough, I guess. */
} }
...@@ -1292,7 +1300,7 @@ BOOL SHELL_execute( LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc ) ...@@ -1292,7 +1300,7 @@ BOOL SHELL_execute( LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc )
ULONG cmask=(sei_tmp.fMask & SEE_MASK_CLASSALL); ULONG cmask=(sei_tmp.fMask & SEE_MASK_CLASSALL);
HCR_GetExecuteCommandW((cmask == SEE_MASK_CLASSKEY) ? sei_tmp.hkeyClass : NULL, HCR_GetExecuteCommandW((cmask == SEE_MASK_CLASSKEY) ? sei_tmp.hkeyClass : NULL,
(cmask == SEE_MASK_CLASSNAME) ? sei_tmp.lpClass: NULL, (cmask == SEE_MASK_CLASSNAME) ? sei_tmp.lpClass: NULL,
(sei_tmp.lpVerb) ? sei_tmp.lpVerb : wszOpen, sei_tmp.lpVerb,
wszParameters, sizeof(wszParameters)/sizeof(WCHAR)); wszParameters, sizeof(wszParameters)/sizeof(WCHAR));
/* FIXME: get the extension of lpFile, check if it fits to the lpClass */ /* FIXME: get the extension of lpFile, check if it fits to the lpClass */
...@@ -1332,7 +1340,7 @@ BOOL SHELL_execute( LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc ) ...@@ -1332,7 +1340,7 @@ BOOL SHELL_execute( LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc )
if (attribs != INVALID_FILE_ATTRIBUTES && if (attribs != INVALID_FILE_ATTRIBUTES &&
(attribs & FILE_ATTRIBUTE_DIRECTORY) && (attribs & FILE_ATTRIBUTE_DIRECTORY) &&
HCR_GetExecuteCommandW(0, wszFolder, HCR_GetExecuteCommandW(0, wszFolder,
sei_tmp.lpVerb?sei_tmp.lpVerb:wszOpen, sei_tmp.lpVerb,
buffer, sizeof(buffer))) { buffer, sizeof(buffer))) {
SHELL_ArgifyW(wszApplicationName, dwApplicationNameLen, SHELL_ArgifyW(wszApplicationName, dwApplicationNameLen,
buffer, target, sei_tmp.lpIDList, NULL); buffer, target, sei_tmp.lpIDList, NULL);
...@@ -1427,11 +1435,6 @@ BOOL SHELL_execute( LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc ) ...@@ -1427,11 +1435,6 @@ BOOL SHELL_execute( LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc )
strcatW(wcmd, wszParameters); 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); retval = execfunc(wcmd, NULL, FALSE, &sei_tmp, sei);
if (retval > 32) { if (retval > 32) {
HeapFree(GetProcessHeap(), 0, wszApplicationName); HeapFree(GetProcessHeap(), 0, wszApplicationName);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment