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