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