query: Add a stub implementation for LocateCatalogs.
[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 static void test_hglobal_storage_stat(void)
35 {
36     ILockBytes *ilb = NULL;
37     IStorage *stg = NULL;
38     HRESULT r;
39     STATSTG stat;
40     DWORD mode, refcount;
41
42     r = CreateILockBytesOnHGlobal( NULL, TRUE, &ilb );
43     ok( r == S_OK, "CreateILockBytesOnHGlobal failed\n");
44
45     mode = STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE;/*0x1012*/
46     r = StgCreateDocfileOnILockBytes( ilb, mode, 0,  &stg );
47     ok( r == S_OK, "CreateILockBytesOnHGlobal failed\n");
48
49     r = WriteClassStg( stg, &test_stg_cls );
50     ok( r == S_OK, "WriteClassStg failed\n");
51
52     memset( &stat, 0, sizeof stat );
53     r = IStorage_Stat( stg, &stat, 0 );
54
55     ok( stat.pwcsName == NULL, "storage name not null\n");
56     ok( stat.type == 1, "type is wrong\n");
57     ok( stat.grfMode == 0x12, "grf mode is incorrect\n");
58     ok( !memcmp(&stat.clsid, &test_stg_cls, sizeof test_stg_cls), "CLSID is wrong\n");
59
60     refcount = IStorage_Release( stg );
61     ok( refcount == 0, "IStorage refcount is wrong\n");
62     refcount = ILockBytes_Release( ilb );
63     ok( refcount == 0, "ILockBytes refcount is wrong\n");
64 }
65
66 static void test_create_storage_modes(void)
67 {
68    static const WCHAR szPrefix[] = { 's','t','g',0 };
69    static const WCHAR szDot[] = { '.',0 };
70    WCHAR filename[MAX_PATH];
71    IStorage *stg = NULL;
72    HRESULT r;
73
74    if(!GetTempFileNameW(szDot, szPrefix, 0, filename))
75       return;
76
77    DeleteFileW(filename);
78
79    /* test with some invalid parameters */
80    r = StgCreateDocfile( NULL, 0, 0, &stg);
81    ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
82    r = StgCreateDocfile( filename, 0, 0, &stg);
83    ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
84    r = StgCreateDocfile( filename, STGM_CREATE, 0, &stg);
85    ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
86    r = StgCreateDocfile( filename, STGM_CREATE | STGM_READWRITE, 0, &stg);
87    ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
88    r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE, 0, &stg);
89    ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
90    r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, NULL);
91    ok(r==STG_E_INVALIDPOINTER, "StgCreateDocfile succeeded\n");
92    r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 1, &stg);
93    ok(r==STG_E_INVALIDPARAMETER, "StgCreateDocfile succeeded\n");
94    r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_DENY_WRITE | STGM_READWRITE, 0, &stg);
95    ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
96    r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READ, 0, &stg);
97    ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
98    r = StgCreateDocfile( filename, STGM_PRIORITY, 0, &stg);
99    ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
100
101    /* StgCreateDocfile seems to be very particular about the flags it accepts */
102    r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED | STGM_WRITE, 0, &stg);
103    ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
104    r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED | 8, 0, &stg);
105    ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
106    r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED | 0x80, 0, &stg);
107    ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
108    r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED | 0x800, 0, &stg);
109    ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
110    r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED | 0x8000, 0, &stg);
111    ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
112    r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED | 0x80000, 0, &stg);
113    ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
114    r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED | 0x800000, 0, &stg);
115    ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
116    ok(stg == NULL, "stg was set\n");
117
118    /* check what happens if the file already exists (which is how it's meant to be used) */
119    r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &stg);
120    ok(r==S_OK, "StgCreateDocfile failed\n");
121    r = IStorage_Release(stg);
122    ok(r == 0, "storage not released\n");
123    r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
124    ok(r==STG_E_FILEALREADYEXISTS, "StgCreateDocfile wrong error\n"); /* FAILIFTHERE is default */
125    r = StgCreateDocfile( filename, STGM_READ, 0, &stg);
126    ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n"); /* need at least readmode and sharemode */
127    r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE, 0, &stg);
128    ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
129    r = StgCreateDocfile( filename, STGM_SHARE_DENY_WRITE, 0, &stg);
130    ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
131    r = StgCreateDocfile( filename, STGM_SHARE_DENY_NONE, 0, &stg);
132    ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile failed\n");
133    r = StgCreateDocfile( filename, STGM_SHARE_DENY_NONE | STGM_TRANSACTED, 0, &stg);
134    ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile failed\n");
135    r = StgCreateDocfile( filename, STGM_SHARE_DENY_NONE | STGM_READWRITE, 0, &stg);
136    ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile failed\n");
137    r = StgCreateDocfile( filename, STGM_SHARE_DENY_NONE | STGM_WRITE, 0, &stg);
138    ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile failed\n");
139    r = StgCreateDocfile( filename, STGM_SHARE_DENY_WRITE | STGM_WRITE, 0, &stg);
140    ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile failed\n");
141    r = StgCreateDocfile( filename, STGM_SHARE_DENY_WRITE | STGM_READ, 0, &stg);
142    ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile wrong error\n");
143    r = StgCreateDocfile( filename, STGM_TRANSACTED | STGM_SHARE_DENY_WRITE | STGM_READ, 0, &stg);
144    ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile wrong error\n");
145    ok(DeleteFileW(filename), "failed to delete file\n");
146
147    r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
148    ok(r==S_OK, "StgCreateDocfile failed\n");
149    r = IStorage_Release(stg);
150    ok(r == 0, "storage not released\n");
151    r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED |STGM_FAILIFTHERE, 0, &stg);
152    ok(r==STG_E_FILEALREADYEXISTS, "StgCreateDocfile wrong error\n");
153    r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_WRITE, 0, &stg);
154    ok(r==STG_E_FILEALREADYEXISTS, "StgCreateDocfile wrong error\n");
155
156    r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_DENY_WRITE | STGM_READWRITE, 0, &stg);
157    ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
158    r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
159    ok(r==S_OK, "StgCreateDocfile failed\n");
160    r = IStorage_Release(stg);
161    ok(r == 0, "storage not released\n");
162    ok(DeleteFileW(filename), "failed to delete file\n");
163
164    /* test the way excel uses StgCreateDocFile */
165    r = StgCreateDocfile( filename, STGM_TRANSACTED|STGM_CREATE|STGM_SHARE_DENY_WRITE|STGM_READWRITE, 0, &stg);
166    ok(r==S_OK, "StgCreateDocfile the excel way failed\n");
167    if(r == S_OK)
168    {
169       r = IStorage_Release(stg);
170       ok(r == 0, "storage not released\n");
171       ok(DeleteFileW(filename), "failed to delete file\n");
172    }
173
174    /* and the way windows media uses it ... */
175    r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_DENY_NONE | STGM_READWRITE | STGM_TRANSACTED, 0, &stg);
176    ok(r==S_OK, "StgCreateDocfile the windows media way failed\n");
177    if (r == S_OK)
178    {
179       r = IStorage_Release(stg);
180       ok(r == 0, "storage not released\n");
181       ok(DeleteFileW(filename), "failed to delete file\n");
182    }
183
184    /* looks like we need STGM_TRANSACTED or STGM_CREATE */
185    r = StgCreateDocfile( filename, STGM_TRANSACTED|STGM_SHARE_DENY_WRITE|STGM_READWRITE, 0, &stg);
186    ok(r==S_OK, "StgCreateDocfile the excel way failed\n");
187    if(r == S_OK)
188    {
189       r = IStorage_Release(stg);
190       ok(r == 0, "storage not released\n");
191       ok(DeleteFileW(filename), "failed to delete file\n");
192    }
193
194    r = StgCreateDocfile( filename, STGM_TRANSACTED|STGM_CREATE|STGM_SHARE_DENY_WRITE|STGM_WRITE, 0, &stg);
195    ok(r==S_OK, "StgCreateDocfile the excel way failed\n");
196    if(r == S_OK)
197    {
198       r = IStorage_Release(stg);
199       ok(r == 0, "storage not released\n");
200       ok(DeleteFileW(filename), "failed to delete file\n");
201    }
202
203    r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &stg);
204    ok(r==S_OK, "StgCreateDocfile the powerpoint way failed\n");
205    if(r == S_OK)
206    {
207       r = IStorage_Release(stg);
208       ok(r == 0, "storage not released\n");
209       ok(DeleteFileW(filename), "failed to delete file\n");
210    }
211
212    /* test the way msi uses StgCreateDocfile */
213    r = StgCreateDocfile( filename, STGM_DIRECT | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &stg);
214    ok(r==S_OK, "StgCreateDocFile failed\n");
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 static void test_storage_stream(void)
221 {
222     static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 };
223     static const WCHAR szPrefix[] = { 's','t','g',0 };
224     static const WCHAR szDot[] = { '.',0 };
225     static const WCHAR longname[] = {
226         'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
227         'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',0
228     };
229     WCHAR filename[MAX_PATH];
230     IStorage *stg = NULL;
231     HRESULT r;
232     IStream *stm = NULL;
233     ULONG count = 0;
234     LARGE_INTEGER pos;
235     ULARGE_INTEGER p;
236     unsigned char buffer[0x100];
237
238     if(!GetTempFileNameW(szDot, szPrefix, 0, filename))
239         return;
240
241     DeleteFileW(filename);
242
243     r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
244     ok(r==S_OK, "StgCreateDocfile failed\n");
245
246     /* try create some invalid streams */
247     r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 1, 0, &stm );
248     ok(r==STG_E_INVALIDPARAMETER, "IStorage->CreateStream wrong error\n");
249     r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 1, &stm );
250     ok(r==STG_E_INVALIDPARAMETER, "IStorage->CreateStream wrong error\n");
251     r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, NULL );
252     ok(r==STG_E_INVALIDPOINTER, "IStorage->CreateStream wrong error\n");
253     r = IStorage_CreateStream(stg, NULL, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
254     ok(r==STG_E_INVALIDNAME, "IStorage->CreateStream wrong error\n");
255     r = IStorage_CreateStream(stg, longname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
256     ok(r==STG_E_INVALIDNAME, "IStorage->CreateStream wrong error, got %ld GetLastError()=%ld\n", r, GetLastError());
257     r = IStorage_CreateStream(stg, stmname, STGM_READWRITE, 0, 0, &stm );
258     ok(r==STG_E_INVALIDFLAG, "IStorage->CreateStream wrong error\n");
259     r = IStorage_CreateStream(stg, stmname, STGM_READ, 0, 0, &stm );
260     ok(r==STG_E_INVALIDFLAG, "IStorage->CreateStream wrong error\n");
261     r = IStorage_CreateStream(stg, stmname, STGM_WRITE, 0, 0, &stm );
262     ok(r==STG_E_INVALIDFLAG, "IStorage->CreateStream wrong error\n");
263     r = IStorage_CreateStream(stg, stmname, STGM_SHARE_DENY_NONE | STGM_READWRITE, 0, 0, &stm );
264     ok(r==STG_E_INVALIDFLAG, "IStorage->CreateStream wrong error\n");
265     r = IStorage_CreateStream(stg, stmname, STGM_SHARE_DENY_NONE | STGM_READ, 0, 0, &stm );
266     ok(r==STG_E_INVALIDFLAG, "IStorage->CreateStream wrong error\n");
267
268     /* now really create a stream and delete it */
269     r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
270     ok(r==S_OK, "IStorage->CreateStream failed\n");
271     r = IStream_Release(stm);
272     ok(r == 0, "wrong ref count\n");
273     r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
274     ok(r==STG_E_FILEALREADYEXISTS, "IStorage->CreateStream failed\n");
275     r = IStorage_DestroyElement(stg,stmname);
276     ok(r==S_OK, "IStorage->DestroyElement failed\n");
277
278     /* create a stream and write to it */
279     r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
280     ok(r==S_OK, "IStorage->CreateStream failed\n");
281
282     r = IStream_Write(stm, NULL, 0, NULL );
283     ok(r==STG_E_INVALIDPOINTER, "IStream->Write wrong error\n");
284     r = IStream_Write(stm, "Hello\n", 0, NULL );
285     ok(r==S_OK, "failed to write stream\n");
286     r = IStream_Write(stm, "Hello\n", 0, &count );
287     ok(r==S_OK, "failed to write stream\n");
288     r = IStream_Write(stm, "Hello\n", 6, &count );
289     ok(r==S_OK, "failed to write stream\n");
290     r = IStream_Commit(stm, STGC_DEFAULT );
291     ok(r==S_OK, "failed to commit stream\n");
292     r = IStream_Commit(stm, STGC_DEFAULT );
293     ok(r==S_OK, "failed to commit stream\n");
294
295     /* seek round a bit, reset the stream size */
296     pos.QuadPart = 0;
297     r = IStream_Seek(stm, pos, 3, &p );
298     ok(r==STG_E_INVALIDFUNCTION, "IStream->Seek returned wrong error\n");
299     r = IStream_Seek(stm, pos, STREAM_SEEK_SET, NULL);
300     ok(r==S_OK, "failed to seek stream\n");
301     r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p );
302     ok(r==S_OK, "failed to seek stream\n");
303     r = IStream_SetSize(stm,p);
304     ok(r==S_OK, "failed to set pos\n");
305     pos.QuadPart = 10;
306     r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p );
307     ok(r==S_OK, "failed to seek stream\n");
308     ok(p.QuadPart == 10, "at wrong place\n");
309     pos.QuadPart = 0;
310     r = IStream_Seek(stm, pos, STREAM_SEEK_END, &p );
311     ok(r==S_OK, "failed to seek stream\n");
312     ok(p.QuadPart == 0, "at wrong place\n");
313     r = IStream_Read(stm, buffer, sizeof buffer, &count );
314     ok(r==S_OK, "failed to set pos\n");
315     ok(count == 0, "read bytes from empty stream\n");
316
317     /* wrap up */
318     r = IStream_Release(stm);
319     ok(r == 0, "wrong ref count\n");
320     r = IStorage_Release(stg);
321     ok(r == 0, "wrong ref count\n");
322     r = DeleteFileW(filename);
323     ok(r, "file should exist\n");
324 }
325
326 static BOOL touch_file(LPCWSTR filename)
327 {
328     HANDLE file;
329
330     file = CreateFileW(filename, GENERIC_READ|GENERIC_WRITE, 0, NULL, 
331                 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
332     if (file==INVALID_HANDLE_VALUE)
333         return FALSE;
334     CloseHandle(file);
335     return TRUE;
336 }
337
338 static BOOL is_zero_length(LPCWSTR filename)
339 {
340     HANDLE file;
341     DWORD len;
342
343     file = CreateFileW(filename, GENERIC_READ, 0, NULL, 
344                 OPEN_EXISTING, 0, NULL);
345     if (file==INVALID_HANDLE_VALUE)
346         return FALSE;
347     len = GetFileSize(file, NULL);
348     CloseHandle(file);
349     return len == 0;
350 }
351
352 static void test_open_storage(void)
353 {
354     static const WCHAR szPrefix[] = { 's','t','g',0 };
355     static const WCHAR szNonExist[] = { 'n','o','n','e','x','i','s','t',0 };
356     static const WCHAR szDot[] = { '.',0 };
357     WCHAR filename[MAX_PATH];
358     IStorage *stg = NULL, *stg2 = NULL;
359     HRESULT r;
360     DWORD stgm;
361
362     if(!GetTempFileNameW(szDot, szPrefix, 0, filename))
363         return;
364
365     /* try opening a zero length file - it should stay zero length */
366     DeleteFileW(filename);
367     touch_file(filename);
368     stgm = STGM_NOSCRATCH | STGM_TRANSACTED | STGM_SHARE_DENY_WRITE | STGM_READWRITE;
369     r = StgOpenStorage( filename, NULL, stgm, NULL, 0, &stg);
370     ok(r==STG_E_FILEALREADYEXISTS, "StgOpenStorage didn't fail\n");
371
372     stgm = STGM_SHARE_EXCLUSIVE | STGM_READWRITE;
373     r = StgOpenStorage( filename, NULL, stgm, NULL, 0, &stg);
374     ok(r==STG_E_FILEALREADYEXISTS, "StgOpenStorage didn't fail\n");
375     ok(is_zero_length(filename), "file length changed\n");
376
377     DeleteFileW(filename);
378
379     /* create the file */
380     r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
381     ok(r==S_OK, "StgCreateDocfile failed\n");
382     IStorage_Release(stg);
383
384     r = StgOpenStorage( filename, NULL, 0, NULL, 0, &stg);
385     ok(r==STG_E_INVALIDFLAG, "StgOpenStorage wrong error\n");
386     r = StgOpenStorage( NULL, NULL, STGM_SHARE_EXCLUSIVE, NULL, 0, &stg);
387     ok(r==STG_E_INVALIDNAME, "StgOpenStorage wrong error\n");
388     r = StgOpenStorage( filename, NULL, STGM_SHARE_EXCLUSIVE | STGM_READ, NULL, 0, NULL);
389     ok(r==STG_E_INVALIDPOINTER, "StgOpenStorage wrong error\n");
390     r = StgOpenStorage( filename, NULL, STGM_SHARE_EXCLUSIVE | STGM_READ, NULL, 1, &stg);
391     ok(r==STG_E_INVALIDPARAMETER, "StgOpenStorage wrong error\n");
392     r = StgOpenStorage( szNonExist, NULL, STGM_SHARE_EXCLUSIVE | STGM_READ, NULL, 0, &stg);
393     ok(r==STG_E_FILENOTFOUND, "StgOpenStorage failed\n");
394     r = StgOpenStorage( filename, NULL, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READ, NULL, 0, &stg);
395     ok(r==STG_E_INVALIDFLAG, "StgOpenStorage failed\n");
396     r = StgOpenStorage( filename, NULL, STGM_SHARE_DENY_NONE | STGM_READ, NULL, 0, &stg);
397     ok(r==STG_E_INVALIDFLAG, "StgOpenStorage failed\n");
398     r = StgOpenStorage( filename, NULL, STGM_SHARE_DENY_READ | STGM_READ, NULL, 0, &stg);
399     ok(r==STG_E_INVALIDFLAG, "StgOpenStorage failed\n");
400     r = StgOpenStorage( filename, NULL, STGM_SHARE_DENY_WRITE | STGM_READWRITE, NULL, 0, &stg);
401     ok(r==STG_E_INVALIDFLAG, "StgOpenStorage failed\n");
402
403     /* open it for real */
404     r = StgOpenStorage( filename, NULL, STGM_SHARE_DENY_NONE | STGM_READ | STGM_TRANSACTED, NULL, 0, &stg); /* XLViewer 97/2000 */
405     ok(r==S_OK, "StgOpenStorage failed\n");
406     if(stg)
407     {
408         r = IStorage_Release(stg);
409         ok(r == 0, "wrong ref count\n");
410     }
411
412     r = StgOpenStorage( filename, NULL, STGM_SHARE_DENY_WRITE | STGM_READ, NULL, 0, &stg);
413     ok(r==S_OK, "StgOpenStorage failed\n");
414     if(stg)
415     {
416         r = IStorage_Release(stg);
417         ok(r == 0, "wrong ref count\n");
418     }
419
420     /* test the way word opens its custom dictionary */
421     r = StgOpenStorage( filename, NULL, STGM_NOSCRATCH | STGM_TRANSACTED |
422                         STGM_SHARE_DENY_WRITE | STGM_READWRITE, NULL, 0, &stg);
423     ok(r==S_OK, "StgOpenStorage failed\n");
424     if(stg)
425     {
426         r = IStorage_Release(stg);
427         ok(r == 0, "wrong ref count\n");
428     }
429
430     r = StgOpenStorage( filename, NULL, STGM_SHARE_EXCLUSIVE | STGM_READ, NULL, 0, &stg);
431     ok(r==S_OK, "StgOpenStorage failed\n");
432     r = StgOpenStorage( filename, NULL, STGM_SHARE_EXCLUSIVE | STGM_READ, NULL, 0, &stg2);
433     ok(r==STG_E_SHAREVIOLATION, "StgOpenStorage failed\n");
434     if(stg)
435     {
436         r = IStorage_Release(stg);
437         ok(r == 0, "wrong ref count\n");
438     }
439
440     /* now try write to a storage file we opened read-only */ 
441     r = StgOpenStorage( filename, NULL, STGM_SHARE_EXCLUSIVE | STGM_READ, NULL, 0, &stg);
442     ok(r==S_OK, "StgOpenStorage failed\n");
443     if(stg)
444     { 
445         static const WCHAR stmname[] =  { 'w','i','n','e','t','e','s','t',0};
446         IStream *stm = NULL;
447         IStorage *stg2 = NULL;
448
449         r = IStorage_CreateStream( stg, stmname, STGM_WRITE | STGM_SHARE_EXCLUSIVE,
450                                    0, 0, &stm );
451         ok(r == STG_E_ACCESSDENIED, "CreateStream should fail\n");
452         r = IStorage_CreateStorage( stg, stmname, STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg2);
453         ok(r == STG_E_ACCESSDENIED, "CreateStream should fail\n");
454
455         r = IStorage_Release(stg);
456         ok(r == 0, "wrong ref count\n");
457     }
458
459     /* open like visio 2003 */
460     stg = NULL;
461     r = StgOpenStorage( filename, NULL, STGM_PRIORITY | STGM_SHARE_DENY_NONE, NULL, 0, &stg);
462     ok(r == S_OK, "should succeed\n");
463     if (stg)
464         IStorage_Release(stg);
465
466     /* test other sharing modes with STGM_PRIORITY */
467     stg = NULL;
468     r = StgOpenStorage( filename, NULL, STGM_PRIORITY | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg);
469     ok(r == S_OK, "should succeed\n");
470     if (stg)
471         IStorage_Release(stg);
472
473     stg = NULL;
474     r = StgOpenStorage( filename, NULL, STGM_PRIORITY | STGM_SHARE_DENY_WRITE, NULL, 0, &stg);
475     ok(r == S_OK, "should succeed\n");
476     if (stg)
477         IStorage_Release(stg);
478
479     stg = NULL;
480     r = StgOpenStorage( filename, NULL, STGM_PRIORITY | STGM_SHARE_DENY_READ, NULL, 0, &stg);
481     ok(r == S_OK, "should succeed\n");
482     if (stg)
483         IStorage_Release(stg);
484
485     /* open like Project 2003 */
486     stg = NULL;
487     r = StgOpenStorage( filename, NULL, STGM_PRIORITY, NULL, 0, &stg);
488     ok(r == S_OK, "should succeed\n");
489     r = StgOpenStorage( filename, NULL, STGM_PRIORITY, NULL, 0, &stg2);
490     ok(r == S_OK, "should succeed\n");
491     if (stg2)
492         IStorage_Release(stg2);
493     if (stg)
494         IStorage_Release(stg);
495
496     stg = NULL;
497     r = StgOpenStorage( filename, NULL, STGM_PRIORITY | STGM_READWRITE, NULL, 0, &stg);
498     ok(r == STG_E_INVALIDFLAG, "should fail\n");
499
500     r = StgOpenStorage( filename, NULL, STGM_TRANSACTED | STGM_PRIORITY, NULL, 0, &stg);
501     ok(r == STG_E_INVALIDFLAG, "should fail\n");
502
503     r = StgOpenStorage( filename, NULL, STGM_SIMPLE | STGM_PRIORITY, NULL, 0, &stg);
504     ok(r == STG_E_INVALIDFLAG, "should fail\n");
505
506     r = StgOpenStorage( filename, NULL, STGM_DELETEONRELEASE | STGM_PRIORITY, NULL, 0, &stg);
507     ok(r == STG_E_INVALIDFUNCTION, "should fail\n");
508
509     r = StgOpenStorage( filename, NULL, STGM_NOSCRATCH | STGM_PRIORITY, NULL, 0, &stg);
510     ok(r == STG_E_INVALIDFLAG, "should fail\n");
511
512     r = StgOpenStorage( filename, NULL, STGM_NOSNAPSHOT | STGM_PRIORITY, NULL, 0, &stg);
513     ok(r == STG_E_INVALIDFLAG, "should fail\n");
514
515     r = DeleteFileW(filename);
516     ok(r, "file didn't exist\n");
517 }
518
519 static void test_storage_suminfo(void)
520 {
521     static const WCHAR szDot[] = { '.',0 };
522     static const WCHAR szPrefix[] = { 's','t','g',0 };
523     WCHAR filename[MAX_PATH];
524     IStorage *stg = NULL;
525     IPropertySetStorage *propset = NULL;
526     IPropertyStorage *ps = NULL;
527     HRESULT r;
528
529     if(!GetTempFileNameW(szDot, szPrefix, 0, filename))
530         return;
531
532     DeleteFileW(filename);
533
534     /* create the file */
535     r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | 
536                             STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
537     ok(r==S_OK, "StgCreateDocfile failed\n");
538
539     r = IStorage_QueryInterface( stg, &IID_IPropertySetStorage, (LPVOID) &propset );
540     ok(r == S_OK, "query interface failed\n");
541
542     /* delete it */
543     r = IPropertySetStorage_Delete( propset, &FMTID_SummaryInformation );
544     ok(r == STG_E_FILENOTFOUND, "deleted property set storage\n");
545
546     r = IPropertySetStorage_Open( propset, &FMTID_SummaryInformation, 
547                                 STGM_READ | STGM_SHARE_EXCLUSIVE, &ps );
548     ok(r == STG_E_FILENOTFOUND, "opened property set storage\n");
549
550     r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0,
551                                 STGM_READ | STGM_SHARE_EXCLUSIVE, &ps );
552     ok(r == STG_E_INVALIDFLAG, "created property set storage\n");
553
554     r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0,
555                                 STGM_READ, &ps );
556     ok(r == STG_E_INVALIDFLAG, "created property set storage\n");
557
558     r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0, 0, &ps );
559     ok(r == STG_E_INVALIDFLAG, "created property set storage\n");
560
561     r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0,
562                                 STGM_WRITE|STGM_SHARE_EXCLUSIVE, &ps );
563     ok(r == STG_E_INVALIDFLAG, "created property set storage\n");
564
565     r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0,
566                                 STGM_CREATE|STGM_WRITE|STGM_SHARE_EXCLUSIVE, &ps );
567     ok(r == STG_E_INVALIDFLAG, "created property set storage\n");
568
569     /* now try really creating a a property set */
570     r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0,
571                                 STGM_CREATE|STGM_READWRITE|STGM_SHARE_EXCLUSIVE, &ps );
572     ok(r == S_OK, "failed to create property set storage\n");
573
574     if( ps )
575         IPropertyStorage_Release(ps);
576
577     /* now try creating the same thing again */
578     r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0,
579                                 STGM_CREATE|STGM_READWRITE|STGM_SHARE_EXCLUSIVE, &ps );
580     ok(r == S_OK, "failed to create property set storage\n");
581     if( ps )
582         IPropertyStorage_Release(ps);
583
584     /* should be able to open it */
585     r = IPropertySetStorage_Open( propset, &FMTID_SummaryInformation, 
586             STGM_READWRITE|STGM_SHARE_EXCLUSIVE, &ps);
587     ok(r == S_OK, "open failed\n");
588     if(r == S_OK)
589         IPropertyStorage_Release(ps);
590
591     /* delete it */
592     r = IPropertySetStorage_Delete( propset, &FMTID_SummaryInformation );
593     ok(r == S_OK, "failed to delete property set storage\n");
594
595     /* try opening with an invalid FMTID */
596     r = IPropertySetStorage_Open( propset, NULL, 
597             STGM_READWRITE|STGM_SHARE_EXCLUSIVE, &ps);
598     ok(r == E_INVALIDARG, "open succeeded\n");
599     if(r == S_OK)
600         IPropertyStorage_Release(ps);
601
602     /* try a bad guid */
603     r = IPropertySetStorage_Open( propset, &IID_IStorage, 
604             STGM_READWRITE|STGM_SHARE_EXCLUSIVE, &ps);
605     ok(r == STG_E_FILENOTFOUND, "open succeeded\n");
606     if(r == S_OK)
607         IPropertyStorage_Release(ps);
608     
609
610     /* try some invalid flags */
611     r = IPropertySetStorage_Open( propset, &FMTID_SummaryInformation, 
612             STGM_CREATE | STGM_READWRITE|STGM_SHARE_EXCLUSIVE, &ps);
613     ok(r == STG_E_INVALIDFLAG, "open succeeded\n");
614     if(r == S_OK)
615         IPropertyStorage_Release(ps);
616
617     /* after deleting it, it should be gone */
618     r = IPropertySetStorage_Open( propset, &FMTID_SummaryInformation, 
619             STGM_READWRITE|STGM_SHARE_EXCLUSIVE, &ps);
620     ok(r == STG_E_FILENOTFOUND, "open failed\n");
621     if(r == S_OK)
622         IPropertyStorage_Release(ps);
623
624     r = IPropertySetStorage_Release( propset );
625     ok(r == 1, "ref count wrong\n");
626
627     r = IStorage_Release(stg);
628     ok(r == 0, "ref count wrong\n");
629
630     DeleteFileW(filename);
631 }
632
633 static void test_storage_refcount(void)
634 {
635     static const WCHAR szPrefix[] = { 's','t','g',0 };
636     static const WCHAR szDot[] = { '.',0 };
637     WCHAR filename[MAX_PATH];
638     IStorage *stg = NULL;
639     IStorage *stgprio = NULL;
640     HRESULT r;
641     IStream *stm = NULL;
642     static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 };
643     LARGE_INTEGER pos;
644     ULARGE_INTEGER upos;
645     STATSTG stat;
646     char buffer[10];
647
648     if(!GetTempFileNameW(szDot, szPrefix, 0, filename))
649         return;
650
651     DeleteFileW(filename);
652
653     /* create the file */
654     r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | 
655                             STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
656     ok(r==S_OK, "StgCreateDocfile failed\n");
657
658     r = WriteClassStg( stg, &test_stg_cls );
659     ok( r == S_OK, "WriteClassStg failed\n");
660
661     r = IStorage_Commit( stg, STGC_DEFAULT );
662     ok( r == S_OK, "IStorage_Commit failed\n");
663
664     /* now create a stream */
665     r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
666     ok(r==S_OK, "IStorage->CreateStream failed\n");
667
668     r = IStorage_Release( stg );
669     ok (r == 0, "storage not released\n");
670
671     pos.QuadPart = 0;
672     r = IStream_Seek( stm, pos, 0, &upos );
673     ok (r == STG_E_REVERTED, "seek should fail\n");
674
675     r = IStream_Stat( stm, &stat, STATFLAG_DEFAULT );
676     ok (r == STG_E_REVERTED, "stat should fail\n");
677
678     r = IStream_Write( stm, "Test string", strlen("Test string"), NULL);
679     ok (r == STG_E_REVERTED, "IStream_Write should return STG_E_REVERTED instead of 0x%08lx\n", r);
680
681     r = IStream_Read( stm, buffer, sizeof(buffer), NULL);
682     ok (r == STG_E_REVERTED, "IStream_Read should return STG_E_REVERTED instead of 0x%08lx\n", r);
683
684     r = IStream_Release(stm);
685     ok (r == 0, "stream not released\n");
686
687     /* tests that STGM_PRIORITY doesn't prevent readwrite access from other
688      * StgOpenStorage calls in transacted mode */
689     r = StgOpenStorage( filename, NULL, STGM_PRIORITY, NULL, 0, &stgprio);
690     ok(r==S_OK, "StgOpenStorage failed with error 0x%08lx\n", r);
691
692     todo_wine {
693     /* non-transacted mode read/write fails */
694     r = StgOpenStorage( filename, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg);
695     ok(r==STG_E_LOCKVIOLATION, "StgOpenStorage should return STG_E_LOCKVIOLATION instead of 0x%08lx\n", r);
696     }
697
698     /* non-transacted mode read-only succeeds */
699     r = StgOpenStorage( filename, NULL, STGM_SHARE_DENY_WRITE|STGM_READ, NULL, 0, &stg);
700     ok(r==S_OK, "StgOpenStorage failed with error 0x%08lx\n", r);
701     IStorage_Release(stg);
702
703     r = StgOpenStorage( filename, NULL, STGM_TRANSACTED|STGM_SHARE_DENY_WRITE|STGM_READWRITE, NULL, 0, &stg);
704     ok(r==S_OK, "StgOpenStorage failed with error 0x%08lx\n", r);
705     if(stg)
706     {
707         static const WCHAR stgname[] = { ' ',' ',' ','2','9',0 };
708         static const WCHAR stgname2[] = { 'C','V','_','i','e','w',0 };
709         static const WCHAR stmname2[] = { 'V','a','r','2','D','a','t','a',0 };
710         IStorage *stg2;
711         IStorage *stg3;
712         STATSTG statstg;
713
714         r = IStorage_Stat( stg, &statstg, STATFLAG_NONAME );
715         ok(r == S_OK, "Stat should have succeded instead of returning 0x%08lx\n", r);
716         ok(statstg.type == STGTY_STORAGE, "Statstg type should have been STGTY_STORAGE instead of %ld\n", statstg.type);
717         ok(U(statstg.cbSize).LowPart == 0, "Statstg cbSize.LowPart should have been 0 instead of %ld\n", U(statstg.cbSize).LowPart);
718         ok(U(statstg.cbSize).HighPart == 0, "Statstg cbSize.HighPart should have been 0 instead of %ld\n", U(statstg.cbSize).HighPart);
719         ok(statstg.grfMode == (STGM_TRANSACTED|STGM_SHARE_DENY_WRITE|STGM_READWRITE),
720             "Statstg grfMode should have been 0x10022 instead of 0x%lx\n", statstg.grfMode);
721         ok(statstg.grfLocksSupported == 0, "Statstg grfLocksSupported should have been 0 instead of %ld\n", statstg.grfLocksSupported);
722         ok(IsEqualCLSID(&statstg.clsid, &test_stg_cls), "Statstg clsid is not test_stg_cls\n");
723         ok(statstg.grfStateBits == 0, "Statstg grfStateBits should have been 0 instead of %ld\n", statstg.grfStateBits);
724         ok(statstg.reserved == 0, "Statstg reserved should have been 0 instead of %ld\n", statstg.reserved);
725
726         r = IStorage_CreateStorage( stg, stgname, STGM_SHARE_EXCLUSIVE, 0, 0, &stg2 );
727         ok(r == S_OK, "CreateStorage should have succeeded instead of returning 0x%08lx\n", r);
728
729         r = IStorage_Stat( stg2, &statstg, STATFLAG_DEFAULT );
730         ok(r == S_OK, "Stat should have succeded instead of returning 0x%08lx\n", r);
731         ok(!lstrcmpW(statstg.pwcsName, stgname),
732             "Statstg pwcsName should have been the name the storage was created with\n");
733         ok(statstg.type == STGTY_STORAGE, "Statstg type should have been STGTY_STORAGE instead of %ld\n", statstg.type);
734         ok(U(statstg.cbSize).LowPart == 0, "Statstg cbSize.LowPart should have been 0 instead of %ld\n", U(statstg.cbSize).LowPart);
735         ok(U(statstg.cbSize).HighPart == 0, "Statstg cbSize.HighPart should have been 0 instead of %ld\n", U(statstg.cbSize).HighPart);
736         ok(statstg.grfMode == STGM_SHARE_EXCLUSIVE,
737             "Statstg grfMode should have been STGM_SHARE_EXCLUSIVE instead of 0x%lx\n", statstg.grfMode);
738         ok(statstg.grfLocksSupported == 0, "Statstg grfLocksSupported should have been 0 instead of %ld\n", statstg.grfLocksSupported);
739         ok(IsEqualCLSID(&statstg.clsid, &CLSID_NULL), "Statstg clsid is not CLSID_NULL\n");
740         ok(statstg.grfStateBits == 0, "Statstg grfStateBits should have been 0 instead of %ld\n", statstg.grfStateBits);
741         ok(statstg.reserved == 0, "Statstg reserved should have been 0 instead of %ld\n", statstg.reserved);
742         CoTaskMemFree(statstg.pwcsName);
743
744         r = IStorage_CreateStorage( stg2, stgname2, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, 0, &stg3 );
745         ok(r == STG_E_ACCESSDENIED, "CreateStorage should have returned STG_E_ACCESSDENIED instead of 0x%08lx\n", r);
746
747         r = IStorage_CreateStream( stg2, stmname2, STGM_CREATE|STGM_SHARE_EXCLUSIVE, 0, 0, &stm );
748         ok(r == STG_E_ACCESSDENIED, "CreateStream should have returned STG_E_ACCESSDENIED instead of 0x%08lx\n", r);
749
750         IStorage_Release(stg2);
751
752         r = IStorage_Release(stg);
753         ok(r == 0, "wrong ref count\n");
754     }
755     IStorage_Release(stgprio);
756
757     DeleteFileW(filename);
758 }
759
760 START_TEST(storage32)
761 {
762     test_hglobal_storage_stat();
763     test_create_storage_modes();
764     test_storage_stream();
765     test_open_storage();
766     test_storage_suminfo();
767     test_storage_refcount();
768 }