ReactOS 0.4.16-dev-983-g23ad936
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 EXE file (18 icons) */
110 {L"%SystemRoot%\\explorer.exe", 18},
111
112 /* Multiple icons in the same ICO file (6 icons)
113 * Per MS: If the file is an .ico file, the return value is 1. */
114 {L"sysicon.ico", 1},
115
116 /* ICO file with both normal and PNG icons */
117 {L"ROS.ico", 0}
118};
119
121{
122 UINT i, nReturnedIcons, nExtractedIcons;
123 CHAR FileName[2][13] = { "ROS.ico", "sysicon.ico" };
124
125 if (!ResourceToFile(2, FileName[0]))
126 return;
127 if (!ResourceToFile(3, FileName[1]))
128 return;
129
130 /* Check count of icons returned */
131 for (i = 0; i < _countof(IconTests); ++i)
132 {
133 nReturnedIcons = ExtractIconExW(IconTests[i].pszFilePath, -1, NULL, NULL, 0);
134 ok(nReturnedIcons == IconTests[i].nIcons, "ExtractIconExW(%u): Expects %u icons, got %u\n", i, IconTests[i].nIcons, nReturnedIcons);
135 }
136
137 /* Check if the 0th icon can be extracted successfully */
138 for (i = 0; i < _countof(IconTests); ++i)
139 {
140 nExtractedIcons = ExtractIconExW(IconTests[i].pszFilePath, 0, NULL, NULL, 1);
141 ok(nExtractedIcons == IconTests[i].nIcons, "ExtractIconExW(%u): Expects %u icons, got %u\n", i, IconTests[i].nIcons, nExtractedIcons);
142 }
143
146}
147
148static HRESULT SHDEI(LPCWSTR pszIconFile, int Index = 0, UINT GIL = 0, UINT Size = 0)
149{
150 HICON hIco = NULL;
151 HRESULT hr = SHDefExtractIcon(pszIconFile, Index, GIL, &hIco, NULL, Size);
152 if (hr == S_OK)
153 {
154 hr = GetIcoSize(hIco);
155 SafeDestroyIcon(hIco);
156 }
157 return hr;
158}
159
161{
162 HRESULT hr;
163 int SysBigIconSize = GetSystemMetrics(SM_CXICON);
164
165 // Modern Windows requires the system image list to be initialized for GIL_SIMULATEDOC to work!
166 SHFILEINFOW shfi;
167 SHGetFileInfoW(L"x", 0, &shfi, sizeof(shfi), SHGFI_SYSICONINDEX | SHGFI_USEFILEATTRIBUTES);
168
171 PathAppendW(path, L"user32.dll");
172 int index = 1;
173
174 ok(SHDEI(path, index, 0, 0) == SysBigIconSize, "0 size must match GetSystemMetrics\n");
175 ok(SHDEI(path, index, 0, SysBigIconSize * 2) == SysBigIconSize * 2, "Resize failed\n");
176
177 HICON hIcoLarge, hIcoSmall;
178 if (SHDefExtractIcon(path, index, 0, &hIcoLarge, &hIcoSmall, 0) != S_OK)
179 hIcoLarge = hIcoSmall = NULL;
180 ok(hIcoLarge && hIcoSmall && !SHAreIconsEqual(hIcoLarge, hIcoSmall), "Large+Small failed\n");
181 SafeDestroyIcon(hIcoLarge);
182 SafeDestroyIcon(hIcoSmall);
183
184 static const int sizes[] = { 0, SysBigIconSize * 2 };
185 for (UINT i = 0; i < _countof(sizes); ++i)
186 {
187 HICON hIcoNormal, hIcoSimDoc;
188 if (FAILED(hr = SHDefExtractIcon(path, index, 0, &hIcoNormal, NULL, sizes[i])))
189 hIcoNormal = NULL;
190 if (FAILED(hr = SHDefExtractIcon(path, index, GIL_SIMULATEDOC, &hIcoSimDoc, NULL, sizes[i])))
191 hIcoSimDoc = NULL;
192 ok(hIcoNormal && hIcoSimDoc && !SHAreIconsEqual(hIcoNormal, hIcoSimDoc), "GIL_SIMULATEDOC failed\n");
193 SafeDestroyIcon(hIcoNormal);
194 SafeDestroyIcon(hIcoSimDoc);
195 }
196
198 GetTempFileNameW(path, L"TEST", 0, path);
199 ok(SHDEI(path) == S_FALSE, "Empty file should return S_FALSE\n");
202 {
203 DWORD io;
204 WriteFile(hFile, "!", 1, &io, NULL);
206 ok(SHDEI(path) == S_FALSE, "File without icons should return S_FALSE\n");
207 }
209}
BOOL ResourceToFile(INT i, LPCSTR FileName)
static HRESULT SHDEI(LPCWSTR pszIconFile, int Index=0, UINT GIL=0, UINT Size=0)
EXTRACTICONTESTS IconTests[]
EXTERN_C BOOL WINAPI SHAreIconsEqual(HICON hIcon1, HICON hIcon2)
Definition: rosordinal.c:43
static UINT GetIcoSize(HICON hIco)
static void SafeDestroyIcon(HICON hIco)
BOOL FileExists(LPCSTR FileName)
static HICON hIcon2
#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
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)
_Check_return_opt_ _CRTIMP size_t __cdecl fwrite(_In_reads_bytes_(_Size *_Count) const void *_Str, _In_ size_t _Size, _In_ size_t _Count, _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 @566 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 L(x)
Definition: ntvdm.h:50
#define PathAppendW
Definition: pathcch.h:309
#define RT_RCDATA
Definition: pedump.c:372
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:172
#define SHGFI_USEFILEATTRIBUTES
Definition: shellapi.h:182
#define ExtractIconEx
Definition: shellapi.h:712
HRESULT hr
Definition: shlfolder.c:183
#define SHDefExtractIcon
Definition: shlobj.h:2308
#define _countof(array)
Definition: sndvol32.h:70
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:4533
#define DeleteFile
Definition: winbase.h:3795
#define WINAPI
Definition: msvc.h:6
#define S_FALSE
Definition: winerror.h:2357
#define GetObject
Definition: wingdi.h:4468
BOOL WINAPI GetIconInfo(_In_ HICON, _Out_ PICONINFO)
Definition: cursoricon.c:2382
#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:2390
const char * LPCSTR
Definition: xmlstorage.h:183
__wchar_t WCHAR
Definition: xmlstorage.h:180
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
char CHAR
Definition: xmlstorage.h:175