crypt32: Support the KeyId type of signer in CMSG_SIGNER_INFO_PARAM.
[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 void test_hglobal_storage_stat(void)
37 {
38     ILockBytes *ilb = NULL;
39     IStorage *stg = NULL;
40     HRESULT r;
41     STATSTG stat;
42     DWORD mode, refcount;
43
44     r = CreateILockBytesOnHGlobal( NULL, TRUE, &ilb );
45     ok( r == S_OK, "CreateILockBytesOnHGlobal failed\n");
46
47     mode = STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE;/*0x1012*/
48     r = StgCreateDocfileOnILockBytes( ilb, mode, 0,  &stg );
49     ok( r == S_OK, "StgCreateDocfileOnILockBytes failed\n");
50
51     r = WriteClassStg( stg, &test_stg_cls );
52     ok( r == S_OK, "WriteClassStg failed\n");
53
54     memset( &stat, 0, sizeof stat );
55     r = IStorage_Stat( stg, &stat, 0 );
56
57     ok( stat.pwcsName == NULL, "storage name not null\n");
58     ok( stat.type == 1, "type is wrong\n");
59     ok( stat.grfMode == 0x12, "grf mode is incorrect\n");
60     ok( !memcmp(&stat.clsid, &test_stg_cls, sizeof test_stg_cls), "CLSID is wrong\n");
61
62     refcount = IStorage_Release( stg );
63     ok( refcount == 0, "IStorage refcount is wrong\n");
64     refcount = ILockBytes_Release( ilb );
65     ok( refcount == 0, "ILockBytes refcount is wrong\n");
66 }
67
68 static void test_create_storage_modes(void)
69 {
70    static const WCHAR szPrefix[] = { 's','t','g',0 };
71    static const WCHAR szDot[] = { '.',0 };
72    WCHAR filename[MAX_PATH];
73    IStorage *stg = NULL;
74    HRESULT r;
75
76    if(!GetTempFileNameW(szDot, szPrefix, 0, filename))
77       return;
78
79    DeleteFileW(filename);
80
81    /* test with some invalid parameters */
82    r = StgCreateDocfile( NULL, 0, 0, &stg);
83    ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
84    r = StgCreateDocfile( filename, 0, 0, &stg);
85    ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
86    r = StgCreateDocfile( filename, STGM_CREATE, 0, &stg);
87    ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
88    r = StgCreateDocfile( filename, STGM_CREATE | STGM_READWRITE, 0, &stg);
89    ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
90    r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE, 0, &stg);
91    ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
92    r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, NULL);
93    ok(r==STG_E_INVALIDPOINTER, "StgCreateDocfile succeeded\n");
94    r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 1, &stg);
95    ok(r==STG_E_INVALIDPARAMETER, "StgCreateDocfile succeeded\n");
96    r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_DENY_WRITE | STGM_READWRITE, 0, &stg);
97    ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
98    r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READ, 0, &stg);
99    ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
100    r = StgCreateDocfile( filename, STGM_PRIORITY, 0, &stg);
101    ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
102
103    /* StgCreateDocfile seems to be very particular about the flags it accepts */
104    r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED | STGM_WRITE, 0, &stg);
105    ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
106    r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED | 8, 0, &stg);
107    ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
108    r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED | 0x80, 0, &stg);
109    ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
110    r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED | 0x800, 0, &stg);
111    ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
112    r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED | 0x8000, 0, &stg);
113    ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
114    r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED | 0x80000, 0, &stg);
115    ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
116    r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED | 0x800000, 0, &stg);
117    ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
118    ok(stg == NULL, "stg was set\n");
119
120    /* check what happens if the file already exists (which is how it's meant to be used) */
121    r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &stg);
122    ok(r==S_OK, "StgCreateDocfile failed\n");
123    r = IStorage_Release(stg);
124    ok(r == 0, "storage not released\n");
125    r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
126    ok(r==STG_E_FILEALREADYEXISTS, "StgCreateDocfile wrong error\n"); /* FAILIFTHERE is default */
127    r = StgCreateDocfile( filename, STGM_READ, 0, &stg);
128    ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n"); /* need at least readmode and sharemode */
129    r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE, 0, &stg);
130    ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
131    r = StgCreateDocfile( filename, STGM_SHARE_DENY_WRITE, 0, &stg);
132    ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
133    r = StgCreateDocfile( filename, STGM_SHARE_DENY_NONE, 0, &stg);
134    ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile failed\n");
135    r = StgCreateDocfile( filename, STGM_SHARE_DENY_NONE | STGM_TRANSACTED, 0, &stg);
136    ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile failed\n");
137    r = StgCreateDocfile( filename, STGM_SHARE_DENY_NONE | STGM_READWRITE, 0, &stg);
138    ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile failed\n");
139    r = StgCreateDocfile( filename, STGM_SHARE_DENY_NONE | STGM_WRITE, 0, &stg);
140    ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile failed\n");
141    r = StgCreateDocfile( filename, STGM_SHARE_DENY_WRITE | STGM_WRITE, 0, &stg);
142    ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile failed\n");
143    r = StgCreateDocfile( filename, STGM_SHARE_DENY_WRITE | STGM_READ, 0, &stg);
144    ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile wrong error\n");
145    r = StgCreateDocfile( filename, STGM_TRANSACTED | STGM_SHARE_DENY_WRITE | STGM_READ, 0, &stg);
146    ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile wrong error\n");
147    ok(DeleteFileW(filename), "failed to delete file\n");
148
149    r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
150    ok(r==S_OK, "StgCreateDocfile failed\n");
151    r = IStorage_Release(stg);
152    ok(r == 0, "storage not released\n");
153    r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED |STGM_FAILIFTHERE, 0, &stg);
154    ok(r==STG_E_FILEALREADYEXISTS, "StgCreateDocfile wrong error\n");
155    r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_WRITE, 0, &stg);
156    ok(r==STG_E_FILEALREADYEXISTS, "StgCreateDocfile wrong error\n");
157
158    r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_DENY_WRITE | STGM_READWRITE, 0, &stg);
159    ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
160    r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
161    ok(r==S_OK, "StgCreateDocfile failed\n");
162    r = IStorage_Release(stg);
163    ok(r == 0, "storage not released\n");
164    ok(DeleteFileW(filename), "failed to delete file\n");
165
166    r = StgCreateDocfile( filename, STGM_CREATE | STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
167    ok(r==S_OK, "StgCreateDocfile failed\n");
168    r = IStorage_Release(stg);
169    ok(r == 0, "storage not released\n");
170    ok(DeleteFileW(filename), "failed to delete file\n");
171
172    /* test the way excel uses StgCreateDocFile */
173    r = StgCreateDocfile( filename, STGM_TRANSACTED|STGM_CREATE|STGM_SHARE_DENY_WRITE|STGM_READWRITE, 0, &stg);
174    ok(r==S_OK, "StgCreateDocfile the excel way failed\n");
175    if(r == S_OK)
176    {
177       r = IStorage_Release(stg);
178       ok(r == 0, "storage not released\n");
179       ok(DeleteFileW(filename), "failed to delete file\n");
180    }
181
182    /* and the way windows media uses it ... */
183    r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_DENY_NONE | STGM_READWRITE | STGM_TRANSACTED, 0, &stg);
184    ok(r==S_OK, "StgCreateDocfile the windows media way failed\n");
185    if (r == S_OK)
186    {
187       r = IStorage_Release(stg);
188       ok(r == 0, "storage not released\n");
189       ok(DeleteFileW(filename), "failed to delete file\n");
190    }
191
192    /* looks like we need STGM_TRANSACTED or STGM_CREATE */
193    r = StgCreateDocfile( filename, STGM_TRANSACTED|STGM_SHARE_DENY_WRITE|STGM_READWRITE, 0, &stg);
194    ok(r==S_OK, "StgCreateDocfile the excel way failed\n");
195    if(r == S_OK)
196    {
197       r = IStorage_Release(stg);
198       ok(r == 0, "storage not released\n");
199       ok(DeleteFileW(filename), "failed to delete file\n");
200    }
201
202    r = StgCreateDocfile( filename, STGM_TRANSACTED|STGM_CREATE|STGM_SHARE_DENY_WRITE|STGM_WRITE, 0, &stg);
203    ok(r==S_OK, "StgCreateDocfile the excel way failed\n");
204    if(r == S_OK)
205    {
206       r = IStorage_Release(stg);
207       ok(r == 0, "storage not released\n");
208       ok(DeleteFileW(filename), "failed to delete file\n");
209    }
210
211    r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &stg);
212    ok(r==S_OK, "StgCreateDocfile the powerpoint way failed\n");
213    if(r == S_OK)
214    {
215       r = IStorage_Release(stg);
216       ok(r == 0, "storage not released\n");
217       ok(DeleteFileW(filename), "failed to delete file\n");
218    }
219
220    /* test the way msi uses StgCreateDocfile */
221    r = StgCreateDocfile( filename, STGM_DIRECT | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &stg);
222    ok(r==S_OK, "StgCreateDocFile failed\n");
223    r = IStorage_Release(stg);
224    ok(r == 0, "storage not released\n");
225    ok(DeleteFileW(filename), "failed to delete file\n");
226 }
227
228 static void test_storage_stream(void)
229 {
230     static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 };
231     static const WCHAR szPrefix[] = { 's','t','g',0 };
232     static const WCHAR szDot[] = { '.',0 };
233     static const WCHAR longname[] = {
234         'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
235         'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',0
236     };
237     WCHAR filename[MAX_PATH];
238     IStorage *stg = NULL;
239     HRESULT r;
240     IStream *stm = NULL;
241     IStream *stm2 = NULL;
242     ULONG count = 0;
243     LARGE_INTEGER pos;
244     ULARGE_INTEGER p;
245     unsigned char buffer[0x100];
246
247     if(!GetTempFileNameW(szDot, szPrefix, 0, filename))
248         return;
249
250     DeleteFileW(filename);
251
252     r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
253     ok(r==S_OK, "StgCreateDocfile failed\n");
254
255     /* try create some invalid streams */
256     r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 1, 0, &stm );
257     ok(r==STG_E_INVALIDPARAMETER, "IStorage->CreateStream wrong error\n");
258     r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 1, &stm );
259     ok(r==STG_E_INVALIDPARAMETER, "IStorage->CreateStream wrong error\n");
260     r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, NULL );
261     ok(r==STG_E_INVALIDPOINTER, "IStorage->CreateStream wrong error\n");
262     r = IStorage_CreateStream(stg, NULL, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
263     ok(r==STG_E_INVALIDNAME, "IStorage->CreateStream wrong error\n");
264     r = IStorage_CreateStream(stg, longname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
265     ok(r==STG_E_INVALIDNAME, "IStorage->CreateStream wrong error, got %d GetLastError()=%d\n", r, GetLastError());
266     r = IStorage_CreateStream(stg, stmname, STGM_READWRITE, 0, 0, &stm );
267     ok(r==STG_E_INVALIDFLAG, "IStorage->CreateStream wrong error\n");
268     r = IStorage_CreateStream(stg, stmname, STGM_READ, 0, 0, &stm );
269     ok(r==STG_E_INVALIDFLAG, "IStorage->CreateStream wrong error\n");
270     r = IStorage_CreateStream(stg, stmname, STGM_WRITE, 0, 0, &stm );
271     ok(r==STG_E_INVALIDFLAG, "IStorage->CreateStream wrong error\n");
272     r = IStorage_CreateStream(stg, stmname, STGM_SHARE_DENY_NONE | STGM_READWRITE, 0, 0, &stm );
273     ok(r==STG_E_INVALIDFLAG, "IStorage->CreateStream wrong error\n");
274     r = IStorage_CreateStream(stg, stmname, STGM_SHARE_DENY_NONE | STGM_READ, 0, 0, &stm );
275     ok(r==STG_E_INVALIDFLAG, "IStorage->CreateStream wrong error\n");
276
277     /* now really create a stream and delete it */
278     r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
279     ok(r==S_OK, "IStorage->CreateStream failed\n");
280     r = IStream_Release(stm);
281     ok(r == 0, "wrong ref count\n");
282     r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
283     ok(r==STG_E_FILEALREADYEXISTS, "IStorage->CreateStream failed\n");
284     r = IStorage_DestroyElement(stg,stmname);
285     ok(r==S_OK, "IStorage->DestroyElement failed\n");
286
287     /* create a stream and write to it */
288     r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
289     ok(r==S_OK, "IStorage->CreateStream failed\n");
290
291     r = IStream_Clone(stm, &stm2);
292     ok(r==S_OK, "failed to clone stream\n");
293
294     r = IStream_Write(stm, NULL, 0, NULL );
295     ok(r==STG_E_INVALIDPOINTER, "IStream->Write wrong error\n");
296     r = IStream_Write(stm, "Hello\n", 0, NULL );
297     ok(r==S_OK, "failed to write stream\n");
298     r = IStream_Write(stm, "Hello\n", 0, &count );
299     ok(r==S_OK, "failed to write stream\n");
300     r = IStream_Write(stm, "Hello\n", 6, &count );
301     ok(r==S_OK, "failed to write stream\n");
302     r = IStream_Commit(stm, STGC_DEFAULT );
303     ok(r==S_OK, "failed to commit stream\n");
304     r = IStream_Commit(stm, STGC_DEFAULT );
305     ok(r==S_OK, "failed to commit stream\n");
306
307     /* seek round a bit, reset the stream size */
308     pos.QuadPart = 0;
309     r = IStream_Seek(stm, pos, 3, &p );
310     ok(r==STG_E_INVALIDFUNCTION, "IStream->Seek returned wrong error\n");
311     r = IStream_Seek(stm, pos, STREAM_SEEK_SET, NULL);
312     ok(r==S_OK, "failed to seek stream\n");
313     r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p );
314     ok(r==S_OK, "failed to seek stream\n");
315     r = IStream_SetSize(stm,p);
316     ok(r==S_OK, "failed to set pos\n");
317     pos.QuadPart = 10;
318     r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p );
319     ok(r==S_OK, "failed to seek stream\n");
320     ok(p.QuadPart == 10, "at wrong place\n");
321     pos.QuadPart = 0;
322     r = IStream_Seek(stm, pos, STREAM_SEEK_END, &p );
323     ok(r==S_OK, "failed to seek stream\n");
324     ok(p.QuadPart == 0, "at wrong place\n");
325     r = IStream_Read(stm, buffer, sizeof buffer, &count );
326     ok(r==S_OK, "failed to set pos\n");
327     ok(count == 0, "read bytes from empty stream\n");
328
329     /* wrap up */
330     r = IStream_Release(stm2);
331     ok(r == 0, "wrong ref count\n");
332
333     /* create a stream and write to it */
334     r = IStorage_CreateStream(stg, stmname, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm2 );
335     ok(r==S_OK, "IStorage->CreateStream failed\n");
336
337     r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p);
338     ok(r==STG_E_REVERTED, "overwritten stream should return STG_E_REVERTED instead of 0x%08x\n", r);
339
340     r = IStream_Release(stm2);
341     ok(r == 0, "wrong ref count\n");
342     r = IStream_Release(stm);
343     ok(r == 0, "wrong ref count\n");
344
345     r = IStorage_Release(stg);
346     ok(r == 0, "wrong ref count\n");
347     r = DeleteFileW(filename);
348     ok(r, "file should exist\n");
349 }
350
351 static BOOL touch_file(LPCWSTR filename)
352 {
353     HANDLE file;
354
355     file = CreateFileW(filename, GENERIC_READ|GENERIC_WRITE, 0, NULL, 
356                 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
357     if (file==INVALID_HANDLE_VALUE)
358         return FALSE;
359     CloseHandle(file);
360     return TRUE;
361 }
362
363 static BOOL is_zero_length(LPCWSTR filename)
364 {
365     HANDLE file;
366     DWORD len;
367
368     file = CreateFileW(filename, GENERIC_READ, 0, NULL, 
369                 OPEN_EXISTING, 0, NULL);
370     if (file==INVALID_HANDLE_VALUE)
371         return FALSE;
372     len = GetFileSize(file, NULL);
373     CloseHandle(file);
374     return len == 0;
375 }
376
377 static BOOL is_existing_file(LPCWSTR filename)
378 {
379     HANDLE file;
380
381     file = CreateFileW(filename, GENERIC_READ, 0, NULL,
382                        OPEN_EXISTING, 0, NULL);
383     if (file==INVALID_HANDLE_VALUE)
384         return FALSE;
385     CloseHandle(file);
386     return TRUE;
387 }
388
389 static void test_open_storage(void)
390 {
391     static const WCHAR szPrefix[] = { 's','t','g',0 };
392     static const WCHAR szNonExist[] = { 'n','o','n','e','x','i','s','t',0 };
393     static const WCHAR szDot[] = { '.',0 };
394     WCHAR filename[MAX_PATH];
395     IStorage *stg = NULL, *stg2 = NULL;
396     HRESULT r;
397     DWORD stgm;
398
399     if(!GetTempFileNameW(szDot, szPrefix, 0, filename))
400         return;
401
402     /* try opening a zero length file - it should stay zero length */
403     DeleteFileW(filename);
404     touch_file(filename);
405     stgm = STGM_NOSCRATCH | STGM_TRANSACTED | STGM_SHARE_DENY_WRITE | STGM_READWRITE;
406     r = StgOpenStorage( filename, NULL, stgm, NULL, 0, &stg);
407     ok(r==STG_E_FILEALREADYEXISTS, "StgOpenStorage didn't fail\n");
408
409     stgm = STGM_SHARE_EXCLUSIVE | STGM_READWRITE;
410     r = StgOpenStorage( filename, NULL, stgm, NULL, 0, &stg);
411     ok(r==STG_E_FILEALREADYEXISTS, "StgOpenStorage didn't fail\n");
412     ok(is_zero_length(filename), "file length changed\n");
413
414     DeleteFileW(filename);
415
416     /* try opening a nonexistent file - it should not create it */
417     stgm = STGM_DIRECT | STGM_SHARE_EXCLUSIVE | STGM_READWRITE;
418     r = StgOpenStorage( filename, NULL, stgm, NULL, 0, &stg);
419     ok(r!=S_OK, "StgOpenStorage failed: 0x%08x\n", r);
420     if (r==S_OK) IStorage_Release(stg);
421     ok(!is_existing_file(filename), "StgOpenStorage should not create a file\n");
422     DeleteFileW(filename);
423
424     /* create the file */
425     r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
426     ok(r==S_OK, "StgCreateDocfile failed\n");
427     IStorage_Release(stg);
428
429     r = StgOpenStorage( filename, NULL, 0, NULL, 0, &stg);
430     ok(r==STG_E_INVALIDFLAG, "StgOpenStorage wrong error\n");
431     r = StgOpenStorage( NULL, NULL, STGM_SHARE_EXCLUSIVE, NULL, 0, &stg);
432     ok(r==STG_E_INVALIDNAME, "StgOpenStorage wrong error\n");
433     r = StgOpenStorage( filename, NULL, STGM_SHARE_EXCLUSIVE | STGM_READ, NULL, 0, NULL);
434     ok(r==STG_E_INVALIDPOINTER, "StgOpenStorage wrong error\n");
435     r = StgOpenStorage( filename, NULL, STGM_SHARE_EXCLUSIVE | STGM_READ, NULL, 1, &stg);
436     ok(r==STG_E_INVALIDPARAMETER, "StgOpenStorage wrong error\n");
437     r = StgOpenStorage( szNonExist, NULL, STGM_SHARE_EXCLUSIVE | STGM_READ, NULL, 0, &stg);
438     ok(r==STG_E_FILENOTFOUND, "StgOpenStorage failed\n");
439     r = StgOpenStorage( filename, NULL, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READ, NULL, 0, &stg);
440     ok(r==STG_E_INVALIDFLAG, "StgOpenStorage failed\n");
441     r = StgOpenStorage( filename, NULL, STGM_SHARE_DENY_NONE | STGM_READ, NULL, 0, &stg);
442     ok(r==STG_E_INVALIDFLAG, "StgOpenStorage failed\n");
443     r = StgOpenStorage( filename, NULL, STGM_SHARE_DENY_READ | STGM_READ, NULL, 0, &stg);
444     ok(r==STG_E_INVALIDFLAG, "StgOpenStorage failed\n");
445     r = StgOpenStorage( filename, NULL, STGM_SHARE_DENY_WRITE | STGM_READWRITE, NULL, 0, &stg);
446     ok(r==STG_E_INVALIDFLAG, "StgOpenStorage failed\n");
447
448     /* open it for real */
449     r = StgOpenStorage( filename, NULL, STGM_SHARE_DENY_NONE | STGM_READ | STGM_TRANSACTED, NULL, 0, &stg); /* XLViewer 97/2000 */
450     ok(r==S_OK, "StgOpenStorage failed\n");
451     if(stg)
452     {
453         r = IStorage_Release(stg);
454         ok(r == 0, "wrong ref count\n");
455     }
456
457     r = StgOpenStorage( filename, NULL, STGM_SHARE_DENY_WRITE | STGM_READ, NULL, 0, &stg);
458     ok(r==S_OK, "StgOpenStorage failed\n");
459     if(stg)
460     {
461         r = IStorage_Release(stg);
462         ok(r == 0, "wrong ref count\n");
463     }
464
465     /* test the way word opens its custom dictionary */
466     r = StgOpenStorage( filename, NULL, STGM_NOSCRATCH | STGM_TRANSACTED |
467                         STGM_SHARE_DENY_WRITE | STGM_READWRITE, NULL, 0, &stg);
468     ok(r==S_OK, "StgOpenStorage failed\n");
469     if(stg)
470     {
471         r = IStorage_Release(stg);
472         ok(r == 0, "wrong ref count\n");
473     }
474
475     r = StgOpenStorage( filename, NULL, STGM_SHARE_EXCLUSIVE | STGM_READ, NULL, 0, &stg);
476     ok(r==S_OK, "StgOpenStorage failed\n");
477     r = StgOpenStorage( filename, NULL, STGM_SHARE_EXCLUSIVE | STGM_READ, NULL, 0, &stg2);
478     ok(r==STG_E_SHAREVIOLATION, "StgOpenStorage failed\n");
479     if(stg)
480     {
481         r = IStorage_Release(stg);
482         ok(r == 0, "wrong ref count\n");
483     }
484
485     /* now try write to a storage file we opened read-only */ 
486     r = StgOpenStorage( filename, NULL, STGM_SHARE_EXCLUSIVE | STGM_READ, NULL, 0, &stg);
487     ok(r==S_OK, "StgOpenStorage failed\n");
488     if(stg)
489     { 
490         static const WCHAR stmname[] =  { 'w','i','n','e','t','e','s','t',0};
491         IStream *stm = NULL;
492         IStorage *stg2 = NULL;
493
494         r = IStorage_CreateStream( stg, stmname, STGM_WRITE | STGM_SHARE_EXCLUSIVE,
495                                    0, 0, &stm );
496         ok(r == STG_E_ACCESSDENIED, "CreateStream should fail\n");
497         r = IStorage_CreateStorage( stg, stmname, STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg2);
498         ok(r == STG_E_ACCESSDENIED, "CreateStream should fail\n");
499
500         r = IStorage_Release(stg);
501         ok(r == 0, "wrong ref count\n");
502     }
503
504     /* open like visio 2003 */
505     stg = NULL;
506     r = StgOpenStorage( filename, NULL, STGM_PRIORITY | STGM_SHARE_DENY_NONE, NULL, 0, &stg);
507     ok(r == S_OK, "should succeed\n");
508     if (stg)
509         IStorage_Release(stg);
510
511     /* test other sharing modes with STGM_PRIORITY */
512     stg = NULL;
513     r = StgOpenStorage( filename, NULL, STGM_PRIORITY | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg);
514     ok(r == S_OK, "should succeed\n");
515     if (stg)
516         IStorage_Release(stg);
517
518     stg = NULL;
519     r = StgOpenStorage( filename, NULL, STGM_PRIORITY | STGM_SHARE_DENY_WRITE, NULL, 0, &stg);
520     ok(r == S_OK, "should succeed\n");
521     if (stg)
522         IStorage_Release(stg);
523
524     stg = NULL;
525     r = StgOpenStorage( filename, NULL, STGM_PRIORITY | STGM_SHARE_DENY_READ, NULL, 0, &stg);
526     ok(r == S_OK, "should succeed\n");
527     if (stg)
528         IStorage_Release(stg);
529
530     /* open like Project 2003 */
531     stg = NULL;
532     r = StgOpenStorage( filename, NULL, STGM_PRIORITY, NULL, 0, &stg);
533     ok(r == S_OK, "should succeed\n");
534     r = StgOpenStorage( filename, NULL, STGM_PRIORITY, NULL, 0, &stg2);
535     ok(r == S_OK, "should succeed\n");
536     if (stg2)
537         IStorage_Release(stg2);
538     if (stg)
539         IStorage_Release(stg);
540
541     stg = NULL;
542     r = StgOpenStorage( filename, NULL, STGM_PRIORITY | STGM_READWRITE, NULL, 0, &stg);
543     ok(r == STG_E_INVALIDFLAG, "should fail\n");
544
545     r = StgOpenStorage( filename, NULL, STGM_TRANSACTED | STGM_PRIORITY, NULL, 0, &stg);
546     ok(r == STG_E_INVALIDFLAG, "should fail\n");
547
548     r = StgOpenStorage( filename, NULL, STGM_SIMPLE | STGM_PRIORITY, NULL, 0, &stg);
549     ok(r == STG_E_INVALIDFLAG, "should fail\n");
550
551     r = StgOpenStorage( filename, NULL, STGM_DELETEONRELEASE | STGM_PRIORITY, NULL, 0, &stg);
552     ok(r == STG_E_INVALIDFUNCTION, "should fail\n");
553
554     r = StgOpenStorage( filename, NULL, STGM_NOSCRATCH | STGM_PRIORITY, NULL, 0, &stg);
555     ok(r == STG_E_INVALIDFLAG, "should fail\n");
556
557     r = StgOpenStorage( filename, NULL, STGM_NOSNAPSHOT | STGM_PRIORITY, NULL, 0, &stg);
558     ok(r == STG_E_INVALIDFLAG, "should fail\n");
559
560     r = DeleteFileW(filename);
561     ok(r, "file didn't exist\n");
562 }
563
564 static void test_storage_suminfo(void)
565 {
566     static const WCHAR szDot[] = { '.',0 };
567     static const WCHAR szPrefix[] = { 's','t','g',0 };
568     WCHAR filename[MAX_PATH];
569     IStorage *stg = NULL;
570     IPropertySetStorage *propset = NULL;
571     IPropertyStorage *ps = NULL;
572     HRESULT r;
573
574     if(!GetTempFileNameW(szDot, szPrefix, 0, filename))
575         return;
576
577     DeleteFileW(filename);
578
579     /* create the file */
580     r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | 
581                             STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
582     ok(r==S_OK, "StgCreateDocfile failed\n");
583
584     r = IStorage_QueryInterface( stg, &IID_IPropertySetStorage, (LPVOID) &propset );
585     ok(r == S_OK, "query interface failed\n");
586
587     /* delete it */
588     r = IPropertySetStorage_Delete( propset, &FMTID_SummaryInformation );
589     ok(r == STG_E_FILENOTFOUND, "deleted property set storage\n");
590
591     r = IPropertySetStorage_Open( propset, &FMTID_SummaryInformation, 
592                                 STGM_READ | STGM_SHARE_EXCLUSIVE, &ps );
593     ok(r == STG_E_FILENOTFOUND, "opened property set storage\n");
594
595     r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0,
596                                 STGM_READ | STGM_SHARE_EXCLUSIVE, &ps );
597     ok(r == STG_E_INVALIDFLAG, "created property set storage\n");
598
599     r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0,
600                                 STGM_READ, &ps );
601     ok(r == STG_E_INVALIDFLAG, "created property set storage\n");
602
603     r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0, 0, &ps );
604     ok(r == STG_E_INVALIDFLAG, "created property set storage\n");
605
606     r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0,
607                                 STGM_WRITE|STGM_SHARE_EXCLUSIVE, &ps );
608     ok(r == STG_E_INVALIDFLAG, "created property set storage\n");
609
610     r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0,
611                                 STGM_CREATE|STGM_WRITE|STGM_SHARE_EXCLUSIVE, &ps );
612     ok(r == STG_E_INVALIDFLAG, "created property set storage\n");
613
614     /* now try really creating a property set */
615     r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0,
616                                 STGM_CREATE|STGM_READWRITE|STGM_SHARE_EXCLUSIVE, &ps );
617     ok(r == S_OK, "failed to create property set storage\n");
618
619     if( ps )
620         IPropertyStorage_Release(ps);
621
622     /* now try creating the same thing again */
623     r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0,
624                                 STGM_CREATE|STGM_READWRITE|STGM_SHARE_EXCLUSIVE, &ps );
625     ok(r == S_OK, "failed to create property set storage\n");
626     if( ps )
627         IPropertyStorage_Release(ps);
628
629     /* should be able to open it */
630     r = IPropertySetStorage_Open( propset, &FMTID_SummaryInformation, 
631             STGM_READWRITE|STGM_SHARE_EXCLUSIVE, &ps);
632     ok(r == S_OK, "open failed\n");
633     if(r == S_OK)
634         IPropertyStorage_Release(ps);
635
636     /* delete it */
637     r = IPropertySetStorage_Delete( propset, &FMTID_SummaryInformation );
638     ok(r == S_OK, "failed to delete property set storage\n");
639
640     /* try opening with an invalid FMTID */
641     r = IPropertySetStorage_Open( propset, NULL, 
642             STGM_READWRITE|STGM_SHARE_EXCLUSIVE, &ps);
643     ok(r == E_INVALIDARG, "open succeeded\n");
644     if(r == S_OK)
645         IPropertyStorage_Release(ps);
646
647     /* try a bad guid */
648     r = IPropertySetStorage_Open( propset, &IID_IStorage, 
649             STGM_READWRITE|STGM_SHARE_EXCLUSIVE, &ps);
650     ok(r == STG_E_FILENOTFOUND, "open succeeded\n");
651     if(r == S_OK)
652         IPropertyStorage_Release(ps);
653     
654
655     /* try some invalid flags */
656     r = IPropertySetStorage_Open( propset, &FMTID_SummaryInformation, 
657             STGM_CREATE | STGM_READWRITE|STGM_SHARE_EXCLUSIVE, &ps);
658     ok(r == STG_E_INVALIDFLAG, "open succeeded\n");
659     if(r == S_OK)
660         IPropertyStorage_Release(ps);
661
662     /* after deleting it, it should be gone */
663     r = IPropertySetStorage_Open( propset, &FMTID_SummaryInformation, 
664             STGM_READWRITE|STGM_SHARE_EXCLUSIVE, &ps);
665     ok(r == STG_E_FILENOTFOUND, "open failed\n");
666     if(r == S_OK)
667         IPropertyStorage_Release(ps);
668
669     r = IPropertySetStorage_Release( propset );
670     ok(r == 1, "ref count wrong\n");
671
672     r = IStorage_Release(stg);
673     ok(r == 0, "ref count wrong\n");
674
675     DeleteFileW(filename);
676 }
677
678 static void test_storage_refcount(void)
679 {
680     static const WCHAR szPrefix[] = { 's','t','g',0 };
681     static const WCHAR szDot[] = { '.',0 };
682     WCHAR filename[MAX_PATH];
683     IStorage *stg = NULL;
684     IStorage *stgprio = NULL;
685     HRESULT r;
686     IStream *stm = NULL;
687     static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 };
688     LARGE_INTEGER pos;
689     ULARGE_INTEGER upos;
690     STATSTG stat;
691     char buffer[10];
692
693     if(!GetTempFileNameW(szDot, szPrefix, 0, filename))
694         return;
695
696     DeleteFileW(filename);
697
698     /* create the file */
699     r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | 
700                             STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
701     ok(r==S_OK, "StgCreateDocfile failed\n");
702
703     r = WriteClassStg( stg, &test_stg_cls );
704     ok( r == S_OK, "WriteClassStg failed\n");
705
706     r = IStorage_Commit( stg, STGC_DEFAULT );
707     ok( r == S_OK, "IStorage_Commit failed\n");
708
709     /* now create a stream */
710     r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
711     ok(r==S_OK, "IStorage->CreateStream failed\n");
712
713     r = IStorage_Release( stg );
714     ok (r == 0, "storage not released\n");
715
716     pos.QuadPart = 0;
717     r = IStream_Seek( stm, pos, 0, &upos );
718     ok (r == STG_E_REVERTED, "seek should fail\n");
719
720     r = IStream_Stat( stm, &stat, STATFLAG_DEFAULT );
721     ok (r == STG_E_REVERTED, "stat should fail\n");
722
723     r = IStream_Write( stm, "Test string", strlen("Test string"), NULL);
724     ok (r == STG_E_REVERTED, "IStream_Write should return STG_E_REVERTED instead of 0x%08x\n", r);
725
726     r = IStream_Read( stm, buffer, sizeof(buffer), NULL);
727     ok (r == STG_E_REVERTED, "IStream_Read should return STG_E_REVERTED instead of 0x%08x\n", r);
728
729     r = IStream_Release(stm);
730     ok (r == 0, "stream not released\n");
731
732     /* tests that STGM_PRIORITY doesn't prevent readwrite access from other
733      * StgOpenStorage calls in transacted mode */
734     r = StgOpenStorage( filename, NULL, STGM_PRIORITY, NULL, 0, &stgprio);
735     ok(r==S_OK, "StgOpenStorage failed with error 0x%08x\n", r);
736
737     todo_wine {
738     /* non-transacted mode read/write fails */
739     r = StgOpenStorage( filename, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg);
740     ok(r==STG_E_LOCKVIOLATION, "StgOpenStorage should return STG_E_LOCKVIOLATION instead of 0x%08x\n", r);
741     }
742
743     /* non-transacted mode read-only succeeds */
744     r = StgOpenStorage( filename, NULL, STGM_SHARE_DENY_WRITE|STGM_READ, NULL, 0, &stg);
745     ok(r==S_OK, "StgOpenStorage failed with error 0x%08x\n", r);
746     IStorage_Release(stg);
747
748     r = StgOpenStorage( filename, NULL, STGM_TRANSACTED|STGM_SHARE_DENY_WRITE|STGM_READWRITE, NULL, 0, &stg);
749     ok(r==S_OK, "StgOpenStorage failed with error 0x%08x\n", r);
750     if(stg)
751     {
752         static const WCHAR stgname[] = { ' ',' ',' ','2','9',0 };
753         static const WCHAR stgname2[] = { 'C','V','_','i','e','w',0 };
754         static const WCHAR stmname2[] = { 'V','a','r','2','D','a','t','a',0 };
755         IStorage *stg2;
756         IStorage *stg3;
757         STATSTG statstg;
758
759         r = IStorage_Stat( stg, &statstg, STATFLAG_NONAME );
760         ok(r == S_OK, "Stat should have succeded instead of returning 0x%08x\n", r);
761         ok(statstg.type == STGTY_STORAGE, "Statstg type should have been STGTY_STORAGE instead of %d\n", statstg.type);
762         ok(U(statstg.cbSize).LowPart == 0, "Statstg cbSize.LowPart should have been 0 instead of %d\n", U(statstg.cbSize).LowPart);
763         ok(U(statstg.cbSize).HighPart == 0, "Statstg cbSize.HighPart should have been 0 instead of %d\n", U(statstg.cbSize).HighPart);
764         ok(statstg.grfMode == (STGM_TRANSACTED|STGM_SHARE_DENY_WRITE|STGM_READWRITE),
765             "Statstg grfMode should have been 0x10022 instead of 0x%x\n", statstg.grfMode);
766         ok(statstg.grfLocksSupported == 0, "Statstg grfLocksSupported should have been 0 instead of %d\n", statstg.grfLocksSupported);
767         ok(IsEqualCLSID(&statstg.clsid, &test_stg_cls), "Statstg clsid is not test_stg_cls\n");
768         ok(statstg.grfStateBits == 0, "Statstg grfStateBits should have been 0 instead of %d\n", statstg.grfStateBits);
769         ok(statstg.reserved == 0, "Statstg reserved should have been 0 instead of %d\n", statstg.reserved);
770
771         r = IStorage_CreateStorage( stg, stgname, STGM_SHARE_EXCLUSIVE, 0, 0, &stg2 );
772         ok(r == S_OK, "CreateStorage should have succeeded instead of returning 0x%08x\n", r);
773
774         r = IStorage_Stat( stg2, &statstg, STATFLAG_DEFAULT );
775         ok(r == S_OK, "Stat should have succeded instead of returning 0x%08x\n", r);
776         ok(!lstrcmpW(statstg.pwcsName, stgname),
777             "Statstg pwcsName should have been the name the storage was created with\n");
778         ok(statstg.type == STGTY_STORAGE, "Statstg type should have been STGTY_STORAGE instead of %d\n", statstg.type);
779         ok(U(statstg.cbSize).LowPart == 0, "Statstg cbSize.LowPart should have been 0 instead of %d\n", U(statstg.cbSize).LowPart);
780         ok(U(statstg.cbSize).HighPart == 0, "Statstg cbSize.HighPart should have been 0 instead of %d\n", U(statstg.cbSize).HighPart);
781         ok(statstg.grfMode == STGM_SHARE_EXCLUSIVE,
782             "Statstg grfMode should have been STGM_SHARE_EXCLUSIVE instead of 0x%x\n", statstg.grfMode);
783         ok(statstg.grfLocksSupported == 0, "Statstg grfLocksSupported should have been 0 instead of %d\n", statstg.grfLocksSupported);
784         ok(IsEqualCLSID(&statstg.clsid, &CLSID_NULL), "Statstg clsid is not CLSID_NULL\n");
785         ok(statstg.grfStateBits == 0, "Statstg grfStateBits should have been 0 instead of %d\n", statstg.grfStateBits);
786         ok(statstg.reserved == 0, "Statstg reserved should have been 0 instead of %d\n", statstg.reserved);
787         CoTaskMemFree(statstg.pwcsName);
788
789         r = IStorage_CreateStorage( stg2, stgname2, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, 0, &stg3 );
790         ok(r == STG_E_ACCESSDENIED, "CreateStorage should have returned STG_E_ACCESSDENIED instead of 0x%08x\n", r);
791
792         r = IStorage_CreateStream( stg2, stmname2, STGM_CREATE|STGM_SHARE_EXCLUSIVE, 0, 0, &stm );
793         ok(r == STG_E_ACCESSDENIED, "CreateStream should have returned STG_E_ACCESSDENIED instead of 0x%08x\n", r);
794
795         IStorage_Release(stg2);
796
797         r = IStorage_Release(stg);
798         ok(r == 0, "wrong ref count\n");
799     }
800     IStorage_Release(stgprio);
801
802     DeleteFileW(filename);
803 }
804
805 static void test_streamenum(void)
806 {
807     static const WCHAR szPrefix[] = { 's','t','g',0 };
808     static const WCHAR szDot[] = { '.',0 };
809     WCHAR filename[MAX_PATH];
810     IStorage *stg = NULL;
811     HRESULT r;
812     IStream *stm = NULL;
813     static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 };
814     STATSTG stat;
815     IEnumSTATSTG *ee = NULL;
816     ULONG count;
817
818     if(!GetTempFileNameW(szDot, szPrefix, 0, filename))
819         return;
820
821     DeleteFileW(filename);
822
823     /* create the file */
824     r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
825                             STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
826     ok(r==S_OK, "StgCreateDocfile failed\n");
827
828     r = WriteClassStg( stg, &test_stg_cls );
829     ok( r == S_OK, "WriteClassStg failed\n");
830
831     r = IStorage_Commit( stg, STGC_DEFAULT );
832     ok( r == S_OK, "IStorage_Commit failed\n");
833
834     /* now create a stream */
835     r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
836     ok(r==S_OK, "IStorage->CreateStream failed\n");
837
838     r = IStream_Release(stm);
839
840     /* first enum ... should be 1 stream */
841     r = IStorage_EnumElements(stg, 0, NULL, 0, &ee);
842     ok(r==S_OK, "IStorage->EnumElements failed\n");
843
844     count = 0xf00;
845     r = IEnumSTATSTG_Next(ee, 1, &stat, &count);
846     ok(r==S_OK, "IEnumSTATSTG->Next failed\n");
847     ok(count == 1, "count wrong\n");
848
849     r = IEnumSTATSTG_Release(ee);
850
851     /* second enum... destroy the stream before reading */
852     r = IStorage_EnumElements(stg, 0, NULL, 0, &ee);
853     ok(r==S_OK, "IStorage->EnumElements failed\n");
854
855     r = IStorage_DestroyElement(stg, stmname);
856     ok(r==S_OK, "IStorage->EnumElements failed\n");
857
858     todo_wine {
859     count = 0xf00;
860     r = IEnumSTATSTG_Next(ee, 1, &stat, &count);
861     ok(r==S_FALSE, "IEnumSTATSTG->Next failed\n");
862     ok(count == 0, "count wrong\n");
863     }
864
865     /* reset and try again */
866     r = IEnumSTATSTG_Reset(ee);
867     ok(r==S_OK, "IEnumSTATSTG->Reset failed\n");
868
869     count = 0xf00;
870     r = IEnumSTATSTG_Next(ee, 1, &stat, &count);
871     ok(r==S_FALSE, "IEnumSTATSTG->Next failed\n");
872     ok(count == 0, "count wrong\n");
873
874     r = IEnumSTATSTG_Release(ee);
875     ok (r == 0, "enum not released\n");
876
877     r = IStorage_Release( stg );
878     ok (r == 0, "storage not released\n");
879
880     DeleteFileW(filename);
881 }
882
883 static void test_transact(void)
884 {
885     static const WCHAR szPrefix[] = { 's','t','g',0 };
886     static const WCHAR szDot[] = { '.',0 };
887     WCHAR filename[MAX_PATH];
888     IStorage *stg = NULL, *stg2 = NULL;
889     HRESULT r;
890     IStream *stm = NULL;
891     static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 };
892     static const WCHAR stmname2[] = { 'F','O','O',0 };
893
894     if(!GetTempFileNameW(szDot, szPrefix, 0, filename))
895         return;
896
897     DeleteFileW(filename);
898
899     /* create the file */
900     r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | 
901                             STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
902     ok(r==S_OK, "StgCreateDocfile failed\n");
903
904     /* now create a stream, but don't commit it */
905     r = IStorage_CreateStream(stg, stmname2, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
906     ok(r==S_OK, "IStorage->CreateStream failed\n");
907
908     r = IStream_Write(stm, "this is stream 1\n", 16, NULL);
909     ok(r==S_OK, "IStream->Write failed\n");
910
911     r = IStream_Release(stm);
912
913     r = IStorage_Commit(stg, 0);
914     ok(r==S_OK, "IStorage->Commit failed\n");
915
916     /* now create a stream, but don't commit it */
917     stm = NULL;
918     r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
919     ok(r==S_OK, "IStorage->CreateStream failed\n");
920
921     r = IStream_Write(stm, "this is stream 2\n", 16, NULL);
922     ok(r==S_OK, "IStream->Write failed\n");
923
924     r = IStream_Commit(stm, STGC_ONLYIFCURRENT | STGC_DANGEROUSLYCOMMITMERELYTODISKCACHE);
925     ok(r==S_OK, "IStream->Commit failed\n");
926
927     r = IStream_Release(stm);
928
929     IStorage_Release(stg);
930
931     stm = NULL;
932     stg = NULL;
933     r = StgOpenStorage( filename, NULL, STGM_SHARE_DENY_NONE | STGM_READ | STGM_TRANSACTED, NULL, 0, &stg);
934     ok(r==S_OK, "StgOpenStorage failed\n");
935
936     if (!stg)
937         return;
938
939     r = IStorage_OpenStream(stg, stmname, NULL, STGM_SHARE_DENY_NONE|STGM_READ, 0, &stm );
940     ok(r==STG_E_INVALIDFLAG, "IStorage->OpenStream failed %08x\n", r);
941
942     r = IStorage_OpenStream(stg, stmname, NULL, STGM_DELETEONRELEASE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
943     ok(r==STG_E_INVALIDFUNCTION, "IStorage->OpenStream failed %08x\n", r);
944
945     r = IStorage_OpenStream(stg, stmname, NULL, STGM_TRANSACTED|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
946     ok(r==STG_E_INVALIDFUNCTION, "IStorage->OpenStream failed %08x\n", r);
947
948     r = IStorage_OpenStorage(stg, stmname, NULL, STGM_TRANSACTED|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg2 );
949     ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStream failed %08x\n", r);
950
951     todo_wine {
952     r = IStorage_OpenStream(stg, stmname, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
953     ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStream should fail %08x\n", r);
954     }
955     if (stm)
956         r = IStream_Release(stm);
957
958     r = IStorage_OpenStorage(stg, stmname2, NULL, STGM_TRANSACTED|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg2 );
959     ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStream failed %08x\n", r);
960
961     r = IStorage_OpenStream(stg, stmname2, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
962     ok(r==S_OK, "IStorage->OpenStream should fail %08x\n", r);
963     if (stm)
964         r = IStream_Release(stm);
965
966     IStorage_Release(stg);
967
968     r = DeleteFileW(filename);
969     ok( r == TRUE, "deleted file\n");
970 }
971
972 static void test_ReadClassStm(void)
973 {
974     CLSID clsid;
975     HRESULT hr;
976     IStream *pStream;
977     static const LARGE_INTEGER llZero;
978
979     hr = ReadClassStm(NULL, &clsid);
980     ok(hr == E_INVALIDARG, "ReadClassStm should have returned E_INVALIDARG instead of 0x%08x\n", hr);
981
982     hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
983     ok_ole_success(hr, "CreateStreamOnHGlobal");
984     hr = WriteClassStm(pStream, &test_stg_cls);
985     ok_ole_success(hr, "WriteClassStm");
986
987     hr = ReadClassStm(pStream, NULL);
988     ok(hr == E_INVALIDARG, "ReadClassStm should have returned E_INVALIDARG instead of 0x%08x\n", hr);
989
990     /* test not rewound stream */
991     hr = ReadClassStm(pStream, &clsid);
992     ok(hr == STG_E_READFAULT, "ReadClassStm should have returned STG_E_READFAULT instead of 0x%08x\n", hr);
993     ok(IsEqualCLSID(&clsid, &CLSID_NULL), "clsid should have been zeroed\n");
994
995     hr = IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
996     ok_ole_success(hr, "IStream_Seek");
997     hr = ReadClassStm(pStream, &clsid);
998     ok_ole_success(hr, "ReadClassStm");
999     ok(IsEqualCLSID(&clsid, &test_stg_cls), "clsid should have been set to CLSID_WineTest\n");
1000 }
1001
1002 struct access_res
1003 {
1004     BOOL gothandle;
1005     DWORD lasterr;
1006 };
1007
1008 static const struct access_res create[16] =
1009 {
1010     { TRUE, ERROR_SUCCESS },
1011     { TRUE, ERROR_SUCCESS },
1012     { TRUE, ERROR_SUCCESS },
1013     { TRUE, ERROR_SUCCESS },
1014     { FALSE, ERROR_SHARING_VIOLATION },
1015     { FALSE, ERROR_SHARING_VIOLATION },
1016     { FALSE, ERROR_SHARING_VIOLATION },
1017     { TRUE, ERROR_SUCCESS },
1018     { FALSE, ERROR_SHARING_VIOLATION },
1019     { FALSE, ERROR_SHARING_VIOLATION },
1020     { FALSE, ERROR_SHARING_VIOLATION },
1021     { TRUE, ERROR_SUCCESS },
1022     { FALSE, ERROR_SHARING_VIOLATION },
1023     { FALSE, ERROR_SHARING_VIOLATION },
1024     { FALSE, ERROR_SHARING_VIOLATION },
1025     { TRUE, ERROR_SUCCESS }
1026 };
1027
1028 static const struct access_res create_commit[16] =
1029 {
1030     { TRUE, ERROR_SUCCESS },
1031     { TRUE, ERROR_SUCCESS },
1032     { TRUE, ERROR_SUCCESS },
1033     { TRUE, ERROR_SUCCESS },
1034     { FALSE, ERROR_SHARING_VIOLATION },
1035     { FALSE, ERROR_SHARING_VIOLATION },
1036     { FALSE, ERROR_SHARING_VIOLATION },
1037     { TRUE, ERROR_SUCCESS },
1038     { FALSE, ERROR_SHARING_VIOLATION },
1039     { FALSE, ERROR_SHARING_VIOLATION },
1040     { FALSE, ERROR_SHARING_VIOLATION },
1041     { TRUE, ERROR_SUCCESS },
1042     { FALSE, ERROR_SHARING_VIOLATION },
1043     { FALSE, ERROR_SHARING_VIOLATION },
1044     { FALSE, ERROR_SHARING_VIOLATION },
1045     { TRUE, ERROR_SUCCESS }
1046 };
1047
1048 static const struct access_res create_close[16] =
1049 {
1050     { TRUE, ERROR_SUCCESS },
1051     { TRUE, ERROR_SUCCESS },
1052     { TRUE, ERROR_SUCCESS },
1053     { TRUE, ERROR_SUCCESS },
1054     { TRUE, ERROR_SUCCESS },
1055     { TRUE, ERROR_SUCCESS },
1056     { TRUE, ERROR_SUCCESS },
1057     { TRUE, ERROR_SUCCESS },
1058     { TRUE, ERROR_SUCCESS },
1059     { TRUE, ERROR_SUCCESS },
1060     { TRUE, ERROR_SUCCESS },
1061     { TRUE, ERROR_SUCCESS },
1062     { TRUE, ERROR_SUCCESS },
1063     { TRUE, ERROR_SUCCESS },
1064     { TRUE, ERROR_SUCCESS },
1065     { TRUE, ERROR_SUCCESS }
1066 };
1067
1068 static void _test_file_access(LPCSTR file, const struct access_res *ares, DWORD line)
1069 {
1070     DWORD access = 0, share = 0;
1071     DWORD lasterr;
1072     HANDLE hfile;
1073     int i, j, idx = 0;
1074
1075     for (i = 0; i < 4; i++)
1076     {
1077         if (i == 0) access = 0;
1078         if (i == 1) access = GENERIC_READ;
1079         if (i == 2) access = GENERIC_WRITE;
1080         if (i == 3) access = GENERIC_READ | GENERIC_WRITE;
1081
1082         for (j = 0; j < 4; j++)
1083         {
1084             if (j == 0) share = 0;
1085             if (j == 1) share = FILE_SHARE_READ;
1086             if (j == 2) share = FILE_SHARE_WRITE;
1087             if (j == 3) share = FILE_SHARE_READ | FILE_SHARE_WRITE;
1088
1089             SetLastError(0xdeadbeef);
1090             hfile = CreateFileA(file, access, share, NULL, OPEN_EXISTING,
1091                                 FILE_ATTRIBUTE_NORMAL, 0);
1092             lasterr = GetLastError();
1093
1094             ok((hfile != INVALID_HANDLE_VALUE) == ares[idx].gothandle,
1095                "(%d, handle, %d): Expected %d, got %d\n",
1096                line, idx, ares[idx].gothandle,
1097                (hfile != INVALID_HANDLE_VALUE));
1098
1099             ok(lasterr == ares[idx].lasterr,
1100                "(%d, lasterr, %d): Expected %d, got %d\n",
1101                line, idx, ares[idx].lasterr, lasterr);
1102
1103             CloseHandle(hfile);
1104             idx++;
1105         }
1106     }
1107 }
1108
1109 #define test_file_access(file, ares) _test_file_access(file, ares, __LINE__)
1110
1111 static void test_access(void)
1112 {
1113     IStorage *stg;
1114     HRESULT hr;
1115
1116     static const WCHAR fileW[] = {'w','i','n','e','t','e','s','t',0};
1117
1118     /* STGM_TRANSACTED */
1119
1120     hr = StgCreateDocfile(fileW, STGM_CREATE | STGM_READWRITE |
1121                           STGM_SHARE_EXCLUSIVE | STGM_TRANSACTED, 0, &stg);
1122     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1123
1124     test_file_access("winetest", create);
1125
1126     hr = IStorage_Commit(stg, STGC_DEFAULT);
1127     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1128
1129     test_file_access("winetest", create_commit);
1130
1131     IStorage_Release(stg);
1132
1133     test_file_access("winetest", create_close);
1134
1135     DeleteFileA("winetest");
1136
1137     /* STGM_DIRECT */
1138
1139     hr = StgCreateDocfile(fileW, STGM_CREATE | STGM_READWRITE |
1140                           STGM_SHARE_EXCLUSIVE | STGM_DIRECT, 0, &stg);
1141     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1142
1143     test_file_access("winetest", create);
1144
1145     hr = IStorage_Commit(stg, STGC_DEFAULT);
1146     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1147
1148     test_file_access("winetest", create_commit);
1149
1150     IStorage_Release(stg);
1151
1152     test_file_access("winetest", create_close);
1153
1154     DeleteFileA("winetest");
1155
1156     /* STGM_SHARE_DENY_NONE */
1157
1158     hr = StgCreateDocfile(fileW, STGM_CREATE | STGM_READWRITE |
1159                           STGM_SHARE_DENY_NONE | STGM_TRANSACTED, 0, &stg);
1160     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1161
1162     test_file_access("winetest", create);
1163
1164     hr = IStorage_Commit(stg, STGC_DEFAULT);
1165     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1166
1167     test_file_access("winetest", create_commit);
1168
1169     IStorage_Release(stg);
1170
1171     test_file_access("winetest", create_close);
1172
1173     DeleteFileA("winetest");
1174
1175     /* STGM_SHARE_DENY_READ */
1176
1177     hr = StgCreateDocfile(fileW, STGM_CREATE | STGM_READWRITE |
1178                           STGM_SHARE_DENY_READ | STGM_TRANSACTED, 0, &stg);
1179     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1180
1181     test_file_access("winetest", create);
1182
1183     hr = IStorage_Commit(stg, STGC_DEFAULT);
1184     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1185
1186     test_file_access("winetest", create_commit);
1187
1188     IStorage_Release(stg);
1189
1190     test_file_access("winetest", create_close);
1191
1192     DeleteFileA("winetest");
1193
1194     /* STGM_SHARE_DENY_WRITE */
1195
1196     hr = StgCreateDocfile(fileW, STGM_CREATE | STGM_READWRITE |
1197                           STGM_SHARE_DENY_WRITE | STGM_TRANSACTED, 0, &stg);
1198     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1199
1200     test_file_access("winetest", create);
1201
1202     hr = IStorage_Commit(stg, STGC_DEFAULT);
1203     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1204
1205     test_file_access("winetest", create_commit);
1206
1207     IStorage_Release(stg);
1208
1209     test_file_access("winetest", create_close);
1210
1211     DeleteFileA("winetest");
1212 }
1213
1214 START_TEST(storage32)
1215 {
1216     test_hglobal_storage_stat();
1217     test_create_storage_modes();
1218     test_storage_stream();
1219     test_open_storage();
1220     test_storage_suminfo();
1221     test_storage_refcount();
1222     test_streamenum();
1223     test_transact();
1224     test_ReadClassStm();
1225     test_access();
1226 }