From deda2a5bb3b681825c9366574a7d7561600043c7 Mon Sep 17 00:00:00 2001
From: Mark Jansen <learn0more@gmail.com>
Date: Sat, 2 May 2015 13:47:30 +0200
Subject: shlwapi/tests: Add tests for AssocGetPerceivedType.

---
 dlls/shlwapi/assoc.c       |   7 +-
 dlls/shlwapi/tests/assoc.c | 283 ++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 284 insertions(+), 6 deletions(-)

diff --git a/dlls/shlwapi/assoc.c b/dlls/shlwapi/assoc.c
index 3156990..62c101d 100644
--- a/dlls/shlwapi/assoc.c
+++ b/dlls/shlwapi/assoc.c
@@ -132,10 +132,9 @@ HRESULT WINAPI AssocGetPerceivedType(LPCWSTR lpszExt, PERCEIVED *lpType,
 {
   FIXME("(%s, %p, %p, %p) not supported\n", debugstr_w(lpszExt), lpType, lpFlag, lppszType);
 
-  if (lpszExt == NULL)
-    return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
-
-  return E_NOTIMPL;
+  if (lpType) *lpType = PERCEIVED_TYPE_UNSPECIFIED;
+  if (lpFlag) *lpFlag = PERCEIVEDFLAG_UNDEFINED;
+  return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
 }
 
 /*************************************************************************
diff --git a/dlls/shlwapi/tests/assoc.c b/dlls/shlwapi/tests/assoc.c
index cbc40ce..2b4e0ad 100644
--- a/dlls/shlwapi/tests/assoc.c
+++ b/dlls/shlwapi/tests/assoc.c
@@ -23,12 +23,13 @@
 #include "shlwapi.h"
 #include "shlguid.h"
 
-#define expect(expected, got) ok ( expected == got, "Expected %d, got %d\n", expected, got)
-#define expect_hr(expected, got) ok ( expected == got, "Expected %08x, got %08x\n", expected, got)
+#define expect(expected, got) ok( (expected) == (got), "Expected %d, got %d\n", (expected), (got))
+#define expect_hr(expected, got) ok( (expected) == (got), "Expected %08x, got %08x\n", (expected), (got))
 
 static HRESULT (WINAPI *pAssocQueryStringA)(ASSOCF,ASSOCSTR,LPCSTR,LPCSTR,LPSTR,LPDWORD) = NULL;
 static HRESULT (WINAPI *pAssocQueryStringW)(ASSOCF,ASSOCSTR,LPCWSTR,LPCWSTR,LPWSTR,LPDWORD) = NULL;
 static HRESULT (WINAPI *pAssocCreate)(CLSID, REFIID, void **) = NULL;
+static HRESULT (WINAPI *pAssocGetPerceivedType)(LPCWSTR, PERCEIVED *, INT *, LPWSTR *) = NULL;
 
 /* Every version of Windows with IE should have this association? */
 static const WCHAR dotHtml[] = { '.','h','t','m','l',0 };
@@ -304,6 +305,282 @@ static void test_assoc_create(void)
     }
 }
 
