756b7691dff4f9ec22b4759cad32ba554eea84b2
[reactos.git] / modules / rostests / winetests / ole32 / storage32.c
1 /*
2 * Unit tests for OLE storage
3 *
4 * Copyright (c) 2004 Mike McCormack
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21 #include "precomp.h"
22
23 #include <initguid.h>
24
25 DEFINE_GUID( test_stg_cls, 0x88888888, 0x0425, 0x0000, 0,0,0,0,0,0,0,0);
26
27 #define ok_ole_success(hr, func) ok(hr == S_OK, func " failed with error 0x%08x\n", hr)
28
29 static CHAR filenameA[MAX_PATH];
30 static WCHAR filename[MAX_PATH];
31
32 static const char file1_nameA[] = {'c','o','p','y','t','e','s','t','A',0};
33 static const WCHAR file1_name[] = {'c','o','p','y','t','e','s','t','A',0};
34 static const char file2_nameA[] = {'c','o','p','y','t','e','s','t','B',0};
35 static const WCHAR file2_name[] = {'c','o','p','y','t','e','s','t','B',0};
36 static const WCHAR stgA_name[] = {'S','t','o','r','a','g','e','A',0};
37 static const WCHAR stgB_name[] = {'S','t','o','r','a','g','e','B',0};
38 static const WCHAR strmA_name[] = {'S','t','r','e','a','m','A',0};
39 static const WCHAR strmB_name[] = {'S','t','r','e','a','m','B',0};
40 static const WCHAR strmC_name[] = {'S','t','r','e','a','m','C',0};
41
42 /* Win9x and WinMe don't have lstrcmpW */
43 static int strcmp_ww(LPCWSTR strw1, LPCWSTR strw2)
44 {
45 CHAR stra1[512], stra2[512];
46 WideCharToMultiByte(CP_ACP, 0, strw1, -1, stra1, sizeof(stra1), NULL, NULL);
47 WideCharToMultiByte(CP_ACP, 0, strw2, -1, stra2, sizeof(stra2), NULL, NULL);
48 return lstrcmpA(stra1, stra2);
49 }
50
51 typedef struct TestLockBytes {
52 ILockBytes ILockBytes_iface;
53 LONG ref;
54 BYTE* contents;
55 ULONG size;
56 ULONG buffer_size;
57 HRESULT lock_hr;
58 ULONG locks_supported;
59 ULONG lock_called;
60 } TestLockBytes;
61
62 static inline TestLockBytes *impl_from_ILockBytes(ILockBytes *iface)
63 {
64 return CONTAINING_RECORD(iface, TestLockBytes, ILockBytes_iface);
65 }
66
67 static HRESULT WINAPI TestLockBytes_QueryInterface(ILockBytes *iface, REFIID iid,
68 void **ppv)
69 {
70 TestLockBytes *This = impl_from_ILockBytes(iface);
71
72 if (!ppv) return E_INVALIDARG;
73
74 if (IsEqualIID(&IID_IUnknown, iid) ||
75 IsEqualIID(&IID_ILockBytes, iid))
76 *ppv = &This->ILockBytes_iface;
77 else
78 return E_NOINTERFACE;
79
80 IUnknown_AddRef((IUnknown*)*ppv);
81 return S_OK;
82 }
83
84 static ULONG WINAPI TestLockBytes_AddRef(ILockBytes *iface)
85 {
86 TestLockBytes *This = impl_from_ILockBytes(iface);
87 ULONG ref = InterlockedIncrement(&This->ref);
88 return ref;
89 }
90
91 static ULONG WINAPI TestLockBytes_Release(ILockBytes *iface)
92 {
93 TestLockBytes *This = impl_from_ILockBytes(iface);
94 ULONG ref = InterlockedDecrement(&This->ref);
95 return ref;
96 }
97
98 static HRESULT WINAPI TestLockBytes_ReadAt(ILockBytes *iface,
99 ULARGE_INTEGER ulOffset, void *pv, ULONG cb, ULONG *pcbRead)
100 {
101 TestLockBytes *This = impl_from_ILockBytes(iface);
102 ULONG dummy;
103
104 if (!pv) return E_INVALIDARG;
105
106 if (!pcbRead) pcbRead = &dummy;
107
108 if (ulOffset.QuadPart >= This->size)
109 {
110 *pcbRead = 0;
111 return S_OK;
112 }
113
114 cb = min(cb, This->size - ulOffset.QuadPart);
115
116 *pcbRead = cb;
117 memcpy(pv, &This->contents[ulOffset.QuadPart], cb);
118
119 return S_OK;
120 }
121
122 static HRESULT WINAPI TestLockBytes_WriteAt(ILockBytes *iface,
123 ULARGE_INTEGER ulOffset, const void *pv, ULONG cb, ULONG *pcbWritten)
124 {
125 TestLockBytes *This = impl_from_ILockBytes(iface);
126 HRESULT hr;
127 ULONG dummy;
128
129 if (!pv) return E_INVALIDARG;
130
131 if (!pcbWritten) pcbWritten = &dummy;
132
133 if (ulOffset.QuadPart + cb > This->size)
134 {
135 ULARGE_INTEGER new_size;
136 new_size.QuadPart = ulOffset.QuadPart + cb;
137 hr = ILockBytes_SetSize(iface, new_size);
138 if (FAILED(hr)) return hr;
139 }
140
141 *pcbWritten = cb;
142 memcpy(&This->contents[ulOffset.QuadPart], pv, cb);
143
144 return S_OK;
145 }
146
147 static HRESULT WINAPI TestLockBytes_Flush(ILockBytes *iface)
148 {
149 return S_OK;
150 }
151
152 static HRESULT WINAPI TestLockBytes_SetSize(ILockBytes *iface,
153 ULARGE_INTEGER cb)
154 {
155 TestLockBytes *This = impl_from_ILockBytes(iface);
156
157 if (This->buffer_size < cb.QuadPart)
158 {
159 ULONG new_buffer_size = max(This->buffer_size * 2, cb.QuadPart);
160 BYTE* new_buffer = HeapAlloc(GetProcessHeap(), 0, new_buffer_size);
161 if (!new_buffer) return E_OUTOFMEMORY;
162 memcpy(new_buffer, This->contents, This->size);
163 HeapFree(GetProcessHeap(), 0, This->contents);
164 This->contents = new_buffer;
165 }
166
167 if (cb.QuadPart > This->size)
168 memset(&This->contents[This->size], 0, cb.QuadPart - This->size);
169
170 This->size = cb.QuadPart;
171
172 return S_OK;
173 }
174
175 static HRESULT WINAPI TestLockBytes_LockRegion(ILockBytes *iface,
176 ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
177 {
178 TestLockBytes *This = impl_from_ILockBytes(iface);
179 This->lock_called++;
180 return This->lock_hr;
181 }
182
183 static HRESULT WINAPI TestLockBytes_UnlockRegion(ILockBytes *iface,
184 ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
185 {
186 TestLockBytes *This = impl_from_ILockBytes(iface);
187 return This->lock_hr;
188 }
189
190 static HRESULT WINAPI TestLockBytes_Stat(ILockBytes *iface,
191 STATSTG *pstatstg, DWORD grfStatFlag)
192 {
193 TestLockBytes *This = impl_from_ILockBytes(iface);
194 static const WCHAR dummy_name[] = {'d','u','m','m','y',0};
195
196 if (!pstatstg) return E_INVALIDARG;
197
198 memset(pstatstg, 0, sizeof(STATSTG));
199
200 if (!(grfStatFlag & STATFLAG_NONAME))
201 {
202 pstatstg->pwcsName = CoTaskMemAlloc(sizeof(dummy_name));
203 if (!pstatstg->pwcsName) return E_OUTOFMEMORY;
204 memcpy(pstatstg->pwcsName, dummy_name, sizeof(dummy_name));
205 }
206
207 pstatstg->type = STGTY_LOCKBYTES;
208 pstatstg->cbSize.QuadPart = This->size;
209 pstatstg->grfLocksSupported = This->locks_supported;
210
211 return S_OK;
212 }
213
214 static /* const */ ILockBytesVtbl TestLockBytes_Vtbl = {
215 TestLockBytes_QueryInterface,
216 TestLockBytes_AddRef,
217 TestLockBytes_Release,
218 TestLockBytes_ReadAt,
219 TestLockBytes_WriteAt,
220 TestLockBytes_Flush,
221 TestLockBytes_SetSize,
222 TestLockBytes_LockRegion,
223 TestLockBytes_UnlockRegion,
224 TestLockBytes_Stat
225 };
226
227 static void CreateTestLockBytes(TestLockBytes **This)
228 {
229 *This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(**This));
230
231 if (*This)
232 {
233 (*This)->ILockBytes_iface.lpVtbl = &TestLockBytes_Vtbl;
234 (*This)->ref = 1;
235 }
236 }
237
238 static void DeleteTestLockBytes(TestLockBytes *This)
239 {
240 ok(This->ILockBytes_iface.lpVtbl == &TestLockBytes_Vtbl, "test lock bytes %p deleted with incorrect vtable\n", This);
241 ok(This->ref == 1, "test lock bytes %p deleted with %i references instead of 1\n", This, This->ref);
242 HeapFree(GetProcessHeap(), 0, This->contents);
243 HeapFree(GetProcessHeap(), 0, This);
244 }
245
246 static void test_hglobal_storage_stat(void)
247 {
248 ILockBytes *ilb = NULL;
249 IStorage *stg = NULL;
250 HRESULT r;
251 STATSTG stat;
252 DWORD mode, refcount;
253
254 r = CreateILockBytesOnHGlobal( NULL, TRUE, &ilb );
255 ok( r == S_OK, "CreateILockBytesOnHGlobal failed\n");
256
257 r = StgIsStorageILockBytes( ilb );
258 ok( r == S_FALSE, "StgIsStorageILockBytes should have failed\n");
259
260 mode = STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE;/*0x1012*/
261 r = StgCreateDocfileOnILockBytes( ilb, mode, 0, &stg );
262 ok( r == S_OK, "StgCreateDocfileOnILockBytes failed\n");
263
264 r = WriteClassStg( stg, &test_stg_cls );
265 ok( r == S_OK, "WriteClassStg failed\n");
266
267 r = StgIsStorageILockBytes( ilb );
268 ok( r == S_OK, "StgIsStorageILockBytes failed\n");
269
270 memset( &stat, 0, sizeof stat );
271 r = IStorage_Stat( stg, &stat, 0 );
272
273 ok( stat.pwcsName == NULL, "storage name not null\n");
274 ok( stat.type == 1, "type is wrong\n");
275 ok( stat.grfMode == 0x12, "grf mode is incorrect\n");
276 ok( !memcmp(&stat.clsid, &test_stg_cls, sizeof test_stg_cls), "CLSID is wrong\n");
277
278 refcount = IStorage_Release( stg );
279 ok( refcount == 0, "IStorage refcount is wrong\n");
280 refcount = ILockBytes_Release( ilb );
281 ok( refcount == 0, "ILockBytes refcount is wrong\n");
282 }
283
284 static void test_create_storage_modes(void)
285 {
286 IStorage *stg = NULL;
287 HRESULT r;
288
289 DeleteFileA(filenameA);
290
291 /* test with some invalid parameters */
292 r = StgCreateDocfile( NULL, 0, 0, &stg);
293 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
294 r = StgCreateDocfile( filename, 0, 0, &stg);
295 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
296 r = StgCreateDocfile( filename, STGM_CREATE, 0, &stg);
297 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
298 r = StgCreateDocfile( filename, STGM_CREATE | STGM_READWRITE, 0, &stg);
299 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
300 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE, 0, &stg);
301 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
302 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, NULL);
303 ok(r==STG_E_INVALIDPOINTER, "StgCreateDocfile succeeded\n");
304 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 1, &stg);
305 ok(r==STG_E_INVALIDPARAMETER, "StgCreateDocfile succeeded\n");
306 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_DENY_WRITE | STGM_READWRITE, 0, &stg);
307 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
308 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READ, 0, &stg);
309 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
310 r = StgCreateDocfile( filename, STGM_PRIORITY, 0, &stg);
311 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
312
313 /* StgCreateDocfile seems to be very particular about the flags it accepts */
314 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED | STGM_WRITE, 0, &stg);
315 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
316 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED | 8, 0, &stg);
317 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
318 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED | 0x80, 0, &stg);
319 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
320 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED | 0x800, 0, &stg);
321 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
322 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED | 0x8000, 0, &stg);
323 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
324 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED | 0x80000, 0, &stg);
325 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
326 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED | 0x800000, 0, &stg);
327 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
328 ok(stg == NULL, "stg was set\n");
329
330 /* check what happens if the file already exists (which is how it's meant to be used) */
331 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &stg);
332 ok(r==S_OK, "StgCreateDocfile failed\n");
333 r = IStorage_Release(stg);
334 ok(r == 0, "storage not released\n");
335 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
336 ok(r==STG_E_FILEALREADYEXISTS, "StgCreateDocfile wrong error\n"); /* FAILIFTHERE is default */
337 r = StgCreateDocfile( filename, STGM_READ, 0, &stg);
338 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n"); /* need at least readmode and sharemode */
339 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE, 0, &stg);
340 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
341 r = StgCreateDocfile( filename, STGM_SHARE_DENY_WRITE, 0, &stg);
342 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
343 r = StgCreateDocfile( filename, STGM_SHARE_DENY_NONE, 0, &stg);
344 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile failed\n");
345 r = StgCreateDocfile( filename, STGM_SHARE_DENY_NONE | STGM_TRANSACTED, 0, &stg);
346 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile failed\n");
347 r = StgCreateDocfile( filename, STGM_SHARE_DENY_NONE | STGM_READWRITE, 0, &stg);
348 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile failed\n");
349 r = StgCreateDocfile( filename, STGM_SHARE_DENY_NONE | STGM_WRITE, 0, &stg);
350 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile failed\n");
351 r = StgCreateDocfile( filename, STGM_SHARE_DENY_WRITE | STGM_WRITE, 0, &stg);
352 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile failed\n");
353 r = StgCreateDocfile( filename, STGM_SHARE_DENY_WRITE | STGM_READ, 0, &stg);
354 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile wrong error\n");
355 r = StgCreateDocfile( filename, STGM_TRANSACTED | STGM_SHARE_DENY_WRITE | STGM_READ, 0, &stg);
356 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile wrong error\n");
357 ok(DeleteFileA(filenameA), "failed to delete file\n");
358
359 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
360 ok(r==S_OK, "StgCreateDocfile failed\n");
361 r = IStorage_Release(stg);
362 ok(r == 0, "storage not released\n");
363 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED |STGM_FAILIFTHERE, 0, &stg);
364 ok(r==STG_E_FILEALREADYEXISTS, "StgCreateDocfile wrong error\n");
365 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_WRITE, 0, &stg);
366 ok(r==STG_E_FILEALREADYEXISTS, "StgCreateDocfile wrong error\n");
367
368 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_DENY_WRITE | STGM_READWRITE, 0, &stg);
369 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
370 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
371 ok(r==S_OK, "StgCreateDocfile failed\n");
372 r = IStorage_Release(stg);
373 ok(r == 0, "storage not released\n");
374 ok(DeleteFileA(filenameA), "failed to delete file\n");
375
376 r = StgCreateDocfile( filename, STGM_CREATE | STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
377 ok(r==S_OK, "StgCreateDocfile failed\n");
378 r = IStorage_Release(stg);
379 ok(r == 0, "storage not released\n");
380 ok(DeleteFileA(filenameA), "failed to delete file\n");
381
382 /* test the way excel uses StgCreateDocFile */
383 r = StgCreateDocfile( filename, STGM_TRANSACTED|STGM_CREATE|STGM_SHARE_DENY_WRITE|STGM_READWRITE, 0, &stg);
384 ok(r==S_OK, "StgCreateDocfile the excel way failed\n");
385 if(r == S_OK)
386 {
387 r = IStorage_Release(stg);
388 ok(r == 0, "storage not released\n");
389 ok(DeleteFileA(filenameA), "failed to delete file\n");
390 }
391
392 /* and the way windows media uses it ... */
393 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_DENY_NONE | STGM_READWRITE | STGM_TRANSACTED, 0, &stg);
394 ok(r==S_OK, "StgCreateDocfile the windows media way failed\n");
395 if (r == S_OK)
396 {
397 r = IStorage_Release(stg);
398 ok(r == 0, "storage not released\n");
399 ok(DeleteFileA(filenameA), "failed to delete file\n");
400 }
401
402 /* looks like we need STGM_TRANSACTED or STGM_CREATE */
403 r = StgCreateDocfile( filename, STGM_TRANSACTED|STGM_SHARE_DENY_WRITE|STGM_READWRITE, 0, &stg);
404 ok(r==S_OK, "StgCreateDocfile the excel way failed\n");
405 if(r == S_OK)
406 {
407 r = IStorage_Release(stg);
408 ok(r == 0, "storage not released\n");
409 ok(DeleteFileA(filenameA), "failed to delete file\n");
410 }
411
412 r = StgCreateDocfile( filename, STGM_TRANSACTED|STGM_CREATE|STGM_SHARE_DENY_WRITE|STGM_WRITE, 0, &stg);
413 ok(r==S_OK, "StgCreateDocfile the excel way failed\n");
414 if(r == S_OK)
415 {
416 r = IStorage_Release(stg);
417 ok(r == 0, "storage not released\n");
418 ok(DeleteFileA(filenameA), "failed to delete file\n");
419 }
420
421 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &stg);
422 ok(r==S_OK, "StgCreateDocfile the powerpoint way failed\n");
423 if(r == S_OK)
424 {
425 r = IStorage_Release(stg);
426 ok(r == 0, "storage not released\n");
427 ok(DeleteFileA(filenameA), "failed to delete file\n");
428 }
429
430 /* test the way msi uses StgCreateDocfile */
431 r = StgCreateDocfile( filename, STGM_DIRECT | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &stg);
432 ok(r==S_OK, "StgCreateDocFile failed\n");
433 r = IStorage_Release(stg);
434 ok(r == 0, "storage not released\n");
435 ok(DeleteFileA(filenameA), "failed to delete file\n");
436 }
437
438 static void test_stgcreatestorageex(void)
439 {
440 HRESULT (WINAPI *pStgCreateStorageEx)(const WCHAR* pwcsName, DWORD grfMode, DWORD stgfmt, DWORD grfAttrs, STGOPTIONS* pStgOptions, void* reserved, REFIID riid, void** ppObjectOpen);
441 HMODULE hOle32 = GetModuleHandleA("ole32");
442 IStorage *stg = NULL;
443 STGOPTIONS stgoptions = {1, 0, 4096};
444 HRESULT r;
445
446 pStgCreateStorageEx = (void *) GetProcAddress(hOle32, "StgCreateStorageEx");
447 if (!pStgCreateStorageEx)
448 {
449 win_skip("skipping test on NT4\n");
450 return;
451 }
452
453 DeleteFileA(filenameA);
454
455 /* Verify that StgCreateStorageEx can accept an options param */
456 r = pStgCreateStorageEx( filename,
457 STGM_SHARE_EXCLUSIVE | STGM_READWRITE,
458 STGFMT_DOCFILE,
459 0,
460 &stgoptions,
461 NULL,
462 &IID_IStorage,
463 (void **) &stg);
464 ok(r==S_OK || r==STG_E_UNIMPLEMENTEDFUNCTION, "StgCreateStorageEx with options failed\n");
465 if (r==STG_E_UNIMPLEMENTEDFUNCTION)
466 {
467 /* We're on win98 which means all bets are off. Let's get out of here. */
468 win_skip("skipping test on win9x\n");
469 return;
470 }
471
472 r = IStorage_Release(stg);
473 ok(r == 0, "storage not released\n");
474 ok(DeleteFileA(filenameA), "failed to delete file\n");
475
476 /* Verify that StgCreateStorageEx can accept a NULL pStgOptions */
477 r = pStgCreateStorageEx( filename,
478 STGM_SHARE_EXCLUSIVE | STGM_READWRITE,
479 STGFMT_STORAGE,
480 0,
481 NULL,
482 NULL,
483 &IID_IStorage,
484 (void **) &stg);
485 ok(r==S_OK, "StgCreateStorageEx with NULL options failed\n");
486 r = IStorage_Release(stg);
487 ok(r == 0, "storage not released\n");
488 ok(DeleteFileA(filenameA), "failed to delete file\n");
489 }
490
491 static void test_storage_stream(void)
492 {
493 static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 };
494 static const WCHAR longname[] = {
495 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
496 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',0
497 };
498 IStorage *stg = NULL;
499 HRESULT r;
500 IStream *stm = NULL;
501 IStream *stm2 = NULL;
502 ULONG count = 0;
503 LARGE_INTEGER pos;
504 ULARGE_INTEGER p;
505 unsigned char buffer[0x100];
506 IUnknown *unk;
507 BOOL ret;
508
509 DeleteFileA(filenameA);
510
511 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
512 ok(r==S_OK, "StgCreateDocfile failed\n");
513
514 /* try create some invalid streams */
515 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 1, 0, &stm );
516 ok(r==STG_E_INVALIDPARAMETER, "IStorage->CreateStream wrong error\n");
517 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 1, &stm );
518 ok(r==STG_E_INVALIDPARAMETER, "IStorage->CreateStream wrong error\n");
519 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, NULL );
520 ok(r==STG_E_INVALIDPOINTER, "IStorage->CreateStream wrong error\n");
521 r = IStorage_CreateStream(stg, NULL, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
522 ok(r==STG_E_INVALIDNAME, "IStorage->CreateStream wrong error\n");
523 r = IStorage_CreateStream(stg, longname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
524 ok(r==STG_E_INVALIDNAME || broken(r==S_OK) /* nt4 */,
525 "IStorage->CreateStream wrong error, got %d GetLastError()=%d\n", r, GetLastError());
526 r = IStorage_CreateStream(stg, stmname, STGM_READWRITE, 0, 0, &stm );
527 ok(r==STG_E_INVALIDFLAG, "IStorage->CreateStream wrong error\n");
528 r = IStorage_CreateStream(stg, stmname, STGM_READ, 0, 0, &stm );
529 ok(r==STG_E_INVALIDFLAG, "IStorage->CreateStream wrong error\n");
530 r = IStorage_CreateStream(stg, stmname, STGM_WRITE, 0, 0, &stm );
531 ok(r==STG_E_INVALIDFLAG, "IStorage->CreateStream wrong error\n");
532 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_DENY_NONE | STGM_READWRITE, 0, 0, &stm );
533 ok(r==STG_E_INVALIDFLAG, "IStorage->CreateStream wrong error\n");
534 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_DENY_NONE | STGM_READ, 0, 0, &stm );
535 ok(r==STG_E_INVALIDFLAG, "IStorage->CreateStream wrong error\n");
536
537 /* now really create a stream and delete it */
538 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
539 ok(r==S_OK, "IStorage->CreateStream failed\n");
540
541 /* test for support interfaces */
542 r = IStream_QueryInterface(stm, &IID_IPersist, (void**)&unk);
543 ok(r==E_NOINTERFACE, "got 0x%08x\n", r);
544 r = IStream_QueryInterface(stm, &IID_IPersistStream, (void**)&unk);
545 ok(r==E_NOINTERFACE, "got 0x%08x\n", r);
546
547 r = IStream_Release(stm);
548 ok(r == 0, "wrong ref count\n");
549 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
550 ok(r==STG_E_FILEALREADYEXISTS, "IStorage->CreateStream failed\n");
551 r = IStorage_DestroyElement(stg,stmname);
552 ok(r==S_OK, "IStorage->DestroyElement failed\n");
553
554 /* create a stream and write to it */
555 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
556 ok(r==S_OK, "IStorage->CreateStream failed\n");
557
558 r = IStream_Clone(stm, &stm2);
559 ok(r==S_OK, "failed to clone stream\n");
560
561 r = IStream_Write(stm, NULL, 0, NULL );
562 ok(r==STG_E_INVALIDPOINTER, "IStream->Write wrong error\n");
563 r = IStream_Write(stm, "Hello\n", 0, NULL );
564 ok(r==S_OK, "failed to write stream\n");
565 r = IStream_Write(stm, "Hello\n", 0, &count );
566 ok(r==S_OK, "failed to write stream\n");
567 r = IStream_Write(stm, "Hello\n", 6, &count );
568 ok(r==S_OK, "failed to write stream\n");
569 r = IStream_Commit(stm, STGC_DEFAULT );
570 ok(r==S_OK, "failed to commit stream\n");
571 r = IStream_Commit(stm, STGC_DEFAULT );
572 ok(r==S_OK, "failed to commit stream\n");
573
574 /* Read past the end of the stream. */
575 pos.QuadPart = 3;
576 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p );
577 ok(r==S_OK, "failed to seek stream\n");
578 ok(p.QuadPart == 3, "at wrong place\n");
579 r = IStream_Read(stm, buffer, sizeof buffer, &count );
580 ok(r==S_OK, "failed to read\n");
581 ok(count == 3, "read bytes past end of stream\n");
582 pos.QuadPart = 10;
583 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p );
584 ok(r==S_OK, "failed to seek stream\n");
585 ok(p.QuadPart == 10, "at wrong place\n");
586 r = IStream_Read(stm, buffer, sizeof buffer, &count );
587 ok(r==S_OK, "failed to read\n");
588 ok(count == 0, "read bytes past end of stream\n");
589 pos.QuadPart = 10000;
590 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p );
591 ok(r==S_OK, "failed to seek stream\n");
592 ok(p.QuadPart == 10000, "at wrong place\n");
593 r = IStream_Read(stm, buffer, sizeof buffer, &count );
594 ok(r==S_OK, "failed to read\n");
595 ok(count == 0, "read bytes past end of stream\n");
596
597 /* Convert to a big block stream, and read past the end. */
598 p.QuadPart = 5000;
599 r = IStream_SetSize(stm,p);
600 ok(r==S_OK, "failed to set pos\n");
601 pos.QuadPart = 4997;
602 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p );
603 ok(r==S_OK, "failed to seek stream\n");
604 ok(p.QuadPart == 4997, "at wrong place\n");
605 r = IStream_Read(stm, buffer, sizeof buffer, &count );
606 ok(r==S_OK, "failed to read\n");
607 ok(count == 3, "read bytes past end of stream\n");
608 pos.QuadPart = 5001;
609 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p );
610 ok(r==S_OK, "failed to seek stream\n");
611 ok(p.QuadPart == 5001, "at wrong place\n");
612 r = IStream_Read(stm, buffer, sizeof buffer, &count );
613 ok(r==S_OK, "failed to read\n");
614 ok(count == 0, "read bytes past end of stream\n");
615 pos.QuadPart = 10000;
616 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p );
617 ok(r==S_OK, "failed to seek stream\n");
618 ok(p.QuadPart == 10000, "at wrong place\n");
619 r = IStream_Read(stm, buffer, sizeof buffer, &count );
620 ok(r==S_OK, "failed to read\n");
621 ok(count == 0, "read bytes past end of stream\n");
622
623 /* seek round a bit, reset the stream size */
624 pos.QuadPart = 0;
625 r = IStream_Seek(stm, pos, 3, &p );
626 ok(r==STG_E_INVALIDFUNCTION, "IStream->Seek returned wrong error\n");
627 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, NULL);
628 ok(r==S_OK, "failed to seek stream\n");
629 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p );
630 ok(r==S_OK, "failed to seek stream\n");
631 r = IStream_SetSize(stm,p);
632 ok(r==S_OK, "failed to set pos\n");
633 pos.QuadPart = 10;
634 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p );
635 ok(r==S_OK, "failed to seek stream\n");
636 ok(p.QuadPart == 10, "at wrong place\n");
637 r = IStream_Read(stm, buffer, sizeof buffer, &count );
638 ok(r==S_OK, "failed to set pos\n");
639 ok(count == 0, "read bytes from empty stream\n");
640 pos.QuadPart = 10000;
641 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p );
642 ok(r==S_OK, "failed to seek stream\n");
643 ok(p.QuadPart == 10000, "at wrong place\n");
644 r = IStream_Read(stm, buffer, sizeof buffer, &count );
645 ok(r==S_OK, "failed to set pos\n");
646 ok(count == 0, "read bytes from empty stream\n");
647 pos.QuadPart = 0;
648 r = IStream_Seek(stm, pos, STREAM_SEEK_END, &p );
649 ok(r==S_OK, "failed to seek stream\n");
650 ok(p.QuadPart == 0, "at wrong place\n");
651 r = IStream_Read(stm, buffer, sizeof buffer, &count );
652 ok(r==S_OK, "failed to set pos\n");
653 ok(count == 0, "read bytes from empty stream\n");
654
655 /* wrap up */
656 r = IStream_Release(stm2);
657 ok(r == 0, "wrong ref count\n");
658
659 /* create a stream and write to it */
660 r = IStorage_CreateStream(stg, stmname, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm2 );
661 ok(r==S_OK, "IStorage->CreateStream failed\n");
662
663 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p);
664 ok(r==STG_E_REVERTED, "overwritten stream should return STG_E_REVERTED instead of 0x%08x\n", r);
665
666 r = IStream_Release(stm2);
667 ok(r == 0, "wrong ref count\n");
668 r = IStream_Release(stm);
669 ok(r == 0, "wrong ref count\n");
670
671 r = IStorage_Release(stg);
672 ok(r == 0, "wrong ref count\n");
673
674 /* try create some invalid streams */
675 stg = NULL;
676 stm = NULL;
677 r = StgOpenStorage(filename, NULL, STGM_READ | STGM_SHARE_DENY_WRITE, NULL, 0, &stg);
678 ok(r == S_OK, "should succeed\n");
679 if (stg)
680 {
681 r = IStorage_OpenStream(stg, stmname, NULL, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &stm);
682 ok(r == STG_E_INVALIDFLAG, "IStorage->OpenStream should return STG_E_INVALIDFLAG instead of 0x%08x\n", r);
683 IStorage_Release(stg);
684 }
685
686 ret = DeleteFileA(filenameA);
687 ok(ret, "file should exist\n");
688 }
689
690 static BOOL touch_file(LPCSTR filename)
691 {
692 HANDLE file;
693
694 file = CreateFileA(filename, GENERIC_READ|GENERIC_WRITE, 0, NULL,
695 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
696 if (file==INVALID_HANDLE_VALUE)
697 return FALSE;
698 CloseHandle(file);
699 return TRUE;
700 }
701
702 static BOOL is_zero_length(LPCSTR filename)
703 {
704 HANDLE file;
705 DWORD len;
706
707 file = CreateFileA(filename, GENERIC_READ, 0, NULL,
708 OPEN_EXISTING, 0, NULL);
709 if (file==INVALID_HANDLE_VALUE)
710 return FALSE;
711 len = GetFileSize(file, NULL);
712 CloseHandle(file);
713 return len == 0;
714 }
715
716 static BOOL is_existing_file(LPCSTR filename)
717 {
718 HANDLE file;
719
720 file = CreateFileA(filename, GENERIC_READ, 0, NULL,
721 OPEN_EXISTING, 0, NULL);
722 if (file==INVALID_HANDLE_VALUE)
723 return FALSE;
724 CloseHandle(file);
725 return TRUE;
726 }
727
728 static void test_open_storage(void)
729 {
730 static const WCHAR szNonExist[] = { 'n','o','n','e','x','i','s','t',0 };
731 IStorage *stg = NULL, *stg2 = NULL;
732 HRESULT r;
733 DWORD stgm;
734 BOOL ret;
735
736 /* try opening a zero length file - it should stay zero length */
737 DeleteFileA(filenameA);
738 touch_file(filenameA);
739 stgm = STGM_NOSCRATCH | STGM_TRANSACTED | STGM_SHARE_DENY_WRITE | STGM_READWRITE;
740 r = StgOpenStorage( filename, NULL, stgm, NULL, 0, &stg);
741 ok(r==STG_E_FILEALREADYEXISTS, "StgOpenStorage didn't fail\n");
742
743 stgm = STGM_SHARE_EXCLUSIVE | STGM_READWRITE;
744 r = StgOpenStorage( filename, NULL, stgm, NULL, 0, &stg);
745 ok(r==STG_E_FILEALREADYEXISTS, "StgOpenStorage didn't fail\n");
746 ok(is_zero_length(filenameA), "file length changed\n");
747
748 DeleteFileA(filenameA);
749
750 /* try opening a nonexistent file - it should not create it */
751 stgm = STGM_DIRECT | STGM_SHARE_EXCLUSIVE | STGM_READWRITE;
752 r = StgOpenStorage( filename, NULL, stgm, NULL, 0, &stg);
753 ok(r!=S_OK, "StgOpenStorage failed: 0x%08x\n", r);
754 if (r==S_OK) IStorage_Release(stg);
755 ok(!is_existing_file(filenameA), "StgOpenStorage should not create a file\n");
756 DeleteFileA(filenameA);
757
758 /* create the file */
759 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
760 ok(r==S_OK, "StgCreateDocfile failed\n");
761 IStorage_Release(stg);
762
763 r = StgOpenStorage( filename, NULL, 0, NULL, 0, &stg);
764 ok(r==STG_E_INVALIDFLAG, "StgOpenStorage wrong error\n");
765 r = StgOpenStorage( NULL, NULL, STGM_SHARE_EXCLUSIVE, NULL, 0, &stg);
766 ok(r==STG_E_INVALIDNAME, "StgOpenStorage wrong error\n");
767 r = StgOpenStorage( filename, NULL, STGM_SHARE_EXCLUSIVE | STGM_READ, NULL, 0, NULL);
768 ok(r==STG_E_INVALIDPOINTER, "StgOpenStorage wrong error\n");
769 r = StgOpenStorage( filename, NULL, STGM_SHARE_EXCLUSIVE | STGM_READ, NULL, 1, &stg);
770 ok(r==STG_E_INVALIDPARAMETER, "StgOpenStorage wrong error\n");
771 r = StgOpenStorage( szNonExist, NULL, STGM_SHARE_EXCLUSIVE | STGM_READ, NULL, 0, &stg);
772 ok(r==STG_E_FILENOTFOUND, "StgOpenStorage failed\n");
773 r = StgOpenStorage( filename, NULL, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READ, NULL, 0, &stg);
774 ok(r==STG_E_INVALIDFLAG, "StgOpenStorage failed\n");
775 r = StgOpenStorage( filename, NULL, STGM_SHARE_DENY_NONE | STGM_READ, NULL, 0, &stg);
776 ok(r==STG_E_INVALIDFLAG, "StgOpenStorage failed\n");
777 r = StgOpenStorage( filename, NULL, STGM_SHARE_DENY_READ | STGM_READ, NULL, 0, &stg);
778 ok(r==STG_E_INVALIDFLAG, "StgOpenStorage failed\n");
779 r = StgOpenStorage( filename, NULL, STGM_SHARE_DENY_WRITE | STGM_READWRITE, NULL, 0, &stg);
780 ok(r==STG_E_INVALIDFLAG, "StgOpenStorage failed\n");
781
782 /* open it for real */
783 r = StgOpenStorage( filename, NULL, STGM_SHARE_DENY_NONE | STGM_READ | STGM_TRANSACTED, NULL, 0, &stg); /* XLViewer 97/2000 */
784 ok(r==S_OK, "StgOpenStorage failed\n");
785 if(stg)
786 {
787 r = IStorage_Release(stg);
788 ok(r == 0, "wrong ref count\n");
789 }
790
791 r = StgOpenStorage( filename, NULL, STGM_SHARE_DENY_WRITE | STGM_READ, NULL, 0, &stg);
792 ok(r==S_OK, "StgOpenStorage failed\n");
793 if(stg)
794 {
795 r = IStorage_Release(stg);
796 ok(r == 0, "wrong ref count\n");
797 }
798
799 /* test the way word opens its custom dictionary */
800 r = StgOpenStorage( filename, NULL, STGM_NOSCRATCH | STGM_TRANSACTED |
801 STGM_SHARE_DENY_WRITE | STGM_READWRITE, NULL, 0, &stg);
802 ok(r==S_OK, "StgOpenStorage failed\n");
803 if(stg)
804 {
805 r = IStorage_Release(stg);
806 ok(r == 0, "wrong ref count\n");
807 }
808
809 r = StgOpenStorage( filename, NULL, STGM_SHARE_EXCLUSIVE | STGM_READ, NULL, 0, &stg);
810 ok(r==S_OK, "StgOpenStorage failed\n");
811 r = StgOpenStorage( filename, NULL, STGM_SHARE_EXCLUSIVE | STGM_READ, NULL, 0, &stg2);
812 ok(r==STG_E_SHAREVIOLATION, "StgOpenStorage failed\n");
813 if(stg)
814 {
815 r = IStorage_Release(stg);
816 ok(r == 0, "wrong ref count\n");
817 }
818
819 /* now try write to a storage file we opened read-only */
820 r = StgOpenStorage( filename, NULL, STGM_SHARE_EXCLUSIVE | STGM_READ, NULL, 0, &stg);
821 ok(r==S_OK, "StgOpenStorage failed\n");
822 if(stg)
823 {
824 static const WCHAR stmname[] = { 'w','i','n','e','t','e','s','t',0};
825 IStream *stm = NULL;
826 IStorage *stg2 = NULL;
827
828 r = IStorage_CreateStream( stg, stmname, STGM_WRITE | STGM_SHARE_EXCLUSIVE,
829 0, 0, &stm );
830 ok(r == STG_E_ACCESSDENIED, "CreateStream should fail\n");
831 r = IStorage_CreateStorage( stg, stmname, STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg2);
832 ok(r == STG_E_ACCESSDENIED, "CreateStream should fail\n");
833
834 r = IStorage_Release(stg);
835 ok(r == 0, "wrong ref count\n");
836 }
837
838 /* open like visio 2003 */
839 stg = NULL;
840 r = StgOpenStorage( filename, NULL, STGM_PRIORITY | STGM_SHARE_DENY_NONE, NULL, 0, &stg);
841 ok(r == S_OK, "should succeed\n");
842 if (stg)
843 IStorage_Release(stg);
844
845 /* test other sharing modes with STGM_PRIORITY */
846 stg = NULL;
847 r = StgOpenStorage( filename, NULL, STGM_PRIORITY | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg);
848 ok(r == S_OK, "should succeed\n");
849 if (stg)
850 IStorage_Release(stg);
851
852 stg = NULL;
853 r = StgOpenStorage( filename, NULL, STGM_PRIORITY | STGM_SHARE_DENY_WRITE, NULL, 0, &stg);
854 ok(r == S_OK, "should succeed\n");
855 if (stg)
856 IStorage_Release(stg);
857
858 stg = NULL;
859 r = StgOpenStorage( filename, NULL, STGM_PRIORITY | STGM_SHARE_DENY_READ, NULL, 0, &stg);
860 ok(r == S_OK, "should succeed\n");
861 if (stg)
862 IStorage_Release(stg);
863
864 /* open like Project 2003 */
865 stg = NULL;
866 r = StgOpenStorage( filename, NULL, STGM_PRIORITY, NULL, 0, &stg);
867 ok(r == S_OK, "should succeed\n");
868 r = StgOpenStorage( filename, NULL, STGM_PRIORITY, NULL, 0, &stg2);
869 ok(r == S_OK, "should succeed\n");
870 if (stg2)
871 IStorage_Release(stg2);
872 if (stg)
873 IStorage_Release(stg);
874
875 stg = NULL;
876 r = StgOpenStorage( filename, NULL, STGM_PRIORITY | STGM_READWRITE, NULL, 0, &stg);
877 ok(r == STG_E_INVALIDFLAG, "should fail\n");
878
879 r = StgOpenStorage( filename, NULL, STGM_TRANSACTED | STGM_PRIORITY, NULL, 0, &stg);
880 ok(r == STG_E_INVALIDFLAG, "should fail\n");
881
882 r = StgOpenStorage( filename, NULL, STGM_SIMPLE | STGM_PRIORITY, NULL, 0, &stg);
883 ok(r == STG_E_INVALIDFLAG, "should fail\n");
884
885 r = StgOpenStorage( filename, NULL, STGM_DELETEONRELEASE | STGM_PRIORITY, NULL, 0, &stg);
886 ok(r == STG_E_INVALIDFUNCTION, "should fail\n");
887
888 r = StgOpenStorage( filename, NULL, STGM_NOSCRATCH | STGM_PRIORITY, NULL, 0, &stg);
889 ok(r == STG_E_INVALIDFLAG, "should fail\n");
890
891 r = StgOpenStorage( filename, NULL, STGM_NOSNAPSHOT | STGM_PRIORITY, NULL, 0, &stg);
892 ok(r == STG_E_INVALIDFLAG, "should fail\n");
893
894 ret = DeleteFileA(filenameA);
895 ok(ret, "file didn't exist\n");
896 }
897
898 static void test_storage_suminfo(void)
899 {
900 IStorage *stg = NULL;
901 IPropertySetStorage *propset = NULL;
902 IPropertyStorage *ps = NULL;
903 HRESULT r;
904
905 DeleteFileA(filenameA);
906
907 /* create the file */
908 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
909 STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
910 ok(r==S_OK, "StgCreateDocfile failed\n");
911
912 r = IStorage_QueryInterface( stg, &IID_IPropertySetStorage, (LPVOID) &propset );
913 ok(r == S_OK, "query interface failed\n");
914
915 /* delete it */
916 r = IPropertySetStorage_Delete( propset, &FMTID_SummaryInformation );
917 ok(r == STG_E_FILENOTFOUND, "deleted property set storage\n");
918
919 r = IPropertySetStorage_Open( propset, &FMTID_SummaryInformation,
920 STGM_READ | STGM_SHARE_EXCLUSIVE, &ps );
921 ok(r == STG_E_FILENOTFOUND, "opened property set storage\n");
922
923 r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0,
924 STGM_READ | STGM_SHARE_EXCLUSIVE, &ps );
925 ok(r == STG_E_INVALIDFLAG, "created property set storage\n");
926
927 r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0,
928 STGM_READ, &ps );
929 ok(r == STG_E_INVALIDFLAG, "created property set storage\n");
930
931 r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0, 0, &ps );
932 ok(r == STG_E_INVALIDFLAG, "created property set storage\n");
933
934 r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0,
935 STGM_WRITE|STGM_SHARE_EXCLUSIVE, &ps );
936 ok(r == STG_E_INVALIDFLAG, "created property set storage\n");
937
938 r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0,
939 STGM_CREATE|STGM_WRITE|STGM_SHARE_EXCLUSIVE, &ps );
940 ok(r == STG_E_INVALIDFLAG, "created property set storage\n");
941
942 /* now try really creating a property set */
943 r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0,
944 STGM_CREATE|STGM_READWRITE|STGM_SHARE_EXCLUSIVE, &ps );
945 ok(r == S_OK, "failed to create property set storage\n");
946
947 if( ps )
948 IPropertyStorage_Release(ps);
949
950 /* now try creating the same thing again */
951 r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0,
952 STGM_CREATE|STGM_READWRITE|STGM_SHARE_EXCLUSIVE, &ps );
953 ok(r == S_OK, "failed to create property set storage\n");
954 if( ps )
955 IPropertyStorage_Release(ps);
956
957 /* should be able to open it */
958 r = IPropertySetStorage_Open( propset, &FMTID_SummaryInformation,
959 STGM_READWRITE|STGM_SHARE_EXCLUSIVE, &ps);
960 ok(r == S_OK, "open failed\n");
961 if(r == S_OK)
962 IPropertyStorage_Release(ps);
963
964 /* delete it */
965 r = IPropertySetStorage_Delete( propset, &FMTID_SummaryInformation );
966 ok(r == S_OK, "failed to delete property set storage\n");
967
968 /* try opening with an invalid FMTID */
969 r = IPropertySetStorage_Open( propset, NULL,
970 STGM_READWRITE|STGM_SHARE_EXCLUSIVE, &ps);
971 ok(r == E_INVALIDARG, "open succeeded\n");
972 if(r == S_OK)
973 IPropertyStorage_Release(ps);
974
975 /* try a bad guid */
976 r = IPropertySetStorage_Open( propset, &IID_IStorage,
977 STGM_READWRITE|STGM_SHARE_EXCLUSIVE, &ps);
978 ok(r == STG_E_FILENOTFOUND, "open succeeded\n");
979 if(r == S_OK)
980 IPropertyStorage_Release(ps);
981
982
983 /* try some invalid flags */
984 r = IPropertySetStorage_Open( propset, &FMTID_SummaryInformation,
985 STGM_CREATE | STGM_READWRITE|STGM_SHARE_EXCLUSIVE, &ps);
986 ok(r == STG_E_INVALIDFLAG, "open succeeded\n");
987 if(r == S_OK)
988 IPropertyStorage_Release(ps);
989
990 /* after deleting it, it should be gone */
991 r = IPropertySetStorage_Open( propset, &FMTID_SummaryInformation,
992 STGM_READWRITE|STGM_SHARE_EXCLUSIVE, &ps);
993 ok(r == STG_E_FILENOTFOUND, "open failed\n");
994 if(r == S_OK)
995 IPropertyStorage_Release(ps);
996
997 r = IPropertySetStorage_Release( propset );
998 ok(r == 1, "ref count wrong\n");
999
1000 r = IStorage_Release(stg);
1001 ok(r == 0, "ref count wrong\n");
1002
1003 DeleteFileA(filenameA);
1004 }
1005
1006 static void test_storage_refcount(void)
1007 {
1008 IStorage *stg = NULL;
1009 IStorage *stgprio = NULL;
1010 HRESULT r;
1011 IStream *stm = NULL;
1012 static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 };
1013 LARGE_INTEGER pos;
1014 ULARGE_INTEGER upos;
1015 STATSTG stat;
1016 char buffer[10];
1017
1018 DeleteFileA(filenameA);
1019
1020 /* create the file */
1021 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
1022 STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
1023 ok(r==S_OK, "StgCreateDocfile failed\n");
1024
1025 r = WriteClassStg( stg, &test_stg_cls );
1026 ok( r == S_OK, "WriteClassStg failed\n");
1027
1028 r = IStorage_Commit( stg, STGC_DEFAULT );
1029 ok( r == S_OK, "IStorage_Commit failed\n");
1030
1031 /* now create a stream */
1032 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1033 ok(r==S_OK, "IStorage->CreateStream failed\n");
1034
1035 r = IStorage_Release( stg );
1036 ok (r == 0, "storage not released\n");
1037
1038 pos.QuadPart = 0;
1039 r = IStream_Seek( stm, pos, 0, &upos );
1040 ok (r == STG_E_REVERTED, "seek should fail\n");
1041
1042 r = IStream_Stat( stm, &stat, STATFLAG_DEFAULT );
1043 ok (r == STG_E_REVERTED, "stat should fail\n");
1044
1045 r = IStream_Write( stm, "Test string", strlen("Test string"), NULL);
1046 ok (r == STG_E_REVERTED, "IStream_Write should return STG_E_REVERTED instead of 0x%08x\n", r);
1047
1048 r = IStream_Read( stm, buffer, sizeof(buffer), NULL);
1049 ok (r == STG_E_REVERTED, "IStream_Read should return STG_E_REVERTED instead of 0x%08x\n", r);
1050
1051 r = IStream_Release(stm);
1052 ok (r == 0, "stream not released\n");
1053
1054 /* tests that STGM_PRIORITY doesn't prevent readwrite access from other
1055 * StgOpenStorage calls in transacted mode */
1056 r = StgOpenStorage( filename, NULL, STGM_PRIORITY, NULL, 0, &stgprio);
1057 ok(r==S_OK, "StgOpenStorage failed with error 0x%08x\n", r);
1058
1059 /* non-transacted mode read/write fails */
1060 r = StgOpenStorage( filename, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg);
1061 ok(r==STG_E_LOCKVIOLATION, "StgOpenStorage should return STG_E_LOCKVIOLATION instead of 0x%08x\n", r);
1062
1063 /* non-transacted mode read-only succeeds */
1064 r = StgOpenStorage( filename, NULL, STGM_SHARE_DENY_WRITE|STGM_READ, NULL, 0, &stg);
1065 ok(r==S_OK, "StgOpenStorage failed with error 0x%08x\n", r);
1066 IStorage_Release(stg);
1067
1068 r = StgOpenStorage( filename, NULL, STGM_TRANSACTED|STGM_SHARE_DENY_WRITE|STGM_READWRITE, NULL, 0, &stg);
1069 ok(r==S_OK, "StgOpenStorage failed with error 0x%08x\n", r);
1070 if(stg)
1071 {
1072 static const WCHAR stgname[] = { ' ',' ',' ','2','9',0 };
1073 static const WCHAR stgname2[] = { 'C','V','_','i','e','w',0 };
1074 static const WCHAR stmname2[] = { 'V','a','r','2','D','a','t','a',0 };
1075 IStorage *stg2;
1076 IStorage *stg3;
1077 STATSTG statstg;
1078
1079 r = IStorage_Stat( stg, &statstg, STATFLAG_NONAME );
1080 ok(r == S_OK, "Stat should have succeeded instead of returning 0x%08x\n", r);
1081 ok(statstg.type == STGTY_STORAGE, "Statstg type should have been STGTY_STORAGE instead of %d\n", statstg.type);
1082 ok(U(statstg.cbSize).LowPart == 0, "Statstg cbSize.LowPart should have been 0 instead of %d\n", U(statstg.cbSize).LowPart);
1083 ok(U(statstg.cbSize).HighPart == 0, "Statstg cbSize.HighPart should have been 0 instead of %d\n", U(statstg.cbSize).HighPart);
1084 ok(statstg.grfMode == (STGM_TRANSACTED|STGM_SHARE_DENY_WRITE|STGM_READWRITE),
1085 "Statstg grfMode should have been 0x10022 instead of 0x%x\n", statstg.grfMode);
1086 ok(statstg.grfLocksSupported == 0, "Statstg grfLocksSupported should have been 0 instead of %d\n", statstg.grfLocksSupported);
1087 ok(IsEqualCLSID(&statstg.clsid, &test_stg_cls), "Statstg clsid is not test_stg_cls\n");
1088 ok(statstg.grfStateBits == 0, "Statstg grfStateBits should have been 0 instead of %d\n", statstg.grfStateBits);
1089 ok(statstg.reserved == 0, "Statstg reserved should have been 0 instead of %d\n", statstg.reserved);
1090
1091 r = IStorage_CreateStorage( stg, stgname, STGM_SHARE_EXCLUSIVE, 0, 0, &stg2 );
1092 ok(r == S_OK, "CreateStorage should have succeeded instead of returning 0x%08x\n", r);
1093
1094 r = IStorage_Stat( stg2, &statstg, STATFLAG_DEFAULT );
1095 ok(r == S_OK, "Stat should have succeeded instead of returning 0x%08x\n", r);
1096 ok(!memcmp(statstg.pwcsName, stgname, sizeof(stgname)),
1097 "Statstg pwcsName should have been the name the storage was created with\n");
1098 ok(statstg.type == STGTY_STORAGE, "Statstg type should have been STGTY_STORAGE instead of %d\n", statstg.type);
1099 ok(U(statstg.cbSize).LowPart == 0, "Statstg cbSize.LowPart should have been 0 instead of %d\n", U(statstg.cbSize).LowPart);
1100 ok(U(statstg.cbSize).HighPart == 0, "Statstg cbSize.HighPart should have been 0 instead of %d\n", U(statstg.cbSize).HighPart);
1101 ok(statstg.grfMode == STGM_SHARE_EXCLUSIVE,
1102 "Statstg grfMode should have been STGM_SHARE_EXCLUSIVE instead of 0x%x\n", statstg.grfMode);
1103 ok(statstg.grfLocksSupported == 0, "Statstg grfLocksSupported should have been 0 instead of %d\n", statstg.grfLocksSupported);
1104 ok(IsEqualCLSID(&statstg.clsid, &CLSID_NULL), "Statstg clsid is not CLSID_NULL\n");
1105 ok(statstg.grfStateBits == 0, "Statstg grfStateBits should have been 0 instead of %d\n", statstg.grfStateBits);
1106 ok(statstg.reserved == 0, "Statstg reserved should have been 0 instead of %d\n", statstg.reserved);
1107 CoTaskMemFree(statstg.pwcsName);
1108
1109 r = IStorage_CreateStorage( stg2, stgname2, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, 0, &stg3 );
1110 ok(r == STG_E_ACCESSDENIED, "CreateStorage should have returned STG_E_ACCESSDENIED instead of 0x%08x\n", r);
1111
1112 r = IStorage_CreateStream( stg2, stmname2, STGM_CREATE|STGM_SHARE_EXCLUSIVE, 0, 0, &stm );
1113 ok(r == STG_E_ACCESSDENIED, "CreateStream should have returned STG_E_ACCESSDENIED instead of 0x%08x\n", r);
1114
1115 IStorage_Release(stg2);
1116
1117 r = IStorage_Release(stg);
1118 ok(r == 0, "wrong ref count\n");
1119 }
1120
1121 /* Multiple STGM_PRIORITY opens are possible. */
1122 r = StgOpenStorage( filename, NULL, STGM_PRIORITY, NULL, 0, &stg);
1123 ok(r==S_OK, "StgOpenStorage failed with error 0x%08x\n", r);
1124 if(stg)
1125 {
1126 r = IStorage_Release(stg);
1127 ok(r == 0, "wrong ref count\n");
1128 }
1129
1130 r = StgOpenStorage( NULL, stgprio, STGM_TRANSACTED|STGM_SHARE_DENY_WRITE|STGM_READWRITE, NULL, 0, &stg);
1131 ok(r==S_OK, "StgOpenStorage failed with error 0x%08x\n", r);
1132 if(stg)
1133 {
1134 static const WCHAR stgname[] = { ' ',' ',' ','2','9',0 };
1135 IStorage *stg2;
1136 STATSTG statstg;
1137
1138 r = IStorage_Stat( stg, &statstg, STATFLAG_NONAME );
1139 ok(r == S_OK, "Stat should have succeeded instead of returning 0x%08x\n", r);
1140 ok(statstg.type == STGTY_STORAGE, "Statstg type should have been STGTY_STORAGE instead of %d\n", statstg.type);
1141 ok(U(statstg.cbSize).LowPart == 0, "Statstg cbSize.LowPart should have been 0 instead of %d\n", U(statstg.cbSize).LowPart);
1142 ok(U(statstg.cbSize).HighPart == 0, "Statstg cbSize.HighPart should have been 0 instead of %d\n", U(statstg.cbSize).HighPart);
1143 ok(statstg.grfMode == (STGM_TRANSACTED|STGM_SHARE_DENY_WRITE|STGM_READWRITE),
1144 "Statstg grfMode should have been 0x10022 instead of 0x%x\n", statstg.grfMode);
1145 ok(statstg.grfLocksSupported == 0, "Statstg grfLocksSupported should have been 0 instead of %d\n", statstg.grfLocksSupported);
1146 ok(IsEqualCLSID(&statstg.clsid, &test_stg_cls), "Statstg clsid is not test_stg_cls\n");
1147 ok(statstg.grfStateBits == 0, "Statstg grfStateBits should have been 0 instead of %d\n", statstg.grfStateBits);
1148 ok(statstg.reserved == 0, "Statstg reserved should have been 0 instead of %d\n", statstg.reserved);
1149
1150 r = IStorage_CreateStorage( stg, stgname, STGM_SHARE_EXCLUSIVE, 0, 0, &stg2 );
1151 ok(r == S_OK, "CreateStorage should have succeeded instead of returning 0x%08x\n", r);
1152
1153 IStorage_Release(stg2);
1154
1155 r = IStorage_Commit( stg, 0 );
1156 ok(r == S_OK, "Commit should have succeeded instead of returning 0x%08x\n", r);
1157
1158 r = IStorage_Release(stg);
1159 ok(r == 0, "wrong ref count\n");
1160 }
1161 /* IStorage_Release(stgprio) not necessary because StgOpenStorage released it. */
1162
1163 DeleteFileA(filenameA);
1164 }
1165
1166 static void test_writeclassstg(void)
1167 {
1168 IStorage *stg = NULL;
1169 HRESULT r;
1170 CLSID temp_cls, cls2;
1171
1172 DeleteFileA(filenameA);
1173
1174 /* create the file */
1175 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
1176 STGM_READWRITE, 0, &stg);
1177 ok(r==S_OK, "StgCreateDocfile failed\n");
1178
1179 r = ReadClassStg( NULL, NULL );
1180 ok(r == E_INVALIDARG, "ReadClassStg should return E_INVALIDARG instead of 0x%08X\n", r);
1181
1182 memset(&temp_cls, 0xcc, sizeof(temp_cls));
1183 memset(&cls2, 0xcc, sizeof(cls2));
1184 r = ReadClassStg( NULL, &temp_cls );
1185 ok(r == E_INVALIDARG, "got 0x%08x\n", r);
1186 ok(IsEqualCLSID(&temp_cls, &cls2), "got wrong clsid\n");
1187
1188 r = ReadClassStg( stg, NULL );
1189 ok(r == E_INVALIDARG, "ReadClassStg should return E_INVALIDARG instead of 0x%08X\n", r);
1190
1191 temp_cls.Data1 = 0xdeadbeef;
1192 r = ReadClassStg( stg, &temp_cls );
1193 ok(r == S_OK, "ReadClassStg failed with 0x%08X\n", r);
1194
1195 ok(IsEqualCLSID(&temp_cls, &CLSID_NULL), "ReadClassStg returned wrong clsid\n");
1196
1197 r = WriteClassStg( NULL, NULL );
1198 ok(r == E_INVALIDARG, "WriteClassStg should return E_INVALIDARG instead of 0x%08X\n", r);
1199
1200 r = WriteClassStg( stg, NULL );
1201 ok(r == STG_E_INVALIDPOINTER, "WriteClassStg should return STG_E_INVALIDPOINTER instead of 0x%08X\n", r);
1202
1203 r = WriteClassStg( stg, &test_stg_cls );
1204 ok( r == S_OK, "WriteClassStg failed with 0x%08X\n", r);
1205
1206 r = ReadClassStg( stg, &temp_cls );
1207 ok( r == S_OK, "ReadClassStg failed with 0x%08X\n", r);
1208 ok(IsEqualCLSID(&temp_cls, &test_stg_cls), "ReadClassStg returned wrong clsid\n");
1209
1210 r = IStorage_Release( stg );
1211 ok (r == 0, "storage not released\n");
1212
1213 DeleteFileA(filenameA);
1214 }
1215
1216 static void test_streamenum(void)
1217 {
1218 IStorage *stg = NULL;
1219 HRESULT r;
1220 IStream *stm = NULL;
1221 static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 };
1222 static const WCHAR stmname2[] = { 'A','B','C','D','E','F','G','H','I',0 };
1223 static const WCHAR stmname3[] = { 'A','B','C','D','E','F','G','H','I','J',0 };
1224 static const STATSTG stat_null;
1225 STATSTG stat;
1226 IEnumSTATSTG *ee = NULL;
1227 ULONG count;
1228
1229 DeleteFileA(filenameA);
1230
1231 /* create the file */
1232 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
1233 STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
1234 ok(r==S_OK, "StgCreateDocfile failed\n");
1235
1236 r = WriteClassStg( stg, &test_stg_cls );
1237 ok( r == S_OK, "WriteClassStg failed\n");
1238
1239 r = IStorage_Commit( stg, STGC_DEFAULT );
1240 ok( r == S_OK, "IStorage_Commit failed\n");
1241
1242 /* now create a stream */
1243 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1244 ok(r==S_OK, "IStorage->CreateStream failed\n");
1245
1246 IStream_Release(stm);
1247
1248 /* first enum ... should be 1 stream */
1249 r = IStorage_EnumElements(stg, 0, NULL, 0, &ee);
1250 ok(r==S_OK, "IStorage->EnumElements failed\n");
1251
1252 count = 0xf00;
1253 r = IEnumSTATSTG_Next(ee, 1, &stat, &count);
1254 ok(r==S_OK, "IEnumSTATSTG->Next failed\n");
1255 ok(count == 1, "count wrong\n");
1256
1257 if (r == S_OK)
1258 CoTaskMemFree(stat.pwcsName);
1259
1260 r = IEnumSTATSTG_Release(ee);
1261 ok(r==S_OK, "EnumSTATSTG_Release failed with error 0x%08x\n", r);
1262
1263 /* second enum... destroy the stream before reading */
1264 r = IStorage_EnumElements(stg, 0, NULL, 0, &ee);
1265 ok(r==S_OK, "IStorage->EnumElements failed\n");
1266
1267 r = IStorage_DestroyElement(stg, stmname);
1268 ok(r==S_OK, "IStorage->DestroyElement failed\n");
1269
1270 memset(&stat, 0xad, sizeof(stat));
1271 count = 0xf00;
1272 r = IEnumSTATSTG_Next(ee, 1, &stat, &count);
1273 ok(r==S_FALSE, "IEnumSTATSTG->Next failed\n");
1274 ok(count == 0, "count wrong\n");
1275 ok(memcmp(&stat, &stat_null, sizeof(stat)) == 0, "stat is not zeroed\n");
1276
1277 /* reset and try again */
1278 r = IEnumSTATSTG_Reset(ee);
1279 ok(r==S_OK, "IEnumSTATSTG->Reset failed\n");
1280
1281 count = 0xf00;
1282 r = IEnumSTATSTG_Next(ee, 1, &stat, &count);
1283 ok(r==S_FALSE, "IEnumSTATSTG->Next failed\n");
1284 ok(count == 0, "count wrong\n");
1285
1286 /* add a stream before reading */
1287 r = IEnumSTATSTG_Reset(ee);
1288 ok(r==S_OK, "IEnumSTATSTG->Reset failed\n");
1289
1290 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1291 ok(r==S_OK, "IStorage->CreateStream failed\n");
1292
1293 r = IStream_Release(stm);
1294 ok(r==S_OK, "Stream_Release failed with error 0x%08x\n", r);
1295
1296 count = 0xf00;
1297 r = IEnumSTATSTG_Next(ee, 1, &stat, &count);
1298 ok(r==S_OK, "IEnumSTATSTG->Next failed\n");
1299 ok(count == 1, "count wrong\n");
1300
1301 if (r == S_OK)
1302 {
1303 ok(lstrcmpiW(stat.pwcsName, stmname) == 0, "expected CONTENTS, got %s\n", wine_dbgstr_w(stat.pwcsName));
1304 CoTaskMemFree(stat.pwcsName);
1305 }
1306
1307 r = IStorage_CreateStream(stg, stmname2, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1308 ok(r==S_OK, "IStorage->CreateStream failed\n");
1309
1310 r = IStream_Release(stm);
1311 ok(r==S_OK, "Stream_Release failed with error 0x%08x\n", r);
1312
1313 count = 0xf00;
1314 r = IEnumSTATSTG_Next(ee, 1, &stat, &count);
1315 ok(r==S_OK, "IEnumSTATSTG->Next failed\n");
1316 ok(count == 1, "count wrong\n");
1317
1318 if (r == S_OK)
1319 {
1320 ok(lstrcmpiW(stat.pwcsName, stmname2) == 0, "expected ABCDEFGHI, got %s\n", wine_dbgstr_w(stat.pwcsName));
1321 CoTaskMemFree(stat.pwcsName);
1322 }
1323
1324 /* delete previous and next stream after reading */
1325 r = IStorage_CreateStream(stg, stmname3, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1326 ok(r==S_OK, "IStorage->CreateStream failed\n");
1327
1328 r = IStream_Release(stm);
1329 ok(r==S_OK, "Stream_Release failed with error 0x%08x\n", r);
1330
1331 r = IEnumSTATSTG_Reset(ee);
1332 ok(r==S_OK, "IEnumSTATSTG->Reset failed\n");
1333
1334 count = 0xf00;
1335 r = IEnumSTATSTG_Next(ee, 1, &stat, &count);
1336 ok(r==S_OK, "IEnumSTATSTG->Next failed\n");
1337 ok(count == 1, "count wrong\n");
1338
1339 if (r == S_OK)
1340 {
1341 ok(lstrcmpiW(stat.pwcsName, stmname) == 0, "expected CONTENTS, got %s\n", wine_dbgstr_w(stat.pwcsName));
1342 CoTaskMemFree(stat.pwcsName);
1343 }
1344
1345 r = IStorage_DestroyElement(stg, stmname);
1346 ok(r==S_OK, "IStorage->DestroyElement failed\n");
1347
1348 r = IStorage_DestroyElement(stg, stmname2);
1349 ok(r==S_OK, "IStorage->DestroyElement failed\n");
1350
1351 count = 0xf00;
1352 r = IEnumSTATSTG_Next(ee, 1, &stat, &count);
1353 ok(r==S_OK, "IEnumSTATSTG->Next failed\n");
1354 ok(count == 1, "count wrong\n");
1355
1356 if (r == S_OK)
1357 {
1358 ok(lstrcmpiW(stat.pwcsName, stmname3) == 0, "expected ABCDEFGHIJ, got %s\n", wine_dbgstr_w(stat.pwcsName));
1359 CoTaskMemFree(stat.pwcsName);
1360 }
1361
1362 r = IStorage_Release( stg );
1363 todo_wine ok (r == 0, "storage not released\n");
1364
1365 /* enumerator is still valid and working after the storage is released */
1366 r = IEnumSTATSTG_Reset(ee);
1367 ok(r==S_OK, "IEnumSTATSTG->Reset failed\n");
1368
1369 count = 0xf00;
1370 r = IEnumSTATSTG_Next(ee, 1, &stat, &count);
1371 ok(r==S_OK, "IEnumSTATSTG->Next failed\n");
1372 ok(count == 1, "count wrong\n");
1373
1374 if (r == S_OK)
1375 {
1376 ok(lstrcmpiW(stat.pwcsName, stmname3) == 0, "expected ABCDEFGHIJ, got %s\n", wine_dbgstr_w(stat.pwcsName));
1377 CoTaskMemFree(stat.pwcsName);
1378 }
1379
1380 /* the storage is left open until the enumerator is freed */
1381 r = StgOpenStorage( filename, NULL, STGM_SHARE_EXCLUSIVE |
1382 STGM_READWRITE |STGM_TRANSACTED, NULL, 0, &stg);
1383 ok(r==STG_E_SHAREVIOLATION ||
1384 r==STG_E_LOCKVIOLATION, /* XP-SP2/W2K3-SP1 and below */
1385 "StgCreateDocfile failed, res=%x\n", r);
1386
1387 r = IEnumSTATSTG_Release(ee);
1388 ok (r == 0, "enum not released\n");
1389
1390 DeleteFileA(filenameA);
1391 }
1392
1393 static void test_transact(void)
1394 {
1395 IStorage *stg = NULL, *stg2 = NULL, *stg3 = NULL;
1396 HRESULT r;
1397 IStream *stm = NULL;
1398 static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 };
1399 static const WCHAR stmname2[] = { 'F','O','O',0 };
1400 static const WCHAR stgname[] = { 'P','E','R','M','S','T','G',0 };
1401 static const WCHAR stgname2[] = { 'T','E','M','P','S','T','G',0 };
1402 BOOL ret;
1403
1404 DeleteFileA(filenameA);
1405
1406 /* create the file */
1407 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
1408 STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
1409 ok(r==S_OK, "StgCreateDocfile failed\n");
1410
1411 /* commit a new stream and storage */
1412 r = IStorage_CreateStream(stg, stmname2, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1413 ok(r==S_OK, "IStorage->CreateStream failed\n");
1414
1415 r = IStream_Write(stm, "this is stream 1\n", 16, NULL);
1416 ok(r==S_OK, "IStream->Write failed\n");
1417
1418 IStream_Release(stm);
1419
1420 r = IStorage_CreateStorage(stg, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg2);
1421 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1422
1423 if (r == S_OK)
1424 {
1425 /* Create two substorages but only commit one */
1426 r = IStorage_CreateStorage(stg2, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg3);
1427 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1428
1429 if (r == S_OK)
1430 IStorage_Release(stg3);
1431
1432 r = IStorage_Commit(stg, 0);
1433 ok(r==S_OK, "IStorage->Commit failed\n");
1434
1435 r = IStorage_CreateStorage(stg2, stgname2, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg3);
1436 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1437
1438 if (r == S_OK)
1439 IStorage_Release(stg3);
1440
1441 IStorage_Release(stg2);
1442 }
1443
1444 /* now create a stream and storage, but don't commit them */
1445 stm = NULL;
1446 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1447 ok(r==S_OK, "IStorage->CreateStream failed\n");
1448
1449 r = IStream_Write(stm, "this is stream 2\n", 16, NULL);
1450 ok(r==S_OK, "IStream->Write failed\n");
1451
1452 /* IStream::Commit does nothing for OLE storage streams */
1453 r = IStream_Commit(stm, STGC_ONLYIFCURRENT | STGC_DANGEROUSLYCOMMITMERELYTODISKCACHE);
1454 ok(r==S_OK, "IStream->Commit failed\n");
1455
1456 r = IStorage_CreateStorage(stg, stgname2, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg2);
1457 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1458
1459 if (r == S_OK)
1460 IStorage_Release(stg2);
1461
1462 IStream_Release(stm);
1463
1464 IStorage_Release(stg);
1465
1466 stm = NULL;
1467 stg = NULL;
1468 r = StgOpenStorage( filename, NULL, STGM_SHARE_DENY_NONE | STGM_READ | STGM_TRANSACTED, NULL, 0, &stg);
1469 ok(r==S_OK, "StgOpenStorage failed\n");
1470
1471 if (!stg)
1472 return;
1473
1474 r = IStorage_OpenStream(stg, stmname, NULL, STGM_SHARE_DENY_NONE|STGM_READ, 0, &stm );
1475 ok(r==STG_E_INVALIDFLAG, "IStorage->OpenStream failed %08x\n", r);
1476
1477 r = IStorage_OpenStream(stg, stmname, NULL, STGM_DELETEONRELEASE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
1478 ok(r==STG_E_INVALIDFUNCTION, "IStorage->OpenStream failed %08x\n", r);
1479
1480 r = IStorage_OpenStream(stg, stmname, NULL, STGM_TRANSACTED|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
1481 ok(r==STG_E_INVALIDFUNCTION, "IStorage->OpenStream failed %08x\n", r);
1482
1483 r = IStorage_OpenStorage(stg, stmname, NULL, STGM_TRANSACTED|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg2 );
1484 ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStream failed %08x\n", r);
1485
1486 r = IStorage_OpenStream(stg, stmname, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
1487 ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStream should fail %08x\n", r);
1488 if (r == S_OK)
1489 IStream_Release(stm);
1490
1491 r = IStorage_OpenStorage(stg, stgname2, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg2 );
1492 ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStorage should fail %08x\n", r);
1493 if (r == S_OK)
1494 IStorage_Release(stg2);
1495
1496 r = IStorage_OpenStorage(stg, stmname2, NULL, STGM_TRANSACTED|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg2 );
1497 ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStream failed %08x\n", r);
1498
1499 r = IStorage_OpenStream(stg, stmname2, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
1500 ok(r==S_OK, "IStorage->OpenStream should succeed %08x\n", r);
1501 if (r == S_OK)
1502 IStream_Release(stm);
1503
1504 r = IStorage_OpenStorage(stg, stgname, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg2 );
1505 ok(r==S_OK, "IStorage->OpenStorage should succeed %08x\n", r);
1506 if (r == S_OK)
1507 {
1508 r = IStorage_OpenStorage(stg2, stgname, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg3 );
1509 ok(r==S_OK, "IStorage->OpenStorage should succeed %08x\n", r);
1510 if (r == S_OK)
1511 IStorage_Release(stg3);
1512
1513 r = IStorage_OpenStorage(stg2, stgname2, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg3 );
1514 ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStorage should fail %08x\n", r);
1515 if (r == S_OK)
1516 IStorage_Release(stg3);
1517
1518 IStorage_Release(stg2);
1519 }
1520
1521 IStorage_Release(stg);
1522
1523 ret = DeleteFileA(filenameA);
1524 ok(ret, "deleted file\n");
1525 }
1526
1527 static void test_substorage_share(void)
1528 {
1529 IStorage *stg, *stg2, *stg3;
1530 IStream *stm, *stm2;
1531 HRESULT r;
1532 static const WCHAR stgname[] = { 'P','E','R','M','S','T','G',0 };
1533 static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 };
1534 static const WCHAR othername[] = { 'N','E','W','N','A','M','E',0 };
1535 BOOL ret;
1536
1537 DeleteFileA(filenameA);
1538
1539 /* create the file */
1540 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
1541 STGM_READWRITE, 0, &stg);
1542 ok(r==S_OK, "StgCreateDocfile failed\n");
1543
1544 /* create a read/write storage and try to open it again */
1545 r = IStorage_CreateStorage(stg, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg2);
1546 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1547
1548 if (r == S_OK)
1549 {
1550 r = IStorage_OpenStorage(stg, stgname, NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg3);
1551 ok(r==STG_E_ACCESSDENIED, "IStorage->OpenStorage should fail %08x\n", r);
1552
1553 if (r == S_OK)
1554 IStorage_Release(stg3);
1555
1556 r = IStorage_OpenStorage(stg, stgname, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, 0, &stg3);
1557 ok(r==STG_E_ACCESSDENIED, "IStorage->OpenStorage should fail %08x\n", r);
1558
1559 if (r == S_OK)
1560 IStorage_Release(stg3);
1561
1562 /* cannot rename the storage while it's open */
1563 r = IStorage_RenameElement(stg, stgname, othername);
1564 ok(r==STG_E_ACCESSDENIED, "IStorage->RenameElement should fail %08x\n", r);
1565 if (SUCCEEDED(r)) IStorage_RenameElement(stg, othername, stgname);
1566
1567 /* destroying an object while it's open invalidates it */
1568 r = IStorage_DestroyElement(stg, stgname);
1569 ok(r==S_OK, "IStorage->DestroyElement failed, hr=%08x\n", r);
1570
1571 r = IStorage_CreateStream(stg2, stmname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm);
1572 ok(r==STG_E_REVERTED, "IStorage->CreateStream failed, hr=%08x\n", r);
1573
1574 if (r == S_OK)
1575 IStream_Release(stm);
1576
1577 IStorage_Release(stg2);
1578 }
1579
1580 /* create a read/write stream and try to open it again */
1581 r = IStorage_CreateStream(stg, stmname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm);
1582 ok(r==S_OK, "IStorage->CreateStream failed, hr=%08x\n", r);
1583
1584 if (r == S_OK)
1585 {
1586 r = IStorage_OpenStream(stg, stmname, NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &stm2);
1587 ok(r==STG_E_ACCESSDENIED, "IStorage->OpenStream should fail %08x\n", r);
1588
1589 if (r == S_OK)
1590 IStream_Release(stm2);
1591
1592 r = IStorage_OpenStream(stg, stmname, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm2);
1593 ok(r==STG_E_ACCESSDENIED, "IStorage->OpenStream should fail %08x\n", r);
1594
1595 if (r == S_OK)
1596 IStream_Release(stm2);
1597
1598 /* cannot rename the stream while it's open */
1599 r = IStorage_RenameElement(stg, stmname, othername);
1600 ok(r==STG_E_ACCESSDENIED, "IStorage->RenameElement should fail %08x\n", r);
1601 if (SUCCEEDED(r)) IStorage_RenameElement(stg, othername, stmname);
1602
1603 /* destroying an object while it's open invalidates it */
1604 r = IStorage_DestroyElement(stg, stmname);
1605 ok(r==S_OK, "IStorage->DestroyElement failed, hr=%08x\n", r);
1606
1607 r = IStream_Write(stm, "this shouldn't work\n", 20, NULL);
1608 ok(r==STG_E_REVERTED, "IStream_Write should fail %08x\n", r);
1609
1610 IStream_Release(stm);
1611 }
1612
1613 IStorage_Release(stg);
1614
1615 ret = DeleteFileA(filenameA);
1616 ok(ret, "deleted file\n");
1617 }
1618
1619 static void test_revert(void)
1620 {
1621 IStorage *stg = NULL, *stg2 = NULL, *stg3 = NULL;
1622 HRESULT r;
1623 IStream *stm = NULL, *stm2 = NULL;
1624 static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 };
1625 static const WCHAR stmname2[] = { 'F','O','O',0 };
1626 static const WCHAR stgname[] = { 'P','E','R','M','S','T','G',0 };
1627 static const WCHAR stgname2[] = { 'T','E','M','P','S','T','G',0 };
1628 STATSTG statstg;
1629 BOOL ret;
1630
1631 DeleteFileA(filenameA);
1632
1633 /* create the file */
1634 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
1635 STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
1636 ok(r==S_OK, "StgCreateDocfile failed\n");
1637
1638 /* commit a new stream and storage */
1639 r = IStorage_CreateStream(stg, stmname2, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1640 ok(r==S_OK, "IStorage->CreateStream failed\n");
1641
1642 r = IStream_Write(stm, "this is stream 1\n", 16, NULL);
1643 ok(r==S_OK, "IStream->Write failed\n");
1644
1645 r = IStorage_CreateStorage(stg, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg2);
1646 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1647
1648 if (r == S_OK)
1649 {
1650 /* Create two substorages but only commit one */
1651 r = IStorage_CreateStorage(stg2, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg3);
1652 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1653
1654 if (r == S_OK)
1655 IStorage_Release(stg3);
1656
1657 r = IStorage_Commit(stg, 0);
1658 ok(r==S_OK, "IStorage->Commit failed\n");
1659
1660 r = IStorage_CreateStorage(stg2, stgname2, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg3);
1661 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1662
1663 if (r == S_OK)
1664 IStorage_Release(stg3);
1665 }
1666
1667 /* now create a stream and storage, then revert */
1668 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm2 );
1669 ok(r==S_OK, "IStorage->CreateStream failed\n");
1670
1671 r = IStream_Write(stm2, "this is stream 2\n", 16, NULL);
1672 ok(r==S_OK, "IStream->Write failed\n");
1673
1674 r = IStorage_CreateStorage(stg, stgname2, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg3);
1675 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1676
1677 r = IStorage_Revert(stg);
1678 ok(r==S_OK, "Storage_Revert failed with error 0x%08x\n", r);
1679
1680 /* all open objects become invalid */
1681 r = IStream_Write(stm, "this shouldn't work\n", 20, NULL);
1682 ok(r==STG_E_REVERTED, "IStream_Write should fail %08x\n", r);
1683
1684 r = IStream_Write(stm2, "this shouldn't work\n", 20, NULL);
1685 ok(r==STG_E_REVERTED, "IStream_Write should fail %08x\n", r);
1686
1687 r = IStorage_Stat(stg2, &statstg, STATFLAG_NONAME);
1688 ok(r==STG_E_REVERTED, "IStorage_Stat should fail %08x\n", r);
1689
1690 r = IStorage_Stat(stg3, &statstg, STATFLAG_NONAME);
1691 ok(r==STG_E_REVERTED, "IStorage_Stat should fail %08x\n", r);
1692
1693 IStream_Release(stm);
1694 IStream_Release(stm2);
1695 IStorage_Release(stg2);
1696 IStorage_Release(stg3);
1697
1698 r = IStorage_OpenStream(stg, stmname, NULL, STGM_SHARE_DENY_NONE|STGM_READ, 0, &stm );
1699 ok(r==STG_E_INVALIDFLAG, "IStorage->OpenStream failed %08x\n", r);
1700
1701 r = IStorage_OpenStream(stg, stmname, NULL, STGM_DELETEONRELEASE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
1702 ok(r==STG_E_INVALIDFUNCTION, "IStorage->OpenStream failed %08x\n", r);
1703
1704 r = IStorage_OpenStream(stg, stmname, NULL, STGM_TRANSACTED|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
1705 ok(r==STG_E_INVALIDFUNCTION, "IStorage->OpenStream failed %08x\n", r);
1706
1707 r = IStorage_OpenStorage(stg, stmname, NULL, STGM_TRANSACTED|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg2 );
1708 ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStream failed %08x\n", r);
1709
1710 r = IStorage_OpenStream(stg, stmname, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
1711 ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStream should fail %08x\n", r);
1712 if (r == S_OK)
1713 IStream_Release(stm);
1714
1715 r = IStorage_OpenStorage(stg, stgname2, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg2 );
1716 ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStorage should fail %08x\n", r);
1717 if (r == S_OK)
1718 IStorage_Release(stg2);
1719
1720 r = IStorage_OpenStorage(stg, stmname2, NULL, STGM_TRANSACTED|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg2 );
1721 ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStream failed %08x\n", r);
1722
1723 r = IStorage_OpenStream(stg, stmname2, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
1724 ok(r==S_OK, "IStorage->OpenStream should succeed %08x\n", r);
1725 if (r == S_OK)
1726 IStream_Release(stm);
1727
1728 r = IStorage_OpenStorage(stg, stgname, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg2 );
1729 ok(r==S_OK, "IStorage->OpenStorage should succeed %08x\n", r);
1730 if (r == S_OK)
1731 {
1732 r = IStorage_OpenStorage(stg2, stgname, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg3 );
1733 ok(r==S_OK, "IStorage->OpenStorage should succeed %08x\n", r);
1734 if (r == S_OK)
1735 IStorage_Release(stg3);
1736
1737 r = IStorage_OpenStorage(stg2, stgname2, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg3 );
1738 ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStorage should fail %08x\n", r);
1739 if (r == S_OK)
1740 IStorage_Release(stg3);
1741
1742 IStorage_Release(stg2);
1743 }
1744
1745 IStorage_Release(stg);
1746
1747 ret = DeleteFileA(filenameA);
1748 ok(ret, "deleted file\n");
1749
1750 /* Revert only invalidates objects in transacted mode */
1751 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
1752 STGM_READWRITE, 0, &stg);
1753 ok(r==S_OK, "StgCreateDocfile failed\n");
1754
1755 r = IStorage_CreateStream(stg, stmname2, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1756 ok(r==S_OK, "IStorage->CreateStream failed\n");
1757
1758 r = IStorage_Revert(stg);
1759 ok(r==S_OK, "IStorage->Revert failed %08x\n", r);
1760
1761 r = IStream_Write(stm, "this works\n", 11, NULL);
1762 ok(r==S_OK, "IStream_Write should succeed %08x\n", r);
1763
1764 IStream_Release(stm);
1765 IStorage_Release(stg);
1766
1767 ret = DeleteFileA(filenameA);
1768 ok(ret, "deleted file\n");
1769 }
1770
1771 static void test_parent_free(void)
1772 {
1773 IStorage *stg = NULL, *stg2 = NULL, *stg3 = NULL;
1774 HRESULT r;
1775 IStream *stm = NULL;
1776 static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 };
1777 static const WCHAR stgname[] = { 'P','E','R','M','S','T','G',0 };
1778 ULONG ref;
1779 STATSTG statstg;
1780 BOOL ret;
1781
1782 DeleteFileA(filenameA);
1783
1784 /* create the file */
1785 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
1786 STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
1787 ok(r==S_OK, "StgCreateDocfile failed\n");
1788
1789 /* create a new storage */
1790 r = IStorage_CreateStorage(stg, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg2);
1791 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1792
1793 if (r == S_OK)
1794 {
1795 /* now create a stream inside the new storage */
1796 r = IStorage_CreateStream(stg2, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1797 ok(r==S_OK, "IStorage->CreateStream failed\n");
1798
1799 if (r == S_OK)
1800 {
1801 /* create a storage inside the new storage */
1802 r = IStorage_CreateStorage(stg2, stgname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stg3 );
1803 ok(r==S_OK, "IStorage->CreateStorage failed\n");
1804 }
1805
1806 /* free the parent */
1807 ref = IStorage_Release(stg2);
1808 ok(ref == 0, "IStorage still has %u references\n", ref);
1809
1810 /* child objects are invalid */
1811 if (r == S_OK)
1812 {
1813 r = IStream_Write(stm, "this should fail\n", 17, NULL);
1814 ok(r==STG_E_REVERTED, "IStream->Write should fail, hr=%x\n", r);
1815
1816 IStream_Release(stm);
1817
1818 r = IStorage_Stat(stg3, &statstg, STATFLAG_NONAME);
1819 ok(r==STG_E_REVERTED, "IStorage_Stat should fail %08x\n", r);
1820
1821 r = IStorage_SetStateBits(stg3, 1, 1);
1822 ok(r==STG_E_REVERTED, "IStorage_Stat should fail %08x\n", r);
1823
1824 IStorage_Release(stg3);
1825 }
1826 }
1827
1828 IStorage_Release(stg);
1829
1830 ret = DeleteFileA(filenameA);
1831 ok(ret, "deleted file\n");
1832 }
1833
1834 static void test_nonroot_transacted(void)
1835 {
1836 IStorage *stg = NULL, *stg2 = NULL, *stg3 = NULL;
1837 HRESULT r;
1838 IStream *stm = NULL;
1839 static const WCHAR stgname[] = { 'P','E','R','M','S','T','G',0 };
1840 static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 };
1841 static const WCHAR stmname2[] = { 'F','O','O',0 };
1842 BOOL ret;
1843
1844 DeleteFileA(filenameA);
1845
1846 /* create a transacted file */
1847 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
1848 STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
1849 ok(r==S_OK, "StgCreateDocfile failed\n");
1850
1851 /* create a transacted substorage */
1852 r = IStorage_CreateStorage(stg, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_TRANSACTED, 0, 0, &stg2);
1853 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1854
1855 if (r == S_OK)
1856 {
1857 /* create and commit stmname */
1858 r = IStorage_CreateStream(stg2, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1859 ok(r==S_OK, "IStorage->CreateStream failed\n");
1860 if (r == S_OK)
1861 IStream_Release(stm);
1862
1863 IStorage_Commit(stg2, 0);
1864
1865 /* create and revert stmname2 */
1866 r = IStorage_CreateStream(stg2, stmname2, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1867 ok(r==S_OK, "IStorage->CreateStream failed\n");
1868 if (r == S_OK)
1869 IStream_Release(stm);
1870
1871 IStorage_Revert(stg2);
1872
1873 /* check that Commit and Revert really worked */
1874 r = IStorage_OpenStream(stg2, stmname, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
1875 ok(r==S_OK, "IStorage->OpenStream should succeed %08x\n", r);
1876 if (r == S_OK)
1877 IStream_Release(stm);
1878
1879 r = IStorage_OpenStream(stg2, stmname2, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
1880 ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStream should fail %08x\n", r);
1881 if (r == S_OK)
1882 IStream_Release(stm);
1883
1884 IStorage_Release(stg2);
1885 }
1886
1887 /* create a read-only transacted substorage */
1888 r = IStorage_OpenStorage(stg, stgname, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE | STGM_TRANSACTED, NULL, 0, &stg2);
1889 ok(r==S_OK, "IStorage->OpenStorage failed, hr=%08x\n", r);
1890
1891 if (r == S_OK)
1892 {
1893 /* The storage can be modified. */
1894 r = IStorage_CreateStorage(stg2, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg3);
1895 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1896 if (r == S_OK)
1897 IStorage_Release(stg3);
1898
1899 /* But changes cannot be committed. */
1900 r = IStorage_Commit(stg2, 0);
1901 ok(r==STG_E_ACCESSDENIED, "IStorage->Commit should fail, hr=%08x\n", r);
1902
1903 IStorage_Release(stg2);
1904 }
1905
1906 IStorage_Release(stg);
1907
1908 /* create a non-transacted file */
1909 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
1910 STGM_READWRITE, 0, &stg);
1911 ok(r==S_OK, "StgCreateDocfile failed\n");
1912
1913 /* create a transacted substorage */
1914 r = IStorage_CreateStorage(stg, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_TRANSACTED, 0, 0, &stg2);
1915 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1916
1917 if (r == S_OK)
1918 {
1919 /* create and commit stmname */
1920 r = IStorage_CreateStream(stg2, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1921 ok(r==S_OK, "IStorage->CreateStream failed\n");
1922 if (r == S_OK)
1923 IStream_Release(stm);
1924
1925 IStorage_Commit(stg2, 0);
1926
1927 /* create and revert stmname2 */
1928 r = IStorage_CreateStream(stg2, stmname2, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1929 ok(r==S_OK, "IStorage->CreateStream failed\n");
1930 if (r == S_OK)
1931 IStream_Release(stm);
1932
1933 IStorage_Revert(stg2);
1934
1935 /* check that Commit and Revert really worked */
1936 r = IStorage_OpenStream(stg2, stmname, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
1937 ok(r==S_OK, "IStorage->OpenStream should succeed %08x\n", r);
1938 if (r == S_OK)
1939 IStream_Release(stm);
1940
1941 r = IStorage_OpenStream(stg2, stmname2, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
1942 ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStream should fail %08x\n", r);
1943 if (r == S_OK)
1944 IStream_Release(stm);
1945
1946 IStorage_Release(stg2);
1947 }
1948
1949 IStorage_Release(stg);
1950
1951 ret = DeleteFileA(filenameA);
1952 ok(ret, "deleted file\n");
1953 }
1954
1955 static void test_ReadClassStm(void)
1956 {
1957 CLSID clsid, clsid2;
1958 HRESULT hr;
1959 IStream *pStream;
1960 static const LARGE_INTEGER llZero;
1961
1962 hr = ReadClassStm(NULL, &clsid);
1963 ok(hr == E_INVALIDARG, "ReadClassStm should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1964
1965 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1966 ok_ole_success(hr, "CreateStreamOnHGlobal");
1967 hr = WriteClassStm(pStream, &test_stg_cls);
1968 ok_ole_success(hr, "WriteClassStm");
1969
1970 hr = ReadClassStm(pStream, NULL);
1971 ok(hr == E_INVALIDARG, "ReadClassStm should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1972
1973 memset(&clsid, 0xcc, sizeof(clsid));
1974 memset(&clsid2, 0xcc, sizeof(clsid2));
1975 hr = ReadClassStm(NULL, &clsid);
1976 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1977 ok(IsEqualCLSID(&clsid, &clsid2), "got wrong clsid\n");
1978
1979 /* test not rewound stream */
1980 hr = ReadClassStm(pStream, &clsid);
1981 ok(hr == STG_E_READFAULT, "ReadClassStm should have returned STG_E_READFAULT instead of 0x%08x\n", hr);
1982 ok(IsEqualCLSID(&clsid, &CLSID_NULL), "clsid should have been zeroed\n");
1983
1984 hr = IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1985 ok_ole_success(hr, "IStream_Seek");
1986 hr = ReadClassStm(pStream, &clsid);
1987 ok_ole_success(hr, "ReadClassStm");
1988 ok(IsEqualCLSID(&clsid, &test_stg_cls), "clsid should have been set to CLSID_WineTest\n");
1989
1990 IStream_Release(pStream);
1991 }
1992
1993 struct access_res
1994 {
1995 BOOL gothandle;
1996 DWORD lasterr;
1997 BOOL ignore;
1998 };
1999
2000 static const struct access_res create[16] =
2001 {
2002 { TRUE, ERROR_SUCCESS, TRUE },
2003 { TRUE, ERROR_SUCCESS, TRUE },
2004 { TRUE, ERROR_SUCCESS, FALSE },
2005 { TRUE, ERROR_SUCCESS, FALSE },
2006 { FALSE, ERROR_SHARING_VIOLATION, FALSE },
2007 { FALSE, ERROR_SHARING_VIOLATION, FALSE },
2008 { FALSE, ERROR_SHARING_VIOLATION, FALSE },
2009 { TRUE, ERROR_SUCCESS, FALSE },
2010 { FALSE, ERROR_SHARING_VIOLATION, FALSE },
2011 { FALSE, ERROR_SHARING_VIOLATION, FALSE },
2012 { FALSE, ERROR_SHARING_VIOLATION, FALSE },
2013 { TRUE, ERROR_SUCCESS, TRUE },
2014 { FALSE, ERROR_SHARING_VIOLATION, FALSE },
2015 { FALSE, ERROR_SHARING_VIOLATION, FALSE },
2016 { FALSE, ERROR_SHARING_VIOLATION, FALSE },
2017 { TRUE, ERROR_SUCCESS, TRUE }
2018 };
2019
2020 static const struct access_res create_commit[16] =
2021 {
2022 { TRUE, ERROR_SUCCESS, TRUE },
2023 { TRUE, ERROR_SUCCESS, TRUE },
2024 { TRUE, ERROR_SUCCESS, FALSE },
2025 { TRUE, ERROR_SUCCESS, FALSE },
2026 { FALSE, ERROR_SHARING_VIOLATION, FALSE },
2027 { FALSE, ERROR_SHARING_VIOLATION, FALSE },
2028 { FALSE, ERROR_SHARING_VIOLATION, FALSE },
2029 { TRUE, ERROR_SUCCESS, FALSE },
2030 { FALSE, ERROR_SHARING_VIOLATION, FALSE },
2031 { FALSE, ERROR_SHARING_VIOLATION, FALSE },
2032 { FALSE, ERROR_SHARING_VIOLATION, FALSE },
2033 { TRUE, ERROR_SUCCESS, TRUE },
2034 { FALSE, ERROR_SHARING_VIOLATION, FALSE },
2035 { FALSE, ERROR_SHARING_VIOLATION, FALSE },
2036 { FALSE, ERROR_SHARING_VIOLATION, FALSE },
2037 { TRUE, ERROR_SUCCESS, TRUE }
2038 };
2039
2040 static const struct access_res create_close[16] =
2041 {
2042 { TRUE, ERROR_SUCCESS, FALSE },
2043 { TRUE, ERROR_SUCCESS, FALSE },
2044 { TRUE, ERROR_SUCCESS, FALSE },
2045 { TRUE, ERROR_SUCCESS, FALSE },
2046 { TRUE, ERROR_SUCCESS, FALSE },
2047 { TRUE, ERROR_SUCCESS, FALSE },
2048 { TRUE, ERROR_SUCCESS, FALSE },
2049 { TRUE, ERROR_SUCCESS, FALSE },
2050 { TRUE, ERROR_SUCCESS, FALSE },
2051 { TRUE, ERROR_SUCCESS, FALSE },
2052 { TRUE, ERROR_SUCCESS, FALSE },
2053 { TRUE, ERROR_SUCCESS, FALSE },
2054 { TRUE, ERROR_SUCCESS, FALSE },
2055 { TRUE, ERROR_SUCCESS, FALSE },
2056 { TRUE, ERROR_SUCCESS, FALSE },
2057 { TRUE, ERROR_SUCCESS }
2058 };
2059
2060 static const DWORD access_modes[4] = {
2061 0,
2062 GENERIC_READ,
2063 GENERIC_WRITE,
2064 GENERIC_READ | GENERIC_WRITE
2065 };
2066
2067 static const DWORD share_modes[4] = {
2068 0,
2069 FILE_SHARE_READ,
2070 FILE_SHARE_WRITE,
2071 FILE_SHARE_READ | FILE_SHARE_WRITE
2072 };
2073
2074 static void _test_file_access(LPCSTR file, const struct access_res *ares, DWORD line)
2075 {
2076 int i, j, idx = 0;
2077
2078 for (i = 0; i < sizeof(access_modes)/sizeof(access_modes[0]); i++)
2079 {
2080 for (j = 0; j < sizeof(share_modes)/sizeof(share_modes[0]); j++)
2081 {
2082 DWORD lasterr;
2083 HANDLE hfile;
2084
2085 if (ares[idx].ignore)
2086 continue;
2087
2088 SetLastError(0xdeadbeef);
2089 hfile = CreateFileA(file, access_modes[i], share_modes[j], NULL, OPEN_EXISTING,
2090 FILE_ATTRIBUTE_NORMAL, 0);
2091 lasterr = GetLastError();
2092
2093 ok((hfile != INVALID_HANDLE_VALUE) == ares[idx].gothandle,
2094 "(%d, handle, %d): Expected %d, got %d\n",
2095 line, idx, ares[idx].gothandle,
2096 (hfile != INVALID_HANDLE_VALUE));
2097
2098 ok(lasterr == ares[idx].lasterr ||
2099 broken(lasterr == 0xdeadbeef) /* win9x */,
2100 "(%d, lasterr, %d): Expected %d, got %d\n",
2101 line, idx, ares[idx].lasterr, lasterr);
2102
2103 CloseHandle(hfile);
2104 idx++;
2105 }
2106 }
2107 }
2108
2109 #define test_file_access(file, ares) _test_file_access(file, ares, __LINE__)
2110
2111 static void test_access(void)
2112 {
2113 static const WCHAR fileW[] = {'w','i','n','e','t','e','s','t',0};
2114 static const char fileA[] = "winetest";
2115 IStorage *stg;
2116 HRESULT hr;
2117
2118 /* STGM_TRANSACTED */
2119 hr = StgCreateDocfile(fileW, STGM_CREATE | STGM_READWRITE |
2120 STGM_SHARE_EXCLUSIVE | STGM_TRANSACTED, 0, &stg);
2121 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
2122
2123 test_file_access(fileA, create);
2124
2125 hr = IStorage_Commit(stg, STGC_DEFAULT);
2126 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
2127
2128 test_file_access(fileA, create_commit);
2129
2130 IStorage_Release(stg);
2131
2132 test_file_access(fileA, create_close);
2133
2134 DeleteFileA(fileA);
2135
2136 /* STGM_DIRECT */
2137 hr = StgCreateDocfile(fileW, STGM_CREATE | STGM_READWRITE |
2138 STGM_SHARE_EXCLUSIVE | STGM_DIRECT, 0, &stg);
2139 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
2140
2141 test_file_access(fileA, create);
2142
2143 hr = IStorage_Commit(stg, STGC_DEFAULT);
2144 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
2145
2146 test_file_access(fileA, create_commit);
2147
2148 IStorage_Release(stg);
2149
2150 test_file_access(fileA, create_close);
2151
2152 DeleteFileA(fileA);
2153
2154 /* STGM_SHARE_DENY_NONE */
2155 hr = StgCreateDocfile(fileW, STGM_CREATE | STGM_READWRITE |
2156 STGM_SHARE_DENY_NONE | STGM_TRANSACTED, 0, &stg);
2157 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
2158
2159 test_file_access(fileA, create);
2160
2161 hr = IStorage_Commit(stg, STGC_DEFAULT);
2162 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
2163
2164 test_file_access(fileA, create_commit);
2165
2166 IStorage_Release(stg);
2167
2168 test_file_access(fileA, create_close);
2169
2170 DeleteFileA(fileA);
2171
2172 /* STGM_SHARE_DENY_READ */
2173 hr = StgCreateDocfile(fileW, STGM_CREATE | STGM_READWRITE |
2174 STGM_SHARE_DENY_READ | STGM_TRANSACTED, 0, &stg);
2175 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
2176
2177 test_file_access(fileA, create);
2178
2179 hr = IStorage_Commit(stg, STGC_DEFAULT);
2180 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
2181
2182 test_file_access(fileA, create_commit);
2183
2184 IStorage_Release(stg);
2185
2186 test_file_access(fileA, create_close);
2187
2188 DeleteFileA(fileA);
2189
2190 /* STGM_SHARE_DENY_WRITE */
2191 hr = StgCreateDocfile(fileW, STGM_CREATE | STGM_READWRITE |
2192 STGM_SHARE_DENY_WRITE | STGM_TRANSACTED, 0, &stg);
2193 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
2194
2195 test_file_access(fileA, create);
2196
2197 hr = IStorage_Commit(stg, STGC_DEFAULT);
2198 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
2199
2200 test_file_access(fileA, create_commit);
2201
2202 IStorage_Release(stg);
2203
2204 test_file_access(fileA, create_close);
2205
2206 DeleteFileA(fileA);
2207
2208 /* STGM_DIRECT_SWMR | STGM_READ | STGM_SHARE_DENY_NONE - reader mode for direct SWMR mode */
2209 hr = StgCreateDocfile(fileW, STGM_CREATE | STGM_READWRITE | STGM_SHARE_DENY_WRITE | STGM_TRANSACTED, 0, &stg);
2210 ok(hr == S_OK, "got %08x\n", hr);
2211 IStorage_Release(stg);
2212
2213 hr = StgOpenStorage(fileW, NULL, STGM_DIRECT_SWMR | STGM_READ | STGM_SHARE_DENY_NONE, NULL, 0, &stg);
2214 ok(hr == S_OK || broken(hr == STG_E_INVALIDFLAG), "got %08x\n", hr);
2215 if(hr != S_OK)
2216 return;
2217
2218 test_file_access(fileA, create);
2219
2220 IStorage_Release(stg);
2221 test_file_access(fileA, create_close);
2222
2223 DeleteFileA(fileA);
2224 }
2225
2226 static void test_readonly(void)
2227 {
2228 IStorage *stg, *stg2, *stg3;
2229 IStream *stream;
2230 HRESULT hr;
2231 static const WCHAR fileW[] = {'w','i','n','e','t','e','s','t',0};
2232 static const WCHAR storageW[] = {'s','t','o','r','a','g','e',0};
2233 static const WCHAR streamW[] = {'s','t','r','e','a','m',0};
2234
2235 hr = StgCreateDocfile( fileW, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &stg);
2236 ok(hr == S_OK, "should succeed, res=%x\n", hr);
2237 if (SUCCEEDED(hr))
2238 {
2239 hr = IStorage_CreateStorage( stg, storageW, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stg2 );
2240 ok(hr == S_OK, "should succeed, res=%x\n", hr);
2241 if (SUCCEEDED(hr))
2242 {
2243 hr = IStorage_CreateStream( stg2, streamW, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stream );
2244 ok(hr == S_OK, "should succeed, res=%x\n", hr);
2245 if (SUCCEEDED(hr))
2246 IStream_Release(stream);
2247 IStorage_Release(stg2);
2248 }
2249 IStorage_Release(stg);
2250 }
2251
2252 /* re-open read only */
2253 hr = StgOpenStorage( fileW, NULL, STGM_TRANSACTED | STGM_SHARE_DENY_NONE | STGM_READ, NULL, 0, &stg);
2254 ok(hr == S_OK, "should succeed, res=%x\n", hr);
2255 if (SUCCEEDED(hr))
2256 {
2257 hr = IStorage_OpenStorage( stg, storageW, NULL, STGM_SHARE_EXCLUSIVE | STGM_READ, NULL, 0, &stg2 );
2258 ok(hr == S_OK, "should succeed, res=%x\n", hr);
2259 if (SUCCEEDED(hr))
2260 {
2261 /* CreateStream on read-only storage, name exists */
2262 hr = IStorage_CreateStream( stg2, streamW, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READ, 0, 0, &stream );
2263 ok(hr == STG_E_ACCESSDENIED, "should fail, res=%x\n", hr);
2264 if (SUCCEEDED(hr))
2265 IStream_Release(stream);
2266
2267 /* CreateStream on read-only storage, name does not exist */
2268 hr = IStorage_CreateStream( stg2, storageW, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READ, 0, 0, &stream );
2269 ok(hr == STG_E_ACCESSDENIED, "should fail, res=%x\n", hr);
2270 if (SUCCEEDED(hr))
2271 IStream_Release(stream);
2272
2273 /* CreateStorage on read-only storage, name exists */
2274 hr = IStorage_CreateStorage( stg2, streamW, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READ, 0, 0, &stg3 );
2275 ok(hr == STG_E_FILEALREADYEXISTS, "should fail, res=%x\n", hr);
2276 if (SUCCEEDED(hr))
2277 IStorage_Release(stg3);
2278
2279 /* CreateStorage on read-only storage, name does not exist */
2280 hr = IStorage_CreateStorage( stg2, storageW, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READ, 0, 0, &stg3 );
2281 ok(hr == STG_E_ACCESSDENIED, "should fail, res=%x\n", hr);
2282 if (SUCCEEDED(hr))
2283 IStorage_Release(stg3);
2284
2285 /* DestroyElement on read-only storage, name exists */
2286 hr = IStorage_DestroyElement( stg2, streamW );
2287 ok(hr == STG_E_ACCESSDENIED, "should fail, res=%x\n", hr);
2288
2289 /* DestroyElement on read-only storage, name does not exist */
2290 hr = IStorage_DestroyElement( stg2, storageW );
2291 ok(hr == STG_E_ACCESSDENIED, "should fail, res=%x\n", hr);
2292
2293 IStorage_Release(stg2);
2294 }
2295
2296 IStorage_Release(stg);
2297 }
2298
2299 DeleteFileA("winetest");
2300 }
2301
2302 static void test_simple(void)
2303 {
2304 /* Tests for STGM_SIMPLE mode */
2305
2306 IStorage *stg, *stg2;
2307 HRESULT r;
2308 IStream *stm;
2309 static const WCHAR stgname[] = { 'S','t','g',0 };
2310 static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 };
2311 static const WCHAR stmname2[] = { 'S','m','a','l','l',0 };
2312 LARGE_INTEGER pos;
2313 ULARGE_INTEGER upos;
2314 DWORD count;
2315 STATSTG stat;
2316
2317 DeleteFileA(filenameA);
2318
2319 r = StgCreateDocfile( filename, STGM_SIMPLE | STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &stg);
2320 ok(r == S_OK, "got %08x\n", r);
2321
2322 r = IStorage_CreateStorage(stg, stgname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stg2);
2323 ok(r == STG_E_INVALIDFUNCTION, "got %08x\n", r);
2324 if (SUCCEEDED(r)) IStorage_Release(stg2);
2325
2326 r = IStorage_CreateStream(stg, stmname, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm);
2327 ok(r == STG_E_INVALIDFLAG, "got %08x\n", r);
2328 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm);
2329 ok(r == S_OK, "got %08x\n", r);
2330
2331 upos.QuadPart = 6000;
2332 r = IStream_SetSize(stm, upos);
2333 ok(r == S_OK, "got %08x\n", r);
2334
2335 r = IStream_Write(stm, "foo", 3, &count);
2336 ok(r == S_OK, "got %08x\n", r);
2337 ok(count == 3, "got %d\n", count);
2338
2339 pos.QuadPart = 0;
2340 r = IStream_Seek(stm, pos, STREAM_SEEK_CUR, &upos);
2341 ok(r == S_OK, "got %08x\n", r);
2342 ok(upos.QuadPart == 3, "got %d\n", upos.u.LowPart);
2343
2344 r = IStream_Stat(stm, &stat, STATFLAG_NONAME);
2345 ok(r == S_OK ||
2346 broken(r == STG_E_INVALIDFUNCTION), /* NT4 and below */
2347 "got %08x\n", r);
2348 if (r == S_OK)
2349 ok(stat.cbSize.QuadPart == 3, "got %d\n", stat.cbSize.u.LowPart);
2350
2351 pos.QuadPart = 1;
2352 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &upos);
2353 ok(r == S_OK, "got %08x\n", r);
2354 ok(upos.QuadPart == 1, "got %d\n", upos.u.LowPart);
2355
2356 r = IStream_Stat(stm, &stat, STATFLAG_NONAME);
2357 ok(r == S_OK ||
2358 broken(r == STG_E_INVALIDFUNCTION), /* NT4 and below */
2359 "got %08x\n", r);
2360 if (r == S_OK)
2361 ok(stat.cbSize.QuadPart == 1, "got %d\n", stat.cbSize.u.LowPart);
2362
2363 IStream_Release(stm);
2364
2365 r = IStorage_CreateStream(stg, stmname2, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm);
2366 ok(r == S_OK, "got %08x\n", r);
2367
2368 upos.QuadPart = 100;
2369 r = IStream_SetSize(stm, upos);
2370 ok(r == S_OK, "got %08x\n", r);
2371
2372 r = IStream_Write(stm, "foo", 3, &count);
2373 ok(r == S_OK, "got %08x\n", r);
2374 ok(count == 3, "got %d\n", count);
2375
2376 IStream_Release(stm);
2377
2378 IStorage_Commit(stg, STGC_DEFAULT);
2379 IStorage_Release(stg);
2380
2381 r = StgOpenStorage( filename, NULL, STGM_SIMPLE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, NULL, 0, &stg);
2382 if (r == STG_E_INVALIDFLAG)
2383 {
2384 win_skip("Flag combination is not supported on NT4 and below\n");
2385 DeleteFileA(filenameA);
2386 return;
2387 }
2388 ok(r == S_OK, "got %08x\n", r);
2389
2390 r = IStorage_OpenStorage(stg, stgname, NULL, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, NULL, 0, &stg2);
2391 ok(r == STG_E_INVALIDFUNCTION, "got %08x\n", r);
2392 if (SUCCEEDED(r)) IStorage_Release(stg2);
2393
2394 r = IStorage_OpenStream(stg, stmname, NULL, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &stm);
2395 ok(r == S_OK, "got %08x\n", r);
2396
2397 r = IStream_Stat(stm, &stat, STATFLAG_NONAME);
2398 ok(r == S_OK, "got %08x\n", r);
2399 ok(stat.cbSize.QuadPart == 6000, "got %d\n", stat.cbSize.u.LowPart);
2400
2401 IStream_Release(stm);
2402
2403 r = IStorage_OpenStream(stg, stmname2, NULL, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &stm);
2404 ok(r == S_OK, "got %08x\n", r);
2405
2406 r = IStream_Stat(stm, &stat, STATFLAG_NONAME);
2407 ok(r == S_OK, "got %08x\n", r);
2408 ok(stat.cbSize.QuadPart == 4096, "got %d\n", stat.cbSize.u.LowPart);
2409
2410 IStream_Release(stm);
2411
2412
2413 IStorage_Release(stg);
2414
2415 DeleteFileA(filenameA);
2416 }
2417
2418 static void test_fmtusertypestg(void)
2419 {
2420 IStorage *stg;
2421 IEnumSTATSTG *stat;
2422 HRESULT hr;
2423 static const char fileA[] = {'f','m','t','t','e','s','t',0};
2424 static const WCHAR fileW[] = {'f','m','t','t','e','s','t',0};
2425 static WCHAR userTypeW[] = {'S','t','g','U','s','r','T','y','p','e',0};
2426 static const WCHAR strmNameW[] = {1,'C','o','m','p','O','b','j',0};
2427 static const STATSTG statstg_null;
2428
2429 hr = StgCreateDocfile( fileW, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &stg);
2430 ok(hr == S_OK, "should succeed, res=%x\n", hr);
2431
2432 if (SUCCEEDED(hr))
2433 {
2434 /* try to write the stream */
2435 hr = WriteFmtUserTypeStg(stg, 0, userTypeW);
2436 ok(hr == S_OK, "should succeed, res=%x\n", hr);
2437
2438 /* check that the stream was created */
2439 hr = IStorage_EnumElements(stg, 0, NULL, 0, &stat);
2440 ok(hr == S_OK, "should succeed, res=%x\n", hr);
2441 if (SUCCEEDED(hr))
2442 {
2443 BOOL found = FALSE;
2444 STATSTG statstg;
2445 DWORD got;
2446 memset(&statstg, 0xad, sizeof(statstg));
2447 while ((hr = IEnumSTATSTG_Next(stat, 1, &statstg, &got)) == S_OK && got == 1)
2448 {
2449 if (strcmp_ww(statstg.pwcsName, strmNameW) == 0)
2450 found = TRUE;
2451 else
2452 ok(0, "found unexpected stream or storage\n");
2453 CoTaskMemFree(statstg.pwcsName);
2454 }
2455 ok(memcmp(&statstg, &statstg_null, sizeof(statstg)) == 0, "statstg is not zeroed\n");
2456 ok(found == TRUE, "expected storage to contain stream \\0001CompObj\n");
2457 IEnumSTATSTG_Release(stat);
2458 }
2459
2460 /* re-write the stream */
2461 hr = WriteFmtUserTypeStg(stg, 0, userTypeW);
2462 ok(hr == S_OK, "should succeed, res=%x\n", hr);
2463
2464 /* check that the stream is still there */
2465 hr = IStorage_EnumElements(stg, 0, NULL, 0, &stat);
2466 ok(hr == S_OK, "should succeed, res=%x\n", hr);
2467 if (SUCCEEDED(hr))
2468 {
2469 BOOL found = FALSE;
2470 STATSTG statstg;
2471 DWORD got;
2472 memset(&statstg, 0xad, sizeof(statstg));
2473 while ((hr = IEnumSTATSTG_Next(stat, 1, &statstg, &got)) == S_OK && got == 1)
2474 {
2475 if (strcmp_ww(statstg.pwcsName, strmNameW) == 0)
2476 found = TRUE;
2477 else
2478 ok(0, "found unexpected stream or storage\n");
2479 CoTaskMemFree(statstg.pwcsName);
2480 }
2481 ok(memcmp(&statstg, &statstg_null, sizeof(statstg)) == 0, "statstg is not zeroed\n");
2482 ok(found == TRUE, "expected storage to contain stream \\0001CompObj\n");
2483 IEnumSTATSTG_Release(stat);
2484 }
2485
2486 IStorage_Release(stg);
2487 DeleteFileA( fileA );
2488 }
2489 }
2490
2491 static void test_references(void)
2492 {
2493 IStorage *stg,*stg2;
2494 HRESULT hr;
2495 unsigned c1,c2;
2496 static const WCHAR StorName[] = { 'D','a','t','a','S','p','a','c','e','I','n','f','o',0 };
2497
2498 DeleteFileA(filenameA);
2499
2500 hr = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
2501 ok(hr==S_OK, "StgCreateDocfile failed\n");
2502
2503 if (SUCCEEDED(hr))
2504 {
2505 IStorage_Release(stg);
2506
2507 hr = StgOpenStorage( filename, NULL, STGM_TRANSACTED | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, NULL, 0, &stg);
2508 ok(hr==S_OK, "StgOpenStorage failed (result=%x)\n",hr);
2509
2510 if (SUCCEEDED(hr))
2511 {
2512 hr = IStorage_CreateStorage(stg,StorName,STGM_READWRITE | STGM_SHARE_EXCLUSIVE,0,0,&stg2);
2513 ok(hr == S_OK, "IStorage_CreateStorage failed (result=%x)\n",hr);
2514
2515 if (SUCCEEDED(hr))
2516 {
2517 c1 = IStorage_AddRef(stg);
2518 ok(c1 == 2, "creating internal storage added references to ancestor\n");
2519 c1 = IStorage_AddRef(stg);
2520 IStorage_Release(stg2);
2521 c2 = IStorage_AddRef(stg) - 1;
2522 ok(c1 == c2, "releasing internal storage removed references to ancestor\n");
2523 }
2524 c1 = IStorage_Release(stg);
2525 while ( c1 ) c1 = IStorage_Release(stg);
2526 }
2527 }
2528
2529 DeleteFileA(filenameA);
2530 }
2531
2532 /* dest
2533 * |-StorageA
2534 * | `StreamA: "StreamA"
2535 * |-StorageB
2536 * | `StreamB: "StreamB"
2537 * `StreamC: "StreamC"
2538 */
2539 static HRESULT create_test_file(IStorage *dest)
2540 {
2541 IStorage *stgA = NULL, *stgB = NULL;
2542 IStream *strmA = NULL, *strmB = NULL, *strmC = NULL;
2543 const ULONG strmA_name_size = lstrlenW(strmA_name) * sizeof(WCHAR);
2544 const ULONG strmB_name_size = lstrlenW(strmB_name) * sizeof(WCHAR);
2545 const ULONG strmC_name_size = lstrlenW(strmC_name) * sizeof(WCHAR);
2546 ULONG bytes;
2547 HRESULT hr;
2548
2549 hr = IStorage_CreateStorage(dest, stgA_name, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stgA);
2550 ok(hr == S_OK, "IStorage_CreateStorage failed: 0x%08x\n", hr);
2551 if(FAILED(hr))
2552 goto cleanup;
2553
2554 hr = IStorage_CreateStream(stgA, strmA_name, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &strmA);
2555 ok(hr == S_OK, "IStorage_CreateStream failed: 0x%08x\n", hr);
2556 if(FAILED(hr))
2557 goto cleanup;
2558
2559 hr = IStream_Write(strmA, strmA_name, strmA_name_size, &bytes);
2560 ok(hr == S_OK && bytes == strmA_name_size, "IStream_Write failed: 0x%08x, %d of %d bytes written\n", hr, bytes, strmA_name_size);
2561
2562 hr = IStorage_CreateStorage(dest, stgB_name, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stgB);
2563 ok(hr == S_OK, "IStorage_CreateStorage failed: 0x%08x\n", hr);
2564 if(FAILED(hr))
2565 goto cleanup;
2566
2567 hr = IStorage_CreateStream(stgB, strmB_name, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &strmB);
2568 ok(hr == S_OK, "IStorage_CreateStream failed: 0x%08x\n", hr);
2569 if(FAILED(hr))
2570 goto cleanup;
2571
2572 hr = IStream_Write(strmB, strmB_name, strmB_name_size, &bytes);
2573 ok(hr == S_OK && bytes == strmB_name_size, "IStream_Write failed: 0x%08x, %d of %d bytes written\n", hr, bytes, strmB_name_size);
2574
2575 hr = IStorage_CreateStream(dest, strmC_name, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &strmC);
2576 ok(hr == S_OK, "IStorage_CreateStream failed: 0x%08x\n", hr);
2577 if(FAILED(hr))
2578 goto cleanup;
2579
2580 hr = IStream_Write(strmC, strmC_name, strmC_name_size, &bytes);
2581 ok(hr == S_OK && bytes == strmC_name_size, "IStream_Write failed: 0x%08x, %d of %d bytes written\n", hr, bytes, strmC_name_size);
2582
2583 cleanup:
2584 if(strmC)
2585 IStream_Release(strmC);
2586 if(strmB)
2587 IStream_Release(strmB);
2588 if(stgB)
2589 IStorage_Release(stgB);
2590 if(strmA)
2591 IStream_Release(strmA);
2592 if(stgA)
2593 IStorage_Release(stgA);
2594
2595 return hr;
2596 }
2597
2598 static void test_copyto(void)
2599 {
2600 IStorage *file1 = NULL, *file2 = NULL, *stg_tmp;
2601 IStream *strm_tmp;
2602 WCHAR buf[64];
2603 HRESULT hr;
2604
2605 /* create & populate file1 */
2606 hr = StgCreateDocfile(file1_name, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &file1);
2607 ok(hr == S_OK, "StgCreateDocfile failed: 0x%08x\n", hr);
2608 if(FAILED(hr))
2609 goto cleanup;
2610
2611 hr = create_test_file(file1);
2612 if(FAILED(hr))
2613 goto cleanup;
2614
2615 /* create file2 */
2616 hr = StgCreateDocfile(file2_name, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &file2);
2617 ok(hr == S_OK, "StgCreateDocfile failed: 0x%08x\n", hr);
2618 if(FAILED(hr))
2619 goto cleanup;
2620
2621 /* copy file1 into file2 */
2622 hr = IStorage_CopyTo(file1, 0, NULL, NULL, NULL);
2623 ok(hr == STG_E_INVALIDPOINTER, "CopyTo should give STG_E_INVALIDPONITER, gave: 0x%08x\n", hr);
2624
2625 hr = IStorage_CopyTo(file1, 0, NULL, NULL, file2);
2626 ok(hr == S_OK, "CopyTo failed: 0x%08x\n", hr);
2627 if(FAILED(hr))
2628 goto cleanup;
2629
2630 /* verify that all of file1 was copied */
2631 hr = IStorage_OpenStorage(file2, stgA_name, NULL,
2632 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg_tmp);
2633 ok(hr == S_OK, "OpenStorage failed: 0x%08x\n", hr);
2634
2635 if(SUCCEEDED(hr)){
2636 hr = IStorage_OpenStream(stg_tmp, strmA_name, NULL,
2637 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp);
2638 ok(hr == S_OK, "OpenStream failed: 0x%08x\n", hr);
2639
2640 if(SUCCEEDED(hr)){
2641 memset(buf, 0, sizeof(buf));
2642 hr = IStream_Read(strm_tmp, buf, sizeof(buf), NULL);
2643 ok(hr == S_OK, "Read failed: 0x%08x\n", hr);
2644 if(SUCCEEDED(hr))
2645 ok(strcmp_ww(buf, strmA_name) == 0,
2646 "Expected %s to be read, got %s\n", wine_dbgstr_w(strmA_name), wine_dbgstr_w(buf));
2647
2648 IStream_Release(strm_tmp);
2649 }
2650
2651 IStorage_Release(stg_tmp);
2652 }
2653
2654 hr = IStorage_OpenStorage(file2, stgB_name, NULL,
2655 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg_tmp);
2656 ok(hr == S_OK, "OpenStorage failed: 0x%08x\n", hr);
2657
2658 if(SUCCEEDED(hr)){
2659 hr = IStorage_OpenStream(stg_tmp, strmB_name, NULL,
2660 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp);
2661 ok(hr == S_OK, "OpenStream failed: 0x%08x\n", hr);
2662
2663 if(SUCCEEDED(hr)){
2664 memset(buf, 0, sizeof(buf));
2665 hr = IStream_Read(strm_tmp, buf, sizeof(buf), NULL);
2666 ok(hr == S_OK, "Read failed: 0x%08x\n", hr);
2667 if(SUCCEEDED(hr))
2668 ok(strcmp_ww(buf, strmB_name) == 0,
2669 "Expected %s to be read, got %s\n", wine_dbgstr_w(strmB_name), wine_dbgstr_w(buf));
2670
2671 IStream_Release(strm_tmp);
2672 }
2673
2674 IStorage_Release(stg_tmp);
2675 }
2676
2677 hr = IStorage_OpenStream(file2, strmC_name, NULL,
2678 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp);
2679 ok(hr == S_OK, "OpenStream failed: 0x%08x\n", hr);
2680
2681 if(SUCCEEDED(hr)){
2682 memset(buf, 0, sizeof(buf));
2683 hr = IStream_Read(strm_tmp, buf, sizeof(buf), NULL);
2684 ok(hr == S_OK, "Read failed: 0x%08x\n", hr);
2685 if(SUCCEEDED(hr))
2686 ok(strcmp_ww(buf, strmC_name) == 0,
2687 "Expected %s to be read, got %s\n", wine_dbgstr_w(strmC_name), wine_dbgstr_w(buf));
2688
2689 IStream_Release(strm_tmp);
2690 }
2691
2692 cleanup:
2693 if(file1)
2694 IStorage_Release(file1);
2695 if(file2)
2696 IStorage_Release(file2);
2697
2698 DeleteFileA(file1_nameA);
2699 DeleteFileA(file2_nameA);
2700 }
2701
2702 static void test_copyto_snbexclusions(void)
2703 {
2704 static const WCHAR *snb_exclude[] = {stgA_name, strmB_name, strmC_name, 0};
2705
2706 IStorage *file1 = NULL, *file2 = NULL, *stg_tmp;
2707 IStream *strm_tmp;
2708 WCHAR buf[64];
2709 HRESULT hr;
2710
2711 /* create & populate file1 */
2712 hr = StgCreateDocfile(file1_name, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &file1);
2713 ok(hr == S_OK, "StgCreateDocfile failed: 0x%08x\n", hr);
2714 if(FAILED(hr))
2715 goto cleanup;
2716
2717 hr = create_test_file(file1);
2718 if(FAILED(hr))
2719 goto cleanup;
2720
2721 /* create file2 */
2722 hr = StgCreateDocfile(file2_name, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &file2);
2723 ok(hr == S_OK, "StgCreateDocfile failed: 0x%08x\n", hr);
2724 if(FAILED(hr))
2725 goto cleanup;
2726
2727 /* copy file1 to file2 with name exclusions */
2728 hr = IStorage_CopyTo(file1, 0, NULL, (SNB)snb_exclude, file2);
2729 ok(hr == S_OK, "CopyTo failed: 0x%08x\n", hr);
2730 if(FAILED(hr))
2731 goto cleanup;
2732
2733 /* verify that file1 copied over, respecting exclusions */
2734 hr = IStorage_OpenStorage(file2, stgA_name, NULL,
2735 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg_tmp);
2736 ok(hr == STG_E_FILENOTFOUND, "OpenStorage should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr);
2737 if(SUCCEEDED(hr))
2738 IStorage_Release(stg_tmp);
2739
2740 hr = IStorage_OpenStream(file2, strmA_name, NULL,
2741 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp);
2742 ok(hr == STG_E_FILENOTFOUND, "OpenStream should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr);
2743 if(SUCCEEDED(hr))
2744 IStream_Release(strm_tmp);
2745
2746 hr = IStorage_OpenStorage(file2, stgB_name, NULL,
2747 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg_tmp);
2748 ok(hr == S_OK, "OpenStorage failed: 0x%08x\n", hr);
2749
2750 if(SUCCEEDED(hr)){
2751 hr = IStorage_OpenStream(stg_tmp, strmB_name, NULL,
2752 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp);
2753 ok(hr == S_OK, "OpenStream failed: 0x%08x\n", hr);
2754
2755 if(SUCCEEDED(hr)){
2756 memset(buf, 0, sizeof(buf));
2757 hr = IStream_Read(strm_tmp, buf, sizeof(buf), NULL);
2758 ok(hr == S_OK, "Read failed: 0x%08x\n", hr);
2759 if(SUCCEEDED(hr))
2760 ok(strcmp_ww(buf, strmB_name) == 0,
2761 "Expected %s to be read, got %s\n", wine_dbgstr_w(strmB_name), wine_dbgstr_w(buf));
2762
2763 IStream_Release(strm_tmp);
2764 }
2765
2766 IStorage_Release(stg_tmp);
2767 }
2768
2769 hr = IStorage_OpenStream(file2, strmC_name, NULL,
2770 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp);
2771 ok(hr == STG_E_FILENOTFOUND, "OpenStream should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr);
2772 if(SUCCEEDED(hr))
2773 IStream_Release(strm_tmp);
2774
2775 cleanup:
2776 if(file1)
2777 IStorage_Release(file1);
2778 if(file2)
2779 IStorage_Release(file2);
2780
2781 DeleteFileA(file1_nameA);
2782 DeleteFileA(file2_nameA);
2783 }
2784
2785 static void test_copyto_iidexclusions_storage(void)
2786 {
2787 IStorage *file1 = NULL, *file2 = NULL, *stg_tmp;
2788 IStream *strm_tmp;
2789 WCHAR buf[64];
2790 HRESULT hr;
2791
2792 /* create & populate file1 */
2793 hr = StgCreateDocfile(file1_name, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &file1);
2794 ok(hr == S_OK, "StgCreateDocfile failed: 0x%08x\n", hr);
2795 if(FAILED(hr))
2796 goto cleanup;
2797
2798 hr = create_test_file(file1);
2799 if(FAILED(hr))
2800 goto cleanup;
2801
2802 /* create file2 */
2803 hr = StgCreateDocfile(file2_name, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &file2);
2804 ok(hr == S_OK, "StgCreateDocfile failed: 0x%08x\n", hr);
2805 if(FAILED(hr))
2806 goto cleanup;
2807
2808 /* copy file1 to file2 with iid exclusions */
2809 hr = IStorage_CopyTo(file1, 1, &IID_IStorage, NULL, file2);
2810 ok(hr == S_OK, "CopyTo failed: 0x%08x\n", hr);
2811 if(FAILED(hr))
2812 goto cleanup;
2813
2814 /* verify that file1 copied over, respecting exclusions */
2815 hr = IStorage_OpenStorage(file2, stgA_name, NULL,
2816 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg_tmp);
2817 ok(hr == STG_E_FILENOTFOUND, "OpenStorage should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr);
2818 if(SUCCEEDED(hr))
2819 IStorage_Release(stg_tmp);
2820
2821 hr = IStorage_OpenStream(file2, strmA_name, NULL,
2822 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp);
2823 ok(hr == STG_E_FILENOTFOUND, "OpenStream should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr);
2824 if(SUCCEEDED(hr))
2825 IStream_Release(strm_tmp);
2826
2827 hr = IStorage_OpenStorage(file2, stgB_name, NULL,
2828 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg_tmp);
2829 ok(hr == STG_E_FILENOTFOUND, "OpenStorage should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr);
2830 if(SUCCEEDED(hr))
2831 IStorage_Release(stg_tmp);
2832
2833 hr = IStorage_OpenStream(file2, strmB_name, NULL,
2834 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp);
2835 ok(hr == STG_E_FILENOTFOUND, "OpenStream should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr);
2836 if(SUCCEEDED(hr))
2837 IStream_Release(strm_tmp);
2838
2839 hr = IStorage_OpenStream(file2, strmC_name, NULL,
2840 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp);
2841 ok(hr == S_OK, "OpenStream failed: 0x%08x\n", hr);
2842
2843 if(SUCCEEDED(hr)){
2844 memset(buf, 0, sizeof(buf));
2845 hr = IStream_Read(strm_tmp, buf, sizeof(buf), NULL);
2846 ok(hr == S_OK, "Read failed: 0x%08x\n", hr);
2847 if(SUCCEEDED(hr))
2848 ok(strcmp_ww(buf, strmC_name) == 0,
2849 "Expected %s to be read, got %s\n", wine_dbgstr_w(strmC_name), wine_dbgstr_w(buf));
2850
2851 IStream_Release(strm_tmp);
2852 }
2853
2854 cleanup:
2855 if(file1)
2856 IStorage_Release(file1);
2857 if(file2)
2858 IStorage_Release(file2);
2859
2860 DeleteFileA(file1_nameA);
2861 DeleteFileA(file2_nameA);
2862 }
2863
2864 static void test_copyto_iidexclusions_stream(void)
2865 {
2866 IStorage *file1 = NULL, *file2 = NULL, *stg_tmp;
2867 IStream *strm_tmp;
2868 HRESULT hr;
2869
2870 /* create & populate file1 */
2871 hr = StgCreateDocfile(file1_name, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &file1);
2872 ok(hr == S_OK, "StgCreateDocfile failed: 0x%08x\n", hr);
2873 if(FAILED(hr))
2874 goto cleanup;
2875
2876 hr = create_test_file(file1);
2877 if(FAILED(hr))
2878 goto cleanup;
2879
2880 /* create file2 */
2881 hr = StgCreateDocfile(file2_name, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &file2);
2882 ok(hr == S_OK, "StgCreateDocfile failed: 0x%08x\n", hr);
2883 if(FAILED(hr))
2884 goto cleanup;
2885
2886 /* copy file1 to file2 with iid exclusions */
2887 hr = IStorage_CopyTo(file1, 1, &IID_IStream, NULL, file2);
2888 ok(hr == S_OK, "CopyTo failed: 0x%08x\n", hr);
2889 if(FAILED(hr))
2890 goto cleanup;
2891
2892 /* verify that file1 copied over, respecting exclusions */
2893 hr = IStorage_OpenStorage(file2, stgA_name, NULL,
2894 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg_tmp);
2895 ok(hr == S_OK, "OpenStorage failed: 0x%08x\n", hr);
2896
2897 if(SUCCEEDED(hr)){
2898 hr = IStorage_OpenStream(stg_tmp, strmA_name, NULL,
2899 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp);
2900 ok(hr == STG_E_FILENOTFOUND, "OpenStream should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr);
2901 if(SUCCEEDED(hr))
2902 IStream_Release(strm_tmp);
2903
2904 IStorage_Release(stg_tmp);
2905 }
2906
2907 hr = IStorage_OpenStorage(file2, stgB_name, NULL,
2908 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg_tmp);
2909 ok(hr == S_OK, "OpenStorage failed: 0x%08x\n", hr);
2910
2911 if(SUCCEEDED(hr)){
2912 hr = IStorage_OpenStream(stg_tmp, strmB_name, NULL,
2913 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp);
2914 ok(hr == STG_E_FILENOTFOUND, "OpenStream should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr);
2915 if(SUCCEEDED(hr))