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