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