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 for zipfldr
5 * COPYRIGHT: Copyright 2020 Mark Jansen (mark.jansen@reactos.org)
6 */
7
8 #include "precomp.h"
9
10 static bool g_bOldZipfldr = false;
11
ok_displayname_(const char * file,int line,IShellFolder * pFolder,PCUITEMID_CHILD pidl,SHGDNF Flags,LPCWSTR Name)12 void ok_displayname_(const char* file, int line, IShellFolder* pFolder, PCUITEMID_CHILD pidl, SHGDNF Flags, LPCWSTR Name)
13 {
14 STRRET NameRet;
15 HRESULT hr;
16
17 hr = pFolder->GetDisplayNameOf(pidl, Flags, &NameRet);
18 ok_hr_(file, line, hr, S_OK);
19 if (!SUCCEEDED(hr))
20 return;
21
22 WCHAR DisplayName[MAX_PATH];
23 hr = StrRetToBufW(&NameRet, pidl, DisplayName, RTL_NUMBER_OF(DisplayName));
24 ok_hr_(file, line, hr, S_OK);
25 if (!SUCCEEDED(hr))
26 return;
27
28 ok_wstr_(file, line, DisplayName, Name);
29 }
30
31 struct ZipFiles
32 {
33 LPCWSTR Name;
34 SFGAOF Attributes;
35 };
36
37 static CLIPFORMAT cfHIDA = RegisterClipboardFormatA(CFSTR_SHELLIDLISTA);
38 static CLIPFORMAT cfFileDescriptor = RegisterClipboardFormatW(CFSTR_FILEDESCRIPTORW);
39
test_EnumObjects_Files(const WCHAR * Filename,IShellFolder * pFolder)40 static void test_EnumObjects_Files(const WCHAR* Filename, IShellFolder* pFolder)
41 {
42 CComPtr<IEnumIDList> spEnum;
43 HRESULT hr = pFolder->EnumObjects(NULL, SHCONTF_NONFOLDERS, &spEnum);
44 ok_hr(hr, S_OK);
45 if (!SUCCEEDED(hr))
46 return;
47
48 SFGAOF BaseAttributes = SFGAO_STREAM | SFGAO_HASPROPSHEET | SFGAO_CANDELETE | SFGAO_CANCOPY | SFGAO_CANMOVE;
49 ZipFiles ExpectedFiles[] = {
50 { L"cccc.txt", BaseAttributes },
51 { L"bbbb.txt", BaseAttributes },
52 };
53
54 ULONG totalFetched = 0;
55 do
56 {
57 CComHeapPtr<ITEMID_CHILD> child;
58 ULONG celtFetched = 0;
59 hr = spEnum->Next(1, &child, &celtFetched);
60 if (hr != S_OK)
61 break;
62 ok_int(celtFetched, 1);
63 if (celtFetched != 1)
64 break;
65
66 LPCWSTR ExpectedName = totalFetched < RTL_NUMBER_OF(ExpectedFiles) ? ExpectedFiles[totalFetched].Name : L"<TOO MANY FILES>";
67 SFGAOF ExpectedAttributes = totalFetched < RTL_NUMBER_OF(ExpectedFiles) ? ExpectedFiles[totalFetched].Attributes : 0xdeaddead;
68
69 totalFetched++;
70
71
72 CComPtr<IDataObject> spDataObj;
73 hr = pFolder->GetUIObjectOf(NULL, 1, &child, IID_IDataObject, NULL, reinterpret_cast<LPVOID*>(&spDataObj));
74 ok_hr(hr, S_OK);
75
76 if (!g_bOldZipfldr && !IsFormatAdvertised(spDataObj, cfHIDA, TYMED_HGLOBAL))
77 {
78 trace("Pre-Vista zipfldr\n");
79 // No seconds in filetimes, less functional IStream* implementation
80 g_bOldZipfldr = true;
81 }
82
83 ok_displayname(pFolder, child, SHGDN_NORMAL, ExpectedName);
84 if (g_bOldZipfldr)
85 {
86 ok_displayname(pFolder, child, SHGDN_FORPARSING, ExpectedName);
87 }
88 else
89 {
90 WCHAR Buffer[MAX_PATH];
91 StringCchPrintfW(Buffer, _countof(Buffer), L"%s\\%s", Filename, ExpectedName);
92 ok_displayname(pFolder, child, SHGDN_FORPARSING, Buffer);
93 }
94 ok_displayname(pFolder, child, SHGDN_FORPARSING | SHGDN_INFOLDER, ExpectedName);
95 ok_displayname(pFolder, child, SHGDN_FOREDITING , ExpectedName);
96 ok_displayname(pFolder, child, SHGDN_FOREDITING | SHGDN_INFOLDER, ExpectedName);
97 ok_displayname(pFolder, child, SHGDN_FORADDRESSBAR , ExpectedName);
98 ok_displayname(pFolder, child, SHGDN_FORADDRESSBAR | SHGDN_INFOLDER, ExpectedName);
99
100 SFGAOF Attributes = 0;
101 hr = pFolder->GetAttributesOf(1, &child, &Attributes);
102 ok_hr(hr, S_OK);
103 ok_hex(Attributes, ExpectedAttributes);
104
105 STGMEDIUM medium = {0};
106 FORMATETC etc = { cfFileDescriptor, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
107 HRESULT hr = spDataObj->GetData(&etc, &medium);
108 ok_hex(hr, S_OK);
109 if (!SUCCEEDED(hr))
110 continue;
111
112 ok_hex(medium.tymed, TYMED_HGLOBAL);
113 PVOID pData = GlobalLock(medium.hGlobal);
114 FILEGROUPDESCRIPTORW* Descriptor = static_cast<FILEGROUPDESCRIPTORW*>(pData);
115 ok_hex(Descriptor->cItems, 1);
116 if (Descriptor->cItems == 1)
117 ok_wstr(Descriptor->fgd[0].cFileName, ExpectedName);
118 GlobalUnlock(medium.hGlobal);
119 ReleaseStgMedium(&medium);
120 } while (true);
121
122 ok_int(totalFetched, RTL_NUMBER_OF(ExpectedFiles));
123 ok_hr(hr, S_FALSE);
124 }
125
test_EnumObjects_Folders(const WCHAR * Filename,IShellFolder * pFolder)126 static void test_EnumObjects_Folders(const WCHAR* Filename, IShellFolder* pFolder)
127 {
128 CComPtr<IEnumIDList> spEnum;
129 HRESULT hr = pFolder->EnumObjects(NULL, SHCONTF_FOLDERS, &spEnum);
130 ok_hr(hr, S_OK);
131 if (!SUCCEEDED(hr))
132 return;
133
134 SFGAOF BaseAttributes = SFGAO_FOLDER | SFGAO_DROPTARGET | SFGAO_HASPROPSHEET | SFGAO_CANDELETE | SFGAO_CANCOPY | SFGAO_CANMOVE;
135 ZipFiles ExpectedFolders[] = {
136 { L"aaaa", BaseAttributes | (g_bOldZipfldr ? 0 : SFGAO_STORAGE) },
137 { L"cccc", BaseAttributes | (g_bOldZipfldr ? 0 : SFGAO_STORAGE) },
138 };
139
140 LPCWSTR ExpectedExtraFiles[2][4] =
141 {
142 {
143 L"aaaa\\a_aaaa",
144 L"aaaa\\a_cccc",
145 L"aaaa\\a_bbbb.txt",
146 L"aaaa\\a_cccc.txt",
147 },
148 {
149 L"cccc\\c_cccc",
150 L"cccc\\c_bbbb.txt",
151 L"cccc\\c_cccc.txt",
152 L"cccc\\c_aaaa",
153 },
154 };
155
156 ULONG totalFetched = 0;
157 do
158 {
159 CComHeapPtr<ITEMID_CHILD> child;
160 ULONG celtFetched = 0;
161 hr = spEnum->Next(1, &child, &celtFetched);
162 if (hr != S_OK)
163 break;
164 ok_int(celtFetched, 1);
165 if (celtFetched != 1)
166 break;
167
168 LPCWSTR ExpectedName = totalFetched < RTL_NUMBER_OF(ExpectedFolders) ? ExpectedFolders[totalFetched].Name : L"<TOO MANY FILES>";
169 SFGAOF ExpectedAttributes = totalFetched < RTL_NUMBER_OF(ExpectedFolders) ? ExpectedFolders[totalFetched].Attributes : 0xdeaddead;
170 LPCWSTR* ExtraFiles = totalFetched < RTL_NUMBER_OF(ExpectedExtraFiles) ? ExpectedExtraFiles[totalFetched] : ExpectedExtraFiles[0];
171
172 totalFetched++;
173
174 ok_displayname(pFolder, child, SHGDN_NORMAL, ExpectedName);
175 if (g_bOldZipfldr)
176 {
177 ok_displayname(pFolder, child, SHGDN_FORPARSING, ExpectedName);
178 }
179 else
180 {
181 WCHAR Buffer[MAX_PATH];
182 StringCchPrintfW(Buffer, _countof(Buffer), L"%s\\%s", Filename, ExpectedName);
183 ok_displayname(pFolder, child, SHGDN_FORPARSING, Buffer);
184 }
185 ok_displayname(pFolder, child, SHGDN_FORPARSING | SHGDN_INFOLDER, ExpectedName);
186 ok_displayname(pFolder, child, SHGDN_FOREDITING , ExpectedName);
187 ok_displayname(pFolder, child, SHGDN_FOREDITING | SHGDN_INFOLDER, ExpectedName);
188
189 SFGAOF Attributes = 0;
190 hr = pFolder->GetAttributesOf(1, &child, &Attributes);
191 ok_hr(hr, S_OK);
192 ok_hex(Attributes, ExpectedAttributes);
193
194 CComPtr<IDataObject> spData;
195 hr = pFolder->GetUIObjectOf(NULL, 1, &child, IID_IDataObject, NULL, reinterpret_cast<LPVOID*>(&spData));
196 ok_hr(hr, S_OK);
197
198 STGMEDIUM medium = {0};
199 FORMATETC etc = { cfFileDescriptor, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
200 HRESULT hr = spData->GetData(&etc, &medium);
201 ok_hex(hr, S_OK);
202 if (!SUCCEEDED(hr))
203 continue;
204
205 ok_hex(medium.tymed, TYMED_HGLOBAL);
206 PVOID pData = GlobalLock(medium.hGlobal);
207 FILEGROUPDESCRIPTORW* Descriptor = static_cast<FILEGROUPDESCRIPTORW*>(pData);
208 ok_hex(Descriptor->cItems, 5);
209 if (Descriptor->cItems == 5)
210 {
211 ok_wstr(Descriptor->fgd[0].cFileName, ExpectedName);
212 ok_wstr(Descriptor->fgd[1].cFileName, ExtraFiles[0]);
213 ok_wstr(Descriptor->fgd[2].cFileName, ExtraFiles[1]);
214 ok_wstr(Descriptor->fgd[3].cFileName, ExtraFiles[2]);
215 ok_wstr(Descriptor->fgd[4].cFileName, ExtraFiles[3]);
216 }
217 GlobalUnlock(medium.hGlobal);
218 ReleaseStgMedium(&medium);
219 } while (true);
220
221 ok_int(totalFetched, RTL_NUMBER_OF(ExpectedFolders));
222 ok_hr(hr, S_FALSE);
223 }
224
test_EnumObjects(const WCHAR * Filename)225 static void test_EnumObjects(const WCHAR* Filename)
226 {
227 CComPtr<IShellFolder> spFolder;
228 if (!InitializeShellFolder(Filename, spFolder))
229 return;
230
231 // Let's ask the shell how it wants to display the full path to our zip file
232 WCHAR ZipFilename[MAX_PATH] = L"<Failed to query zip path>";
233 {
234 CComPtr<IPersistFolder2> spPersistFolder;
235 HRESULT hr = spFolder->QueryInterface(IID_PPV_ARG(IPersistFolder2, &spPersistFolder));
236 ok_hr(hr, S_OK);
237 if (SUCCEEDED(hr))
238 {
239 CComHeapPtr<ITEMIDLIST_ABSOLUTE> zipPidl;
240 hr = spPersistFolder->GetCurFolder(&zipPidl);
241 ok_hr(hr, S_OK);
242 if (SUCCEEDED(hr))
243 {
244 BOOL bHasPath = SHGetPathFromIDListW(zipPidl, ZipFilename);
245 ok_int(bHasPath, TRUE);
246 }
247 }
248 }
249
250
251 test_EnumObjects_Files(ZipFilename, spFolder);
252 test_EnumObjects_Folders(ZipFilename, spFolder);
253 }
254
START_TEST(EnumObjects)255 START_TEST(EnumObjects)
256 {
257 skip("Code in zipfldr not implemented yet\n");
258 return;
259
260 HRESULT hr = CoInitialize(NULL);
261
262 ok_hr(hr, S_OK);
263 if (!SUCCEEDED(hr))
264 return;
265
266 WCHAR ZipTestFile[MAX_PATH];
267 if (!extract_resource(ZipTestFile, MAKEINTRESOURCEW(IDR_ZIP_TEST_ENUM), NULL))
268 return;
269 test_EnumObjects(ZipTestFile);
270 DeleteFileW(ZipTestFile);
271 CoUninitialize();
272 }
273