shlwapi: Partially implement SHGetObjectCompatFlags with tests.
This commit is contained in:
parent
82a4b85424
commit
533f7558aa
|
@ -4854,3 +4854,127 @@ BOOL WINAPI SHPropertyBag_ReadLONG(IPropertyBag *ppb, LPCWSTR pszPropName, LPLON
|
|||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
/* return flags for SHGetObjectCompatFlags, names derived from registry value names */
|
||||
#define OBJCOMPAT_OTNEEDSSFCACHE 0x00000001
|
||||
#define OBJCOMPAT_NO_WEBVIEW 0x00000002
|
||||
#define OBJCOMPAT_UNBINDABLE 0x00000004
|
||||
#define OBJCOMPAT_PINDLL 0x00000008
|
||||
#define OBJCOMPAT_NEEDSFILESYSANCESTOR 0x00000010
|
||||
#define OBJCOMPAT_NOTAFILESYSTEM 0x00000020
|
||||
#define OBJCOMPAT_CTXMENU_NOVERBS 0x00000040
|
||||
#define OBJCOMPAT_CTXMENU_LIMITEDQI 0x00000080
|
||||
#define OBJCOMPAT_COCREATESHELLFOLDERONLY 0x00000100
|
||||
#define OBJCOMPAT_NEEDSSTORAGEANCESTOR 0x00000200
|
||||
#define OBJCOMPAT_NOLEGACYWEBVIEW 0x00000400
|
||||
#define OBJCOMPAT_CTXMENU_XPQCMFLAGS 0x00001000
|
||||
#define OBJCOMPAT_NOIPROPERTYSTORE 0x00002000
|
||||
|
||||
/* a search table for compatibility flags */
|
||||
struct objcompat_entry {
|
||||
const WCHAR name[30];
|
||||
DWORD value;
|
||||
};
|
||||
|
||||
/* expected to be sorted by name */
|
||||
static const struct objcompat_entry objcompat_table[] = {
|
||||
{ {'C','O','C','R','E','A','T','E','S','H','E','L','L','F','O','L','D','E','R','O','N','L','Y',0},
|
||||
OBJCOMPAT_COCREATESHELLFOLDERONLY },
|
||||
{ {'C','T','X','M','E','N','U','_','L','I','M','I','T','E','D','Q','I',0},
|
||||
OBJCOMPAT_CTXMENU_LIMITEDQI },
|
||||
{ {'C','T','X','M','E','N','U','_','N','O','V','E','R','B','S',0},
|
||||
OBJCOMPAT_CTXMENU_LIMITEDQI },
|
||||
{ {'C','T','X','M','E','N','U','_','X','P','Q','C','M','F','L','A','G','S',0},
|
||||
OBJCOMPAT_CTXMENU_XPQCMFLAGS },
|
||||
{ {'N','E','E','D','S','F','I','L','E','S','Y','S','A','N','C','E','S','T','O','R',0},
|
||||
OBJCOMPAT_NEEDSFILESYSANCESTOR },
|
||||
{ {'N','E','E','D','S','S','T','O','R','A','G','E','A','N','C','E','S','T','O','R',0},
|
||||
OBJCOMPAT_NEEDSSTORAGEANCESTOR },
|
||||
{ {'N','O','I','P','R','O','P','E','R','T','Y','S','T','O','R','E',0},
|
||||
OBJCOMPAT_NOIPROPERTYSTORE },
|
||||
{ {'N','O','L','E','G','A','C','Y','W','E','B','V','I','E','W',0},
|
||||
OBJCOMPAT_NOLEGACYWEBVIEW },
|
||||
{ {'N','O','T','A','F','I','L','E','S','Y','S','T','E','M',0},
|
||||
OBJCOMPAT_NOTAFILESYSTEM },
|
||||
{ {'N','O','_','W','E','B','V','I','E','W',0},
|
||||
OBJCOMPAT_NO_WEBVIEW },
|
||||
{ {'O','T','N','E','E','D','S','S','F','C','A','C','H','E',0},
|
||||
OBJCOMPAT_OTNEEDSSFCACHE },
|
||||
{ {'P','I','N','D','L','L',0},
|
||||
OBJCOMPAT_PINDLL },
|
||||
{ {'U','N','B','I','N','D','A','B','L','E',0},
|
||||
OBJCOMPAT_UNBINDABLE }
|
||||
};
|
||||
|
||||
/**************************************************************************
|
||||
* SHGetObjectCompatFlags (SHLWAPI.476)
|
||||
*
|
||||
* Function returns an integer representation of compatibility flags stored
|
||||
* in registry for CLSID under ShellCompatibility subkey.
|
||||
*
|
||||
* PARAMS
|
||||
* pUnk: pointer to object IUnknown interface, idetifies CLSID
|
||||
* clsid: pointer to CLSID to retrieve data for
|
||||
*
|
||||
* RETURNS
|
||||
* 0 on failure, flags set on success
|
||||
*/
|
||||
DWORD WINAPI SHGetObjectCompatFlags(IUnknown *pUnk, const CLSID *clsid)
|
||||
{
|
||||
static const WCHAR compatpathW[] =
|
||||
{'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
|
||||
'W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
|
||||
'S','h','e','l','l','C','o','m','p','a','t','i','b','i','l','i','t','y','\\',
|
||||
'O','b','j','e','c','t','s','\\','%','s',0};
|
||||
WCHAR strW[sizeof(compatpathW)/sizeof(WCHAR) + 38 /* { CLSID } */];
|
||||
DWORD ret, length = sizeof(strW)/sizeof(WCHAR);
|
||||
OLECHAR *clsid_str;
|
||||
HKEY key;
|
||||
INT i;
|
||||
|
||||
TRACE("%p %s\n", pUnk, debugstr_guid(clsid));
|
||||
|
||||
if (!pUnk && !clsid) return 0;
|
||||
|
||||
if (pUnk && !clsid)
|
||||
{
|
||||
FIXME("iface not handled\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
StringFromCLSID(clsid, &clsid_str);
|
||||
sprintfW(strW, compatpathW, clsid_str);
|
||||
CoTaskMemFree(clsid_str);
|
||||
|
||||
ret = RegOpenKeyW(HKEY_LOCAL_MACHINE, strW, &key);
|
||||
if (ret != ERROR_SUCCESS) return 0;
|
||||
|
||||
/* now collect flag values */
|
||||
ret = 0;
|
||||
for (i = 0; RegEnumValueW(key, i, strW, &length, NULL, NULL, NULL, NULL) == ERROR_SUCCESS; i++)
|
||||
{
|
||||
INT left, right, res, x;
|
||||
|
||||
/* search in table */
|
||||
left = 0;
|
||||
right = sizeof(objcompat_table) / sizeof(struct objcompat_entry) - 1;
|
||||
|
||||
while (right >= left) {
|
||||
x = (left + right) / 2;
|
||||
res = strcmpW(strW, objcompat_table[x].name);
|
||||
if (res == 0)
|
||||
{
|
||||
ret |= objcompat_table[x].value;
|
||||
break;
|
||||
}
|
||||
else if (res < 0)
|
||||
right = x - 1;
|
||||
else
|
||||
left = x + 1;
|
||||
}
|
||||
|
||||
length = sizeof(strW)/sizeof(WCHAR);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -473,7 +473,7 @@
|
|||
473 stub -noname SHGetIniStringUTF7W
|
||||
474 stub -noname SHSetIniStringUTF7W
|
||||
475 stdcall -noname GetShellSecurityDescriptor(ptr long)
|
||||
476 stub -noname SHGetObjectCompatFlags
|
||||
476 stdcall -noname SHGetObjectCompatFlags(ptr ptr)
|
||||
477 stub -noname SHCreatePropertyBagOnMemory
|
||||
478 stdcall -noname IUnknown_TranslateAcceleratorIO(ptr ptr)
|
||||
479 stdcall -noname IUnknown_UIActivateIO(ptr long ptr)
|
||||
|
|
|
@ -47,6 +47,8 @@ static HRESULT(WINAPI *pSHPropertyBag_ReadLONG)(IPropertyBag *,LPCWSTR,LPLONG);
|
|||
static LONG (WINAPI *pSHSetWindowBits)(HWND, INT, UINT, UINT);
|
||||
static INT (WINAPI *pSHFormatDateTimeA)(const FILETIME UNALIGNED*, DWORD*, LPSTR, UINT);
|
||||
static INT (WINAPI *pSHFormatDateTimeW)(const FILETIME UNALIGNED*, DWORD*, LPWSTR, UINT);
|
||||
static DWORD (WINAPI *pSHGetObjectCompatFlags)(IUnknown*, const CLSID*);
|
||||
static BOOL (WINAPI *pGUIDFromStringA)(LPSTR, CLSID *);
|
||||
|
||||
static HMODULE hmlang;
|
||||
static HRESULT (WINAPI *pLcidToRfc1766A)(LCID, LPSTR, INT);
|
||||
|
@ -1787,6 +1789,88 @@ if (0)
|
|||
ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
|
||||
}
|
||||
|
||||
static void test_SHGetObjectCompatFlags(void)
|
||||
{
|
||||
struct compat_value {
|
||||
CHAR nameA[30];
|
||||
DWORD value;
|
||||
};
|
||||
|
||||
struct compat_value values[] = {
|
||||
{ "OTNEEDSSFCACHE", 0x1 },
|
||||
{ "NO_WEBVIEW", 0x2 },
|
||||
{ "UNBINDABLE", 0x4 },
|
||||
{ "PINDLL", 0x8 },
|
||||
{ "NEEDSFILESYSANCESTOR", 0x10 },
|
||||
{ "NOTAFILESYSTEM", 0x20 },
|
||||
{ "CTXMENU_NOVERBS", 0x40 },
|
||||
{ "CTXMENU_LIMITEDQI", 0x80 },
|
||||
{ "COCREATESHELLFOLDERONLY", 0x100 },
|
||||
{ "NEEDSSTORAGEANCESTOR", 0x200 },
|
||||
{ "NOLEGACYWEBVIEW", 0x400 },
|
||||
{ "CTXMENU_XPQCMFLAGS", 0x1000 },
|
||||
{ "NOIPROPERTYSTORE", 0x2000 }
|
||||
};
|
||||
|
||||
static const char compat_path[] = "Software\\Microsoft\\Windows\\CurrentVersion\\ShellCompatibility\\Objects";
|
||||
CHAR keyA[39]; /* {CLSID} */
|
||||
HKEY root;
|
||||
DWORD ret;
|
||||
int i;
|
||||
|
||||
if (!pSHGetObjectCompatFlags)
|
||||
{
|
||||
win_skip("SHGetObjectCompatFlags isn't available\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* null args */
|
||||
ret = pSHGetObjectCompatFlags(NULL, NULL);
|
||||
ok(ret == 0, "got %d\n", ret);
|
||||
|
||||
ret = RegOpenKeyA(HKEY_LOCAL_MACHINE, compat_path, &root);
|
||||
if (ret != ERROR_SUCCESS)
|
||||
{
|
||||
skip("No compatibility class data found\n");
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; RegEnumKeyA(root, i, keyA, sizeof(keyA)) == ERROR_SUCCESS; i++)
|
||||
{
|
||||
HKEY clsid_key;
|
||||
|
||||
if (RegOpenKeyA(root, keyA, &clsid_key) == ERROR_SUCCESS)
|
||||
{
|
||||
CHAR valueA[30];
|
||||
DWORD expected = 0, got, length = sizeof(valueA);
|
||||
CLSID clsid;
|
||||
int v;
|
||||
|
||||
for (v = 0; RegEnumValueA(clsid_key, v, valueA, &length, NULL, NULL, NULL, NULL) == ERROR_SUCCESS; v++)
|
||||
{
|
||||
int j;
|
||||
|
||||
for (j = 0; j < sizeof(values)/sizeof(struct compat_value); j++)
|
||||
if (lstrcmpA(values[j].nameA, valueA) == 0)
|
||||
{
|
||||
expected |= values[j].value;
|
||||
break;
|
||||
}
|
||||
|
||||
length = sizeof(valueA);
|
||||
}
|
||||
|
||||
pGUIDFromStringA(keyA, &clsid);
|
||||
got = pSHGetObjectCompatFlags(NULL, &clsid);
|
||||
ok(got == expected, "got 0x%08x, expected 0x%08x. Key %s\n", got, expected, keyA);
|
||||
|
||||
RegCloseKey(clsid_key);
|
||||
}
|
||||
}
|
||||
|
||||
RegCloseKey(root);
|
||||
}
|
||||
|
||||
static void init_pointers(void)
|
||||
{
|
||||
#define MAKEFUNC(f, ord) (p##f = (void*)GetProcAddress(hShlwapi, (LPSTR)(ord)))
|
||||
|
@ -1798,11 +1882,13 @@ static void init_pointers(void)
|
|||
MAKEFUNC(SHSetWindowBits, 165);
|
||||
MAKEFUNC(ConnectToConnectionPoint, 168);
|
||||
MAKEFUNC(SHSearchMapInt, 198);
|
||||
MAKEFUNC(GUIDFromStringA, 269);
|
||||
MAKEFUNC(SHPackDispParams, 282);
|
||||
MAKEFUNC(IConnectionPoint_InvokeWithCancel, 283);
|
||||
MAKEFUNC(IConnectionPoint_SimpleInvoke, 284);
|
||||
MAKEFUNC(SHFormatDateTimeA, 353);
|
||||
MAKEFUNC(SHFormatDateTimeW, 354);
|
||||
MAKEFUNC(SHGetObjectCompatFlags, 476);
|
||||
MAKEFUNC(SHPropertyBag_ReadLONG, 496);
|
||||
#undef MAKEFUNC
|
||||
}
|
||||
|
@ -1827,4 +1913,5 @@ START_TEST(ordinal)
|
|||
test_SHSetWindowBits();
|
||||
test_SHFormatDateTimeA();
|
||||
test_SHFormatDateTimeW();
|
||||
test_SHGetObjectCompatFlags();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue