ReactOS 0.4.16-dev-1946-g52006dd
ExtractIconEx.cpp
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS API Tests
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: Tests for ExtractIconEx routine
5 * COPYRIGHT: Copyright 2019 George Bișoc (george.bisoc@reactos.org)
6 * Copyright 2023 Doug Lyons (douglyons@douglyons.com)
7 */
8
9#include "shelltest.h"
10#include <stdio.h>
11
13
14static void SafeDestroyIcon(HICON hIco)
15{
16 if (hIco)
17 DestroyIcon(hIco);
18}
19
20static UINT GetIcoSize(HICON hIco)
21{
23 if (!GetIconInfo(hIco, &info))
24 return 0;
25
26 BITMAP bm;
27 if (!GetObject(info.hbmColor ? info.hbmColor : info.hbmMask, sizeof(bm), &bm))
28 bm.bmWidth = 0;
29 DeleteObject(info.hbmMask);
30 DeleteObject(info.hbmColor);
31 return bm.bmWidth;
32}
33
34typedef struct
35{
39
41{
42 FILE *fp = NULL;
43 bool exists = FALSE;
44
45 fp = fopen(FileName, "r");
46 if (fp != NULL)
47 {
48 exists = TRUE;
49 fclose(fp);
50 }
51 return exists;
52}
53
55{
56 FILE *fout;
57 HGLOBAL hData;
58 HRSRC hRes;
59 LPVOID lpResLock;
60 UINT iSize;
61
63 {
64 skip("'%s' already exists. Exiting now\n", FileName);
65 return FALSE;
66 }
67
69 if (hRes == NULL)
70 {
71 skip("Could not locate resource (%d). Exiting now\n", i);
72 return FALSE;
73 }
74
75 iSize = SizeofResource(NULL, hRes);
76
77 hData = LoadResource(NULL, hRes);
78 if (hData == NULL)
79 {
80 skip("Could not load resource (%d). Exiting now\n", i);
81 return FALSE;
82 }
83
84 // Lock the resource into global memory.
85 lpResLock = LockResource(hData);
86 if (lpResLock == NULL)
87 {
88 skip("Could not lock resource (%d). Exiting now\n", i);
89 return FALSE;
90 }
91
92 fout = fopen(FileName, "wb");
93 fwrite(lpResLock, iSize, 1, fout);
94 fclose(fout);
95 return TRUE;
96}
97
99{
100 /* Executable file with icon */
101 {L"%SystemRoot%\\System32\\cmd.exe", 1},
102
103 /* Executable file without icon */
104 {L"%SystemRoot%\\System32\\autochk.exe", 0},
105
106 /* Non-existing files */
107 {L"%SystemRoot%\\non-existent-file.sdf", 0},
108
109 /* Multiple icons in the same ICO file (6 icons)
110 * Per MS: If the file is an .ico file, the return value is 1. */
111 {L"sysicon.ico", 1},
112
113 /* ICO file with both normal and PNG icons */
114 {L"ROS.ico", (UINT)(GetNTVersion() >= _WIN32_WINNT_VISTA ? 1 : 0)}
115};
116
118{
119 UINT nReturnedIcons, nExtractedIcons;
120
121 /* Check count of icons returned */
122 nReturnedIcons = ExtractIconExW(Test->pszFilePath, -1, NULL, NULL, 0);
123 ok(nReturnedIcons == Test->nIcons, "ExtractIconExW(L\"%S\"): Expects %u icons, got %u\n", Test->pszFilePath, Test->nIcons, nReturnedIcons);
124
125 /* Check if the 0th icon can be extracted successfully */
126 nExtractedIcons = ExtractIconExW(Test->pszFilePath, 0, NULL, NULL, 1);
127 ok(nExtractedIcons == Test->nIcons, "ExtractIconExW(L\"%S\"): Expects %u icons, got %u\n", Test->pszFilePath, Test->nIcons, nExtractedIcons);
128}
129
131{
132 UINT i;
133 CHAR FileName[2][13] = { "ROS.ico", "sysicon.ico" };
134 EXTRACTICONTEST explorer_exe = {L"%SystemRoot%\\explorer.exe", 0};
135
136 if (!ResourceToFile(2, FileName[0]))
137 return;
138 if (!ResourceToFile(3, FileName[1]))
139 return;
140
141 /* Run normal tests */
142 for (i = 0; i < _countof(IconTests); ++i)
144
145 /* Run special case checks */
146 switch (GetNTVersion())
147 {
149 explorer_exe.nIcons = 18;
150 break;
152 explorer_exe.nIcons = 23;
153 break;
155 explorer_exe.nIcons = 25;
156 break;
159 explorer_exe.nIcons = 24;
160 break;
162 explorer_exe.nIcons = 28;
163 break;
164 }
165
166 if (explorer_exe.nIcons)
167 RunExtractIconTest(&explorer_exe);
168 else
169 skip("Unknown NT Version: 0x%lX\n", GetNTVersion());
170
173}
174
175static HRESULT SHDEI(LPCWSTR pszIconFile, int Index = 0, UINT GIL = 0, UINT Size = 0)
176{
177 HICON hIco = NULL;
178 HRESULT hr = SHDefExtractIcon(pszIconFile, Index, GIL, &hIco, NULL, Size);
179 if (hr == S_OK)
180 {
181 hr = GetIcoSize(hIco);
182 SafeDestroyIcon(hIco);
183 }
184 return hr;
185}
186
188{
189 HRESULT hr;
190 int SysBigIconSize = GetSystemMetrics(SM_CXICON);
191
192 // Modern Windows requires the system image list to be initialized for GIL_SIMULATEDOC to work!
193 SHFILEINFOW shfi;
194 SHGetFileInfoW(L"x", 0, &shfi, sizeof(shfi), SHGFI_SYSICONINDEX | SHGFI_USEFILEATTRIBUTES);
195
198 PathAppendW(path, L"user32.dll");
199 int index = 1;
200
201 ok(SHDEI(path, index, 0, 0) == SysBigIconSize, "0 size must match GetSystemMetrics\n");
202 ok(SHDEI(path, index, 0, SysBigIconSize * 2) == SysBigIconSize * 2, "Resize failed\n");
203
204 HICON hIcoLarge, hIcoSmall;
205 if (SHDefExtractIcon(path, index, 0, &hIcoLarge, &hIcoSmall, 0) != S_OK)
206 hIcoLarge = hIcoSmall = NULL;
207 ok(hIcoLarge && hIcoSmall && !SHAreIconsEqual(hIcoLarge, hIcoSmall), "Large+Small failed\n");
208 SafeDestroyIcon(hIcoLarge);
209 SafeDestroyIcon(hIcoSmall);
210
211 static const int sizes[] = { 0, SysBigIconSize * 2 };
212 for (UINT i = 0; i < _countof(sizes); ++i)
213 {
214 HICON hIcoNormal, hIcoSimDoc;
215 if (FAILED(hr = SHDefExtractIcon(path, index, 0, &hIcoNormal, NULL, sizes[i])))
216 hIcoNormal = NULL;
217 if (FAILED(hr = SHDefExtractIcon(path, index, GIL_SIMULATEDOC, &hIcoSimDoc, NULL, sizes[i])))
218 hIcoSimDoc = NULL;
219 ok(hIcoNormal && hIcoSimDoc && !SHAreIconsEqual(hIcoNormal, hIcoSimDoc), "GIL_SIMULATEDOC failed\n");
220 SafeDestroyIcon(hIcoNormal);
221 SafeDestroyIcon(hIcoSimDoc);
222 }
223
225 GetTempFileNameW(path, L"TEST", 0, path);
226 ok(SHDEI(path) == S_FALSE, "Empty file should return S_FALSE\n");
229 {
230 DWORD io;
231 WriteFile(hFile, "!", 1, &io, NULL);
233 ok(SHDEI(path) == S_FALSE, "File without icons should return S_FALSE\n");
234 }
236}
BOOL ResourceToFile(INT i, LPCSTR FileName)
static HRESULT SHDEI(LPCWSTR pszIconFile, int Index=0, UINT GIL=0, UINT Size=0)
VOID RunExtractIconTest(EXTRACTICONTEST *Test)
EXTERN_C BOOL WINAPI SHAreIconsEqual(HICON hIcon1, HICON hIcon2)
Definition: rosordinal.c:48
static UINT GetIcoSize(HICON hIco)
static void SafeDestroyIcon(HICON hIco)
EXTRACTICONTEST IconTests[]
BOOL FileExists(LPCSTR FileName)
static HICON hIcon2
#define GetNTVersion()
Definition: apitest.h:17
#define ok(value,...)
Definition: atltest.h:57
#define skip(...)
Definition: atltest.h:64
#define START_TEST(x)
Definition: atltest.h:75
#define EXTERN_C
Definition: basetyps.h:12
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define CloseHandle
Definition: compat.h:739
#define OPEN_EXISTING
Definition: compat.h:775
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define MAX_PATH
Definition: compat.h:34
#define CreateFileW
Definition: compat.h:741
#define FILE_SHARE_READ
Definition: compat.h:136
BOOL WINAPI DeleteFileA(IN LPCSTR lpFileName)
Definition: delete.c:24
BOOL WINAPI WriteFile(IN HANDLE hFile, IN LPCVOID lpBuffer, IN DWORD nNumberOfBytesToWrite OPTIONAL, OUT LPDWORD lpNumberOfBytesWritten, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: rw.c:24
DWORD WINAPI GetTempPathW(IN DWORD count, OUT LPWSTR path)
Definition: path.c:2080
UINT WINAPI GetSystemDirectoryW(OUT LPWSTR lpBuffer, IN UINT uSize)
Definition: path.c:2313
HRSRC WINAPI FindResourceW(HINSTANCE hModule, LPCWSTR name, LPCWSTR type)
Definition: res.c:176
DWORD WINAPI SizeofResource(HINSTANCE hModule, HRSRC hRsrc)
Definition: res.c:568
LPVOID WINAPI LockResource(HGLOBAL handle)
Definition: res.c:550
HGLOBAL WINAPI LoadResource(HINSTANCE hModule, HRSRC hRsrc)
Definition: res.c:532
#define L(x)
Definition: resources.c:13
UINT WINAPI GetTempFileNameW(IN LPCWSTR lpPathName, IN LPCWSTR lpPrefixString, IN UINT uUnique, OUT LPWSTR lpTempFileName)
Definition: filename.c:84
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
pKey DeleteObject()
GLuint index
Definition: glext.h:6031
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
UINT WINAPI ExtractIconExW(LPCWSTR lpszFile, INT nIconIndex, HICON *phiconLarge, HICON *phiconSmall, UINT nIcons)
Definition: iconcache.cpp:855
_Check_return_ _CRTIMP FILE *__cdecl fopen(_In_z_ const char *_Filename, _In_z_ const char *_Mode)
_Check_return_opt_ _CRTIMP int __cdecl fclose(_Inout_ FILE *_File)
#define S_OK
Definition: intsafe.h:52
#define FAILED(hr)
Definition: intsafe.h:51
static HICON
Definition: imagelist.c:80
static HANDLE PIO_APC_ROUTINE PVOID PIO_STATUS_BLOCK io
Definition: file.c:100
static const struct @594 sizes[]
_In_ HANDLE hFile
Definition: mswsock.h:90
unsigned int UINT
Definition: ndis.h:50
#define FILE_SHARE_DELETE
Definition: nt_native.h:682
#define GENERIC_WRITE
Definition: nt_native.h:90
#define PathAppendW
Definition: pathcch.h:310
#define RT_RCDATA
Definition: pedump.c:372
#define _WIN32_WINNT_WIN10
Definition: sdkddkver.h:32
#define _WIN32_WINNT_WS03
Definition: sdkddkver.h:23
#define _WIN32_WINNT_WINBLUE
Definition: sdkddkver.h:30
#define _WIN32_WINNT_WIN8
Definition: sdkddkver.h:29
#define _WIN32_WINNT_WIN7
Definition: sdkddkver.h:28
#define _WIN32_WINNT_VISTA
Definition: sdkddkver.h:25
DWORD_PTR WINAPI SHGetFileInfoW(LPCWSTR path, DWORD dwFileAttributes, SHFILEINFOW *psfi, UINT sizeofpsfi, UINT flags)
Definition: shell32_main.c:430
#define SHGFI_SYSICONINDEX
Definition: shellapi.h:171
#define SHGFI_USEFILEATTRIBUTES
Definition: shellapi.h:181
#define ExtractIconEx
Definition: shellapi.h:728
HRESULT hr
Definition: shlfolder.c:183
#define SHDefExtractIcon
Definition: shlobj.h:2306
#define _countof(array)
Definition: sndvol32.h:70
size_t fwrite(const void *, size_t, size_t, FILE *)
Definition: file.c:3077
Definition: bl.h:1331
const uint16_t * PCWSTR
Definition: typedefs.h:57
int32_t INT
Definition: typedefs.h:58
_In_ WDFCOLLECTION _In_ ULONG Index
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4539
#define DeleteFile
Definition: winbase.h:3513
#define WINAPI
Definition: msvc.h:6
#define S_FALSE
Definition: winerror.h:3451
#define GetObject
Definition: wingdi.h:4914
BOOL WINAPI GetIconInfo(_In_ HICON, _Out_ PICONINFO)
Definition: cursoricon.c:2397
#define MAKEINTRESOURCEW(i)
Definition: winuser.h:582
#define SM_CXICON
Definition: winuser.h:983
int WINAPI GetSystemMetrics(_In_ int)
BOOL WINAPI DestroyIcon(_In_ HICON)
Definition: cursoricon.c:2405
const char * LPCSTR
Definition: xmlstorage.h:183
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
__wchar_t WCHAR
Definition: xmlstorage.h:180
char CHAR
Definition: xmlstorage.h:175