+/* Based on http://www.geoffchappell.com/studies/windows/shell/shlwapi/api/assocapi/getperceivedtype.htm */
+struct assoc_test_struct
+{
+    PCSTR     extension;
+    PERCEIVED perceived;
+    INT       flags;
+    PCSTR     type;
+    DWORD     minversion;
+    HRESULT   hr;
+};
+
+#define HARDCODED_NATIVE_WMSDK      (PERCEIVEDFLAG_HARDCODED | PERCEIVEDFLAG_NATIVESUPPORT | PERCEIVEDFLAG_WMSDK)
+#define HARDCODED_NATIVE_GDIPLUS    (PERCEIVEDFLAG_HARDCODED | PERCEIVEDFLAG_NATIVESUPPORT | PERCEIVEDFLAG_GDIPLUS)
+#define HARDCODED_NATIVE_ZIPFLDR    (PERCEIVEDFLAG_HARDCODED | PERCEIVEDFLAG_NATIVESUPPORT | PERCEIVEDFLAG_ZIPFOLDER)
+#define SOFTCODED_NATIVESUPPORT     (PERCEIVEDFLAG_SOFTCODED | PERCEIVEDFLAG_NATIVESUPPORT)
+
+static const struct assoc_test_struct assoc_perceived_types[] =
+{
+    /* builtins */
+    { ".aif",           PERCEIVED_TYPE_AUDIO,       HARDCODED_NATIVE_WMSDK,     "audio" },
+    { ".aifc",          PERCEIVED_TYPE_AUDIO,       HARDCODED_NATIVE_WMSDK,     "audio" },
+    { ".aiff",          PERCEIVED_TYPE_AUDIO,       HARDCODED_NATIVE_WMSDK,     "audio" },
+    { ".asf",           PERCEIVED_TYPE_VIDEO,       HARDCODED_NATIVE_WMSDK,     "video" },
+    { ".asx",           PERCEIVED_TYPE_VIDEO,       HARDCODED_NATIVE_WMSDK,     "video" },
+    { ".au",            PERCEIVED_TYPE_AUDIO,       HARDCODED_NATIVE_WMSDK,     "audio" },
+    { ".avi",           PERCEIVED_TYPE_VIDEO,       HARDCODED_NATIVE_WMSDK,     "video" },
+    { ".bas",           PERCEIVED_TYPE_APPLICATION, PERCEIVEDFLAG_HARDCODED,    "application" },
+    { ".bat",           PERCEIVED_TYPE_APPLICATION, PERCEIVEDFLAG_HARDCODED,    "application" },
+    { ".bmp",           PERCEIVED_TYPE_IMAGE,       HARDCODED_NATIVE_GDIPLUS,   "image" },
+    { ".cmd",           PERCEIVED_TYPE_APPLICATION, PERCEIVEDFLAG_HARDCODED,    "application" },
+    { ".com",           PERCEIVED_TYPE_APPLICATION, PERCEIVEDFLAG_HARDCODED,    "application" },
+    { ".cpl",           PERCEIVED_TYPE_SYSTEM,      PERCEIVEDFLAG_HARDCODED,    "system",       0x600 },
+    { ".dib",           PERCEIVED_TYPE_IMAGE,       HARDCODED_NATIVE_GDIPLUS,   "image" },
+    { ".dvr-ms",        PERCEIVED_TYPE_VIDEO,       HARDCODED_NATIVE_WMSDK,     "video" },
+    { ".emf",           PERCEIVED_TYPE_IMAGE,       HARDCODED_NATIVE_GDIPLUS,   "image" },
+    { ".exe",           PERCEIVED_TYPE_APPLICATION, PERCEIVEDFLAG_HARDCODED,    "application" },
+    { ".gif",           PERCEIVED_TYPE_IMAGE,       HARDCODED_NATIVE_GDIPLUS,   "image" },
+    { ".hta",           PERCEIVED_TYPE_APPLICATION, PERCEIVEDFLAG_HARDCODED,    "application" },
+    /* htm & html are PERCEIVED_TYPE_TEXT, PERCEIVEDFLAG_NATIVESUPPORT | PERCEIVEDFLAG_SOFTCODED in w2k3 */
+    { ".htm",           PERCEIVED_TYPE_DOCUMENT,    PERCEIVEDFLAG_HARDCODED,    "document",     0x600 },
+    { ".html",          PERCEIVED_TYPE_DOCUMENT,    PERCEIVEDFLAG_HARDCODED,    "document",     0x600 },
+    { ".ico",           PERCEIVED_TYPE_IMAGE,       HARDCODED_NATIVE_GDIPLUS,   "image" },
+    { ".IVF",           PERCEIVED_TYPE_VIDEO,       HARDCODED_NATIVE_WMSDK,     "video" },
+    { ".jfif",          PERCEIVED_TYPE_IMAGE,       HARDCODED_NATIVE_GDIPLUS,   "image" },
+    { ".jpe",           PERCEIVED_TYPE_IMAGE,       HARDCODED_NATIVE_GDIPLUS,   "image" },
+    { ".jpeg",          PERCEIVED_TYPE_IMAGE,       HARDCODED_NATIVE_GDIPLUS,   "image" },
+    { ".jpg",           PERCEIVED_TYPE_IMAGE,       HARDCODED_NATIVE_GDIPLUS,   "image" },
+    { ".lnk",           PERCEIVED_TYPE_UNSPECIFIED, PERCEIVEDFLAG_HARDCODED,    NULL,           0x600, E_FAIL },
+    { ".m1v",           PERCEIVED_TYPE_VIDEO,       HARDCODED_NATIVE_WMSDK,     "video" },
+    { ".m3u",           PERCEIVED_TYPE_AUDIO,       HARDCODED_NATIVE_WMSDK,     "audio" },
+    { ".mht",           PERCEIVED_TYPE_DOCUMENT,    PERCEIVEDFLAG_HARDCODED,    "document",     0x600 },
+    { ".mid",           PERCEIVED_TYPE_AUDIO,       HARDCODED_NATIVE_WMSDK,     "audio" },
+    { ".midi",          PERCEIVED_TYPE_AUDIO,       HARDCODED_NATIVE_WMSDK,     "audio" },
+    { ".msi",           PERCEIVED_TYPE_APPLICATION, PERCEIVEDFLAG_HARDCODED,    "application" },
+    /* below win8 this is defined to be video */
+    { ".mp2",           PERCEIVED_TYPE_AUDIO,       HARDCODED_NATIVE_WMSDK,     "audio",        0x602 },
+    { ".mp2v",          PERCEIVED_TYPE_VIDEO,       HARDCODED_NATIVE_WMSDK,     "video" },
+    { ".mp3",           PERCEIVED_TYPE_AUDIO,       HARDCODED_NATIVE_WMSDK,     "audio" },
+    { ".mpa",           PERCEIVED_TYPE_VIDEO,       HARDCODED_NATIVE_WMSDK,     "video" },
+    { ".mpe",           PERCEIVED_TYPE_VIDEO,       HARDCODED_NATIVE_WMSDK,     "video" },
+    { ".mpeg",          PERCEIVED_TYPE_VIDEO,       HARDCODED_NATIVE_WMSDK,     "video" },
+    { ".mpg",           PERCEIVED_TYPE_VIDEO,       HARDCODED_NATIVE_WMSDK,     "video" },
+    { ".mpv2",          PERCEIVED_TYPE_VIDEO,       HARDCODED_NATIVE_WMSDK,     "video" },
+    { ".pif",           PERCEIVED_TYPE_APPLICATION, PERCEIVEDFLAG_HARDCODED,    "application" },
+    { ".png",           PERCEIVED_TYPE_IMAGE,       HARDCODED_NATIVE_GDIPLUS,   "image" },
+    { ".reg",           PERCEIVED_TYPE_APPLICATION, PERCEIVEDFLAG_HARDCODED,    "application" },
+    { ".rle",           PERCEIVED_TYPE_IMAGE,       HARDCODED_NATIVE_GDIPLUS,   "image" },
+    { ".rmi",           PERCEIVED_TYPE_AUDIO,       HARDCODED_NATIVE_WMSDK,     "audio" },
+    { ".scr",           PERCEIVED_TYPE_APPLICATION, PERCEIVEDFLAG_HARDCODED,    "application" },
+    { ".search-ms",     PERCEIVED_TYPE_UNSPECIFIED, PERCEIVEDFLAG_HARDCODED,    NULL,           0x600, E_FAIL },
+    { ".snd",           PERCEIVED_TYPE_AUDIO,       HARDCODED_NATIVE_WMSDK,     "audio" },
+    { ".tif",           PERCEIVED_TYPE_IMAGE,       HARDCODED_NATIVE_GDIPLUS,   "image" },
+    { ".tiff",          PERCEIVED_TYPE_IMAGE,       HARDCODED_NATIVE_GDIPLUS,   "image" },
+    { ".vb",            PERCEIVED_TYPE_APPLICATION, PERCEIVEDFLAG_HARDCODED,    "application" },
+    { ".wav",           PERCEIVED_TYPE_AUDIO,       HARDCODED_NATIVE_WMSDK,     "audio" },
+    { ".wax",           PERCEIVED_TYPE_AUDIO,       HARDCODED_NATIVE_WMSDK,     "audio" },
+    { ".wm",            PERCEIVED_TYPE_VIDEO,       HARDCODED_NATIVE_WMSDK,     "video" },
+    { ".wma",           PERCEIVED_TYPE_AUDIO,       HARDCODED_NATIVE_WMSDK,     "audio" },
+    { ".wmf",           PERCEIVED_TYPE_IMAGE,       HARDCODED_NATIVE_GDIPLUS,   "image" },
+    { ".wmv",           PERCEIVED_TYPE_VIDEO,       HARDCODED_NATIVE_WMSDK,     "video" },
+    { ".wmx",           PERCEIVED_TYPE_VIDEO,       HARDCODED_NATIVE_WMSDK,     "video" },
+    { ".wvx",           PERCEIVED_TYPE_VIDEO,       HARDCODED_NATIVE_WMSDK,     "video" },
+    { ".zip",           PERCEIVED_TYPE_COMPRESSED,  HARDCODED_NATIVE_ZIPFLDR,   "compressed" },
+    /* found in the registry under HKEY_CLASSES_ROOT on a new Win7 VM */
+    { ".386",           PERCEIVED_TYPE_SYSTEM,      PERCEIVEDFLAG_SOFTCODED,    "system" },
+    { ".3g2",           PERCEIVED_TYPE_VIDEO,       PERCEIVEDFLAG_SOFTCODED,    "video",        0x601 },
+    { ".3gp",           PERCEIVED_TYPE_VIDEO,       PERCEIVEDFLAG_SOFTCODED,    "video",        0x601 },
+    { ".3gp2",          PERCEIVED_TYPE_VIDEO,       PERCEIVEDFLAG_SOFTCODED,    "video",        0x601 },
+    { ".3gpp",          PERCEIVED_TYPE_VIDEO,       PERCEIVEDFLAG_SOFTCODED,    "video",        0x601 },
+    { ".AAC",           PERCEIVED_TYPE_AUDIO,       PERCEIVEDFLAG_SOFTCODED,    "audio",        0x601 },
+    { ".ADT",           PERCEIVED_TYPE_AUDIO,       PERCEIVEDFLAG_SOFTCODED,    "audio",        0x601 },
+    { ".ADTS",          PERCEIVED_TYPE_AUDIO,       PERCEIVEDFLAG_SOFTCODED,    "audio",        0x601 },
+    { ".asm",           PERCEIVED_TYPE_TEXT,        SOFTCODED_NATIVESUPPORT,    "text" },
+    { ".asmx",          PERCEIVED_TYPE_TEXT,        SOFTCODED_NATIVESUPPORT,    "text" },
+    { ".aspx",          PERCEIVED_TYPE_TEXT,        SOFTCODED_NATIVESUPPORT,    "text" },
+    { ".c",             PERCEIVED_TYPE_TEXT,        SOFTCODED_NATIVESUPPORT,    "text" },
+    { ".cab",           PERCEIVED_TYPE_COMPRESSED,  PERCEIVEDFLAG_SOFTCODED,    "compressed",   0x600 },
+    { ".chk",           PERCEIVED_TYPE_SYSTEM,      PERCEIVEDFLAG_SOFTCODED,    "system" },
+    { ".cpp",           PERCEIVED_TYPE_TEXT,        SOFTCODED_NATIVESUPPORT,    "text" },
+    { ".css",           PERCEIVED_TYPE_TEXT,        SOFTCODED_NATIVESUPPORT,    "text" },
+    { ".cxx",           PERCEIVED_TYPE_TEXT,        SOFTCODED_NATIVESUPPORT,    "text" },
+    { ".def",           PERCEIVED_TYPE_TEXT,        SOFTCODED_NATIVESUPPORT,    "text" },
+    { ".diz",           PERCEIVED_TYPE_TEXT,        SOFTCODED_NATIVESUPPORT,    "text" },
+    { ".docx",          PERCEIVED_TYPE_DOCUMENT,    PERCEIVEDFLAG_SOFTCODED,    "document",     0x601 },
+    { ".drv",           PERCEIVED_TYPE_SYSTEM,      PERCEIVEDFLAG_SOFTCODED,    "system",       0x600 },
+    { ".gz",            PERCEIVED_TYPE_COMPRESSED,  PERCEIVEDFLAG_SOFTCODED,    "compressed" },
+    { ".h",             PERCEIVED_TYPE_TEXT,        SOFTCODED_NATIVESUPPORT,    "text" },
+    { ".hpp",           PERCEIVED_TYPE_TEXT,        SOFTCODED_NATIVESUPPORT,    "text" },
+    { ".hxx",           PERCEIVED_TYPE_TEXT,        SOFTCODED_NATIVESUPPORT,    "text" },
+    { ".inc",           PERCEIVED_TYPE_TEXT,        SOFTCODED_NATIVESUPPORT,    "text" },
+    { ".ini",           PERCEIVED_TYPE_TEXT,        SOFTCODED_NATIVESUPPORT,    "text",         0x600 },
+    { ".java",          PERCEIVED_TYPE_TEXT,        SOFTCODED_NATIVESUPPORT,    "text" },
+    { ".local",         PERCEIVED_TYPE_SYSTEM,      PERCEIVEDFLAG_SOFTCODED,    "system" },
+    { ".M2T",           PERCEIVED_TYPE_VIDEO,       PERCEIVEDFLAG_SOFTCODED,    "video",        0x601 },
+    { ".M2TS",          PERCEIVED_TYPE_VIDEO,       PERCEIVEDFLAG_SOFTCODED,    "video",        0x601 },
+    { ".M2V",           PERCEIVED_TYPE_VIDEO,       PERCEIVEDFLAG_SOFTCODED,    "video",        0x601 },
+    { ".m4a",           PERCEIVED_TYPE_AUDIO,       PERCEIVEDFLAG_SOFTCODED,    "audio",        0x601 },
+    { ".m4b",           PERCEIVED_TYPE_AUDIO,       PERCEIVEDFLAG_SOFTCODED,    "audio",        0x601 },
+    { ".m4p",           PERCEIVED_TYPE_AUDIO,       PERCEIVEDFLAG_SOFTCODED,    "audio",        0x601 },
+    { ".m4v",           PERCEIVED_TYPE_VIDEO,       PERCEIVEDFLAG_SOFTCODED,    "video",        0x601 },
+    { ".manifest",      PERCEIVED_TYPE_SYSTEM,      PERCEIVEDFLAG_SOFTCODED,    "system" },
+    { ".MOD",           PERCEIVED_TYPE_VIDEO,       PERCEIVEDFLAG_SOFTCODED,    "video",        0x601 },
+    { ".mov",           PERCEIVED_TYPE_VIDEO,       PERCEIVEDFLAG_SOFTCODED,    "video",        0x601 },
+    { ".mp4",           PERCEIVED_TYPE_VIDEO,       PERCEIVEDFLAG_SOFTCODED,    "video",        0x601 },
+    { ".mp4v",          PERCEIVED_TYPE_VIDEO,       PERCEIVEDFLAG_SOFTCODED,    "video",        0x601 },
+    { ".MTS",           PERCEIVED_TYPE_VIDEO,       PERCEIVEDFLAG_SOFTCODED,    "video",        0x601 },
+    { ".nvr",           PERCEIVED_TYPE_TEXT,        SOFTCODED_NATIVESUPPORT,    "text" },
+    { ".ocx",           PERCEIVED_TYPE_SYSTEM,      PERCEIVEDFLAG_SOFTCODED,    "system" },
+    { ".odt",           PERCEIVED_TYPE_DOCUMENT,    PERCEIVEDFLAG_SOFTCODED,    "document",     0x601 },
+    { ".php3",          PERCEIVED_TYPE_TEXT,        SOFTCODED_NATIVESUPPORT,    "text" },
+    { ".pl",            PERCEIVED_TYPE_TEXT,        SOFTCODED_NATIVESUPPORT,    "text" },
+    { ".plg",           PERCEIVED_TYPE_TEXT,        SOFTCODED_NATIVESUPPORT,    "text" },
+    { ".ps1xml",        PERCEIVED_TYPE_TEXT,        SOFTCODED_NATIVESUPPORT,    "Text" },
+    { ".rtf",           PERCEIVED_TYPE_DOCUMENT,    PERCEIVEDFLAG_SOFTCODED,    "document",     0x600 },
+    { ".sed",           PERCEIVED_TYPE_TEXT,        SOFTCODED_NATIVESUPPORT,    "text" },
+    { ".shtml",         PERCEIVED_TYPE_TEXT,        SOFTCODED_NATIVESUPPORT,    "text" },
+    { ".sql",           PERCEIVED_TYPE_TEXT,        SOFTCODED_NATIVESUPPORT,    "text" },
+    { ".sys",           PERCEIVED_TYPE_SYSTEM,      PERCEIVEDFLAG_SOFTCODED,    "system",       0x600 },
+    { ".tar",           PERCEIVED_TYPE_COMPRESSED,  PERCEIVEDFLAG_SOFTCODED,    "compressed" },
+    { ".text",          PERCEIVED_TYPE_TEXT,        SOFTCODED_NATIVESUPPORT,    "text" },
+    { ".tgz",           PERCEIVED_TYPE_COMPRESSED,  PERCEIVEDFLAG_SOFTCODED,    "compressed" },
+    { ".TS",            PERCEIVED_TYPE_VIDEO,       PERCEIVEDFLAG_SOFTCODED,    "video",        0x601 },
+    { ".tsv",           PERCEIVED_TYPE_TEXT,        SOFTCODED_NATIVESUPPORT,    "text" },
+    { ".TTS",           PERCEIVED_TYPE_VIDEO,       PERCEIVEDFLAG_SOFTCODED,    "video",        0x601 },
+    { ".txt",           PERCEIVED_TYPE_TEXT,        SOFTCODED_NATIVESUPPORT,    "text" },
+    { ".vob",           PERCEIVED_TYPE_VIDEO,       PERCEIVEDFLAG_SOFTCODED,    "video",        0x601 },
+    { ".vxd",           PERCEIVED_TYPE_SYSTEM,      PERCEIVEDFLAG_SOFTCODED,    "system" },
+    { ".wdp",           PERCEIVED_TYPE_IMAGE,       PERCEIVEDFLAG_SOFTCODED,    "image" },
+    { ".wmz",           PERCEIVED_TYPE_COMPRESSED,  PERCEIVEDFLAG_SOFTCODED,    "compressed" },
+    { ".wpl",           PERCEIVED_TYPE_AUDIO,       PERCEIVEDFLAG_SOFTCODED,    "audio",        0x601 },
+    { ".wsz",           PERCEIVED_TYPE_COMPRESSED,  PERCEIVEDFLAG_SOFTCODED,    "compressed" },
+    { ".x",             PERCEIVED_TYPE_TEXT,        SOFTCODED_NATIVESUPPORT,    "text" },
+    { ".xml",           PERCEIVED_TYPE_TEXT,        SOFTCODED_NATIVESUPPORT,    "text",         0x601 },
+    { ".xsl",           PERCEIVED_TYPE_TEXT,        SOFTCODED_NATIVESUPPORT,    "text",         0x601 },
+    { ".z",             PERCEIVED_TYPE_COMPRESSED,  PERCEIVEDFLAG_SOFTCODED,    "compressed" },
+    /* found in the registry under HKEY_CLASSES_ROOT\PerceivedType */
+    { ".doc",           PERCEIVED_TYPE_DOCUMENT,    PERCEIVEDFLAG_SOFTCODED,    "document",     0x600 },
+    { ".dot",           PERCEIVED_TYPE_DOCUMENT,    PERCEIVEDFLAG_SOFTCODED,    "document",     0x600 },
+    { ".mhtml",         PERCEIVED_TYPE_DOCUMENT,    PERCEIVEDFLAG_SOFTCODED,    "document",     0x600 },
+    { ".pot",           PERCEIVED_TYPE_DOCUMENT,    PERCEIVEDFLAG_SOFTCODED,    "document",     0x600 },
+    { ".ppt",           PERCEIVED_TYPE_DOCUMENT,    PERCEIVEDFLAG_SOFTCODED,    "document",     0x600 },
+    { ".rtf",           PERCEIVED_TYPE_DOCUMENT,    PERCEIVEDFLAG_SOFTCODED,    "document",     0x600 },
+    { ".wri",           PERCEIVED_TYPE_DOCUMENT,    PERCEIVEDFLAG_SOFTCODED,    "document",     0x600 },
+    { ".xls",           PERCEIVED_TYPE_DOCUMENT,    PERCEIVEDFLAG_SOFTCODED,    "document",     0x600 },
+    { ".xlt",           PERCEIVED_TYPE_DOCUMENT,    PERCEIVEDFLAG_SOFTCODED,    "document",     0x600 },
+
+};
+
+static void test_assoc_one(const struct assoc_test_struct* test)
+{
+    LPWSTR extension, type_expected, type_returned;
+    PERCEIVED perceived;
+    HRESULT hr;
+    INT flags;
+
+    /* if SHStrDupA receives a nullptr as input, it will null the output */
+    SHStrDupA(test->extension, &extension);
+    SHStrDupA(test->type, &type_expected);
+
+    perceived = 0xdeadbeef;
+    flags = 0xdeadbeef;
+
+    hr = pAssocGetPerceivedType(extension, &perceived, &flags, NULL);
+    expect_hr(type_expected ? S_OK : test->hr, hr);
+    ok(perceived == test->perceived, "%s: got perceived 0x%x, expected 0x%x\n",
+       test->extension, perceived, test->perceived);
+    ok(flags == test->flags, "%s: got flags 0x%x, expected 0x%x\n",
+       test->extension, flags, test->flags);
+
+    type_returned = (void *)0xdeadbeef;
+    perceived = 0xdeadbeef;
+    flags = 0xdeadbeef;
+
+    hr = pAssocGetPerceivedType(extension, &perceived, &flags, &type_returned);
+    expect_hr(type_expected ? S_OK : test->hr, hr);
+    ok(perceived == test->perceived, "%s: got perceived 0x%x, expected 0x%x\n",
+       test->extension, perceived, test->perceived);
+    ok(flags == test->flags, "%s: got flags 0x%x, expected 0x%x\n",
+       test->extension, flags, test->flags);
+
+    if (!type_expected)
+    {
+        ok(type_returned == (void *)0xdeadbeef || broken(type_returned == NULL) /* Win 8 */,
+           "%s: got type %p, expected 0xdeadbeef\n", test->extension, type_returned);
+    }
+    else if (type_returned == (void *)0xdeadbeef)
+    {
+        ok(type_returned != (void *)0xdeadbeef, "%s: got type %p, expected '%s'\n",
+           test->extension, type_returned, test->type);
+    }
+    else
+    {
+        ok(StrCmpIW(type_expected, type_returned) == 0, "%s: got type %s, expected '%s'\n",
+           test->extension, wine_dbgstr_w(type_returned), test->type);
+    }
+
+    CoTaskMemFree(type_returned);
+    CoTaskMemFree(extension);
+    CoTaskMemFree(type_expected);
+}
+
+static void test_assoc_perceived(void)
+{
+    static const struct assoc_test_struct should_not_exist =
+        { ".should_not_exist", PERCEIVED_TYPE_UNSPECIFIED, PERCEIVEDFLAG_UNDEFINED, NULL, 0, 0x80070002 };
+    static const struct assoc_test_struct htm[] =
+    {
+        { ".htm",  PERCEIVED_TYPE_TEXT, SOFTCODED_NATIVESUPPORT, "text", 0x600 },
+        { ".html", PERCEIVED_TYPE_TEXT, SOFTCODED_NATIVESUPPORT, "text", 0x600 },
+    };
+    static const struct assoc_test_struct mp2 =
+        { ".mp2", PERCEIVED_TYPE_VIDEO, HARDCODED_NATIVE_WMSDK, "video" };
+
+    OSVERSIONINFOEXW osvi;
+    DWORD version;
+    size_t i;
+
+    if (!pAssocGetPerceivedType)
+    {
+        win_skip("AssocGetPerceivedType() is missing\n");
+        return;
+    }
+
+    memset(&osvi, 0, sizeof(osvi));
+    osvi.dwOSVersionInfoSize = sizeof(osvi);
+    GetVersionExW((LPOSVERSIONINFOW)&osvi);
+    version = (osvi.dwMajorVersion << 8) | osvi.dwMinorVersion;
+
+    /* invalid entry results in HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) */
+    test_assoc_one(&should_not_exist);
+
+    for (i = 0; i < sizeof(assoc_perceived_types) / sizeof(assoc_perceived_types[0]); ++i)
+    {
+        if (assoc_perceived_types[i].minversion && assoc_perceived_types[i].minversion > version)
+            continue;
+        todo_wine
+        test_assoc_one(&assoc_perceived_types[i]);
+    }
+
+    /* below Vista */
+    if (version < 0x600)
+    {
+        todo_wine
+        test_assoc_one(&htm[0]);
+        todo_wine
+        test_assoc_one(&htm[1]);
+    }
+
+    /* below Win8 */
+    if (version < 0x602)
+    {
+        todo_wine
+        test_assoc_one(&mp2);
+    }
+}
+
 START_TEST(assoc)
 {
     HMODULE hshlwapi;
@@ -311,9 +588,11 @@ START_TEST(assoc)
     pAssocQueryStringA = (void*)GetProcAddress(hshlwapi, "AssocQueryStringA");
     pAssocQueryStringW = (void*)GetProcAddress(hshlwapi, "AssocQueryStringW");
     pAssocCreate       = (void*)GetProcAddress(hshlwapi, "AssocCreate");
+    pAssocGetPerceivedType = (void*)GetProcAddress(hshlwapi, "AssocGetPerceivedType");
 
     test_getstring_bad();
     test_getstring_basic();
     test_getstring_no_extra();
     test_assoc_create();
+    test_assoc_perceived();
 }
-- 
2.3.7

