https://git.reactos.org/?p=reactos.git;a=commitdiff;h=4ac511405f69535076bbd…
commit 4ac511405f69535076bbdabfc2710891978e5d02
Author: Mark Jansen <mark.jansen(a)reactos.org>
AuthorDate: Sat Dec 9 00:51:56 2017 +0100
[SHELL32_APITEST] Add test for SHCreateFileExtractIconW
CORE-14082
---
modules/rostests/apitests/shell32/1.ico | Bin 0 -> 4286 bytes
modules/rostests/apitests/shell32/CMakeLists.txt | 2 +
.../apitests/shell32/SHCreateFileExtractIconW.cpp | 204 +++++++++++++++++++++
modules/rostests/apitests/shell32/resource.rc | 5 +
modules/rostests/apitests/shell32/testlist.c | 2 +
5 files changed, 213 insertions(+)
diff --git a/modules/rostests/apitests/shell32/1.ico
b/modules/rostests/apitests/shell32/1.ico
new file mode 100644
index 0000000000..0b2dee3cc6
Binary files /dev/null and b/modules/rostests/apitests/shell32/1.ico differ
diff --git a/modules/rostests/apitests/shell32/CMakeLists.txt
b/modules/rostests/apitests/shell32/CMakeLists.txt
index 65d0f6c504..48c41820c9 100644
--- a/modules/rostests/apitests/shell32/CMakeLists.txt
+++ b/modules/rostests/apitests/shell32/CMakeLists.txt
@@ -14,10 +14,12 @@ add_executable(shell32_apitest
CShellLink.cpp
menu.cpp
PathResolve.cpp
+ SHCreateFileExtractIconW.cpp
ShellExecuteEx.cpp
shelltest.cpp
SHParseDisplayName.cpp
testlist.c
+ resource.rc
${CMAKE_CURRENT_BINARY_DIR}/shell32_apitest.def)
target_link_libraries(shell32_apitest wine uuid ${PSEH_LIB})
set_module_type(shell32_apitest win32cui)
diff --git a/modules/rostests/apitests/shell32/SHCreateFileExtractIconW.cpp
b/modules/rostests/apitests/shell32/SHCreateFileExtractIconW.cpp
new file mode 100644
index 0000000000..38247dabe3
--- /dev/null
+++ b/modules/rostests/apitests/shell32/SHCreateFileExtractIconW.cpp
@@ -0,0 +1,204 @@
+/*
+ * PROJECT: ReactOS API tests
+ * LICENSE: GPL-2.0+ (
https://spdx.org/licenses/GPL-2.0+)
+ * PURPOSE: Test for SHCreateFileExtractIconW
+ * COPYRIGHT: Copyright 2017 Mark Jansen (mark.jansen(a)reactos.org)
+ */
+
+#include "shelltest.h"
+#include <atlbase.h>
+#include <atlcom.h>
+ULONG DbgPrint(PCH Format,...);
+#include <shellutils.h>
+#include <wincon.h>
+#include <wingdi.h>
+
+
+HRESULT (STDAPICALLTYPE *pSHCreateFileExtractIconW)(LPCWSTR pszFile, DWORD
dwFileAttributes, REFIID riid, void **ppv);
+
+struct test_data
+{
+ const WCHAR* Name;
+ DWORD dwFlags;
+};
+
+static test_data Tests[] =
+{
+ { L"xxx.zip", FILE_ATTRIBUTE_NORMAL },
+ { L"xxx.zip", FILE_ATTRIBUTE_DIRECTORY },
+ { L"xxx.exe", FILE_ATTRIBUTE_NORMAL },
+ { L"xxx.exe", FILE_ATTRIBUTE_DIRECTORY },
+ { L"xxx.dll", FILE_ATTRIBUTE_NORMAL },
+ { L"xxx.dll", FILE_ATTRIBUTE_DIRECTORY },
+ { L"xxx.txt", FILE_ATTRIBUTE_NORMAL },
+ { L"xxx.txt", FILE_ATTRIBUTE_DIRECTORY },
+ { NULL, FILE_ATTRIBUTE_NORMAL },
+ { NULL, FILE_ATTRIBUTE_DIRECTORY },
+};
+
+
+static void ExtractOneBitmap(HBITMAP hbm, CComHeapPtr<BYTE>& data, DWORD&
size)
+{
+ HDC hdc = CreateCompatibleDC(NULL);
+ HGDIOBJ obj = SelectObject(hdc, hbm);
+
+ CComHeapPtr<BITMAPINFO> pInfoBM;
+
+ pInfoBM.AllocateBytes(sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
+ memset(pInfoBM, 0, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
+ pInfoBM->bmiHeader.biSize = sizeof(pInfoBM->bmiHeader);
+ if (!GetDIBits(hdc, hbm, 0, 0, NULL, pInfoBM, DIB_RGB_COLORS))
+ return;
+
+ size = pInfoBM->bmiHeader.biSizeImage;
+ data.Allocate(size);
+ GetDIBits(hdc, hbm, 0, pInfoBM->bmiHeader.biHeight, data, pInfoBM,
DIB_RGB_COLORS);
+
+ SelectObject(hdc, obj);
+ DeleteDC(hdc);
+}
+
+static bool GetIconData(HICON icon, CComHeapPtr<BYTE>& colorData, DWORD&
colorSize, CComHeapPtr<BYTE>& maskData, DWORD& maskSize)
+{
+ ICONINFO iconinfo;
+
+ if (!GetIconInfo(icon, &iconinfo))
+ return false;
+
+ ExtractOneBitmap(iconinfo.hbmColor, colorData, colorSize);
+ ExtractOneBitmap(iconinfo.hbmMask, maskData, maskSize);
+
+ DeleteObject(iconinfo.hbmColor);
+ DeleteObject(iconinfo.hbmMask);
+
+ return true;
+}
+
+
+START_TEST(SHCreateFileExtractIconW)
+{
+ WCHAR CurrentModule[MAX_PATH];
+ HMODULE shell32 = LoadLibraryA("shell32.dll");
+ HICON myIcon;
+ pSHCreateFileExtractIconW = (HRESULT (__stdcall *)(LPCWSTR, DWORD, REFIID, void
**))GetProcAddress(shell32, "SHCreateFileExtractIconW");
+
+ CoInitialize(NULL);
+
+ GetModuleFileNameW(NULL, CurrentModule, _countof(CurrentModule));
+ {
+ SHFILEINFOW shfi;
+ ULONG_PTR firet = SHGetFileInfoW(CurrentModule, 0, &shfi, sizeof(shfi),
SHGFI_ICON);
+ myIcon = shfi.hIcon;
+ if (!firet)
+ {
+ skip("Unable to get my own icon\n");
+ return;
+ }
+ }
+
+ if (!pSHCreateFileExtractIconW)
+ {
+ skip("SHCreateFileExtractIconW not available\n");
+ return;
+ }
+
+ for (size_t n = 0; n < _countof(Tests); ++n)
+ {
+ test_data& cur = Tests[n];
+ bool useMyIcon = false;
+
+ if (cur.Name == NULL)
+ {
+ cur.Name = CurrentModule;
+ useMyIcon = true;
+ }
+
+ CComPtr<IExtractIconW> spExtract;
+ HRESULT hr = pSHCreateFileExtractIconW(cur.Name, cur.dwFlags,
IID_PPV_ARG(IExtractIconW, &spExtract));
+ ok(hr == S_OK, "Expected hr to be S_OK, was 0x%lx for %S(%lx)\n", hr,
cur.Name, cur.dwFlags);
+
+ if (!SUCCEEDED(hr))
+ continue;
+
+ int ilIndex = -1;
+ UINT wFlags = 0xdeaddead;
+ WCHAR Buffer[MAX_PATH];
+
+ hr = spExtract->GetIconLocation(0, Buffer, _countof(Buffer), &ilIndex,
&wFlags);
+ ok(hr == S_OK, "Expected hr to be S_OK, was 0x%lx for %S(%lx)\n", hr,
cur.Name, cur.dwFlags);
+ if (!SUCCEEDED(hr))
+ continue;
+
+ ok(wFlags & (GIL_NOTFILENAME|GIL_PERCLASS), "Expected
GIL_NOTFILENAME|GIL_PERCLASS to be set for %S(%lx)\n", cur.Name, cur.dwFlags);
+ ok(!wcscmp(Buffer, L"*"), "Expected '*', was '%S'
for %S(%lx)\n", Buffer, cur.Name, cur.dwFlags);
+
+ HICON ico;
+ hr = spExtract->Extract(Buffer, ilIndex, &ico, NULL, 0);
+
+ /* Visualize the icon extracted for whoever is stepping through this code. */
+ HWND console = GetConsoleWindow();
+ SendMessage(console, WM_SETICON, ICON_BIG, (LPARAM)ico);
+ SendMessage(console, WM_SETICON, ICON_SMALL, (LPARAM)ico);
+
+ CComHeapPtr<BYTE> colorData, maskData;
+ DWORD colorSize = 0, maskSize = 0;
+
+ GetIconData(ico, colorData, colorSize, maskData, maskSize);
+
+ if (!colorSize || !maskSize)
+ continue;
+
+ SHFILEINFOW shfi;
+ ULONG_PTR firet = SHGetFileInfoW(cur.Name, cur.dwFlags, &shfi, sizeof(shfi),
SHGFI_USEFILEATTRIBUTES | SHGFI_ICON);
+
+ if (!firet)
+ continue;
+
+ CComHeapPtr<BYTE> colorDataRef, maskDataRef;
+ DWORD colorSizeRef = 0, maskSizeRef = 0;
+ GetIconData(shfi.hIcon, colorDataRef, colorSizeRef, maskDataRef, maskSizeRef);
+
+ ok(colorSizeRef == colorSize, "Expected %lu, was %lu for %S(%lx)\n",
colorSizeRef, colorSize, cur.Name, cur.dwFlags);
+ ok(maskSizeRef == maskSize, "Expected %lu, was %lu for %S(%lx)\n",
maskSizeRef, maskSize, cur.Name, cur.dwFlags);
+
+ if (colorSizeRef == colorSize)
+ {
+ ok(!memcmp(colorData, colorDataRef, colorSize), "Expected equal
colorData for %S(%lx)\n", cur.Name, cur.dwFlags);
+ }
+
+ if (maskSizeRef == maskSize)
+ {
+ ok(!memcmp(maskData, maskDataRef, maskSize), "Expected equal maskData
for %S(%lx)\n", cur.Name, cur.dwFlags);
+ }
+
+ if (useMyIcon)
+ {
+ colorDataRef.Free();
+ maskDataRef.Free();
+ colorSizeRef = maskSizeRef = 0;
+ GetIconData(myIcon, colorDataRef, colorSizeRef, maskDataRef, maskSizeRef);
+
+ ok(colorSizeRef == colorSize, "Expected %lu, was %lu for
%S(%lx)\n", colorSizeRef, colorSize, cur.Name, cur.dwFlags);
+ ok(maskSizeRef == maskSize, "Expected %lu, was %lu for %S(%lx)\n",
maskSizeRef, maskSize, cur.Name, cur.dwFlags);
+
+ if (colorSizeRef == colorSize)
+ {
+ /* Incase requested filetype does not match, the exe icon is not used!
*/
+ if (cur.dwFlags == FILE_ATTRIBUTE_DIRECTORY)
+ {
+ ok(memcmp(colorData, colorDataRef, colorSize), "Expected
colorData to be changed for %S(%lx)\n", cur.Name, cur.dwFlags);
+ }
+ else
+ {
+ ok(!memcmp(colorData, colorDataRef, colorSize), "Expected equal
colorData for %S(%lx)\n", cur.Name, cur.dwFlags);
+ }
+ }
+
+ // Mask is not reliable for some reason
+ //if (maskSizeRef == maskSize)
+ //{
+ // ok(!memcmp(maskData, maskDataRef, maskSize), "Expected equal
maskData for %S(%lx)\n", cur.Name, cur.dwFlags);
+ //}
+ }
+ }
+}
diff --git a/modules/rostests/apitests/shell32/resource.rc
b/modules/rostests/apitests/shell32/resource.rc
new file mode 100644
index 0000000000..89a0f853a8
--- /dev/null
+++ b/modules/rostests/apitests/shell32/resource.rc
@@ -0,0 +1,5 @@
+#include <windef.h>
+
+LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
+
+1 ICON "1.ico"
diff --git a/modules/rostests/apitests/shell32/testlist.c
b/modules/rostests/apitests/shell32/testlist.c
index 769f587800..b0a8638046 100644
--- a/modules/rostests/apitests/shell32/testlist.c
+++ b/modules/rostests/apitests/shell32/testlist.c
@@ -11,6 +11,7 @@ extern void func_CShellDesktop(void);
extern void func_CShellLink(void);
extern void func_menu(void);
extern void func_PathResolve(void);
+extern void func_SHCreateFileExtractIconW(void);
extern void func_ShellExecuteEx(void);
extern void func_SHParseDisplayName(void);
@@ -24,6 +25,7 @@ const struct test winetest_testlist[] =
{ "CShellLink", func_CShellLink },
{ "menu", func_menu },
{ "PathResolve", func_PathResolve },
+ { "SHCreateFileExtractIconW", func_SHCreateFileExtractIconW },
{ "ShellExecuteEx", func_ShellExecuteEx },
{ "SHParseDisplayName", func_SHParseDisplayName },
{ 0, 0 }