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 
12 typedef struct
13 {
14     PCWSTR pszFilePath;
15     UINT nIcons;
16 } EXTRACTICONTESTS;
17 
18 BOOL FileExists(LPCSTR FileName)
19 {
20     FILE *fp = NULL;
21     bool exists = FALSE;
22 
23     fp = fopen(FileName, "r");
24     if (fp != NULL)
25     {
26         exists = TRUE;
27         fclose(fp);
28     }
29     return exists;
30 }
31 
32 BOOL ResourceToFile(INT i, LPCSTR FileName)
33 {
34     FILE *fout;
35     HGLOBAL hData;
36     HRSRC hRes;
37     LPVOID lpResLock;
38     UINT iSize;
39 
40     if (FileExists(FileName))
41     {
42         skip("'%s' already exists. Exiting now\n", FileName);
43         return FALSE;
44     }
45 
46     hRes = FindResourceW(NULL, MAKEINTRESOURCEW(i), MAKEINTRESOURCEW(RT_RCDATA));
47     if (hRes == NULL)
48     {
49         skip("Could not locate resource (%d). Exiting now\n", i);
50         return FALSE;
51     }
52 
53     iSize = SizeofResource(NULL, hRes);
54 
55     hData = LoadResource(NULL, hRes);
56     if (hData == NULL)
57     {
58         skip("Could not load resource (%d). Exiting now\n", i);
59         return FALSE;
60     }
61 
62     // Lock the resource into global memory.
63     lpResLock = LockResource(hData);
64     if (lpResLock == NULL)
65     {
66         skip("Could not lock resource (%d). Exiting now\n", i);
67         return FALSE;
68     }
69 
70     fout = fopen(FileName, "wb");
71     fwrite(lpResLock, iSize, 1, fout);
72     fclose(fout);
73     return TRUE;
74 }
75 
76 EXTRACTICONTESTS IconTests[] =
77 {
78     /* Executable file with icon */
79     {L"%SystemRoot%\\System32\\cmd.exe", 1},
80 
81     /* Executable file without icon */
82     {L"%SystemRoot%\\System32\\autochk.exe", 0},
83 
84     /* Non-existing files */
85     {L"%SystemRoot%\\non-existent-file.sdf", 0},
86 
87     /* Multiple icons in the same EXE file (18 icons) */
88     {L"%SystemRoot%\\explorer.exe", 18},
89 
90     /* Multiple icons in the same ICO file (6 icons)
91      * Per MS: If the file is an .ico file, the return value is 1. */
92     {L"sysicon.ico", 1},
93 
94     /* ICO file with both normal and PNG icons */
95     {L"ROS.ico", 0}
96 };
97 
98 START_TEST(ExtractIconEx)
99 {
100     UINT i, nReturnedIcons, nExtractedIcons;
101     CHAR FileName[2][13] = { "ROS.ico", "sysicon.ico" };
102 
103     if (!ResourceToFile(2, FileName[0]))
104         return;
105     if (!ResourceToFile(3, FileName[1]))
106         return;
107 
108     /* Check count of icons returned */
109     for (i = 0; i < _countof(IconTests); ++i)
110     {
111         nReturnedIcons = ExtractIconExW(IconTests[i].pszFilePath, -1, NULL, NULL, 0);
112         ok(nReturnedIcons == IconTests[i].nIcons, "ExtractIconExW(%u): Expects %u icons, got %u\n", i, IconTests[i].nIcons, nReturnedIcons);
113     }
114 
115     /* Check if the 0th icon can be extracted successfully */
116     for (i = 0; i < _countof(IconTests); ++i)
117     {
118         nExtractedIcons = ExtractIconExW(IconTests[i].pszFilePath, 0, NULL, NULL, 1);
119         ok(nExtractedIcons == IconTests[i].nIcons, "ExtractIconExW(%u): Expects %u icons, got %u\n", i, IconTests[i].nIcons, nExtractedIcons);
120     }
121 
122     DeleteFileA(FileName[0]);
123     DeleteFileA(FileName[1]);
124 }
125