1 /*
2 * PROJECT: ReactOS api tests
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: Test the result of enumerating over a folder with a zip in it
5 * COPYRIGHT: Copyright 2020-2023 Mark Jansen (mark.jansen@reactos.org)
6 */
7
8 #include "precomp.h"
9
10 struct FileInfo
11 {
12 LPCWSTR Name;
13 SFGAOF Attributes;
14 bool Found;
15 };
16
zipfldr_loaded()17 int zipfldr_loaded()
18 {
19 return GetModuleHandleA("zipfldr.dll") ? TRUE : FALSE;
20 }
21
FindExpectedFile(FileInfo * Array,size_t len,IShellFolder * pFolder,PCUITEMID_CHILD pidl,LPCWSTR & ExpectedName,SFGAOF & ExpectedAttributes)22 void FindExpectedFile(FileInfo* Array, size_t len, IShellFolder* pFolder, PCUITEMID_CHILD pidl, LPCWSTR& ExpectedName, SFGAOF& ExpectedAttributes)
23 {
24 ExpectedName = L"<WRONG FILE>";
25 ExpectedAttributes = (SFGAOF)~0;
26
27 STRRET NameRet;
28 HRESULT hr;
29
30 hr = pFolder->GetDisplayNameOf(pidl, SHGDN_NORMAL, &NameRet);
31 ok_hr(hr, S_OK);
32 if (!SUCCEEDED(hr))
33 return;
34
35 WCHAR DisplayName[MAX_PATH];
36 hr = StrRetToBufW(&NameRet, pidl, DisplayName, RTL_NUMBER_OF(DisplayName));
37 ok_hr(hr, S_OK);
38 if (!SUCCEEDED(hr))
39 return;
40
41 for (size_t n = 0; n < len; ++n)
42 {
43 if (!_wcsicmp(Array[n].Name, DisplayName) && !Array[n].Found)
44 {
45 Array[n].Found = true;
46 ExpectedName = Array[n].Name;
47 ExpectedAttributes = Array[n].Attributes;
48 return;
49 }
50 }
51 }
52
53 const SFGAOF BaseFileAttributes = SFGAO_FILESYSTEM;
54 const SFGAOF BaseFolderAttributes = SFGAO_FILESYSTEM | SFGAO_FOLDER;
55 FileInfo ExpectedFiles[] = {
56 { L"test.txt", BaseFileAttributes, false },
57 { L"TMP0.zip", BaseFileAttributes, false}, // 2k3 Shows this as a file, newer shows this as a folder
58 { L"ASUBFLD", BaseFolderAttributes | SFGAO_FILESYSANCESTOR | SFGAO_STORAGEANCESTOR, false },
59 };
60 BOOL FoundZipfldr = FALSE;
61
62 static void
test_EnumDirFiles(const WCHAR * TestFolder,BOOL EnumFolders)63 test_EnumDirFiles(const WCHAR *TestFolder, BOOL EnumFolders)
64 {
65 CComPtr<IShellFolder> spFolder;
66 if (!InitializeShellFolder(TestFolder, spFolder))
67 return;
68
69 CComPtr<IEnumIDList> spEnum;
70 ok_int(zipfldr_loaded(), FoundZipfldr);
71 HRESULT hr = spFolder->EnumObjects(NULL, EnumFolders ? SHCONTF_FOLDERS : SHCONTF_NONFOLDERS, &spEnum);
72 ok_hr(hr, S_OK);
73 if (!SUCCEEDED(hr))
74 return;
75 ok_int(zipfldr_loaded(), FoundZipfldr);
76
77 do
78 {
79 CComHeapPtr<ITEMID_CHILD> child;
80 ULONG celtFetched = 0;
81 ok_int(zipfldr_loaded(), FoundZipfldr);
82 hr = spEnum->Next(1, &child, &celtFetched);
83 ok_int(zipfldr_loaded(), FoundZipfldr);
84 if (hr != S_OK)
85 break;
86 ok_int(celtFetched, 1);
87 if (celtFetched != 1)
88 break;
89
90 LPCWSTR ExpectedName;
91 SFGAOF ExpectedAttributes;
92 FindExpectedFile(ExpectedFiles, RTL_NUMBER_OF(ExpectedFiles), spFolder, child, ExpectedName, ExpectedAttributes);
93
94 ok_int(zipfldr_loaded(), FoundZipfldr);
95 ok_displayname(spFolder, child, SHGDN_NORMAL, ExpectedName);
96 ok_int(zipfldr_loaded(), FoundZipfldr);
97
98 SFGAOF Attributes = SFGAO_FILESYSANCESTOR | SFGAO_FOLDER | SFGAO_FILESYSTEM | SFGAO_HASSUBFOLDER;
99 hr = spFolder->GetAttributesOf(1, &child, &Attributes);
100
101 if (!_wcsicmp(ExpectedName, L"TMP0.zip"))
102 {
103 // We allow both .zip files being a 'file' (2k3) or a 'folder' (win10)
104 if (Attributes & SFGAO_FOLDER)
105 ExpectedAttributes |= SFGAO_FOLDER;
106 // Only at this point (after calling GetAttributesOf) it will load zipfldr
107 FoundZipfldr = TRUE;
108 trace("Found zip (%S)\n", ExpectedName);
109 }
110 ok_int(zipfldr_loaded(), FoundZipfldr);
111
112 /* Just keep the ones we are interested in */
113 Attributes &= (SFGAO_FILESYSTEM | SFGAO_FOLDER | SFGAO_FILESYSANCESTOR | SFGAO_STORAGEANCESTOR);
114 ok_hr(hr, S_OK);
115 ok_hex(Attributes, ExpectedAttributes);
116 } while (true);
117
118 ok_hr(hr, S_FALSE);
119 ok_int(zipfldr_loaded(), FoundZipfldr);
120 }
121
122
START_TEST(EnumParentDir)123 START_TEST(EnumParentDir)
124 {
125 HRESULT hr = CoInitialize(NULL);
126
127 ok_hr(hr, S_OK);
128 if (!SUCCEEDED(hr))
129 return;
130
131 ok_int(zipfldr_loaded(), FALSE);
132
133 WCHAR TestFolder[MAX_PATH], TestFile[MAX_PATH], SubFolder[MAX_PATH];
134 GetTempPathW(_countof(TestFolder), TestFolder);
135 PathAppendW(TestFolder, L"ZipDir");
136 PathAddBackslashW(TestFolder);
137
138 CreateDirectoryW(TestFolder, NULL);
139
140 WCHAR ZipTestFile[MAX_PATH];
141 if (!extract_resource(ZipTestFile, MAKEINTRESOURCEW(IDR_ZIP_TEST_FILE), TestFolder))
142 {
143 RemoveDirectoryW(TestFolder);
144 return;
145 }
146
147 StringCchPrintfW(TestFile, _countof(TestFile), L"%stest.txt", TestFolder);
148
149 HANDLE hFile = CreateFileW(TestFile, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_NEW, FILE_FLAG_DELETE_ON_CLOSE, NULL);
150
151 ok(hFile != INVALID_HANDLE_VALUE, "Error creating %S\n", TestFile);
152 if (hFile != INVALID_HANDLE_VALUE)
153 {
154 StringCchPrintfW(SubFolder, _countof(SubFolder), L"%sASUBFLD", TestFolder);
155
156 CreateDirectoryW(SubFolder, NULL);
157
158 winetest_push_context("Files");
159 test_EnumDirFiles(TestFolder, FALSE);
160 winetest_pop_context();
161 winetest_push_context("Folders");
162 test_EnumDirFiles(TestFolder, TRUE);
163 winetest_pop_context();
164
165 for (size_t n = 0; n < RTL_NUMBER_OF(ExpectedFiles); ++n)
166 {
167 ok(ExpectedFiles[n].Found, "Did not find %S\n", ExpectedFiles[n].Name);
168 }
169
170 RemoveDirectoryW(SubFolder);
171
172 CloseHandle(hFile);
173 }
174
175 DeleteFileW(ZipTestFile);
176 RemoveDirectoryW(TestFolder);
177 CoUninitialize();
178 }
179