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