shlwapi: Beginning implementation of IUnknown_QueryServiceForWebBrowserApp.
[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     STATSTG stat;
849     IEnumSTATSTG *ee = NULL;
850     ULONG count;
851
852     DeleteFileA(filenameA);
853
854     /* create the file */
855     r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
856                             STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
857     ok(r==S_OK, "StgCreateDocfile failed\n");
858
859     r = WriteClassStg( stg, &test_stg_cls );
860     ok( r == S_OK, "WriteClassStg failed\n");
861
862     r = IStorage_Commit( stg, STGC_DEFAULT );
863     ok( r == S_OK, "IStorage_Commit failed\n");
864
865     /* now create a stream */
866     r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
867     ok(r==S_OK, "IStorage->CreateStream failed\n");
868
869     r = IStream_Release(stm);
870
871     /* first enum ... should be 1 stream */
872     r = IStorage_EnumElements(stg, 0, NULL, 0, &ee);
873     ok(r==S_OK, "IStorage->EnumElements failed\n");
874
875     count = 0xf00;
876     r = IEnumSTATSTG_Next(ee, 1, &stat, &count);
877     ok(r==S_OK, "IEnumSTATSTG->Next failed\n");
878     ok(count == 1, "count wrong\n");
879
880     r = IEnumSTATSTG_Release(ee);
881
882     /* second enum... destroy the stream before reading */
883     r = IStorage_EnumElements(stg, 0, NULL, 0, &ee);
884     ok(r==S_OK, "IStorage->EnumElements failed\n");
885
886     r = IStorage_DestroyElement(stg, stmname);
887     ok(r==S_OK, "IStorage->EnumElements failed\n");
888
889     todo_wine {
890     count = 0xf00;
891     r = IEnumSTATSTG_Next(ee, 1, &stat, &count);
892     ok(r==S_FALSE, "IEnumSTATSTG->Next failed\n");
893     ok(count == 0, "count wrong\n");
894     }
895
896     /* reset and try again */
897     r = IEnumSTATSTG_Reset(ee);
898     ok(r==S_OK, "IEnumSTATSTG->Reset failed\n");
899
900     count = 0xf00;
901     r = IEnumSTATSTG_Next(ee, 1, &stat, &count);
902     ok(r==S_FALSE, "IEnumSTATSTG->Next failed\n");
903     ok(count == 0, "count wrong\n");
904
905     r = IEnumSTATSTG_Release(ee);
906     ok (r == 0, "enum not released\n");
907
908     r = IStorage_Release( stg );
909     ok (r == 0, "storage not released\n");
910
911     DeleteFileA(filenameA);
912 }
913
914 static void test_transact(void)
915 {
916     IStorage *stg = NULL, *stg2 = NULL, *stg3 = NULL;
917     HRESULT r;
918     IStream *stm = NULL;
919     static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 };
920     static const WCHAR stmname2[] = { 'F','O','O',0 };
921     static const WCHAR stgname[] = { 'P','E','R','M','S','T','G',0 };
922     static const WCHAR stgname2[] = { 'T','E','M','P','S','T','G',0 };
923
924     DeleteFileA(filenameA);
925
926     /* create the file */
927     r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | 
928                             STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
929     ok(r==S_OK, "StgCreateDocfile failed\n");
930
931     /* commit a new stream and storage */
932     r = IStorage_CreateStream(stg, stmname2, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
933     ok(r==S_OK, "IStorage->CreateStream failed\n");
934
935     r = IStream_Write(stm, "this is stream 1\n", 16, NULL);
936     ok(r==S_OK, "IStream->Write failed\n");
937
938     IStream_Release(stm);
939
940     r = IStorage_CreateStorage(stg, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg2);
941     ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
942
943     if (r == S_OK)
944     {
945         /* Create two substorages but only commit one */
946         r = IStorage_CreateStorage(stg2, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg3);
947         ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
948
949         if (r == S_OK)
950             IStorage_Release(stg3);
951
952         r = IStorage_Commit(stg, 0);
953         ok(r==S_OK, "IStorage->Commit failed\n");
954
955         r = IStorage_CreateStorage(stg2, stgname2, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg3);
956         ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
957
958         if (r == S_OK)
959             IStorage_Release(stg3);
960
961         IStorage_Release(stg2);
962     }
963
964     /* now create a stream and storage, but don't commit them */
965     stm = NULL;
966     r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
967     ok(r==S_OK, "IStorage->CreateStream failed\n");
968
969     r = IStream_Write(stm, "this is stream 2\n", 16, NULL);
970     ok(r==S_OK, "IStream->Write failed\n");
971
972     /* IStream::Commit does nothing for OLE storage streams */
973     r = IStream_Commit(stm, STGC_ONLYIFCURRENT | STGC_DANGEROUSLYCOMMITMERELYTODISKCACHE);
974     ok(r==S_OK, "IStream->Commit failed\n");
975
976     r = IStorage_CreateStorage(stg, stgname2, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg2);
977     ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
978
979     if (r == S_OK)
980         IStorage_Release(stg2);
981
982     IStream_Release(stm);
983
984     IStorage_Release(stg);
985
986     stm = NULL;
987     stg = NULL;
988     r = StgOpenStorage( filename, NULL, STGM_SHARE_DENY_NONE | STGM_READ | STGM_TRANSACTED, NULL, 0, &stg);
989     ok(r==S_OK, "StgOpenStorage failed\n");
990
991     if (!stg)
992         return;
993
994     r = IStorage_OpenStream(stg, stmname, NULL, STGM_SHARE_DENY_NONE|STGM_READ, 0, &stm );
995     ok(r==STG_E_INVALIDFLAG, "IStorage->OpenStream failed %08x\n", r);
996
997     r = IStorage_OpenStream(stg, stmname, NULL, STGM_DELETEONRELEASE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
998     ok(r==STG_E_INVALIDFUNCTION, "IStorage->OpenStream failed %08x\n", r);
999
1000     r = IStorage_OpenStream(stg, stmname, NULL, STGM_TRANSACTED|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
1001     ok(r==STG_E_INVALIDFUNCTION, "IStorage->OpenStream failed %08x\n", r);
1002
1003     r = IStorage_OpenStorage(stg, stmname, NULL, STGM_TRANSACTED|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg2 );
1004     ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStream failed %08x\n", r);
1005
1006     r = IStorage_OpenStream(stg, stmname, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
1007     ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStream should fail %08x\n", r);
1008     if (r == S_OK)
1009         IStream_Release(stm);
1010
1011     r = IStorage_OpenStorage(stg, stgname2, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg2 );
1012     ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStorage should fail %08x\n", r);
1013     if (r == S_OK)
1014         IStorage_Release(stg2);
1015
1016     r = IStorage_OpenStorage(stg, stmname2, NULL, STGM_TRANSACTED|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg2 );
1017     ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStream failed %08x\n", r);
1018
1019     r = IStorage_OpenStream(stg, stmname2, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
1020     ok(r==S_OK, "IStorage->OpenStream should succeed %08x\n", r);
1021     if (r == S_OK)
1022         IStream_Release(stm);
1023
1024     r = IStorage_OpenStorage(stg, stgname, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg2 );
1025     ok(r==S_OK, "IStorage->OpenStorage should succeed %08x\n", r);
1026     if (r == S_OK)
1027     {
1028         r = IStorage_OpenStorage(stg2, stgname, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg3 );
1029         ok(r==S_OK, "IStorage->OpenStorage should succeed %08x\n", r);
1030         if (r == S_OK)
1031             IStorage_Release(stg3);
1032
1033         r = IStorage_OpenStorage(stg2, stgname2, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg3 );
1034         ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStorage should fail %08x\n", r);
1035         if (r == S_OK)
1036             IStorage_Release(stg3);
1037
1038         IStorage_Release(stg2);
1039     }
1040
1041     IStorage_Release(stg);
1042
1043     r = DeleteFileA(filenameA);
1044     ok( r == TRUE, "deleted file\n");
1045 }
1046
1047 static void test_substorage_share(void)
1048 {
1049     IStorage *stg, *stg2, *stg3;
1050     IStream *stm, *stm2;
1051     HRESULT r;
1052     static const WCHAR stgname[] = { 'P','E','R','M','S','T','G',0 };
1053     static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 };
1054     static const WCHAR othername[] = { 'N','E','W','N','A','M','E',0 };
1055
1056     DeleteFileA(filenameA);
1057
1058     /* create the file */
1059     r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
1060                             STGM_READWRITE, 0, &stg);
1061     ok(r==S_OK, "StgCreateDocfile failed\n");
1062
1063     /* create a read/write storage and try to open it again */
1064     r = IStorage_CreateStorage(stg, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg2);
1065     ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1066
1067     if (r == S_OK)
1068     {
1069         r = IStorage_OpenStorage(stg, stgname, NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg3);
1070         ok(r==STG_E_ACCESSDENIED, "IStorage->OpenStorage should fail %08x\n", r);
1071
1072         if (r == S_OK)
1073             IStorage_Release(stg3);
1074
1075         r = IStorage_OpenStorage(stg, stgname, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, 0, &stg3);
1076         ok(r==STG_E_ACCESSDENIED, "IStorage->OpenStorage should fail %08x\n", r);
1077
1078         if (r == S_OK)
1079             IStorage_Release(stg3);
1080
1081         /* cannot rename the storage while it's open */
1082         r = IStorage_RenameElement(stg, stgname, othername);
1083         ok(r==STG_E_ACCESSDENIED, "IStorage->RenameElement should fail %08x\n", r);
1084         if (SUCCEEDED(r)) IStorage_RenameElement(stg, othername, stgname);
1085
1086         /* destroying an object while it's open invalidates it */
1087         r = IStorage_DestroyElement(stg, stgname);
1088         ok(r==S_OK, "IStorage->DestroyElement failed, hr=%08x\n", r);
1089
1090         r = IStorage_CreateStream(stg2, stmname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm);
1091         ok(r==STG_E_REVERTED, "IStorage->CreateStream failed, hr=%08x\n", r);
1092
1093         if (r == S_OK)
1094             IStorage_Release(stm);
1095
1096         IStorage_Release(stg2);
1097     }
1098
1099     /* create a read/write stream and try to open it again */
1100     r = IStorage_CreateStream(stg, stmname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm);
1101     ok(r==S_OK, "IStorage->CreateStream failed, hr=%08x\n", r);
1102
1103     if (r == S_OK)
1104     {
1105         r = IStorage_OpenStream(stg, stmname, NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &stm2);
1106         ok(r==STG_E_ACCESSDENIED, "IStorage->OpenStream should fail %08x\n", r);
1107
1108         if (r == S_OK)
1109             IStorage_Release(stm2);
1110
1111         r = IStorage_OpenStream(stg, stmname, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm2);
1112         ok(r==STG_E_ACCESSDENIED, "IStorage->OpenStream should fail %08x\n", r);
1113
1114         if (r == S_OK)
1115             IStorage_Release(stm2);
1116
1117         /* cannot rename the stream while it's open */
1118         r = IStorage_RenameElement(stg, stmname, othername);
1119         ok(r==STG_E_ACCESSDENIED, "IStorage->RenameElement should fail %08x\n", r);
1120         if (SUCCEEDED(r)) IStorage_RenameElement(stg, othername, stmname);
1121
1122         /* destroying an object while it's open invalidates it */
1123         r = IStorage_DestroyElement(stg, stmname);
1124         ok(r==S_OK, "IStorage->DestroyElement failed, hr=%08x\n", r);
1125
1126         r = IStream_Write(stm, "this shouldn't work\n", 20, NULL);
1127         ok(r==STG_E_REVERTED, "IStream_Write should fail %08x\n", r);
1128
1129         IStorage_Release(stm);
1130     }
1131
1132     IStorage_Release(stg);
1133
1134     r = DeleteFileA(filenameA);
1135     ok( r == TRUE, "deleted file\n");
1136 }
1137
1138 static void test_revert(void)
1139 {
1140     IStorage *stg = NULL, *stg2 = NULL, *stg3 = NULL;
1141     HRESULT r;
1142     IStream *stm = NULL, *stm2 = NULL;
1143     static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 };
1144     static const WCHAR stmname2[] = { 'F','O','O',0 };
1145     static const WCHAR stgname[] = { 'P','E','R','M','S','T','G',0 };
1146     static const WCHAR stgname2[] = { 'T','E','M','P','S','T','G',0 };
1147     STATSTG statstg;
1148
1149     DeleteFileA(filenameA);
1150
1151     /* create the file */
1152     r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
1153                             STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
1154     ok(r==S_OK, "StgCreateDocfile failed\n");
1155
1156     /* commit a new stream and storage */
1157     r = IStorage_CreateStream(stg, stmname2, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1158     ok(r==S_OK, "IStorage->CreateStream failed\n");
1159
1160     r = IStream_Write(stm, "this is stream 1\n", 16, NULL);
1161     ok(r==S_OK, "IStream->Write failed\n");
1162
1163     r = IStorage_CreateStorage(stg, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg2);
1164     ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1165
1166     if (r == S_OK)
1167     {
1168         /* Create two substorages but only commit one */
1169         r = IStorage_CreateStorage(stg2, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg3);
1170         ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1171
1172         if (r == S_OK)
1173             IStorage_Release(stg3);
1174
1175         r = IStorage_Commit(stg, 0);
1176         ok(r==S_OK, "IStorage->Commit failed\n");
1177
1178         r = IStorage_CreateStorage(stg2, stgname2, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg3);
1179         ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1180
1181         if (r == S_OK)
1182             IStorage_Release(stg3);
1183     }
1184
1185     /* now create a stream and storage, then revert */
1186     r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm2 );
1187     ok(r==S_OK, "IStorage->CreateStream failed\n");
1188
1189     r = IStream_Write(stm2, "this is stream 2\n", 16, NULL);
1190     ok(r==S_OK, "IStream->Write failed\n");
1191
1192     r = IStorage_CreateStorage(stg, stgname2, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg3);
1193     ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1194
1195     r = IStorage_Revert(stg);
1196
1197     /* all open objects become invalid */
1198     r = IStream_Write(stm, "this shouldn't work\n", 20, NULL);
1199     ok(r==STG_E_REVERTED, "IStream_Write should fail %08x\n", r);
1200
1201     r = IStream_Write(stm2, "this shouldn't work\n", 20, NULL);
1202     ok(r==STG_E_REVERTED, "IStream_Write should fail %08x\n", r);
1203
1204     r = IStorage_Stat(stg2, &statstg, STATFLAG_NONAME);
1205     ok(r==STG_E_REVERTED, "IStorage_Stat should fail %08x\n", r);
1206
1207     r = IStorage_Stat(stg3, &statstg, STATFLAG_NONAME);
1208     ok(r==STG_E_REVERTED, "IStorage_Stat should fail %08x\n", r);
1209
1210     IStream_Release(stm);
1211     IStream_Release(stm2);
1212     IStorage_Release(stg2);
1213     IStorage_Release(stg3);
1214
1215     r = IStorage_OpenStream(stg, stmname, NULL, STGM_SHARE_DENY_NONE|STGM_READ, 0, &stm );
1216     ok(r==STG_E_INVALIDFLAG, "IStorage->OpenStream failed %08x\n", r);
1217
1218     r = IStorage_OpenStream(stg, stmname, NULL, STGM_DELETEONRELEASE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
1219     ok(r==STG_E_INVALIDFUNCTION, "IStorage->OpenStream failed %08x\n", r);
1220
1221     r = IStorage_OpenStream(stg, stmname, NULL, STGM_TRANSACTED|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
1222     ok(r==STG_E_INVALIDFUNCTION, "IStorage->OpenStream failed %08x\n", r);
1223
1224     r = IStorage_OpenStorage(stg, stmname, NULL, STGM_TRANSACTED|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg2 );
1225     ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStream failed %08x\n", r);
1226
1227     r = IStorage_OpenStream(stg, stmname, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
1228     ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStream should fail %08x\n", r);
1229     if (r == S_OK)
1230         IStream_Release(stm);
1231
1232     r = IStorage_OpenStorage(stg, stgname2, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg2 );
1233     ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStorage should fail %08x\n", r);
1234     if (r == S_OK)
1235         IStorage_Release(stg2);
1236
1237     r = IStorage_OpenStorage(stg, stmname2, NULL, STGM_TRANSACTED|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg2 );
1238     ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStream failed %08x\n", r);
1239
1240     r = IStorage_OpenStream(stg, stmname2, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
1241     ok(r==S_OK, "IStorage->OpenStream should succeed %08x\n", r);
1242     if (r == S_OK)
1243         IStream_Release(stm);
1244
1245     r = IStorage_OpenStorage(stg, stgname, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg2 );
1246     ok(r==S_OK, "IStorage->OpenStorage should succeed %08x\n", r);
1247     if (r == S_OK)
1248     {
1249         r = IStorage_OpenStorage(stg2, stgname, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg3 );
1250         ok(r==S_OK, "IStorage->OpenStorage should succeed %08x\n", r);
1251         if (r == S_OK)
1252             IStorage_Release(stg3);
1253
1254         r = IStorage_OpenStorage(stg2, stgname2, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg3 );
1255         ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStorage should fail %08x\n", r);
1256         if (r == S_OK)
1257             IStorage_Release(stg3);
1258
1259         IStorage_Release(stg2);
1260     }
1261
1262     IStorage_Release(stg);
1263
1264     r = DeleteFileA(filenameA);
1265     ok( r == TRUE, "deleted file\n");
1266
1267     /* Revert only invalidates objects in transacted mode */
1268     r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
1269                             STGM_READWRITE, 0, &stg);
1270     ok(r==S_OK, "StgCreateDocfile failed\n");
1271
1272     r = IStorage_CreateStream(stg, stmname2, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1273     ok(r==S_OK, "IStorage->CreateStream failed\n");
1274
1275     r = IStorage_Revert(stg);
1276     todo_wine ok(r==S_OK, "IStorage->Revert failed %08x\n", r);
1277
1278     r = IStream_Write(stm, "this works\n", 11, NULL);
1279     ok(r==S_OK, "IStream_Write should succeed %08x\n", r);
1280
1281     IStream_Release(stm);
1282     IStream_Release(stg);
1283
1284     r = DeleteFileA(filenameA);
1285     ok( r == TRUE, "deleted file\n");
1286 }
1287
1288 static void test_parent_free(void)
1289 {
1290     IStorage *stg = NULL, *stg2 = NULL, *stg3 = NULL;
1291     HRESULT r;
1292     IStream *stm = NULL;
1293     static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 };
1294     static const WCHAR stgname[] = { 'P','E','R','M','S','T','G',0 };
1295     ULONG ref;
1296     STATSTG statstg;
1297
1298     DeleteFileA(filenameA);
1299
1300     /* create the file */
1301     r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
1302                             STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
1303     ok(r==S_OK, "StgCreateDocfile failed\n");
1304
1305     /* create a new storage */
1306     r = IStorage_CreateStorage(stg, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg2);
1307     ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1308
1309     if (r == S_OK)
1310     {
1311         /* now create a stream inside the new storage */
1312         r = IStorage_CreateStream(stg2, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1313         ok(r==S_OK, "IStorage->CreateStream failed\n");
1314
1315         if (r == S_OK)
1316         {
1317             /* create a storage inside the new storage */
1318             r = IStorage_CreateStorage(stg2, stgname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stg3 );
1319             ok(r==S_OK, "IStorage->CreateStorage failed\n");
1320         }
1321
1322         /* free the parent */
1323         ref = IStorage_Release(stg2);
1324         ok(ref == 0, "IStorage still has %u references\n", ref);
1325
1326         /* child objects are invalid */
1327         if (r == S_OK)
1328         {
1329             r = IStream_Write(stm, "this should fail\n", 17, NULL);
1330             ok(r==STG_E_REVERTED, "IStream->Write sould fail, hr=%x\n", r);
1331
1332             IStream_Release(stm);
1333
1334             r = IStorage_Stat(stg3, &statstg, STATFLAG_NONAME);
1335             ok(r==STG_E_REVERTED, "IStorage_Stat should fail %08x\n", r);
1336
1337             r = IStorage_SetStateBits(stg3, 1, 1);
1338             ok(r==STG_E_REVERTED, "IStorage_Stat should fail %08x\n", r);
1339
1340             IStorage_Release(stg3);
1341         }
1342     }
1343
1344     IStorage_Release(stg);
1345
1346     r = DeleteFileA(filenameA);
1347     ok( r == TRUE, "deleted file\n");
1348 }
1349
1350 static void test_nonroot_transacted(void)
1351 {
1352     IStorage *stg = NULL, *stg2 = NULL, *stg3 = NULL;
1353     HRESULT r;
1354     IStream *stm = NULL;
1355     static const WCHAR stgname[] = { 'P','E','R','M','S','T','G',0 };
1356     static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 };
1357     static const WCHAR stmname2[] = { 'F','O','O',0 };
1358
1359     DeleteFileA(filenameA);
1360
1361     /* create a transacted file */
1362     r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
1363                             STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
1364     ok(r==S_OK, "StgCreateDocfile failed\n");
1365
1366     /* create a transacted substorage */
1367     r = IStorage_CreateStorage(stg, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_TRANSACTED, 0, 0, &stg2);
1368     ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1369
1370     if (r == S_OK)
1371     {
1372         /* create and commit stmname */
1373         r = IStorage_CreateStream(stg2, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1374         ok(r==S_OK, "IStorage->CreateStream failed\n");
1375         if (r == S_OK)
1376             IStream_Release(stm);
1377
1378         IStorage_Commit(stg2, 0);
1379
1380         /* create and revert stmname2 */
1381         r = IStorage_CreateStream(stg2, stmname2, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1382         ok(r==S_OK, "IStorage->CreateStream failed\n");
1383         if (r == S_OK)
1384             IStream_Release(stm);
1385
1386         IStorage_Revert(stg2);
1387
1388         /* check that Commit and Revert really worked */
1389         r = IStorage_OpenStream(stg2, stmname, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
1390         ok(r==S_OK, "IStorage->OpenStream should succeed %08x\n", r);
1391         if (r == S_OK)
1392             IStream_Release(stm);
1393
1394         r = IStorage_OpenStream(stg2, stmname2, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
1395         ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStream should fail %08x\n", r);
1396         if (r == S_OK)
1397             IStream_Release(stm);
1398
1399         IStorage_Release(stg2);
1400     }
1401
1402     /* create a read-only transacted substorage */
1403     r = IStorage_OpenStorage(stg, stgname, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE | STGM_TRANSACTED, NULL, 0, &stg2);
1404     ok(r==S_OK, "IStorage->OpenStorage failed, hr=%08x\n", r);
1405
1406     if (r == S_OK)
1407     {
1408         /* The storage can be modified. */
1409         r = IStorage_CreateStorage(stg2, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg3);
1410         todo_wine ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1411         if (r == S_OK)
1412             IStream_Release(stg3);
1413
1414         /* But changes cannot be committed. */
1415         r = IStorage_Commit(stg2, 0);
1416         ok(r==STG_E_ACCESSDENIED, "IStorage->Commit should fail, hr=%08x\n", r);
1417
1418         IStorage_Release(stg2);
1419     }
1420
1421     IStorage_Release(stg);
1422
1423     /* create a non-transacted file */
1424     r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
1425                             STGM_READWRITE, 0, &stg);
1426     ok(r==S_OK, "StgCreateDocfile failed\n");
1427
1428     /* create a transacted substorage */
1429     r = IStorage_CreateStorage(stg, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_TRANSACTED, 0, 0, &stg2);
1430     ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1431
1432     if (r == S_OK)
1433     {
1434         /* create and commit stmname */
1435         r = IStorage_CreateStream(stg2, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1436         ok(r==S_OK, "IStorage->CreateStream failed\n");
1437         if (r == S_OK)
1438             IStream_Release(stm);
1439
1440         IStorage_Commit(stg2, 0);
1441
1442         /* create and revert stmname2 */
1443         r = IStorage_CreateStream(stg2, stmname2, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1444         ok(r==S_OK, "IStorage->CreateStream failed\n");
1445         if (r == S_OK)
1446             IStream_Release(stm);
1447
1448         IStorage_Revert(stg2);
1449
1450         /* check that Commit and Revert really worked */
1451         r = IStorage_OpenStream(stg2, stmname, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
1452         ok(r==S_OK, "IStorage->OpenStream should succeed %08x\n", r);
1453         if (r == S_OK)
1454             IStream_Release(stm);
1455
1456         r = IStorage_OpenStream(stg2, stmname2, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
1457         ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStream should fail %08x\n", r);
1458         if (r == S_OK)
1459             IStream_Release(stm);
1460
1461         IStorage_Release(stg2);
1462     }
1463
1464     IStream_Release(stg);
1465
1466     r = DeleteFileA(filenameA);
1467     ok( r == TRUE, "deleted file\n");
1468 }
1469
1470 static void test_ReadClassStm(void)
1471 {
1472     CLSID clsid;
1473     HRESULT hr;
1474     IStream *pStream;
1475     static const LARGE_INTEGER llZero;
1476
1477     hr = ReadClassStm(NULL, &clsid);
1478     ok(hr == E_INVALIDARG, "ReadClassStm should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1479
1480     hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1481     ok_ole_success(hr, "CreateStreamOnHGlobal");
1482     hr = WriteClassStm(pStream, &test_stg_cls);
1483     ok_ole_success(hr, "WriteClassStm");
1484
1485     hr = ReadClassStm(pStream, NULL);
1486     ok(hr == E_INVALIDARG, "ReadClassStm should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1487
1488     /* test not rewound stream */
1489     hr = ReadClassStm(pStream, &clsid);
1490     ok(hr == STG_E_READFAULT, "ReadClassStm should have returned STG_E_READFAULT instead of 0x%08x\n", hr);
1491     ok(IsEqualCLSID(&clsid, &CLSID_NULL), "clsid should have been zeroed\n");
1492
1493     hr = IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1494     ok_ole_success(hr, "IStream_Seek");
1495     hr = ReadClassStm(pStream, &clsid);
1496     ok_ole_success(hr, "ReadClassStm");
1497     ok(IsEqualCLSID(&clsid, &test_stg_cls), "clsid should have been set to CLSID_WineTest\n");
1498 }
1499
1500 struct access_res
1501 {
1502     BOOL gothandle;
1503     DWORD lasterr;
1504     BOOL ignore;
1505 };
1506
1507 static const struct access_res create[16] =
1508 {
1509     { TRUE, ERROR_SUCCESS, TRUE },
1510     { TRUE, ERROR_SUCCESS, TRUE },
1511     { TRUE, ERROR_SUCCESS, FALSE },
1512     { TRUE, ERROR_SUCCESS, FALSE },
1513     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
1514     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
1515     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
1516     { TRUE, ERROR_SUCCESS, FALSE },
1517     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
1518     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
1519     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
1520     { TRUE, ERROR_SUCCESS, TRUE },
1521     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
1522     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
1523     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
1524     { TRUE, ERROR_SUCCESS, TRUE }
1525 };
1526
1527 static const struct access_res create_commit[16] =
1528 {
1529     { TRUE, ERROR_SUCCESS, TRUE },
1530     { TRUE, ERROR_SUCCESS, TRUE },
1531     { TRUE, ERROR_SUCCESS, FALSE },
1532     { TRUE, ERROR_SUCCESS, FALSE },
1533     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
1534     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
1535     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
1536     { TRUE, ERROR_SUCCESS, FALSE },
1537     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
1538     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
1539     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
1540     { TRUE, ERROR_SUCCESS, TRUE },
1541     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
1542     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
1543     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
1544     { TRUE, ERROR_SUCCESS, TRUE }
1545 };
1546
1547 static const struct access_res create_close[16] =
1548 {
1549     { TRUE, ERROR_SUCCESS, FALSE },
1550     { TRUE, ERROR_SUCCESS, FALSE },
1551     { TRUE, ERROR_SUCCESS, FALSE },
1552     { TRUE, ERROR_SUCCESS, FALSE },
1553     { TRUE, ERROR_SUCCESS, FALSE },
1554     { TRUE, ERROR_SUCCESS, FALSE },
1555     { TRUE, ERROR_SUCCESS, FALSE },
1556     { TRUE, ERROR_SUCCESS, FALSE },
1557     { TRUE, ERROR_SUCCESS, FALSE },
1558     { TRUE, ERROR_SUCCESS, FALSE },
1559     { TRUE, ERROR_SUCCESS, FALSE },
1560     { TRUE, ERROR_SUCCESS, FALSE },
1561     { TRUE, ERROR_SUCCESS, FALSE },
1562     { TRUE, ERROR_SUCCESS, FALSE },
1563     { TRUE, ERROR_SUCCESS, FALSE },
1564     { TRUE, ERROR_SUCCESS }
1565 };
1566
1567 static void _test_file_access(LPCSTR file, const struct access_res *ares, DWORD line)
1568 {
1569     DWORD access = 0, share = 0;
1570     DWORD lasterr;
1571     HANDLE hfile;
1572     int i, j, idx = 0;
1573
1574     for (i = 0; i < 4; i++)
1575     {
1576         if (i == 0) access = 0;
1577         if (i == 1) access = GENERIC_READ;
1578         if (i == 2) access = GENERIC_WRITE;
1579         if (i == 3) access = GENERIC_READ | GENERIC_WRITE;
1580
1581         for (j = 0; j < 4; j++)
1582         {
1583             if (ares[idx].ignore)
1584                 continue;
1585
1586             if (j == 0) share = 0;
1587             if (j == 1) share = FILE_SHARE_READ;
1588             if (j == 2) share = FILE_SHARE_WRITE;
1589             if (j == 3) share = FILE_SHARE_READ | FILE_SHARE_WRITE;
1590
1591             SetLastError(0xdeadbeef);
1592             hfile = CreateFileA(file, access, share, NULL, OPEN_EXISTING,
1593                                 FILE_ATTRIBUTE_NORMAL, 0);
1594             lasterr = GetLastError();
1595
1596             ok((hfile != INVALID_HANDLE_VALUE) == ares[idx].gothandle,
1597                "(%d, handle, %d): Expected %d, got %d\n",
1598                line, idx, ares[idx].gothandle,
1599                (hfile != INVALID_HANDLE_VALUE));
1600
1601             ok(lasterr == ares[idx].lasterr ||
1602                broken(lasterr == 0xdeadbeef) /* win9x */,
1603                "(%d, lasterr, %d): Expected %d, got %d\n",
1604                line, idx, ares[idx].lasterr, lasterr);
1605
1606             CloseHandle(hfile);
1607             idx++;
1608         }
1609     }
1610 }
1611
1612 #define test_file_access(file, ares) _test_file_access(file, ares, __LINE__)
1613
1614 static void test_access(void)
1615 {
1616     IStorage *stg;
1617     HRESULT hr;
1618
1619     static const WCHAR fileW[] = {'w','i','n','e','t','e','s','t',0};
1620
1621     /* STGM_TRANSACTED */
1622
1623     hr = StgCreateDocfile(fileW, STGM_CREATE | STGM_READWRITE |
1624                           STGM_SHARE_EXCLUSIVE | STGM_TRANSACTED, 0, &stg);
1625     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1626
1627     test_file_access("winetest", create);
1628
1629     hr = IStorage_Commit(stg, STGC_DEFAULT);
1630     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1631
1632     test_file_access("winetest", create_commit);
1633
1634     IStorage_Release(stg);
1635
1636     test_file_access("winetest", create_close);
1637
1638     DeleteFileA("winetest");
1639
1640     /* STGM_DIRECT */
1641
1642     hr = StgCreateDocfile(fileW, STGM_CREATE | STGM_READWRITE |
1643                           STGM_SHARE_EXCLUSIVE | STGM_DIRECT, 0, &stg);
1644     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1645
1646     test_file_access("winetest", create);
1647
1648     hr = IStorage_Commit(stg, STGC_DEFAULT);
1649     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1650
1651     test_file_access("winetest", create_commit);
1652
1653     IStorage_Release(stg);
1654
1655     test_file_access("winetest", create_close);
1656
1657     DeleteFileA("winetest");
1658
1659     /* STGM_SHARE_DENY_NONE */
1660
1661     hr = StgCreateDocfile(fileW, STGM_CREATE | STGM_READWRITE |
1662                           STGM_SHARE_DENY_NONE | STGM_TRANSACTED, 0, &stg);
1663     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1664
1665     test_file_access("winetest", create);
1666
1667     hr = IStorage_Commit(stg, STGC_DEFAULT);
1668     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1669
1670     test_file_access("winetest", create_commit);
1671
1672     IStorage_Release(stg);
1673
1674     test_file_access("winetest", create_close);
1675
1676     DeleteFileA("winetest");
1677
1678     /* STGM_SHARE_DENY_READ */
1679
1680     hr = StgCreateDocfile(fileW, STGM_CREATE | STGM_READWRITE |
1681                           STGM_SHARE_DENY_READ | STGM_TRANSACTED, 0, &stg);
1682     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1683
1684     test_file_access("winetest", create);
1685
1686     hr = IStorage_Commit(stg, STGC_DEFAULT);
1687     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1688
1689     test_file_access("winetest", create_commit);
1690
1691     IStorage_Release(stg);
1692
1693     test_file_access("winetest", create_close);
1694
1695     DeleteFileA("winetest");
1696
1697     /* STGM_SHARE_DENY_WRITE */
1698
1699     hr = StgCreateDocfile(fileW, STGM_CREATE | STGM_READWRITE |
1700                           STGM_SHARE_DENY_WRITE | STGM_TRANSACTED, 0, &stg);
1701     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1702
1703     test_file_access("winetest", create);
1704
1705     hr = IStorage_Commit(stg, STGC_DEFAULT);
1706     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1707
1708     test_file_access("winetest", create_commit);
1709
1710     IStorage_Release(stg);
1711
1712     test_file_access("winetest", create_close);
1713
1714     DeleteFileA("winetest");
1715 }
1716
1717 static void test_readonly(void)
1718 {
1719     IStorage *stg, *stg2, *stg3;
1720     IStream *stream;
1721     HRESULT hr;
1722     static const WCHAR fileW[] = {'w','i','n','e','t','e','s','t',0};
1723     static const WCHAR storageW[] = {'s','t','o','r','a','g','e',0};
1724     static const WCHAR streamW[] = {'s','t','r','e','a','m',0};
1725
1726     hr = StgCreateDocfile( fileW, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &stg);
1727     ok(hr == S_OK, "should succeed, res=%x\n", hr);
1728     if (SUCCEEDED(hr))
1729     {
1730         hr = IStorage_CreateStorage( stg, storageW, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stg2 );
1731         ok(hr == S_OK, "should succeed, res=%x\n", hr);
1732         if (SUCCEEDED(hr))
1733         {
1734             hr = IStorage_CreateStream( stg2, streamW, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stream );
1735             ok(hr == S_OK, "should succeed, res=%x\n", hr);
1736             if (SUCCEEDED(hr))
1737                 IStream_Release(stream);
1738             IStorage_Release(stg2);
1739         }
1740         IStorage_Release(stg);
1741     }
1742
1743     /* re-open read only */
1744     hr = StgOpenStorage( fileW, NULL, STGM_TRANSACTED | STGM_SHARE_DENY_NONE | STGM_READ, NULL, 0, &stg);
1745     ok(hr == S_OK, "should succeed, res=%x\n", hr);
1746     if (SUCCEEDED(hr))
1747     {
1748         hr = IStorage_OpenStorage( stg, storageW, NULL, STGM_SHARE_EXCLUSIVE | STGM_READ, NULL, 0, &stg2 );
1749         ok(hr == S_OK, "should succeed, res=%x\n", hr);
1750         if (SUCCEEDED(hr))
1751         {
1752             /* CreateStream on read-only storage, name exists */
1753             hr = IStorage_CreateStream( stg2, streamW, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READ, 0, 0, &stream );
1754             ok(hr == STG_E_ACCESSDENIED, "should fail, res=%x\n", hr);
1755             if (SUCCEEDED(hr))
1756                 IStream_Release(stream);
1757
1758             /* CreateStream on read-only storage, name does not exist */
1759             hr = IStorage_CreateStream( stg2, storageW, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READ, 0, 0, &stream );
1760             ok(hr == STG_E_ACCESSDENIED, "should fail, res=%x\n", hr);
1761             if (SUCCEEDED(hr))
1762                 IStream_Release(stream);
1763
1764             /* CreateStorage on read-only storage, name exists */
1765             hr = IStorage_CreateStorage( stg2, streamW, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READ, 0, 0, &stg3 );
1766             ok(hr == STG_E_FILEALREADYEXISTS, "should fail, res=%x\n", hr);
1767             if (SUCCEEDED(hr))
1768                 IStream_Release(stg3);
1769
1770             /* CreateStorage on read-only storage, name does not exist */
1771             hr = IStorage_CreateStorage( stg2, storageW, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READ, 0, 0, &stg3 );
1772             ok(hr == STG_E_ACCESSDENIED, "should fail, res=%x\n", hr);
1773             if (SUCCEEDED(hr))
1774                 IStream_Release(stg3);
1775
1776             /* DestroyElement on read-only storage, name exists */
1777             hr = IStorage_DestroyElement( stg2, streamW );
1778             ok(hr == STG_E_ACCESSDENIED, "should fail, res=%x\n", hr);
1779
1780             /* DestroyElement on read-only storage, name does not exist */
1781             hr = IStorage_DestroyElement( stg2, storageW );
1782             ok(hr == STG_E_ACCESSDENIED, "should fail, res=%x\n", hr);
1783
1784             IStorage_Release(stg2);
1785         }
1786
1787         IStorage_Release(stg);
1788     }
1789
1790     DeleteFileA("winetest");
1791 }
1792
1793 static void test_simple(void)
1794 {
1795     /* Tests for STGM_SIMPLE mode */
1796
1797     IStorage *stg, *stg2;
1798     HRESULT r;
1799     IStream *stm;
1800     static const WCHAR stgname[] = { 'S','t','g',0 };
1801     static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 };
1802     static const WCHAR stmname2[] = { 'S','m','a','l','l',0 };
1803     LARGE_INTEGER pos;
1804     ULARGE_INTEGER upos;
1805     DWORD count;
1806     STATSTG stat;
1807
1808     DeleteFileA(filenameA);
1809
1810     r = StgCreateDocfile( filename, STGM_SIMPLE | STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &stg);
1811     ok(r == S_OK, "got %08x\n", r);
1812
1813     r = IStorage_CreateStorage(stg, stgname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stg2);
1814     ok(r == STG_E_INVALIDFUNCTION, "got %08x\n", r);
1815     if (SUCCEEDED(r)) IStorage_Release(stg2);
1816
1817     r = IStorage_CreateStream(stg, stmname, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm);
1818     ok(r == STG_E_INVALIDFLAG, "got %08x\n", r);
1819     r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm);
1820     ok(r == S_OK, "got %08x\n", r);
1821
1822     upos.QuadPart = 6000;
1823     r = IStream_SetSize(stm, upos);
1824     ok(r == S_OK, "got %08x\n", r);
1825
1826     r = IStream_Write(stm, "foo", 3, &count);
1827     ok(r == S_OK, "got %08x\n", r);
1828     ok(count == 3, "got %d\n", count);
1829
1830     pos.QuadPart = 0;
1831     r = IStream_Seek(stm, pos, STREAM_SEEK_CUR, &upos);
1832     ok(r == S_OK, "got %08x\n", r);
1833     ok(upos.QuadPart == 3, "got %d\n", upos.u.LowPart);
1834
1835     r = IStream_Stat(stm, &stat, STATFLAG_NONAME);
1836     ok(r == S_OK ||
1837        broken(r == STG_E_INVALIDFUNCTION), /* NT4 and below */
1838        "got %08x\n", r);
1839     if (r == S_OK)
1840         ok(stat.cbSize.QuadPart == 3, "got %d\n", stat.cbSize.u.LowPart);
1841
1842     pos.QuadPart = 1;
1843     r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &upos);
1844     ok(r == S_OK, "got %08x\n", r);
1845     ok(upos.QuadPart == 1, "got %d\n", upos.u.LowPart);
1846
1847     r = IStream_Stat(stm, &stat, STATFLAG_NONAME);
1848     ok(r == S_OK ||
1849        broken(r == STG_E_INVALIDFUNCTION), /* NT4 and below */
1850        "got %08x\n", r);
1851     if (r == S_OK)
1852         ok(stat.cbSize.QuadPart == 1, "got %d\n", stat.cbSize.u.LowPart);
1853
1854     IStream_Release(stm);
1855
1856     r = IStorage_CreateStream(stg, stmname2, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm);
1857     ok(r == S_OK, "got %08x\n", r);
1858
1859     upos.QuadPart = 100;
1860     r = IStream_SetSize(stm, upos);
1861     ok(r == S_OK, "got %08x\n", r);
1862
1863     r = IStream_Write(stm, "foo", 3, &count);
1864     ok(r == S_OK, "got %08x\n", r);
1865     ok(count == 3, "got %d\n", count);
1866
1867     IStream_Release(stm);
1868
1869     IStorage_Commit(stg, STGC_DEFAULT);
1870     IStorage_Release(stg);
1871
1872     r = StgOpenStorage( filename, NULL, STGM_SIMPLE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, NULL, 0, &stg);
1873     if (r == STG_E_INVALIDFLAG)
1874     {
1875         win_skip("Flag combination is not supported on NT4 and below\n");
1876         DeleteFileA(filenameA);
1877         return;
1878     }
1879     ok(r == S_OK, "got %08x\n", r);
1880
1881     r = IStorage_OpenStorage(stg, stgname, NULL, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, NULL, 0, &stg2);
1882     ok(r == STG_E_INVALIDFUNCTION, "got %08x\n", r);
1883     if (SUCCEEDED(r)) IStorage_Release(stg2);
1884
1885     r = IStorage_OpenStream(stg, stmname, NULL, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &stm);
1886     ok(r == S_OK, "got %08x\n", r);
1887
1888     r = IStream_Stat(stm, &stat, STATFLAG_NONAME);
1889     ok(r == S_OK, "got %08x\n", r);
1890     ok(stat.cbSize.QuadPart == 6000, "got %d\n", stat.cbSize.u.LowPart);
1891
1892     IStream_Release(stm);
1893
1894     r = IStorage_OpenStream(stg, stmname2, NULL, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &stm);
1895     ok(r == S_OK, "got %08x\n", r);
1896
1897     r = IStream_Stat(stm, &stat, STATFLAG_NONAME);
1898     ok(r == S_OK, "got %08x\n", r);
1899     ok(stat.cbSize.QuadPart == 4096, "got %d\n", stat.cbSize.u.LowPart);
1900
1901     IStream_Release(stm);
1902
1903
1904     IStorage_Release(stg);
1905
1906     DeleteFileA(filenameA);
1907 }
1908
1909 static void test_fmtusertypestg(void)
1910 {
1911     IStorage *stg;
1912     IEnumSTATSTG *stat;
1913     HRESULT hr;
1914     static const char fileA[]  = {'f','m','t','t','e','s','t',0};
1915     static const WCHAR fileW[] = {'f','m','t','t','e','s','t',0};
1916     static WCHAR userTypeW[] = {'S','t','g','U','s','r','T','y','p','e',0};
1917     static WCHAR strmNameW[] = {1,'C','o','m','p','O','b','j',0};
1918
1919     hr = StgCreateDocfile( fileW, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &stg);
1920     ok(hr == S_OK, "should succeed, res=%x\n", hr);
1921
1922     if (SUCCEEDED(hr))
1923     {
1924         /* try to write the stream */
1925         hr = WriteFmtUserTypeStg(stg, 0, userTypeW);
1926         ok(hr == S_OK, "should succeed, res=%x\n", hr);
1927
1928         /* check that the stream was created */
1929         hr = IStorage_EnumElements(stg, 0, NULL, 0, &stat);
1930         ok(hr == S_OK, "should succeed, res=%x\n", hr);
1931         if (SUCCEEDED(hr))
1932         {
1933             BOOL found = FALSE;
1934             STATSTG statstg;
1935             DWORD got;
1936             while ((hr = IEnumSTATSTG_Next(stat, 1, &statstg, &got)) == S_OK && got == 1)
1937             {
1938                 if (strcmp_ww(statstg.pwcsName, strmNameW) == 0)
1939                     found = TRUE;
1940                 else
1941                     ok(0, "found unexpected stream or storage\n");
1942             }
1943             ok(found == TRUE, "expected storage to contain stream \\0001CompObj\n");
1944             IEnumSTATSTG_Release(stat);
1945         }
1946
1947         /* re-write the stream */
1948         hr = WriteFmtUserTypeStg(stg, 0, userTypeW);
1949         ok(hr == S_OK, "should succeed, res=%x\n", hr);
1950
1951         /* check that the stream is still there */
1952         hr = IStorage_EnumElements(stg, 0, NULL, 0, &stat);
1953         ok(hr == S_OK, "should succeed, res=%x\n", hr);
1954         if (SUCCEEDED(hr))
1955         {
1956             BOOL found = FALSE;
1957             STATSTG statstg;
1958             DWORD got;
1959             while ((hr = IEnumSTATSTG_Next(stat, 1, &statstg, &got)) == S_OK && got == 1)
1960             {
1961                 if (strcmp_ww(statstg.pwcsName, strmNameW) == 0)
1962                     found = TRUE;
1963                 else
1964                     ok(0, "found unexpected stream or storage\n");
1965             }
1966             ok(found == TRUE, "expected storage to contain stream \\0001CompObj\n");
1967             IEnumSTATSTG_Release(stat);
1968         }
1969
1970         IStorage_Release(stg);
1971         DeleteFileA( fileA );
1972     }
1973 }
1974
1975 static void test_references(void)
1976 {
1977     IStorage *stg,*stg2;
1978     HRESULT hr;
1979     unsigned c1,c2;
1980     static const WCHAR StorName[] = { 'D','a','t','a','S','p','a','c','e','I','n','f','o',0 };
1981
1982     DeleteFileA(filenameA);
1983
1984     hr = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
1985     ok(hr==S_OK, "StgCreateDocfile failed\n");
1986
1987     if (SUCCEEDED(hr))
1988     {
1989         IStorage_Release(stg);
1990
1991         hr = StgOpenStorage( filename, NULL, STGM_TRANSACTED | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, NULL, 0, &stg);
1992         ok(hr==S_OK, "StgOpenStorage failed (result=%x)\n",hr);
1993
1994         if (SUCCEEDED(hr))
1995         {
1996             hr = IStorage_CreateStorage(stg,StorName,STGM_READWRITE | STGM_SHARE_EXCLUSIVE,0,0,&stg2);
1997             ok(hr == S_OK, "IStorage_CreateStorage failed (result=%x)\n",hr);
1998
1999             if (SUCCEEDED(hr))
2000             {
2001                 c1 = IStorage_AddRef(stg);
2002                 ok(c1 == 2, "creating internal storage added references to ancestor\n");
2003                 c1 = IStorage_AddRef(stg);
2004                 IStorage_Release(stg2);
2005                 c2 = IStorage_AddRef(stg) - 1;
2006                 ok(c1 == c2, "releasing internal storage removed references to ancestor\n");
2007             }
2008             c1 = IStorage_Release(stg);
2009             while ( c1 ) c1 = IStorage_Release(stg);
2010         }
2011     }
2012
2013     DeleteFileA(filenameA);
2014 }
2015
2016 /* dest
2017  *  |-StorageA
2018  *  |  `StreamA: "StreamA"
2019  *  |-StorageB
2020  *  |  `StreamB: "StreamB"
2021  *  `StreamC: "StreamC"
2022  */
2023 static HRESULT create_test_file(IStorage *dest)
2024 {
2025     IStorage *stgA = NULL, *stgB = NULL;
2026     IStream *strmA = NULL, *strmB = NULL, *strmC = NULL;
2027     const ULONG strmA_name_size = lstrlenW(strmA_name) * sizeof(WCHAR);
2028     const ULONG strmB_name_size = lstrlenW(strmB_name) * sizeof(WCHAR);
2029     const ULONG strmC_name_size = lstrlenW(strmC_name) * sizeof(WCHAR);
2030     ULONG bytes;
2031     HRESULT hr;
2032
2033     hr = IStorage_CreateStorage(dest, stgA_name, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stgA);
2034     ok(hr == S_OK, "IStorage_CreateStorage failed: 0x%08x\n", hr);
2035     if(FAILED(hr))
2036         goto cleanup;
2037
2038     hr = IStorage_CreateStream(stgA, strmA_name, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &strmA);
2039     ok(hr == S_OK, "IStorage_CreateStream failed: 0x%08x\n", hr);
2040     if(FAILED(hr))
2041         goto cleanup;
2042
2043     hr = IStream_Write(strmA, strmA_name, strmA_name_size, &bytes);
2044     ok(hr == S_OK && bytes == strmA_name_size, "IStream_Write failed: 0x%08x, %d of %d bytes written\n", hr, bytes, strmA_name_size);
2045
2046     hr = IStorage_CreateStorage(dest, stgB_name, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stgB);
2047     ok(hr == S_OK, "IStorage_CreateStorage failed: 0x%08x\n", hr);
2048     if(FAILED(hr))
2049         goto cleanup;
2050
2051     hr = IStorage_CreateStream(stgB, strmB_name, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &strmB);
2052     ok(hr == S_OK, "IStorage_CreateStream failed: 0x%08x\n", hr);
2053     if(FAILED(hr))
2054         goto cleanup;
2055
2056     hr = IStream_Write(strmB, strmB_name, strmB_name_size, &bytes);
2057     ok(hr == S_OK && bytes == strmB_name_size, "IStream_Write failed: 0x%08x, %d of %d bytes written\n", hr, bytes, strmB_name_size);
2058
2059     hr = IStorage_CreateStream(dest, strmC_name, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &strmC);
2060     ok(hr == S_OK, "IStorage_CreateStream failed: 0x%08x\n", hr);
2061     if(FAILED(hr))
2062         goto cleanup;
2063
2064     hr = IStream_Write(strmC, strmC_name, strmC_name_size, &bytes);
2065     ok(hr == S_OK && bytes == strmC_name_size, "IStream_Write failed: 0x%08x, %d of %d bytes written\n", hr, bytes, strmC_name_size);
2066
2067 cleanup:
2068     if(strmC)
2069         IStream_Release(strmC);
2070     if(strmB)
2071         IStream_Release(strmB);
2072     if(stgB)
2073         IStorage_Release(stgB);
2074     if(strmA)
2075         IStream_Release(strmA);
2076     if(stgA)
2077         IStorage_Release(stgA);
2078
2079     return hr;
2080 }
2081
2082 static void test_copyto(void)
2083 {
2084     IStorage *file1 = NULL, *file2 = NULL, *stg_tmp;
2085     IStream *strm_tmp;
2086     WCHAR buf[64];
2087     HRESULT hr;
2088
2089     /* create & populate file1 */
2090     hr = StgCreateDocfile(file1_name, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &file1);
2091     ok(hr == S_OK, "StgCreateDocfile failed: 0x%08x\n", hr);
2092     if(FAILED(hr))
2093         goto cleanup;
2094
2095     hr = create_test_file(file1);
2096     if(FAILED(hr))
2097         goto cleanup;
2098
2099     /* create file2 */
2100     hr = StgCreateDocfile(file2_name, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &file2);
2101     ok(hr == S_OK, "StgCreateDocfile failed: 0x%08x\n", hr);
2102     if(FAILED(hr))
2103         goto cleanup;
2104
2105     /* copy file1 into file2 */
2106     hr = IStorage_CopyTo(file1, 0, NULL, NULL, NULL);
2107     ok(hr == STG_E_INVALIDPOINTER, "CopyTo should give STG_E_INVALIDPONITER, gave: 0x%08x\n", hr);
2108
2109     hr = IStorage_CopyTo(file1, 0, NULL, NULL, file2);
2110     ok(hr == S_OK, "CopyTo failed: 0x%08x\n", hr);
2111     if(FAILED(hr))
2112         goto cleanup;
2113
2114     /* verify that all of file1 was copied */
2115     hr = IStorage_OpenStorage(file2, stgA_name, NULL,
2116             STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg_tmp);
2117     ok(hr == S_OK, "OpenStorage failed: 0x%08x\n", hr);
2118
2119     if(SUCCEEDED(hr)){
2120         hr = IStorage_OpenStream(stg_tmp, strmA_name, NULL,
2121                 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp);
2122         ok(hr == S_OK, "OpenStream failed: 0x%08x\n", hr);
2123
2124         if(SUCCEEDED(hr)){
2125             memset(buf, 0, sizeof(buf));
2126             hr = IStream_Read(strm_tmp, buf, sizeof(buf), NULL);
2127             ok(hr == S_OK, "Read failed: 0x%08x\n", hr);
2128             if(SUCCEEDED(hr))
2129                 ok(strcmp_ww(buf, strmA_name) == 0,
2130                         "Expected %s to be read, got %s\n", wine_dbgstr_w(strmA_name), wine_dbgstr_w(buf));
2131
2132             IStream_Release(strm_tmp);
2133         }
2134
2135         IStorage_Release(stg_tmp);
2136     }
2137
2138     hr = IStorage_OpenStorage(file2, stgB_name, NULL,
2139             STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg_tmp);
2140     ok(hr == S_OK, "OpenStorage failed: 0x%08x\n", hr);
2141
2142     if(SUCCEEDED(hr)){
2143         hr = IStorage_OpenStream(stg_tmp, strmB_name, NULL,
2144                 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp);
2145         ok(hr == S_OK, "OpenStream failed: 0x%08x\n", hr);
2146
2147         if(SUCCEEDED(hr)){
2148             memset(buf, 0, sizeof(buf));
2149             hr = IStream_Read(strm_tmp, buf, sizeof(buf), NULL);
2150             ok(hr == S_OK, "Read failed: 0x%08x\n", hr);
2151             if(SUCCEEDED(hr))
2152                 ok(strcmp_ww(buf, strmB_name) == 0,
2153                         "Expected %s to be read, got %s\n", wine_dbgstr_w(strmB_name), wine_dbgstr_w(buf));
2154
2155             IStream_Release(strm_tmp);
2156         }
2157
2158         IStorage_Release(stg_tmp);
2159     }
2160
2161     hr = IStorage_OpenStream(file2, strmC_name, NULL,
2162             STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp);
2163     ok(hr == S_OK, "OpenStream failed: 0x%08x\n", hr);
2164
2165     if(SUCCEEDED(hr)){
2166         memset(buf, 0, sizeof(buf));
2167         hr = IStream_Read(strm_tmp, buf, sizeof(buf), NULL);
2168         ok(hr == S_OK, "Read failed: 0x%08x\n", hr);
2169         if(SUCCEEDED(hr))
2170             ok(strcmp_ww(buf, strmC_name) == 0,
2171                     "Expected %s to be read, got %s\n", wine_dbgstr_w(strmC_name), wine_dbgstr_w(buf));
2172
2173         IStream_Release(strm_tmp);
2174     }
2175
2176 cleanup:
2177     if(file1)
2178         IStorage_Release(file1);
2179     if(file2)
2180         IStorage_Release(file2);
2181
2182     DeleteFileA(file1_nameA);
2183     DeleteFileA(file2_nameA);
2184 }
2185
2186 static void test_copyto_snbexclusions(void)
2187 {
2188     static const WCHAR *snb_exclude[] = {stgA_name, strmB_name, strmC_name, 0};
2189
2190     IStorage *file1 = NULL, *file2 = NULL, *stg_tmp;
2191     IStream *strm_tmp;
2192     WCHAR buf[64];
2193     HRESULT hr;
2194
2195     /* create & populate file1 */
2196     hr = StgCreateDocfile(file1_name, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &file1);
2197     ok(hr == S_OK, "StgCreateDocfile failed: 0x%08x\n", hr);
2198     if(FAILED(hr))
2199         goto cleanup;
2200
2201     hr = create_test_file(file1);
2202     if(FAILED(hr))
2203         goto cleanup;
2204
2205     /* create file2 */
2206     hr = StgCreateDocfile(file2_name, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &file2);
2207     ok(hr == S_OK, "StgCreateDocfile failed: 0x%08x\n", hr);
2208     if(FAILED(hr))
2209         goto cleanup;
2210
2211     /* copy file1 to file2 with name exclusions */
2212     hr = IStorage_CopyTo(file1, 0, NULL, (SNB)snb_exclude, file2);
2213     ok(hr == S_OK, "CopyTo failed: 0x%08x\n", hr);
2214     if(FAILED(hr))
2215         goto cleanup;
2216
2217     /* verify that file1 copied over, respecting exclusions */
2218     hr = IStorage_OpenStorage(file2, stgA_name, NULL,
2219             STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg_tmp);
2220     ok(hr == STG_E_FILENOTFOUND, "OpenStorage should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr);
2221     if(SUCCEEDED(hr))
2222         IStorage_Release(stg_tmp);
2223
2224     hr = IStorage_OpenStream(file2, strmA_name, NULL,
2225             STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp);
2226     ok(hr == STG_E_FILENOTFOUND, "OpenStream should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr);
2227     if(SUCCEEDED(hr))
2228         IStream_Release(strm_tmp);
2229
2230     hr = IStorage_OpenStorage(file2, stgB_name, NULL,
2231             STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg_tmp);
2232     ok(hr == S_OK, "OpenStorage failed: 0x%08x\n", hr);
2233
2234     if(SUCCEEDED(hr)){
2235         hr = IStorage_OpenStream(stg_tmp, strmB_name, NULL,
2236                 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp);
2237         ok(hr == S_OK, "OpenStream failed: 0x%08x\n", hr);
2238
2239         if(SUCCEEDED(hr)){
2240             memset(buf, 0, sizeof(buf));
2241             hr = IStream_Read(strm_tmp, buf, sizeof(buf), NULL);
2242             ok(hr == S_OK, "Read failed: 0x%08x\n", hr);
2243             if(SUCCEEDED(hr))
2244                 ok(strcmp_ww(buf, strmB_name) == 0,
2245                         "Expected %s to be read, got %s\n", wine_dbgstr_w(strmB_name), wine_dbgstr_w(buf));
2246
2247             IStream_Release(strm_tmp);
2248         }
2249
2250         IStorage_Release(stg_tmp);
2251     }
2252
2253     hr = IStorage_OpenStream(file2, strmC_name, NULL,
2254             STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp);
2255     ok(hr == STG_E_FILENOTFOUND, "OpenStream should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr);
2256     if(SUCCEEDED(hr))
2257         IStream_Release(strm_tmp);
2258
2259 cleanup:
2260     if(file1)
2261         IStorage_Release(file1);
2262     if(file2)
2263         IStorage_Release(file2);
2264
2265     DeleteFileA(file1_nameA);
2266     DeleteFileA(file2_nameA);
2267 }
2268
2269 static void test_copyto_iidexclusions_storage(void)
2270 {
2271     IStorage *file1 = NULL, *file2 = NULL, *stg_tmp;
2272     IStream *strm_tmp;
2273     WCHAR buf[64];
2274     HRESULT hr;
2275
2276     /* create & populate file1 */
2277     hr = StgCreateDocfile(file1_name, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &file1);
2278     ok(hr == S_OK, "StgCreateDocfile failed: 0x%08x\n", hr);
2279     if(FAILED(hr))
2280         goto cleanup;
2281
2282     hr = create_test_file(file1);
2283     if(FAILED(hr))
2284         goto cleanup;
2285
2286     /* create file2 */
2287     hr = StgCreateDocfile(file2_name, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &file2);
2288     ok(hr == S_OK, "StgCreateDocfile failed: 0x%08x\n", hr);
2289     if(FAILED(hr))
2290         goto cleanup;
2291
2292     /* copy file1 to file2 with iid exclusions */
2293     hr = IStorage_CopyTo(file1, 1, &IID_IStorage, NULL, file2);
2294     ok(hr == S_OK, "CopyTo failed: 0x%08x\n", hr);
2295     if(FAILED(hr))
2296         goto cleanup;
2297
2298     /* verify that file1 copied over, respecting exclusions */
2299     hr = IStorage_OpenStorage(file2, stgA_name, NULL,
2300             STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg_tmp);
2301     ok(hr == STG_E_FILENOTFOUND, "OpenStorage should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr);
2302     if(SUCCEEDED(hr))
2303         IStorage_Release(stg_tmp);
2304
2305     hr = IStorage_OpenStream(file2, strmA_name, NULL,
2306             STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp);
2307     ok(hr == STG_E_FILENOTFOUND, "OpenStream should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr);
2308     if(SUCCEEDED(hr))
2309         IStream_Release(strm_tmp);
2310
2311     hr = IStorage_OpenStorage(file2, stgB_name, NULL,
2312             STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg_tmp);
2313     ok(hr == STG_E_FILENOTFOUND, "OpenStorage should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr);
2314     if(SUCCEEDED(hr))
2315         IStorage_Release(stg_tmp);
2316
2317     hr = IStorage_OpenStream(file2, strmB_name, NULL,
2318             STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp);
2319     ok(hr == STG_E_FILENOTFOUND, "OpenStream should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr);
2320     if(SUCCEEDED(hr))
2321         IStream_Release(strm_tmp);
2322
2323     hr = IStorage_OpenStream(file2, strmC_name, NULL,
2324             STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp);
2325     ok(hr == S_OK, "OpenStream failed: 0x%08x\n", hr);
2326
2327     if(SUCCEEDED(hr)){
2328         memset(buf, 0, sizeof(buf));
2329         hr = IStream_Read(strm_tmp, buf, sizeof(buf), NULL);
2330         ok(hr == S_OK, "Read failed: 0x%08x\n", hr);
2331         if(SUCCEEDED(hr))
2332             ok(strcmp_ww(buf, strmC_name) == 0,
2333                     "Expected %s to be read, got %s\n", wine_dbgstr_w(strmC_name), wine_dbgstr_w(buf));
2334
2335         IStream_Release(strm_tmp);
2336     }
2337
2338 cleanup:
2339     if(file1)
2340         IStorage_Release(file1);
2341     if(file2)
2342         IStorage_Release(file2);
2343
2344     DeleteFileA(file1_nameA);
2345     DeleteFileA(file2_nameA);
2346 }
2347
2348 static void test_copyto_iidexclusions_stream(void)
2349 {
2350     IStorage *file1 = NULL, *file2 = NULL, *stg_tmp;
2351     IStream *strm_tmp;
2352     HRESULT hr;
2353
2354     /* create & populate file1 */
2355     hr = StgCreateDocfile(file1_name, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &file1);
2356     ok(hr == S_OK, "StgCreateDocfile failed: 0x%08x\n", hr);
2357     if(FAILED(hr))
2358         goto cleanup;
2359
2360     hr = create_test_file(file1);
2361     if(FAILED(hr))
2362         goto cleanup;
2363
2364     /* create file2 */
2365     hr = StgCreateDocfile(file2_name, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &file2);
2366     ok(hr == S_OK, "StgCreateDocfile failed: 0x%08x\n", hr);
2367     if(FAILED(hr))
2368         goto cleanup;
2369
2370     /* copy file1 to file2 with iid exclusions */
2371     hr = IStorage_CopyTo(file1, 1, &IID_IStream, NULL, file2);
2372     ok(hr == S_OK, "CopyTo failed: 0x%08x\n", hr);
2373     if(FAILED(hr))
2374         goto cleanup;
2375
2376     /* verify that file1 copied over, respecting exclusions */
2377     hr = IStorage_OpenStorage(file2, stgA_name, NULL,
2378             STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg_tmp);
2379     ok(hr == S_OK, "OpenStorage failed: 0x%08x\n", hr);
2380
2381     if(SUCCEEDED(hr)){
2382         hr = IStorage_OpenStream(stg_tmp, strmA_name, NULL,
2383                 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp);
2384         ok(hr == STG_E_FILENOTFOUND, "OpenStream should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr);
2385         if(SUCCEEDED(hr))
2386             IStream_Release(strm_tmp);
2387
2388         IStorage_Release(stg_tmp);
2389     }
2390
2391     hr = IStorage_OpenStorage(file2, stgB_name, NULL,
2392             STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg_tmp);
2393     ok(hr == S_OK, "OpenStorage failed: 0x%08x\n", hr);
2394
2395     if(SUCCEEDED(hr)){
2396         hr = IStorage_OpenStream(stg_tmp, strmB_name, NULL,
2397                 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp);
2398         ok(hr == STG_E_FILENOTFOUND, "OpenStream should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr);
2399         if(SUCCEEDED(hr))
2400             IStream_Release(strm_tmp);
2401
2402         IStorage_Release(stg_tmp);
2403     }
2404
2405     hr = IStorage_OpenStream(file2, strmC_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 cleanup:
2412     if(file1)
2413         IStorage_Release(file1);
2414     if(file2)
2415         IStorage_Release(file2);
2416
2417     DeleteFileA(file1_nameA);
2418     DeleteFileA(file2_nameA);
2419 }
2420
2421 static void test_rename(void)
2422 {
2423     IStorage *stg, *stg2;
2424     IStream *stm;
2425     HRESULT r;
2426     static const WCHAR stgname[] = { 'P','E','R','M','S','T','G',0 };
2427     static const WCHAR stgname2[] = { 'S','T','G',0 };
2428     static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 };
2429     static const WCHAR stmname2[] = { 'E','N','T','S',0 };
2430
2431     DeleteFileA(filenameA);
2432
2433     /* create the file */
2434     r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
2435                             STGM_READWRITE, 0, &stg);
2436     ok(r==S_OK, "StgCreateDocfile failed\n");
2437
2438     /* create a substorage */
2439     r = IStorage_CreateStorage(stg, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg2);
2440     ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
2441
2442     /* create a stream in the substorage */
2443     r = IStorage_CreateStream(stg2, stmname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm);
2444     ok(r==S_OK, "IStorage->CreateStream failed, hr=%08x\n", r);
2445     IStream_Release(stm);
2446
2447     /* rename the stream */
2448     r = IStorage_RenameElement(stg2, stmname, stmname2);
2449     ok(r==S_OK, "IStorage->RenameElement failed, hr=%08x\n", r);
2450
2451     /* cannot open stream with old name */
2452     r = IStorage_OpenStream(stg2, stmname, NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &stm);
2453     ok(r==STG_E_FILENOTFOUND, "IStorage_OpenStream should fail, hr=%08x\n", r);
2454     if (SUCCEEDED(r)) IStream_Release(stm);
2455
2456     /* can open stream with new name */
2457     r = IStorage_OpenStream(stg2, stmname2, NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &stm);
2458     ok(r==S_OK, "IStorage_OpenStream failed, hr=%08x\n", r);
2459     if (SUCCEEDED(r)) IStream_Release(stm);
2460
2461     IStorage_Release(stg2);
2462
2463     /* rename the storage */
2464     IStorage_RenameElement(stg, stgname, stgname2);
2465
2466     /* cannot open storage with old name */
2467     r = IStorage_OpenStorage(stg, stgname, NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg2);
2468     ok(r==STG_E_FILENOTFOUND, "IStorage_OpenStream should fail, hr=%08x\n", r);
2469     if (SUCCEEDED(r)) IStorage_Release(stg2);
2470
2471     /* can open storage with new name */
2472     r = IStorage_OpenStorage(stg, stgname2, NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg2);
2473     ok(r==S_OK, "IStorage_OpenStream should fail, hr=%08x\n", r);
2474     if (SUCCEEDED(r))
2475     {
2476         /* opened storage still has the stream */
2477         r = IStorage_OpenStream(stg2, stmname2, NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &stm);
2478         ok(r==S_OK, "IStorage_OpenStream failed, hr=%08x\n", r);
2479         if (SUCCEEDED(r)) IStream_Release(stm);
2480
2481         IStorage_Release(stg2);
2482     }
2483
2484     IStorage_Release(stg);
2485
2486     r = DeleteFileA(filenameA);
2487     ok( r == TRUE, "deleted file\n");
2488 }
2489
2490 static void test_toplevel_stat(void)
2491 {
2492     IStorage *stg = NULL;
2493     HRESULT r;
2494     STATSTG stat;
2495     char prev_dir[MAX_PATH];
2496     char temp[MAX_PATH];
2497     char full_path[MAX_PATH];
2498     LPSTR rel_pathA;
2499     WCHAR rel_path[MAX_PATH];
2500
2501     DeleteFileA(filenameA);
2502
2503     r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
2504                             STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
2505     ok(r==S_OK, "StgCreateDocfile failed\n");
2506
2507     r = IStorage_Stat( stg, &stat, STATFLAG_DEFAULT );
2508     ok(!strcmp_ww(stat.pwcsName, filename), "expected %s, got %s\n",
2509         wine_dbgstr_w(filename), wine_dbgstr_w(stat.pwcsName));
2510     CoTaskMemFree(stat.pwcsName);
2511
2512     IStorage_Release( stg );
2513
2514     r = StgOpenStorage( filename, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg);
2515     ok(r==S_OK, "StgOpenStorage failed with error 0x%08x\n", r);
2516
2517     r = IStorage_Stat( stg, &stat, STATFLAG_DEFAULT );
2518     ok(!strcmp_ww(stat.pwcsName, filename), "expected %s, got %s\n",
2519         wine_dbgstr_w(filename), wine_dbgstr_w(stat.pwcsName));
2520     CoTaskMemFree(stat.pwcsName);
2521
2522     IStorage_Release( stg );
2523
2524     DeleteFileA(filenameA);
2525
2526     /* Stat always returns the full path, even for files opened with a relative path. */
2527     GetCurrentDirectoryA(MAX_PATH, prev_dir);
2528
2529     GetTempPathA(MAX_PATH, temp);
2530
2531     SetCurrentDirectoryA(temp);
2532
2533     GetFullPathNameA(filenameA, MAX_PATH, full_path, &rel_pathA);
2534     MultiByteToWideChar(CP_ACP, 0, rel_pathA, -1, rel_path, MAX_PATH);
2535
2536     r = StgCreateDocfile( rel_path, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
2537                             STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
2538     ok(r==S_OK, "StgCreateDocfile failed\n");
2539
2540     r = IStorage_Stat( stg, &stat, STATFLAG_DEFAULT );
2541     ok(!strcmp_ww(stat.pwcsName, filename), "expected %s, got %s\n",
2542         wine_dbgstr_w(filename), wine_dbgstr_w(stat.pwcsName));
2543     CoTaskMemFree(stat.pwcsName);
2544
2545     IStorage_Release( stg );
2546
2547     r = StgOpenStorage( rel_path, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg);
2548     ok(r==S_OK, "StgOpenStorage failed with error 0x%08x\n", r);
2549
2550     r = IStorage_Stat( stg, &stat, STATFLAG_DEFAULT );
2551     ok(!strcmp_ww(stat.pwcsName, filename), "expected %s, got %s\n",
2552         wine_dbgstr_w(filename), wine_dbgstr_w(stat.pwcsName));
2553     CoTaskMemFree(stat.pwcsName);
2554
2555     IStorage_Release( stg );
2556
2557     SetCurrentDirectoryA(prev_dir);
2558
2559     DeleteFileA(filenameA);
2560 }
2561
2562 START_TEST(storage32)
2563 {
2564     CHAR temp[MAX_PATH];
2565
2566     GetTempPathA(MAX_PATH, temp);
2567     if(!GetTempFileNameA(temp, "stg", 0, filenameA))
2568     {
2569         win_skip("Could not create temp file, %u\n", GetLastError());
2570         return;
2571     }
2572     MultiByteToWideChar(CP_ACP, 0, filenameA, -1, filename, MAX_PATH);
2573     DeleteFileA(filenameA);
2574
2575     test_hglobal_storage_stat();
2576     test_create_storage_modes();
2577     test_storage_stream();
2578     test_open_storage();
2579     test_storage_suminfo();
2580     test_storage_refcount();
2581     test_streamenum();
2582     test_transact();
2583     test_substorage_share();
2584     test_revert();
2585     test_parent_free();
2586     test_nonroot_transacted();
2587     test_ReadClassStm();
2588     test_access();
2589     test_writeclassstg();
2590     test_readonly();
2591     test_simple();
2592     test_fmtusertypestg();
2593     test_references();
2594     test_copyto();
2595     test_copyto_snbexclusions();
2596     test_copyto_iidexclusions_storage();
2597     test_copyto_iidexclusions_stream();
2598     test_rename();
2599     test_toplevel_stat();
2600 }