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 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 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 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 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 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