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