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