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 #ifndef FILE_ATTRIBUTE_VIRTUAL 11 #define FILE_ATTRIBUTE_VIRTUAL 0x10000 12 #endif 13 14 DEFINE_GUID(CLSID_ZipFolderContextMenu, 0xb8cdcb65, 0xb1bf, 0x4b42, 0x94, 0x28, 0x1d, 0xfd, 0xb7, 0xee, 0x92, 0xaf); 15 16 17 static bool g_bOldZipfldr; 18 const char test_file_1_contents[] = "Some generic text in the root file.\r\nMore text on a new line."; 19 const char test_file_2_contents[] = "Some generic text in the file in folder_1.\r\nMore text on a new line."; 20 21 static BOOL write_raw_file(const WCHAR* FileName, const void* Data, DWORD Size) 22 { 23 BOOL Success; 24 DWORD dwWritten; 25 HANDLE Handle = CreateFileW(FileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 26 27 if (Handle == INVALID_HANDLE_VALUE) 28 { 29 skip("Failed to create temp file %ls, error %lu\n", FileName, GetLastError()); 30 return FALSE; 31 } 32 Success = WriteFile(Handle, Data, Size, &dwWritten, NULL); 33 ok(Success == TRUE, "WriteFile failed with %lu\n", GetLastError()); 34 ok(dwWritten == Size, "WriteFile wrote %lu bytes instead of %lu\n", dwWritten, Size); 35 CloseHandle(Handle); 36 return Success && (dwWritten == Size); 37 } 38 39 BOOL extract_resource(WCHAR* Filename, LPCWSTR ResourceName, WCHAR* ParentFolder) 40 { 41 WCHAR workdir[MAX_PATH]; 42 UINT TickMask = 0xffff; 43 if (!ParentFolder) 44 { 45 GetTempPathW(_countof(workdir), workdir); 46 ParentFolder = workdir; 47 } 48 else 49 { 50 // Fixed filename 51 TickMask = 0; 52 } 53 StringCchPrintfW(Filename, MAX_PATH, L"%sTMP%u.zip", ParentFolder, GetTickCount() & TickMask); 54 55 HMODULE hMod = GetModuleHandleW(NULL); 56 HRSRC hRsrc = FindResourceW(hMod, ResourceName, MAKEINTRESOURCEW(RT_RCDATA)); 57 ok(!!hRsrc, "Unable to find %s\n", wine_dbgstr_w(ResourceName)); 58 if (!hRsrc) 59 return FALSE; 60 61 HGLOBAL hGlobal = LoadResource(hMod, hRsrc); 62 DWORD Size = SizeofResource(hMod, hRsrc); 63 LPVOID pData = LockResource(hGlobal); 64 65 ok(Size && !!pData, "Unable to load %s\n", wine_dbgstr_w(ResourceName)); 66 if (!Size || !pData) 67 return FALSE; 68 69 BOOL Written = write_raw_file(Filename, pData, Size); 70 UnlockResource(pData); 71 return Written; 72 } 73 74 bool InitializeShellFolder_(const char* file, int line, const WCHAR* Filename, CComPtr<IShellFolder>& spFolder) 75 { 76 CComHeapPtr<ITEMIDLIST_ABSOLUTE> pidl; 77 HRESULT hr; 78 ok_hr_(file, line, (hr = SHParseDisplayName(Filename, NULL, &pidl, 0, NULL)), S_OK); 79 if (!SUCCEEDED(hr)) 80 return false; 81 82 CComPtr<IShellFolder> spParent; 83 PCUIDLIST_RELATIVE pidlLast; 84 ok_hr_(file, line, (hr = SHBindToParent(pidl, IID_PPV_ARG(IShellFolder, &spParent), &pidlLast)), S_OK); 85 if (!SUCCEEDED(hr)) 86 return false; 87 88 ok_hr_(file, line, (hr = spParent->BindToObject(pidlLast, 0, IID_PPV_ARG(IShellFolder, &spFolder))), S_OK); 89 90 return SUCCEEDED(hr); 91 } 92 93 #define GetFirstDataObject(spFolder, grfFlags, spData) GetFirstDataObject_(__FILE__, __LINE__, spFolder, grfFlags, spData) 94 static bool GetFirstDataObject_(const char* file, int line, IShellFolder* spFolder, SHCONTF grfFlags, CComPtr<IDataObject>& spData) 95 { 96 CComPtr<IEnumIDList> spEnum; 97 HRESULT hr; 98 ok_hr_(file, line, (hr = spFolder->EnumObjects(NULL, grfFlags, &spEnum)), S_OK); 99 if (!SUCCEEDED(hr)) 100 return false; 101 102 CComHeapPtr<ITEMID_CHILD> child; 103 ULONG celtFetched = 0; 104 ok_hr_(file, line, (hr = spEnum->Next(1, &child, &celtFetched)), S_OK); 105 ok_int_(file, line, celtFetched, 1); 106 if (!SUCCEEDED(hr)) 107 return false; 108 109 // This call fails without the extension being '.zip' 110 ok_hr_(file, line, (hr = spFolder->GetUIObjectOf(NULL, 1, &child, IID_IDataObject, NULL, reinterpret_cast<LPVOID*>(&spData))), S_OK); 111 return SUCCEEDED(hr); 112 } 113 114 bool IsFormatAdvertised_(const char* file, int line, IDataObject* pDataObj, CLIPFORMAT cfFormat, TYMED tymed) 115 { 116 CComPtr<IEnumFORMATETC> pEnumFmt; 117 HRESULT hr = pDataObj->EnumFormatEtc(DATADIR_GET, &pEnumFmt); 118 119 ok_hex_(file, line, hr, S_OK); 120 if (!SUCCEEDED(hr)) 121 return false; 122 123 FORMATETC fmt; 124 while (S_OK == (hr = pEnumFmt->Next(1, &fmt, NULL))) 125 { 126 if (fmt.cfFormat == cfFormat) 127 { 128 ok_hex_(file, line, fmt.lindex, -1); 129 if (tymed) 130 ok_hex_(file, line, fmt.tymed, tymed); 131 return true; 132 } 133 } 134 ok_hex_(file, line, hr, S_FALSE); 135 return false; 136 } 137 138 #if 0 139 #define DumpDataObjectFormats(pDataObj) DumpDataObjectFormats_(__FILE__, __LINE__, pDataObj) 140 static inline void DumpDataObjectFormats_(const char* file, int line, IDataObject* pDataObj) 141 { 142 CComPtr<IEnumFORMATETC> pEnumFmt; 143 HRESULT hr = pDataObj->EnumFormatEtc(DATADIR_GET, &pEnumFmt); 144 145 if (FAILED_UNEXPECTEDLY(hr)) 146 return; 147 148 FORMATETC fmt; 149 while (S_OK == pEnumFmt->Next(1, &fmt, NULL)) 150 { 151 char szBuf[512]; 152 GetClipboardFormatNameA(fmt.cfFormat, szBuf, sizeof(szBuf)); 153 trace_(file, line)("Format: %s\n", szBuf); 154 trace_(file, line)(" Tymed: %u\n", fmt.tymed); 155 if (fmt.tymed & TYMED_HGLOBAL) 156 { 157 trace_(file, line)(" TYMED_HGLOBAL supported\n"); 158 } 159 } 160 } 161 #endif 162 163 static void test_FileDescriptor(FILEGROUPDESCRIPTORW* Descriptor) 164 { 165 ok_int(Descriptor->cItems, 1u); 166 if (Descriptor->cItems > 0) 167 { 168 FILETIME LocalFileTime, FileTime; 169 WORD Mask = g_bOldZipfldr ? 0xffe0 : (0xffff); // bits 0-4 are the seconds 170 DosDateTimeToFileTime(0x5024, (0xa5f2 & Mask), &LocalFileTime); 171 LocalFileTimeToFileTime(&LocalFileTime, &FileTime); 172 173 FILEDESCRIPTORW* FileDescriptor = Descriptor->fgd; 174 ok_hex(FileDescriptor->dwFlags, FD_ATTRIBUTES | FD_WRITESTIME | FD_FILESIZE | FD_PROGRESSUI); 175 ok_hex(FileDescriptor->dwFileAttributes, FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_VIRTUAL); 176 ok_hex(FileDescriptor->ftLastWriteTime.dwHighDateTime, FileTime.dwHighDateTime); 177 ok_hex(FileDescriptor->ftLastWriteTime.dwLowDateTime, FileTime.dwLowDateTime); 178 ok_hex(FileDescriptor->nFileSizeHigh, 0); 179 ok_hex(FileDescriptor->nFileSizeLow, strlen(test_file_1_contents)); 180 ok_wstr(FileDescriptor->cFileName, L"test_file_for_zip.txt"); 181 } 182 } 183 184 static void test_FileDescriptor_Folder(FILEGROUPDESCRIPTORW* Descriptor) 185 { 186 ok_int(Descriptor->cItems, 2u); 187 if (Descriptor->cItems > 0) 188 { 189 FILETIME LocalFileTime, FileTime; 190 WORD Mask = g_bOldZipfldr ? 0xffe0 : (0xffff); // bits 0-4 are the seconds 191 DosDateTimeToFileTime(0x5024, (0xa5fc & Mask), &LocalFileTime); 192 LocalFileTimeToFileTime(&LocalFileTime, &FileTime); 193 194 FILEDESCRIPTORW* FileDescriptor = Descriptor->fgd; 195 ok_hex(FileDescriptor->dwFlags, FD_ATTRIBUTES | FD_WRITESTIME | FD_FILESIZE | FD_PROGRESSUI); 196 ok(FileDescriptor->dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY || 197 FileDescriptor->dwFileAttributes == (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_VIRTUAL), "Got attr: 0x%lx\n", FileDescriptor->dwFileAttributes); 198 //ok_hex(FileDescriptor->dwFileAttributes, FILE_ATTRIBUTE_DIRECTORY); 199 ok_hex(FileDescriptor->ftLastWriteTime.dwHighDateTime, FileTime.dwHighDateTime); 200 ok_hex(FileDescriptor->ftLastWriteTime.dwLowDateTime, FileTime.dwLowDateTime); 201 ok_hex(FileDescriptor->nFileSizeHigh, 0); 202 ok_hex(FileDescriptor->nFileSizeLow, 0); 203 ok_wstr(FileDescriptor->cFileName, L"folder_1"); 204 205 if (Descriptor->cItems > 1) 206 { 207 DosDateTimeToFileTime(0x5024, (0xa60d & Mask), &LocalFileTime); 208 LocalFileTimeToFileTime(&LocalFileTime, &FileTime); 209 210 FileDescriptor = Descriptor->fgd + 1; 211 ok_hex(FileDescriptor->dwFlags, FD_ATTRIBUTES | FD_WRITESTIME | FD_FILESIZE | FD_PROGRESSUI); 212 ok_hex(FileDescriptor->dwFileAttributes, FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_VIRTUAL); 213 ok_hex(FileDescriptor->ftLastWriteTime.dwHighDateTime, FileTime.dwHighDateTime); 214 ok_hex(FileDescriptor->ftLastWriteTime.dwLowDateTime, FileTime.dwLowDateTime); 215 ok_hex(FileDescriptor->nFileSizeHigh, 0); 216 ok_hex(FileDescriptor->nFileSizeLow, strlen(test_file_2_contents)); 217 ok_wstr(FileDescriptor->cFileName, L"folder_1\\test_file_for_zip.txt"); 218 } 219 } 220 } 221 222 static GUID GUID_NULL_; 223 static void test_FileContents1(IStream* Stream) 224 { 225 STATSTG statstg = {0}; 226 HRESULT hr = Stream->Stat(&statstg, STATFLAG_DEFAULT); 227 ok_hex(hr, g_bOldZipfldr ? E_NOTIMPL : S_OK); 228 if (SUCCEEDED(hr)) 229 { 230 FILETIME LocalFileTime, FileTime; 231 WORD Mask = g_bOldZipfldr ? 0xffe0 : (0xffff); // bits 0-4 are the seconds 232 DosDateTimeToFileTime(0x5024, (0xa5f2 & Mask), &LocalFileTime); 233 LocalFileTimeToFileTime(&LocalFileTime, &FileTime); 234 235 ok_wstr(statstg.pwcsName, L"test_file_for_zip.txt"); 236 ok_hex(statstg.type, STGTY_STREAM); 237 ok_int(statstg.cbSize.LowPart, strlen(test_file_1_contents)); 238 ok_hex(statstg.cbSize.HighPart, 0); 239 ok_hex(statstg.mtime.dwHighDateTime, FileTime.dwHighDateTime); 240 ok_hex(statstg.mtime.dwLowDateTime, FileTime.dwLowDateTime); 241 ok_hex(statstg.ctime.dwHighDateTime, FileTime.dwHighDateTime); 242 ok_hex(statstg.ctime.dwLowDateTime, FileTime.dwLowDateTime); 243 ok_hex(statstg.atime.dwHighDateTime, FileTime.dwHighDateTime); 244 ok_hex(statstg.atime.dwLowDateTime, FileTime.dwLowDateTime); 245 ok_hex(statstg.grfMode, STGM_SHARE_DENY_WRITE); 246 ok_hex(statstg.grfLocksSupported, 0); 247 ok(!memcmp(&statstg.clsid, &GUID_NULL_, sizeof(GUID_NULL_)), "Expected GUID_NULL, got %s\n", wine_dbgstr_guid(&statstg.clsid)); 248 ok_hex(statstg.grfStateBits, 0); 249 CoTaskMemFree(statstg.pwcsName); 250 } 251 252 LARGE_INTEGER Offset = { {0} }; 253 ULARGE_INTEGER NewPosition = { {0} }; 254 hr = Stream->Seek(Offset, STREAM_SEEK_CUR, &NewPosition); 255 ok_hex(hr, g_bOldZipfldr ? E_NOTIMPL : S_OK); 256 ok_int(NewPosition.HighPart, 0); 257 ok_int(NewPosition.LowPart, 0); 258 259 char buf[100] = { 0 }; 260 ULONG cbRead; 261 hr = Stream->Read(buf, sizeof(buf)-1, &cbRead); 262 ok_hex(hr, S_FALSE); 263 ok_int(cbRead, strlen(test_file_1_contents)); 264 ok_str(buf, test_file_1_contents); 265 266 hr = Stream->Seek(Offset, STREAM_SEEK_CUR, &NewPosition); 267 ok_hex(hr, g_bOldZipfldr ? E_NOTIMPL : S_OK); 268 ok_int(NewPosition.HighPart, 0); 269 if (SUCCEEDED(hr)) 270 ok_int(NewPosition.LowPart, strlen(test_file_1_contents)); 271 272 ULONG cbWritten; 273 hr = Stream->Write("DUMMY", 5, &cbWritten); 274 if (!g_bOldZipfldr) 275 { 276 ok_hex(hr, STG_E_ACCESSDENIED); 277 } 278 else 279 { 280 // Write succeeds, but is not reflected in the file on disk 281 ok_hex(hr, S_OK); 282 } 283 284 // Can increase the size... 285 NewPosition.LowPart = statstg.cbSize.LowPart + 1; 286 hr = Stream->SetSize(NewPosition); 287 ok_hex(hr, g_bOldZipfldr ? E_NOTIMPL : S_OK); 288 289 // But is not reflected in the Stat result 290 hr = Stream->Stat(&statstg, STATFLAG_DEFAULT); 291 ok_hex(hr, g_bOldZipfldr ? E_NOTIMPL : S_OK); 292 if (SUCCEEDED(hr)) 293 { 294 ok_int(statstg.cbSize.LowPart, strlen(test_file_1_contents)); 295 CoTaskMemFree(statstg.pwcsName); 296 } 297 298 // Old zipfldr does not support seek, so we can not read it again 299 if (!g_bOldZipfldr) 300 { 301 Offset.QuadPart = 0; 302 hr = Stream->Seek(Offset, STREAM_SEEK_SET, &NewPosition); 303 ok_hex(hr, S_OK); 304 305 memset(buf, 0, sizeof(buf)); 306 hr = Stream->Read(buf, sizeof(buf)-1, &cbRead); 307 ok_hex(hr, S_FALSE); 308 ok_int(cbRead, strlen(test_file_1_contents)); 309 } 310 } 311 312 313 static void test_FileContents2(IStream* Stream) 314 { 315 STATSTG statstg = {0}; 316 HRESULT hr = Stream->Stat(&statstg, STATFLAG_DEFAULT); 317 ok_hex(hr, g_bOldZipfldr ? E_NOTIMPL : S_OK); 318 if (SUCCEEDED(hr)) 319 { 320 FILETIME LocalFileTime, FileTime; 321 WORD Mask = g_bOldZipfldr ? 0xffe0 : (0xffff); // bits 0-4 are the seconds 322 DosDateTimeToFileTime(0x5024, (0xa60d & Mask), &LocalFileTime); 323 LocalFileTimeToFileTime(&LocalFileTime, &FileTime); 324 325 ok_wstr(statstg.pwcsName, L"test_file_for_zip.txt"); 326 ok_hex(statstg.type, STGTY_STREAM); 327 ok_int(statstg.cbSize.LowPart, strlen(test_file_2_contents)); 328 ok_hex(statstg.cbSize.HighPart, 0); 329 ok_hex(statstg.mtime.dwHighDateTime, FileTime.dwHighDateTime); 330 ok_hex(statstg.mtime.dwLowDateTime, FileTime.dwLowDateTime); 331 ok_hex(statstg.ctime.dwHighDateTime, FileTime.dwHighDateTime); 332 ok_hex(statstg.ctime.dwLowDateTime, FileTime.dwLowDateTime); 333 ok_hex(statstg.atime.dwHighDateTime, FileTime.dwHighDateTime); 334 ok_hex(statstg.atime.dwLowDateTime, FileTime.dwLowDateTime); 335 ok_hex(statstg.grfMode, STGM_SHARE_DENY_WRITE); 336 ok_hex(statstg.grfLocksSupported, 0); 337 ok(!memcmp(&statstg.clsid, &GUID_NULL_, sizeof(GUID_NULL_)), "Expected GUID_NULL, got %s\n", wine_dbgstr_guid(&statstg.clsid)); 338 ok_hex(statstg.grfStateBits, 0); 339 CoTaskMemFree(statstg.pwcsName); 340 } 341 342 LARGE_INTEGER Offset = { {0} }; 343 ULARGE_INTEGER NewPosition = { {0} }; 344 hr = Stream->Seek(Offset, STREAM_SEEK_CUR, &NewPosition); 345 ok_hex(hr, g_bOldZipfldr ? E_NOTIMPL : S_OK); 346 ok_int(NewPosition.HighPart, 0); 347 ok_int(NewPosition.LowPart, 0); 348 349 char buf[100] = { 0 }; 350 ULONG cbRead; 351 hr = Stream->Read(buf, sizeof(buf)-1, &cbRead); 352 ok_hex(hr, S_FALSE); 353 ok_int(cbRead, strlen(test_file_2_contents)); 354 ok_str(buf, test_file_2_contents); 355 356 hr = Stream->Seek(Offset, STREAM_SEEK_CUR, &NewPosition); 357 ok_hex(hr, g_bOldZipfldr ? E_NOTIMPL : S_OK); 358 ok_int(NewPosition.HighPart, 0); 359 if (SUCCEEDED(hr)) 360 ok_int(NewPosition.LowPart, strlen(test_file_2_contents)); 361 362 ULONG cbWritten; 363 hr = Stream->Write("DUMMY", 5, &cbWritten); 364 if (!g_bOldZipfldr) 365 { 366 ok_hex(hr, STG_E_ACCESSDENIED); 367 } 368 else 369 { 370 // Write succeeds, but is not reflected in the file on disk 371 ok_hex(hr, S_OK); 372 } 373 374 // Can increase the size... 375 NewPosition.LowPart = statstg.cbSize.LowPart + 1; 376 hr = Stream->SetSize(NewPosition); 377 ok_hex(hr, g_bOldZipfldr ? E_NOTIMPL : S_OK); 378 379 // But is not reflected in the Stat result 380 hr = Stream->Stat(&statstg, STATFLAG_DEFAULT); 381 ok_hex(hr, g_bOldZipfldr ? E_NOTIMPL : S_OK); 382 if (SUCCEEDED(hr)) 383 { 384 ok_int(statstg.cbSize.LowPart, strlen(test_file_2_contents)); 385 CoTaskMemFree(statstg.pwcsName); 386 } 387 388 // Old zipfldr does not support seek, so we can not read it again 389 if (!g_bOldZipfldr) 390 { 391 Offset.QuadPart = 0; 392 hr = Stream->Seek(Offset, STREAM_SEEK_SET, &NewPosition); 393 ok_hex(hr, S_OK); 394 395 memset(buf, 0, sizeof(buf)); 396 hr = Stream->Read(buf, sizeof(buf)-1, &cbRead); 397 ok_hex(hr, S_FALSE); 398 ok_int(cbRead, strlen(test_file_2_contents)); 399 ok_str(buf, test_file_2_contents); 400 } 401 } 402 403 404 405 static CLIPFORMAT cfHIDA = RegisterClipboardFormatA(CFSTR_SHELLIDLISTA); 406 static CLIPFORMAT cfFileDescriptor = RegisterClipboardFormatW(CFSTR_FILEDESCRIPTORW); 407 static CLIPFORMAT cfFileContents = RegisterClipboardFormatW(CFSTR_FILECONTENTSW); 408 409 static void test_DataObject_FirstFile(IShellFolder* pFolder) 410 { 411 CComPtr<IDataObject> spDataObj; 412 if (!GetFirstDataObject(pFolder, SHCONTF_NONFOLDERS, spDataObj)) 413 return; 414 415 if (!IsFormatAdvertised(spDataObj, cfHIDA, TYMED_HGLOBAL)) 416 { 417 trace("Pre-Vista zipfldr\n"); 418 // No seconds in filetimes, less functional IStream* implementation 419 g_bOldZipfldr = true; 420 } 421 422 ok(!IsFormatAdvertised(spDataObj, CF_HDROP, TYMED_NULL), "Expected CF_HDROP to be absent\n"); 423 ok(IsFormatAdvertised(spDataObj, cfFileDescriptor, TYMED_HGLOBAL), "Expected FileDescriptorW to be supported\n"); 424 ok(IsFormatAdvertised(spDataObj, cfFileContents, TYMED_ISTREAM), "Expected FileContents to be supported\n"); 425 426 STGMEDIUM medium = {0}; 427 FORMATETC etc = { cfFileDescriptor, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; 428 HRESULT hr = spDataObj->GetData(&etc, &medium); 429 ok_hex(hr, S_OK); 430 if (!SUCCEEDED(hr)) 431 return; 432 433 ok_hex(medium.tymed, TYMED_HGLOBAL); 434 PVOID pData = GlobalLock(medium.hGlobal); 435 test_FileDescriptor(static_cast<FILEGROUPDESCRIPTORW*>(pData)); 436 GlobalUnlock(medium.hGlobal); 437 ReleaseStgMedium(&medium); 438 439 // Invalid index 440 etc.cfFormat = cfFileContents; 441 etc.ptd = NULL; 442 etc.dwAspect = DVASPECT_CONTENT; 443 etc.lindex = -1; 444 etc.tymed = TYMED_ISTREAM; 445 memset(&medium, 0xcc, sizeof(medium)); 446 hr = spDataObj->GetData(&etc, &medium); 447 ok_hex(hr, E_INVALIDARG); 448 ok_hex(medium.tymed, TYMED_NULL); 449 ok_ptr(medium.hGlobal, NULL); 450 ok_ptr(medium.pUnkForRelease, NULL); 451 if (SUCCEEDED(hr)) 452 ReleaseStgMedium(&medium); 453 454 // Correct index 455 etc.cfFormat = cfFileContents; 456 etc.ptd = NULL; 457 etc.dwAspect = DVASPECT_CONTENT; 458 etc.lindex = 0; 459 etc.tymed = TYMED_ISTREAM; 460 memset(&medium, 0xcc, sizeof(medium)); 461 // During this call a temp file is created: %TMP%\Temp%u_%s\test_file_for_zip.txt 462 // Or for the 2k3 version: %TMP%\Temporary Directory %u for %s\test_file_for_zip.txt 463 hr = spDataObj->GetData(&etc, &medium); 464 ok_hex(hr, S_OK); 465 ok_hex(medium.tymed, TYMED_ISTREAM); 466 if (SUCCEEDED(hr)) 467 { 468 test_FileContents1(medium.pstm); 469 ReleaseStgMedium(&medium); 470 } 471 472 //if (winetest_get_failures()) 473 // DumpDataObjectFormats(spDataObj); 474 } 475 476 static void test_DataObject_FirstFolder(IShellFolder* pFolder) 477 { 478 CComPtr<IDataObject> spDataObj; 479 if (!GetFirstDataObject(pFolder, SHCONTF_FOLDERS, spDataObj)) 480 return; 481 482 ok(!IsFormatAdvertised(spDataObj, CF_HDROP, TYMED_NULL), "Expected CF_HDROP to be absent\n"); 483 ok(IsFormatAdvertised(spDataObj, cfFileDescriptor, TYMED_HGLOBAL), "Expected FileDescriptorW to be supported\n"); 484 ok(IsFormatAdvertised(spDataObj, cfFileContents, TYMED_ISTREAM), "Expected FileContents to be supported\n"); 485 // 7+ 486 ok(!!IsFormatAdvertised(spDataObj, cfHIDA, TYMED_HGLOBAL) != g_bOldZipfldr, "Expected HIDA to be %s\n", g_bOldZipfldr ? "absent" : "supported"); 487 488 STGMEDIUM medium = {0}; 489 FORMATETC etc = { cfFileDescriptor, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; 490 HRESULT hr = spDataObj->GetData(&etc, &medium); 491 ok_hex(hr, S_OK); 492 if (!SUCCEEDED(hr)) 493 return; 494 495 ok_hex(medium.tymed, TYMED_HGLOBAL); 496 PVOID pData = GlobalLock(medium.hGlobal); 497 test_FileDescriptor_Folder(static_cast<FILEGROUPDESCRIPTORW*>(pData)); 498 GlobalUnlock(medium.hGlobal); 499 ReleaseStgMedium(&medium); 500 501 // Invalid index 502 etc.cfFormat = cfFileContents; 503 etc.ptd = NULL; 504 etc.dwAspect = DVASPECT_CONTENT; 505 etc.lindex = -1; 506 etc.tymed = TYMED_ISTREAM; 507 memset(&medium, 0xcc, sizeof(medium)); 508 hr = spDataObj->GetData(&etc, &medium); 509 ok_hex(hr, E_INVALIDARG); 510 ok_hex(medium.tymed, TYMED_NULL); 511 ok_ptr(medium.hGlobal, NULL); 512 ok_ptr(medium.pUnkForRelease, NULL); 513 if (SUCCEEDED(hr)) 514 ReleaseStgMedium(&medium); 515 516 // Not a file (first index is the folder) 517 etc.cfFormat = cfFileContents; 518 etc.ptd = NULL; 519 etc.dwAspect = DVASPECT_CONTENT; 520 etc.lindex = 0; 521 etc.tymed = TYMED_ISTREAM; 522 memset(&medium, 0xcc, sizeof(medium)); 523 hr = spDataObj->GetData(&etc, &medium); 524 ok_hex(hr, E_FAIL); 525 ok_hex(medium.tymed, TYMED_NULL); 526 ok_ptr(medium.hGlobal, NULL); 527 ok_ptr(medium.pUnkForRelease, NULL); 528 if (SUCCEEDED(hr)) 529 ReleaseStgMedium(&medium); 530 531 // The file (content of the folder) 532 etc.cfFormat = cfFileContents; 533 etc.ptd = NULL; 534 etc.dwAspect = DVASPECT_CONTENT; 535 etc.lindex = 1; 536 etc.tymed = TYMED_ISTREAM; 537 memset(&medium, 0xcc, sizeof(medium)); 538 // During this call a temp file is created: %TMP%\Temp%u_%s\folder1\test_file_for_zip.txt 539 // Or for the 2k3 version: %TMP%\Temporary Directory %u for %s\folder1\test_file_for_zip.txt 540 hr = spDataObj->GetData(&etc, &medium); 541 ok_hex(hr, S_OK); 542 ok_hex(medium.tymed, TYMED_ISTREAM); 543 if (SUCCEEDED(hr)) 544 { 545 test_FileContents2(medium.pstm); 546 ReleaseStgMedium(&medium); 547 } 548 549 //if (winetest_get_failures()) 550 // DumpDataObjectFormats(spDataObj); 551 } 552 553 554 static void test_DataObject(const WCHAR* Filename) 555 { 556 CComPtr<IShellFolder> spFolder; 557 if (!InitializeShellFolder(Filename, spFolder)) 558 return; 559 560 test_DataObject_FirstFile(spFolder); 561 test_DataObject_FirstFolder(spFolder); 562 } 563 564 565 START_TEST(IDataObject) 566 { 567 skip("Code in zipfldr not implemented yet\n"); 568 return; 569 570 HRESULT hr = CoInitialize(NULL); 571 572 ok_hr(hr, S_OK); 573 if (!SUCCEEDED(hr)) 574 return; 575 576 WCHAR ZipTestFile[MAX_PATH]; 577 if (!extract_resource(ZipTestFile, MAKEINTRESOURCEW(IDR_ZIP_TEST_FILE), NULL)) 578 return; 579 test_DataObject(ZipTestFile); 580 DeleteFileW(ZipTestFile); 581 CoUninitialize(); 582 } 583