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