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