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.
This commit is contained in:
Francois Gouget 2006-06-23 18:32:38 +02:00 committed by Alexandre Julliard
parent 21668ad76a
commit 9607151e38
3 changed files with 86 additions and 26 deletions

View file

@ -117,30 +117,86 @@ BOOL HCR_MapTypeToValueA(LPCSTR szExtension, LPSTR szFileType, LONG len, BOOL bP
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)
return FALSE;
ret = FALSE;
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 (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;

View file

@ -57,6 +57,7 @@ INT SIC_GetIconIndex (LPCWSTR sSourceFile, INT dwSourceIndex, DWORD dwFlags );
/* 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);

View file

@ -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, LPCWSTR lpFile, LPCWSTR lpOperation,
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 sei, SHELL_ExecuteW32 execfunc )
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 sei, SHELL_ExecuteW32 execfunc )
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 sei, SHELL_ExecuteW32 execfunc )
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);