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