Nikolay Sivov : shlwapi: Partially implement SHGetObjectCompatFlags with tests.
Alexandre Julliard
julliard at winehq.org
Mon Mar 15 12:19:37 CDT 2010
Module: wine
Branch: master
Commit: 533f7558aa8de258b37a87b3faf21328acc201a4
URL: http://source.winehq.org/git/wine.git/?a=commit;h=533f7558aa8de258b37a87b3faf21328acc201a4
Author: Nikolay Sivov <nsivov at codeweavers.com>
Date: Fri Mar 12 02:16:00 2010 +0300
shlwapi: Partially implement SHGetObjectCompatFlags with tests.
---
dlls/shlwapi/ordinal.c | 124 ++++++++++++++++++++++++++++++++++++++++++
dlls/shlwapi/shlwapi.spec | 2 +-
dlls/shlwapi/tests/ordinal.c | 87 +++++++++++++++++++++++++++++
3 files changed, 212 insertions(+), 1 deletions(-)
diff --git a/dlls/shlwapi/ordinal.c b/dlls/shlwapi/ordinal.c
index 375ddaf..412dac1 100644
--- a/dlls/shlwapi/ordinal.c
+++ b/dlls/shlwapi/ordinal.c
@@ -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;
+}
diff --git a/dlls/shlwapi/shlwapi.spec b/dlls/shlwapi/shlwapi.spec
index 3091783..6047646 100644
--- a/dlls/shlwapi/shlwapi.spec
+++ b/dlls/shlwapi/shlwapi.spec
@@ -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)
diff --git a/dlls/shlwapi/tests/ordinal.c b/dlls/shlwapi/tests/ordinal.c
index 083934b..223aac4 100644
--- a/dlls/shlwapi/tests/ordinal.c
+++ b/dlls/shlwapi/tests/ordinal.c
@@ -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();
}
More information about the wine-cvs
mailing list