18ec05f5fSBișoc George /*
28ec05f5fSBișoc George  * PROJECT:     ReactOS API Tests
38ec05f5fSBișoc George  * LICENSE:     GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
48ec05f5fSBișoc George  * PURPOSE:     Tests for ExtractIconEx routine
5b00ecdcaSGeorge Bișoc  * COPYRIGHT:   Copyright 2019 George Bișoc (george.bisoc@reactos.org)
6*c8fc8264SDoug Lyons  *              Copyright 2023 Doug Lyons (douglyons@douglyons.com)
78ec05f5fSBișoc George  */
88ec05f5fSBișoc George 
98ec05f5fSBișoc George #include "shelltest.h"
10*c8fc8264SDoug Lyons #include <stdio.h>
118ec05f5fSBișoc George 
128ec05f5fSBișoc George typedef struct
138ec05f5fSBișoc George {
148ec05f5fSBișoc George     PCWSTR pszFilePath;
158ec05f5fSBișoc George     UINT nIcons;
168ec05f5fSBișoc George } EXTRACTICONTESTS;
178ec05f5fSBișoc George 
FileExists(LPCSTR FileName)18*c8fc8264SDoug Lyons BOOL FileExists(LPCSTR FileName)
19*c8fc8264SDoug Lyons {
20*c8fc8264SDoug Lyons     FILE *fp = NULL;
21*c8fc8264SDoug Lyons     bool exists = FALSE;
22*c8fc8264SDoug Lyons 
23*c8fc8264SDoug Lyons     fp = fopen(FileName, "r");
24*c8fc8264SDoug Lyons     if (fp != NULL)
25*c8fc8264SDoug Lyons     {
26*c8fc8264SDoug Lyons         exists = TRUE;
27*c8fc8264SDoug Lyons         fclose(fp);
28*c8fc8264SDoug Lyons     }
29*c8fc8264SDoug Lyons     return exists;
30*c8fc8264SDoug Lyons }
31*c8fc8264SDoug Lyons 
ResourceToFile(INT i,LPCSTR FileName)32*c8fc8264SDoug Lyons BOOL ResourceToFile(INT i, LPCSTR FileName)
33*c8fc8264SDoug Lyons {
34*c8fc8264SDoug Lyons     FILE *fout;
35*c8fc8264SDoug Lyons     HGLOBAL hData;
36*c8fc8264SDoug Lyons     HRSRC hRes;
37*c8fc8264SDoug Lyons     LPVOID lpResLock;
38*c8fc8264SDoug Lyons     UINT iSize;
39*c8fc8264SDoug Lyons 
40*c8fc8264SDoug Lyons     if (FileExists(FileName))
41*c8fc8264SDoug Lyons     {
42*c8fc8264SDoug Lyons         skip("'%s' already exists. Exiting now\n", FileName);
43*c8fc8264SDoug Lyons         return FALSE;
44*c8fc8264SDoug Lyons     }
45*c8fc8264SDoug Lyons 
46*c8fc8264SDoug Lyons     hRes = FindResourceW(NULL, MAKEINTRESOURCEW(i), MAKEINTRESOURCEW(RT_RCDATA));
47*c8fc8264SDoug Lyons     if (hRes == NULL)
48*c8fc8264SDoug Lyons     {
49*c8fc8264SDoug Lyons         skip("Could not locate resource (%d). Exiting now\n", i);
50*c8fc8264SDoug Lyons         return FALSE;
51*c8fc8264SDoug Lyons     }
52*c8fc8264SDoug Lyons 
53*c8fc8264SDoug Lyons     iSize = SizeofResource(NULL, hRes);
54*c8fc8264SDoug Lyons 
55*c8fc8264SDoug Lyons     hData = LoadResource(NULL, hRes);
56*c8fc8264SDoug Lyons     if (hData == NULL)
57*c8fc8264SDoug Lyons     {
58*c8fc8264SDoug Lyons         skip("Could not load resource (%d). Exiting now\n", i);
59*c8fc8264SDoug Lyons         return FALSE;
60*c8fc8264SDoug Lyons     }
61*c8fc8264SDoug Lyons 
62*c8fc8264SDoug Lyons     // Lock the resource into global memory.
63*c8fc8264SDoug Lyons     lpResLock = LockResource(hData);
64*c8fc8264SDoug Lyons     if (lpResLock == NULL)
65*c8fc8264SDoug Lyons     {
66*c8fc8264SDoug Lyons         skip("Could not lock resource (%d). Exiting now\n", i);
67*c8fc8264SDoug Lyons         return FALSE;
68*c8fc8264SDoug Lyons     }
69*c8fc8264SDoug Lyons 
70*c8fc8264SDoug Lyons     fout = fopen(FileName, "wb");
71*c8fc8264SDoug Lyons     fwrite(lpResLock, iSize, 1, fout);
72*c8fc8264SDoug Lyons     fclose(fout);
73*c8fc8264SDoug Lyons     return TRUE;
74*c8fc8264SDoug Lyons }
75*c8fc8264SDoug Lyons 
768ec05f5fSBișoc George EXTRACTICONTESTS IconTests[] =
778ec05f5fSBișoc George {
788ec05f5fSBișoc George     /* Executable file with icon */
798ec05f5fSBișoc George     {L"%SystemRoot%\\System32\\cmd.exe", 1},
808ec05f5fSBișoc George 
818ec05f5fSBișoc George     /* Executable file without icon */
828ec05f5fSBișoc George     {L"%SystemRoot%\\System32\\autochk.exe", 0},
838ec05f5fSBișoc George 
848ec05f5fSBișoc George     /* Non-existing files */
85*c8fc8264SDoug Lyons     {L"%SystemRoot%\\non-existent-file.sdf", 0},
86*c8fc8264SDoug Lyons 
87*c8fc8264SDoug Lyons     /* Multiple icons in the same EXE file (18 icons) */
88*c8fc8264SDoug Lyons     {L"%SystemRoot%\\explorer.exe", 18},
89*c8fc8264SDoug Lyons 
90*c8fc8264SDoug Lyons     /* Multiple icons in the same ICO file (6 icons)
91*c8fc8264SDoug Lyons      * Per MS: If the file is an .ico file, the return value is 1. */
92*c8fc8264SDoug Lyons     {L"sysicon.ico", 1},
93*c8fc8264SDoug Lyons 
94*c8fc8264SDoug Lyons     /* ICO file with both normal and PNG icons */
95*c8fc8264SDoug Lyons     {L"ROS.ico", 0}
968ec05f5fSBișoc George };
978ec05f5fSBișoc George 
START_TEST(ExtractIconEx)988ec05f5fSBișoc George START_TEST(ExtractIconEx)
998ec05f5fSBișoc George {
100*c8fc8264SDoug Lyons     UINT i, nReturnedIcons, nExtractedIcons;
101*c8fc8264SDoug Lyons     CHAR FileName[2][13] = { "ROS.ico", "sysicon.ico" };
1028ec05f5fSBișoc George 
103*c8fc8264SDoug Lyons     if (!ResourceToFile(2, FileName[0]))
104*c8fc8264SDoug Lyons         return;
105*c8fc8264SDoug Lyons     if (!ResourceToFile(3, FileName[1]))
106*c8fc8264SDoug Lyons         return;
107*c8fc8264SDoug Lyons 
108*c8fc8264SDoug Lyons     /* Check count of icons returned */
1098ec05f5fSBișoc George     for (i = 0; i < _countof(IconTests); ++i)
1108ec05f5fSBișoc George     {
111*c8fc8264SDoug Lyons         nReturnedIcons = ExtractIconExW(IconTests[i].pszFilePath, -1, NULL, NULL, 0);
112*c8fc8264SDoug Lyons         ok(nReturnedIcons == IconTests[i].nIcons, "ExtractIconExW(%u): Expects %u icons, got %u\n", i, IconTests[i].nIcons, nReturnedIcons);
1138ec05f5fSBișoc George     }
114*c8fc8264SDoug Lyons 
115*c8fc8264SDoug Lyons     /* Check if the 0th icon can be extracted successfully */
116*c8fc8264SDoug Lyons     for (i = 0; i < _countof(IconTests); ++i)
117*c8fc8264SDoug Lyons     {
118*c8fc8264SDoug Lyons         nExtractedIcons = ExtractIconExW(IconTests[i].pszFilePath, 0, NULL, NULL, 1);
119*c8fc8264SDoug Lyons         ok(nExtractedIcons == IconTests[i].nIcons, "ExtractIconExW(%u): Expects %u icons, got %u\n", i, IconTests[i].nIcons, nExtractedIcons);
120*c8fc8264SDoug Lyons     }
121*c8fc8264SDoug Lyons 
122*c8fc8264SDoug Lyons     DeleteFileA(FileName[0]);
123*c8fc8264SDoug Lyons     DeleteFileA(FileName[1]);
1248ec05f5fSBișoc George }
125