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
write_raw_file(const WCHAR * FileName,const void * Data,DWORD Size)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
extract_resource(WCHAR * Filename,LPCWSTR ResourceName,WCHAR * ParentFolder)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
InitializeShellFolder_(const char * file,int line,const WCHAR * Filename,CComPtr<IShellFolder> & spFolder)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)
GetFirstDataObject_(const char * file,int line,IShellFolder * spFolder,SHCONTF grfFlags,CComPtr<IDataObject> & 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
IsFormatAdvertised_(const char * file,int line,IDataObject * pDataObj,CLIPFORMAT cfFormat,TYMED tymed)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
test_FileDescriptor(FILEGROUPDESCRIPTORW * Descriptor)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
test_FileDescriptor_Folder(FILEGROUPDESCRIPTORW * Descriptor)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_;
test_FileContents1(IStream * Stream)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
test_FileContents2(IStream * Stream)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
test_DataObject_FirstFile(IShellFolder * pFolder)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
test_DataObject_FirstFolder(IShellFolder * pFolder)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
test_DataObject(const WCHAR * Filename)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
START_TEST(IDataObject)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