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