ole32: Accept STGM_TRANSACTED with no share mode specified.
[wine/multimedia.git] / dlls / ole32 / tests / storage32.c
blobb5c93aefb2fc5d8a2decb6ab114e4bd22673ce39
1 /*
2 * Unit tests for OLE storage
4 * Copyright (c) 2004 Mike McCormack
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.
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.
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
21 #include <stdio.h>
23 #define COBJMACROS
24 #define NONAMELESSUNION
25 #define NONAMELESSSTRUCT
27 #include <windows.h>
28 #include "wine/test.h"
30 #include "ole2.h"
31 #include "objidl.h"
32 #include "initguid.h"
34 DEFINE_GUID( test_stg_cls, 0x88888888, 0x0425, 0x0000, 0,0,0,0,0,0,0,0);
36 #define ok_ole_success(hr, func) ok(hr == S_OK, func " failed with error 0x%08x\n", hr)
38 static CHAR filenameA[MAX_PATH];
39 static WCHAR filename[MAX_PATH];
41 static const char file1_nameA[] = {'c','o','p','y','t','e','s','t','A',0};
42 static const WCHAR file1_name[] = {'c','o','p','y','t','e','s','t','A',0};
43 static const char file2_nameA[] = {'c','o','p','y','t','e','s','t','B',0};
44 static const WCHAR file2_name[] = {'c','o','p','y','t','e','s','t','B',0};
45 static const WCHAR stgA_name[] = {'S','t','o','r','a','g','e','A',0};
46 static const WCHAR stgB_name[] = {'S','t','o','r','a','g','e','B',0};
47 static const WCHAR strmA_name[] = {'S','t','r','e','a','m','A',0};
48 static const WCHAR strmB_name[] = {'S','t','r','e','a','m','B',0};
49 static const WCHAR strmC_name[] = {'S','t','r','e','a','m','C',0};
51 /* Win9x and WinMe don't have lstrcmpW */
52 static int strcmp_ww(LPCWSTR strw1, LPCWSTR strw2)
54 CHAR stra1[512], stra2[512];
55 WideCharToMultiByte(CP_ACP, 0, strw1, -1, stra1, sizeof(stra1), NULL, NULL);
56 WideCharToMultiByte(CP_ACP, 0, strw2, -1, stra2, sizeof(stra2), NULL, NULL);
57 return lstrcmpA(stra1, stra2);
60 static void test_hglobal_storage_stat(void)
62 ILockBytes *ilb = NULL;
63 IStorage *stg = NULL;
64 HRESULT r;
65 STATSTG stat;
66 DWORD mode, refcount;
68 r = CreateILockBytesOnHGlobal( NULL, TRUE, &ilb );
69 ok( r == S_OK, "CreateILockBytesOnHGlobal failed\n");
71 r = StgIsStorageILockBytes( ilb );
72 ok( r == S_FALSE, "StgIsStorageILockBytes should have failed\n");
74 mode = STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE;/*0x1012*/
75 r = StgCreateDocfileOnILockBytes( ilb, mode, 0, &stg );
76 ok( r == S_OK, "StgCreateDocfileOnILockBytes failed\n");
78 r = WriteClassStg( stg, &test_stg_cls );
79 ok( r == S_OK, "WriteClassStg failed\n");
81 r = StgIsStorageILockBytes( ilb );
82 ok( r == S_OK, "StgIsStorageILockBytes failed\n");
84 memset( &stat, 0, sizeof stat );
85 r = IStorage_Stat( stg, &stat, 0 );
87 ok( stat.pwcsName == NULL, "storage name not null\n");
88 ok( stat.type == 1, "type is wrong\n");
89 ok( stat.grfMode == 0x12, "grf mode is incorrect\n");
90 ok( !memcmp(&stat.clsid, &test_stg_cls, sizeof test_stg_cls), "CLSID is wrong\n");
92 refcount = IStorage_Release( stg );
93 ok( refcount == 0, "IStorage refcount is wrong\n");
94 refcount = ILockBytes_Release( ilb );
95 ok( refcount == 0, "ILockBytes refcount is wrong\n");
98 static void test_create_storage_modes(void)
100 IStorage *stg = NULL;
101 HRESULT r;
103 DeleteFileA(filenameA);
105 /* test with some invalid parameters */
106 r = StgCreateDocfile( NULL, 0, 0, &stg);
107 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
108 r = StgCreateDocfile( filename, 0, 0, &stg);
109 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
110 r = StgCreateDocfile( filename, STGM_CREATE, 0, &stg);
111 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
112 r = StgCreateDocfile( filename, STGM_CREATE | STGM_READWRITE, 0, &stg);
113 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
114 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE, 0, &stg);
115 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
116 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, NULL);
117 ok(r==STG_E_INVALIDPOINTER, "StgCreateDocfile succeeded\n");
118 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 1, &stg);
119 ok(r==STG_E_INVALIDPARAMETER, "StgCreateDocfile succeeded\n");
120 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_DENY_WRITE | STGM_READWRITE, 0, &stg);
121 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
122 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READ, 0, &stg);
123 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
124 r = StgCreateDocfile( filename, STGM_PRIORITY, 0, &stg);
125 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
127 /* StgCreateDocfile seems to be very particular about the flags it accepts */
128 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED | STGM_WRITE, 0, &stg);
129 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
130 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED | 8, 0, &stg);
131 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
132 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED | 0x80, 0, &stg);
133 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
134 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED | 0x800, 0, &stg);
135 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
136 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED | 0x8000, 0, &stg);
137 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
138 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED | 0x80000, 0, &stg);
139 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
140 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED | 0x800000, 0, &stg);
141 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
142 ok(stg == NULL, "stg was set\n");
144 /* check what happens if the file already exists (which is how it's meant to be used) */
145 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &stg);
146 ok(r==S_OK, "StgCreateDocfile failed\n");
147 r = IStorage_Release(stg);
148 ok(r == 0, "storage not released\n");
149 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
150 ok(r==STG_E_FILEALREADYEXISTS, "StgCreateDocfile wrong error\n"); /* FAILIFTHERE is default */
151 r = StgCreateDocfile( filename, STGM_READ, 0, &stg);
152 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n"); /* need at least readmode and sharemode */
153 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE, 0, &stg);
154 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
155 r = StgCreateDocfile( filename, STGM_SHARE_DENY_WRITE, 0, &stg);
156 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
157 r = StgCreateDocfile( filename, STGM_SHARE_DENY_NONE, 0, &stg);
158 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile failed\n");
159 r = StgCreateDocfile( filename, STGM_SHARE_DENY_NONE | STGM_TRANSACTED, 0, &stg);
160 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile failed\n");
161 r = StgCreateDocfile( filename, STGM_SHARE_DENY_NONE | STGM_READWRITE, 0, &stg);
162 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile failed\n");
163 r = StgCreateDocfile( filename, STGM_SHARE_DENY_NONE | STGM_WRITE, 0, &stg);
164 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile failed\n");
165 r = StgCreateDocfile( filename, STGM_SHARE_DENY_WRITE | STGM_WRITE, 0, &stg);
166 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile failed\n");
167 r = StgCreateDocfile( filename, STGM_SHARE_DENY_WRITE | STGM_READ, 0, &stg);
168 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile wrong error\n");
169 r = StgCreateDocfile( filename, STGM_TRANSACTED | STGM_SHARE_DENY_WRITE | STGM_READ, 0, &stg);
170 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile wrong error\n");
171 ok(DeleteFileA(filenameA), "failed to delete file\n");
173 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
174 ok(r==S_OK, "StgCreateDocfile failed\n");
175 r = IStorage_Release(stg);
176 ok(r == 0, "storage not released\n");
177 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED |STGM_FAILIFTHERE, 0, &stg);
178 ok(r==STG_E_FILEALREADYEXISTS, "StgCreateDocfile wrong error\n");
179 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_WRITE, 0, &stg);
180 ok(r==STG_E_FILEALREADYEXISTS, "StgCreateDocfile wrong error\n");
182 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_DENY_WRITE | STGM_READWRITE, 0, &stg);
183 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
184 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
185 ok(r==S_OK, "StgCreateDocfile failed\n");
186 r = IStorage_Release(stg);
187 ok(r == 0, "storage not released\n");
188 ok(DeleteFileA(filenameA), "failed to delete file\n");
190 r = StgCreateDocfile( filename, STGM_CREATE | STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
191 ok(r==S_OK, "StgCreateDocfile failed\n");
192 r = IStorage_Release(stg);
193 ok(r == 0, "storage not released\n");
194 ok(DeleteFileA(filenameA), "failed to delete file\n");
196 /* test the way excel uses StgCreateDocFile */
197 r = StgCreateDocfile( filename, STGM_TRANSACTED|STGM_CREATE|STGM_SHARE_DENY_WRITE|STGM_READWRITE, 0, &stg);
198 ok(r==S_OK, "StgCreateDocfile the excel way failed\n");
199 if(r == S_OK)
201 r = IStorage_Release(stg);
202 ok(r == 0, "storage not released\n");
203 ok(DeleteFileA(filenameA), "failed to delete file\n");
206 /* and the way windows media uses it ... */
207 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_DENY_NONE | STGM_READWRITE | STGM_TRANSACTED, 0, &stg);
208 ok(r==S_OK, "StgCreateDocfile the windows media way failed\n");
209 if (r == S_OK)
211 r = IStorage_Release(stg);
212 ok(r == 0, "storage not released\n");
213 ok(DeleteFileA(filenameA), "failed to delete file\n");
216 /* looks like we need STGM_TRANSACTED or STGM_CREATE */
217 r = StgCreateDocfile( filename, STGM_TRANSACTED|STGM_SHARE_DENY_WRITE|STGM_READWRITE, 0, &stg);
218 ok(r==S_OK, "StgCreateDocfile the excel way failed\n");
219 if(r == S_OK)
221 r = IStorage_Release(stg);
222 ok(r == 0, "storage not released\n");
223 ok(DeleteFileA(filenameA), "failed to delete file\n");
226 r = StgCreateDocfile( filename, STGM_TRANSACTED|STGM_CREATE|STGM_SHARE_DENY_WRITE|STGM_WRITE, 0, &stg);
227 ok(r==S_OK, "StgCreateDocfile the excel way failed\n");
228 if(r == S_OK)
230 r = IStorage_Release(stg);
231 ok(r == 0, "storage not released\n");
232 ok(DeleteFileA(filenameA), "failed to delete file\n");
235 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &stg);
236 ok(r==S_OK, "StgCreateDocfile the powerpoint way failed\n");
237 if(r == S_OK)
239 r = IStorage_Release(stg);
240 ok(r == 0, "storage not released\n");
241 ok(DeleteFileA(filenameA), "failed to delete file\n");
244 /* test the way msi uses StgCreateDocfile */
245 r = StgCreateDocfile( filename, STGM_DIRECT | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &stg);
246 ok(r==S_OK, "StgCreateDocFile failed\n");
247 r = IStorage_Release(stg);
248 ok(r == 0, "storage not released\n");
249 ok(DeleteFileA(filenameA), "failed to delete file\n");
252 static void test_stgcreatestorageex(void)
254 HRESULT (WINAPI *pStgCreateStorageEx)(const WCHAR* pwcsName, DWORD grfMode, DWORD stgfmt, DWORD grfAttrs, STGOPTIONS* pStgOptions, void* reserved, REFIID riid, void** ppObjectOpen);
255 HMODULE hOle32 = GetModuleHandleA("ole32");
256 IStorage *stg = NULL;
257 STGOPTIONS stgoptions = {1, 0, 4096};
258 HRESULT r;
260 pStgCreateStorageEx = (void *) GetProcAddress(hOle32, "StgCreateStorageEx");
261 if (!pStgCreateStorageEx)
263 win_skip("skipping test on NT4\n");
264 return;
267 DeleteFileA(filenameA);
269 /* Verify that StgCreateStorageEx can accept an options param */
270 r = pStgCreateStorageEx( filename,
271 STGM_SHARE_EXCLUSIVE | STGM_READWRITE,
272 STGFMT_DOCFILE,
274 &stgoptions,
275 NULL,
276 &IID_IStorage,
277 (void **) &stg);
278 ok(r==S_OK || r==STG_E_UNIMPLEMENTEDFUNCTION, "StgCreateStorageEx with options failed\n");
279 if (r==STG_E_UNIMPLEMENTEDFUNCTION)
281 /* We're on win98 which means all bets are off. Let's get out of here. */
282 win_skip("skipping test on win9x\n");
283 return;
286 r = IStorage_Release(stg);
287 ok(r == 0, "storage not released\n");
288 ok(DeleteFileA(filenameA), "failed to delete file\n");
290 /* Verify that StgCreateStorageEx can accept a NULL pStgOptions */
291 r = pStgCreateStorageEx( filename,
292 STGM_SHARE_EXCLUSIVE | STGM_READWRITE,
293 STGFMT_STORAGE,
295 NULL,
296 NULL,
297 &IID_IStorage,
298 (void **) &stg);
299 ok(r==S_OK, "StgCreateStorageEx with NULL options failed\n");
300 r = IStorage_Release(stg);
301 ok(r == 0, "storage not released\n");
302 ok(DeleteFileA(filenameA), "failed to delete file\n");
305 static void test_storage_stream(void)
307 static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 };
308 static const WCHAR longname[] = {
309 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
310 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',0
312 IStorage *stg = NULL;
313 HRESULT r;
314 IStream *stm = NULL;
315 IStream *stm2 = NULL;
316 ULONG count = 0;
317 LARGE_INTEGER pos;
318 ULARGE_INTEGER p;
319 unsigned char buffer[0x100];
320 IUnknown *unk;
322 DeleteFileA(filenameA);
324 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
325 ok(r==S_OK, "StgCreateDocfile failed\n");
327 /* try create some invalid streams */
328 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 1, 0, &stm );
329 ok(r==STG_E_INVALIDPARAMETER, "IStorage->CreateStream wrong error\n");
330 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 1, &stm );
331 ok(r==STG_E_INVALIDPARAMETER, "IStorage->CreateStream wrong error\n");
332 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, NULL );
333 ok(r==STG_E_INVALIDPOINTER, "IStorage->CreateStream wrong error\n");
334 r = IStorage_CreateStream(stg, NULL, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
335 ok(r==STG_E_INVALIDNAME, "IStorage->CreateStream wrong error\n");
336 r = IStorage_CreateStream(stg, longname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
337 ok(r==STG_E_INVALIDNAME || broken(r==S_OK) /* nt4 */,
338 "IStorage->CreateStream wrong error, got %d GetLastError()=%d\n", r, GetLastError());
339 r = IStorage_CreateStream(stg, stmname, STGM_READWRITE, 0, 0, &stm );
340 ok(r==STG_E_INVALIDFLAG, "IStorage->CreateStream wrong error\n");
341 r = IStorage_CreateStream(stg, stmname, STGM_READ, 0, 0, &stm );
342 ok(r==STG_E_INVALIDFLAG, "IStorage->CreateStream wrong error\n");
343 r = IStorage_CreateStream(stg, stmname, STGM_WRITE, 0, 0, &stm );
344 ok(r==STG_E_INVALIDFLAG, "IStorage->CreateStream wrong error\n");
345 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_DENY_NONE | STGM_READWRITE, 0, 0, &stm );
346 ok(r==STG_E_INVALIDFLAG, "IStorage->CreateStream wrong error\n");
347 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_DENY_NONE | STGM_READ, 0, 0, &stm );
348 ok(r==STG_E_INVALIDFLAG, "IStorage->CreateStream wrong error\n");
350 /* now really create a stream and delete it */
351 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
352 ok(r==S_OK, "IStorage->CreateStream failed\n");
354 /* test for support interfaces */
355 r = IStream_QueryInterface(stm, &IID_IPersist, (void**)&unk);
356 ok(r==E_NOINTERFACE, "got 0x%08x\n", r);
357 r = IStream_QueryInterface(stm, &IID_IPersistStream, (void**)&unk);
358 ok(r==E_NOINTERFACE, "got 0x%08x\n", r);
360 r = IStream_Release(stm);
361 ok(r == 0, "wrong ref count\n");
362 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
363 ok(r==STG_E_FILEALREADYEXISTS, "IStorage->CreateStream failed\n");
364 r = IStorage_DestroyElement(stg,stmname);
365 ok(r==S_OK, "IStorage->DestroyElement failed\n");
367 /* create a stream and write to it */
368 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
369 ok(r==S_OK, "IStorage->CreateStream failed\n");
371 r = IStream_Clone(stm, &stm2);
372 ok(r==S_OK, "failed to clone stream\n");
374 r = IStream_Write(stm, NULL, 0, NULL );
375 ok(r==STG_E_INVALIDPOINTER, "IStream->Write wrong error\n");
376 r = IStream_Write(stm, "Hello\n", 0, NULL );
377 ok(r==S_OK, "failed to write stream\n");
378 r = IStream_Write(stm, "Hello\n", 0, &count );
379 ok(r==S_OK, "failed to write stream\n");
380 r = IStream_Write(stm, "Hello\n", 6, &count );
381 ok(r==S_OK, "failed to write stream\n");
382 r = IStream_Commit(stm, STGC_DEFAULT );
383 ok(r==S_OK, "failed to commit stream\n");
384 r = IStream_Commit(stm, STGC_DEFAULT );
385 ok(r==S_OK, "failed to commit stream\n");
387 /* Read past the end of the stream. */
388 pos.QuadPart = 3;
389 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p );
390 ok(r==S_OK, "failed to seek stream\n");
391 ok(p.QuadPart == 3, "at wrong place\n");
392 r = IStream_Read(stm, buffer, sizeof buffer, &count );
393 ok(r==S_OK, "failed to read\n");
394 ok(count == 3, "read bytes past end of stream\n");
395 pos.QuadPart = 10;
396 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p );
397 ok(r==S_OK, "failed to seek stream\n");
398 ok(p.QuadPart == 10, "at wrong place\n");
399 r = IStream_Read(stm, buffer, sizeof buffer, &count );
400 ok(r==S_OK, "failed to read\n");
401 ok(count == 0, "read bytes past end of stream\n");
402 pos.QuadPart = 10000;
403 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p );
404 ok(r==S_OK, "failed to seek stream\n");
405 ok(p.QuadPart == 10000, "at wrong place\n");
406 r = IStream_Read(stm, buffer, sizeof buffer, &count );
407 ok(r==S_OK, "failed to read\n");
408 ok(count == 0, "read bytes past end of stream\n");
410 /* Convert to a big block stream, and read past the end. */
411 p.QuadPart = 5000;
412 r = IStream_SetSize(stm,p);
413 ok(r==S_OK, "failed to set pos\n");
414 pos.QuadPart = 4997;
415 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p );
416 ok(r==S_OK, "failed to seek stream\n");
417 ok(p.QuadPart == 4997, "at wrong place\n");
418 r = IStream_Read(stm, buffer, sizeof buffer, &count );
419 ok(r==S_OK, "failed to read\n");
420 ok(count == 3, "read bytes past end of stream\n");
421 pos.QuadPart = 5001;
422 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p );
423 ok(r==S_OK, "failed to seek stream\n");
424 ok(p.QuadPart == 5001, "at wrong place\n");
425 r = IStream_Read(stm, buffer, sizeof buffer, &count );
426 ok(r==S_OK, "failed to read\n");
427 ok(count == 0, "read bytes past end of stream\n");
428 pos.QuadPart = 10000;
429 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p );
430 ok(r==S_OK, "failed to seek stream\n");
431 ok(p.QuadPart == 10000, "at wrong place\n");
432 r = IStream_Read(stm, buffer, sizeof buffer, &count );
433 ok(r==S_OK, "failed to read\n");
434 ok(count == 0, "read bytes past end of stream\n");
436 /* seek round a bit, reset the stream size */
437 pos.QuadPart = 0;
438 r = IStream_Seek(stm, pos, 3, &p );
439 ok(r==STG_E_INVALIDFUNCTION, "IStream->Seek returned wrong error\n");
440 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, NULL);
441 ok(r==S_OK, "failed to seek stream\n");
442 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p );
443 ok(r==S_OK, "failed to seek stream\n");
444 r = IStream_SetSize(stm,p);
445 ok(r==S_OK, "failed to set pos\n");
446 pos.QuadPart = 10;
447 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p );
448 ok(r==S_OK, "failed to seek stream\n");
449 ok(p.QuadPart == 10, "at wrong place\n");
450 r = IStream_Read(stm, buffer, sizeof buffer, &count );
451 ok(r==S_OK, "failed to set pos\n");
452 ok(count == 0, "read bytes from empty stream\n");
453 pos.QuadPart = 10000;
454 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p );
455 ok(r==S_OK, "failed to seek stream\n");
456 ok(p.QuadPart == 10000, "at wrong place\n");
457 r = IStream_Read(stm, buffer, sizeof buffer, &count );
458 ok(r==S_OK, "failed to set pos\n");
459 ok(count == 0, "read bytes from empty stream\n");
460 pos.QuadPart = 0;
461 r = IStream_Seek(stm, pos, STREAM_SEEK_END, &p );
462 ok(r==S_OK, "failed to seek stream\n");
463 ok(p.QuadPart == 0, "at wrong place\n");
464 r = IStream_Read(stm, buffer, sizeof buffer, &count );
465 ok(r==S_OK, "failed to set pos\n");
466 ok(count == 0, "read bytes from empty stream\n");
468 /* wrap up */
469 r = IStream_Release(stm2);
470 ok(r == 0, "wrong ref count\n");
472 /* create a stream and write to it */
473 r = IStorage_CreateStream(stg, stmname, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm2 );
474 ok(r==S_OK, "IStorage->CreateStream failed\n");
476 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p);
477 ok(r==STG_E_REVERTED, "overwritten stream should return STG_E_REVERTED instead of 0x%08x\n", r);
479 r = IStream_Release(stm2);
480 ok(r == 0, "wrong ref count\n");
481 r = IStream_Release(stm);
482 ok(r == 0, "wrong ref count\n");
484 r = IStorage_Release(stg);
485 ok(r == 0, "wrong ref count\n");
487 /* try create some invalid streams */
488 stg = NULL;
489 stm = NULL;
490 r = StgOpenStorage(filename, NULL, STGM_READ | STGM_SHARE_DENY_WRITE, NULL, 0, &stg);
491 ok(r == S_OK, "should succeed\n");
492 if (stg)
494 r = IStorage_OpenStream(stg, stmname, NULL, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &stm);
495 ok(r == STG_E_INVALIDFLAG, "IStorage->OpenStream should return STG_E_INVALIDFLAG instead of 0x%08x\n", r);
496 IStorage_Release(stg);
499 r = DeleteFileA(filenameA);
500 ok(r, "file should exist\n");
503 static BOOL touch_file(LPCSTR filename)
505 HANDLE file;
507 file = CreateFileA(filename, GENERIC_READ|GENERIC_WRITE, 0, NULL,
508 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
509 if (file==INVALID_HANDLE_VALUE)
510 return FALSE;
511 CloseHandle(file);
512 return TRUE;
515 static BOOL is_zero_length(LPCSTR filename)
517 HANDLE file;
518 DWORD len;
520 file = CreateFileA(filename, GENERIC_READ, 0, NULL,
521 OPEN_EXISTING, 0, NULL);
522 if (file==INVALID_HANDLE_VALUE)
523 return FALSE;
524 len = GetFileSize(file, NULL);
525 CloseHandle(file);
526 return len == 0;
529 static BOOL is_existing_file(LPCSTR filename)
531 HANDLE file;
533 file = CreateFileA(filename, GENERIC_READ, 0, NULL,
534 OPEN_EXISTING, 0, NULL);
535 if (file==INVALID_HANDLE_VALUE)
536 return FALSE;
537 CloseHandle(file);
538 return TRUE;
541 static void test_open_storage(void)
543 static const WCHAR szNonExist[] = { 'n','o','n','e','x','i','s','t',0 };
544 IStorage *stg = NULL, *stg2 = NULL;
545 HRESULT r;
546 DWORD stgm;
548 /* try opening a zero length file - it should stay zero length */
549 DeleteFileA(filenameA);
550 touch_file(filenameA);
551 stgm = STGM_NOSCRATCH | STGM_TRANSACTED | STGM_SHARE_DENY_WRITE | STGM_READWRITE;
552 r = StgOpenStorage( filename, NULL, stgm, NULL, 0, &stg);
553 ok(r==STG_E_FILEALREADYEXISTS, "StgOpenStorage didn't fail\n");
555 stgm = STGM_SHARE_EXCLUSIVE | STGM_READWRITE;
556 r = StgOpenStorage( filename, NULL, stgm, NULL, 0, &stg);
557 ok(r==STG_E_FILEALREADYEXISTS, "StgOpenStorage didn't fail\n");
558 ok(is_zero_length(filenameA), "file length changed\n");
560 DeleteFileA(filenameA);
562 /* try opening a nonexistent file - it should not create it */
563 stgm = STGM_DIRECT | STGM_SHARE_EXCLUSIVE | STGM_READWRITE;
564 r = StgOpenStorage( filename, NULL, stgm, NULL, 0, &stg);
565 ok(r!=S_OK, "StgOpenStorage failed: 0x%08x\n", r);
566 if (r==S_OK) IStorage_Release(stg);
567 ok(!is_existing_file(filenameA), "StgOpenStorage should not create a file\n");
568 DeleteFileA(filenameA);
570 /* create the file */
571 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
572 ok(r==S_OK, "StgCreateDocfile failed\n");
573 IStorage_Release(stg);
575 r = StgOpenStorage( filename, NULL, 0, NULL, 0, &stg);
576 ok(r==STG_E_INVALIDFLAG, "StgOpenStorage wrong error\n");
577 r = StgOpenStorage( NULL, NULL, STGM_SHARE_EXCLUSIVE, NULL, 0, &stg);
578 ok(r==STG_E_INVALIDNAME, "StgOpenStorage wrong error\n");
579 r = StgOpenStorage( filename, NULL, STGM_SHARE_EXCLUSIVE | STGM_READ, NULL, 0, NULL);
580 ok(r==STG_E_INVALIDPOINTER, "StgOpenStorage wrong error\n");
581 r = StgOpenStorage( filename, NULL, STGM_SHARE_EXCLUSIVE | STGM_READ, NULL, 1, &stg);
582 ok(r==STG_E_INVALIDPARAMETER, "StgOpenStorage wrong error\n");
583 r = StgOpenStorage( szNonExist, NULL, STGM_SHARE_EXCLUSIVE | STGM_READ, NULL, 0, &stg);
584 ok(r==STG_E_FILENOTFOUND, "StgOpenStorage failed\n");
585 r = StgOpenStorage( filename, NULL, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READ, NULL, 0, &stg);
586 ok(r==STG_E_INVALIDFLAG, "StgOpenStorage failed\n");
587 r = StgOpenStorage( filename, NULL, STGM_SHARE_DENY_NONE | STGM_READ, NULL, 0, &stg);
588 ok(r==STG_E_INVALIDFLAG, "StgOpenStorage failed\n");
589 r = StgOpenStorage( filename, NULL, STGM_SHARE_DENY_READ | STGM_READ, NULL, 0, &stg);
590 ok(r==STG_E_INVALIDFLAG, "StgOpenStorage failed\n");
591 r = StgOpenStorage( filename, NULL, STGM_SHARE_DENY_WRITE | STGM_READWRITE, NULL, 0, &stg);
592 ok(r==STG_E_INVALIDFLAG, "StgOpenStorage failed\n");
594 /* open it for real */
595 r = StgOpenStorage( filename, NULL, STGM_SHARE_DENY_NONE | STGM_READ | STGM_TRANSACTED, NULL, 0, &stg); /* XLViewer 97/2000 */
596 ok(r==S_OK, "StgOpenStorage failed\n");
597 if(stg)
599 r = IStorage_Release(stg);
600 ok(r == 0, "wrong ref count\n");
603 r = StgOpenStorage( filename, NULL, STGM_SHARE_DENY_WRITE | STGM_READ, NULL, 0, &stg);
604 ok(r==S_OK, "StgOpenStorage failed\n");
605 if(stg)
607 r = IStorage_Release(stg);
608 ok(r == 0, "wrong ref count\n");
611 /* test the way word opens its custom dictionary */
612 r = StgOpenStorage( filename, NULL, STGM_NOSCRATCH | STGM_TRANSACTED |
613 STGM_SHARE_DENY_WRITE | STGM_READWRITE, NULL, 0, &stg);
614 ok(r==S_OK, "StgOpenStorage failed\n");
615 if(stg)
617 r = IStorage_Release(stg);
618 ok(r == 0, "wrong ref count\n");
621 r = StgOpenStorage( filename, NULL, STGM_SHARE_EXCLUSIVE | STGM_READ, NULL, 0, &stg);
622 ok(r==S_OK, "StgOpenStorage failed\n");
623 r = StgOpenStorage( filename, NULL, STGM_SHARE_EXCLUSIVE | STGM_READ, NULL, 0, &stg2);
624 ok(r==STG_E_SHAREVIOLATION, "StgOpenStorage failed\n");
625 if(stg)
627 r = IStorage_Release(stg);
628 ok(r == 0, "wrong ref count\n");
631 /* now try write to a storage file we opened read-only */
632 r = StgOpenStorage( filename, NULL, STGM_SHARE_EXCLUSIVE | STGM_READ, NULL, 0, &stg);
633 ok(r==S_OK, "StgOpenStorage failed\n");
634 if(stg)
636 static const WCHAR stmname[] = { 'w','i','n','e','t','e','s','t',0};
637 IStream *stm = NULL;
638 IStorage *stg2 = NULL;
640 r = IStorage_CreateStream( stg, stmname, STGM_WRITE | STGM_SHARE_EXCLUSIVE,
641 0, 0, &stm );
642 ok(r == STG_E_ACCESSDENIED, "CreateStream should fail\n");
643 r = IStorage_CreateStorage( stg, stmname, STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg2);
644 ok(r == STG_E_ACCESSDENIED, "CreateStream should fail\n");
646 r = IStorage_Release(stg);
647 ok(r == 0, "wrong ref count\n");
650 /* open like visio 2003 */
651 stg = NULL;
652 r = StgOpenStorage( filename, NULL, STGM_PRIORITY | STGM_SHARE_DENY_NONE, NULL, 0, &stg);
653 ok(r == S_OK, "should succeed\n");
654 if (stg)
655 IStorage_Release(stg);
657 /* test other sharing modes with STGM_PRIORITY */
658 stg = NULL;
659 r = StgOpenStorage( filename, NULL, STGM_PRIORITY | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg);
660 ok(r == S_OK, "should succeed\n");
661 if (stg)
662 IStorage_Release(stg);
664 stg = NULL;
665 r = StgOpenStorage( filename, NULL, STGM_PRIORITY | STGM_SHARE_DENY_WRITE, NULL, 0, &stg);
666 ok(r == S_OK, "should succeed\n");
667 if (stg)
668 IStorage_Release(stg);
670 stg = NULL;
671 r = StgOpenStorage( filename, NULL, STGM_PRIORITY | STGM_SHARE_DENY_READ, NULL, 0, &stg);
672 ok(r == S_OK, "should succeed\n");
673 if (stg)
674 IStorage_Release(stg);
676 /* open like Project 2003 */
677 stg = NULL;
678 r = StgOpenStorage( filename, NULL, STGM_PRIORITY, NULL, 0, &stg);
679 ok(r == S_OK, "should succeed\n");
680 r = StgOpenStorage( filename, NULL, STGM_PRIORITY, NULL, 0, &stg2);
681 ok(r == S_OK, "should succeed\n");
682 if (stg2)
683 IStorage_Release(stg2);
684 if (stg)
685 IStorage_Release(stg);
687 stg = NULL;
688 r = StgOpenStorage( filename, NULL, STGM_PRIORITY | STGM_READWRITE, NULL, 0, &stg);
689 ok(r == STG_E_INVALIDFLAG, "should fail\n");
691 r = StgOpenStorage( filename, NULL, STGM_TRANSACTED | STGM_PRIORITY, NULL, 0, &stg);
692 ok(r == STG_E_INVALIDFLAG, "should fail\n");
694 r = StgOpenStorage( filename, NULL, STGM_SIMPLE | STGM_PRIORITY, NULL, 0, &stg);
695 ok(r == STG_E_INVALIDFLAG, "should fail\n");
697 r = StgOpenStorage( filename, NULL, STGM_DELETEONRELEASE | STGM_PRIORITY, NULL, 0, &stg);
698 ok(r == STG_E_INVALIDFUNCTION, "should fail\n");
700 r = StgOpenStorage( filename, NULL, STGM_NOSCRATCH | STGM_PRIORITY, NULL, 0, &stg);
701 ok(r == STG_E_INVALIDFLAG, "should fail\n");
703 r = StgOpenStorage( filename, NULL, STGM_NOSNAPSHOT | STGM_PRIORITY, NULL, 0, &stg);
704 ok(r == STG_E_INVALIDFLAG, "should fail\n");
706 r = DeleteFileA(filenameA);
707 ok(r, "file didn't exist\n");
710 static void test_storage_suminfo(void)
712 IStorage *stg = NULL;
713 IPropertySetStorage *propset = NULL;
714 IPropertyStorage *ps = NULL;
715 HRESULT r;
717 DeleteFileA(filenameA);
719 /* create the file */
720 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
721 STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
722 ok(r==S_OK, "StgCreateDocfile failed\n");
724 r = IStorage_QueryInterface( stg, &IID_IPropertySetStorage, (LPVOID) &propset );
725 ok(r == S_OK, "query interface failed\n");
727 /* delete it */
728 r = IPropertySetStorage_Delete( propset, &FMTID_SummaryInformation );
729 ok(r == STG_E_FILENOTFOUND, "deleted property set storage\n");
731 r = IPropertySetStorage_Open( propset, &FMTID_SummaryInformation,
732 STGM_READ | STGM_SHARE_EXCLUSIVE, &ps );
733 ok(r == STG_E_FILENOTFOUND, "opened property set storage\n");
735 r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0,
736 STGM_READ | STGM_SHARE_EXCLUSIVE, &ps );
737 ok(r == STG_E_INVALIDFLAG, "created property set storage\n");
739 r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0,
740 STGM_READ, &ps );
741 ok(r == STG_E_INVALIDFLAG, "created property set storage\n");
743 r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0, 0, &ps );
744 ok(r == STG_E_INVALIDFLAG, "created property set storage\n");
746 r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0,
747 STGM_WRITE|STGM_SHARE_EXCLUSIVE, &ps );
748 ok(r == STG_E_INVALIDFLAG, "created property set storage\n");
750 r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0,
751 STGM_CREATE|STGM_WRITE|STGM_SHARE_EXCLUSIVE, &ps );
752 ok(r == STG_E_INVALIDFLAG, "created property set storage\n");
754 /* now try really creating a property set */
755 r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0,
756 STGM_CREATE|STGM_READWRITE|STGM_SHARE_EXCLUSIVE, &ps );
757 ok(r == S_OK, "failed to create property set storage\n");
759 if( ps )
760 IPropertyStorage_Release(ps);
762 /* now try creating the same thing again */
763 r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0,
764 STGM_CREATE|STGM_READWRITE|STGM_SHARE_EXCLUSIVE, &ps );
765 ok(r == S_OK, "failed to create property set storage\n");
766 if( ps )
767 IPropertyStorage_Release(ps);
769 /* should be able to open it */
770 r = IPropertySetStorage_Open( propset, &FMTID_SummaryInformation,
771 STGM_READWRITE|STGM_SHARE_EXCLUSIVE, &ps);
772 ok(r == S_OK, "open failed\n");
773 if(r == S_OK)
774 IPropertyStorage_Release(ps);
776 /* delete it */
777 r = IPropertySetStorage_Delete( propset, &FMTID_SummaryInformation );
778 ok(r == S_OK, "failed to delete property set storage\n");
780 /* try opening with an invalid FMTID */
781 r = IPropertySetStorage_Open( propset, NULL,
782 STGM_READWRITE|STGM_SHARE_EXCLUSIVE, &ps);
783 ok(r == E_INVALIDARG, "open succeeded\n");
784 if(r == S_OK)
785 IPropertyStorage_Release(ps);
787 /* try a bad guid */
788 r = IPropertySetStorage_Open( propset, &IID_IStorage,
789 STGM_READWRITE|STGM_SHARE_EXCLUSIVE, &ps);
790 ok(r == STG_E_FILENOTFOUND, "open succeeded\n");
791 if(r == S_OK)
792 IPropertyStorage_Release(ps);
795 /* try some invalid flags */
796 r = IPropertySetStorage_Open( propset, &FMTID_SummaryInformation,
797 STGM_CREATE | STGM_READWRITE|STGM_SHARE_EXCLUSIVE, &ps);
798 ok(r == STG_E_INVALIDFLAG, "open succeeded\n");
799 if(r == S_OK)
800 IPropertyStorage_Release(ps);
802 /* after deleting it, it should be gone */
803 r = IPropertySetStorage_Open( propset, &FMTID_SummaryInformation,
804 STGM_READWRITE|STGM_SHARE_EXCLUSIVE, &ps);
805 ok(r == STG_E_FILENOTFOUND, "open failed\n");
806 if(r == S_OK)
807 IPropertyStorage_Release(ps);
809 r = IPropertySetStorage_Release( propset );
810 ok(r == 1, "ref count wrong\n");
812 r = IStorage_Release(stg);
813 ok(r == 0, "ref count wrong\n");
815 DeleteFileA(filenameA);
818 static void test_storage_refcount(void)
820 IStorage *stg = NULL;
821 IStorage *stgprio = NULL;
822 HRESULT r;
823 IStream *stm = NULL;
824 static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 };
825 LARGE_INTEGER pos;
826 ULARGE_INTEGER upos;
827 STATSTG stat;
828 char buffer[10];
830 DeleteFileA(filenameA);
832 /* create the file */
833 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
834 STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
835 ok(r==S_OK, "StgCreateDocfile failed\n");
837 r = WriteClassStg( stg, &test_stg_cls );
838 ok( r == S_OK, "WriteClassStg failed\n");
840 r = IStorage_Commit( stg, STGC_DEFAULT );
841 ok( r == S_OK, "IStorage_Commit failed\n");
843 /* now create a stream */
844 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
845 ok(r==S_OK, "IStorage->CreateStream failed\n");
847 r = IStorage_Release( stg );
848 ok (r == 0, "storage not released\n");
850 pos.QuadPart = 0;
851 r = IStream_Seek( stm, pos, 0, &upos );
852 ok (r == STG_E_REVERTED, "seek should fail\n");
854 r = IStream_Stat( stm, &stat, STATFLAG_DEFAULT );
855 ok (r == STG_E_REVERTED, "stat should fail\n");
857 r = IStream_Write( stm, "Test string", strlen("Test string"), NULL);
858 ok (r == STG_E_REVERTED, "IStream_Write should return STG_E_REVERTED instead of 0x%08x\n", r);
860 r = IStream_Read( stm, buffer, sizeof(buffer), NULL);
861 ok (r == STG_E_REVERTED, "IStream_Read should return STG_E_REVERTED instead of 0x%08x\n", r);
863 r = IStream_Release(stm);
864 ok (r == 0, "stream not released\n");
866 /* tests that STGM_PRIORITY doesn't prevent readwrite access from other
867 * StgOpenStorage calls in transacted mode */
868 r = StgOpenStorage( filename, NULL, STGM_PRIORITY, NULL, 0, &stgprio);
869 ok(r==S_OK, "StgOpenStorage failed with error 0x%08x\n", r);
871 /* non-transacted mode read/write fails */
872 r = StgOpenStorage( filename, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg);
873 ok(r==STG_E_LOCKVIOLATION, "StgOpenStorage should return STG_E_LOCKVIOLATION instead of 0x%08x\n", r);
875 /* non-transacted mode read-only succeeds */
876 r = StgOpenStorage( filename, NULL, STGM_SHARE_DENY_WRITE|STGM_READ, NULL, 0, &stg);
877 ok(r==S_OK, "StgOpenStorage failed with error 0x%08x\n", r);
878 IStorage_Release(stg);
880 r = StgOpenStorage( filename, NULL, STGM_TRANSACTED|STGM_SHARE_DENY_WRITE|STGM_READWRITE, NULL, 0, &stg);
881 ok(r==S_OK, "StgOpenStorage failed with error 0x%08x\n", r);
882 if(stg)
884 static const WCHAR stgname[] = { ' ',' ',' ','2','9',0 };
885 static const WCHAR stgname2[] = { 'C','V','_','i','e','w',0 };
886 static const WCHAR stmname2[] = { 'V','a','r','2','D','a','t','a',0 };
887 IStorage *stg2;
888 IStorage *stg3;
889 STATSTG statstg;
891 r = IStorage_Stat( stg, &statstg, STATFLAG_NONAME );
892 ok(r == S_OK, "Stat should have succeeded instead of returning 0x%08x\n", r);
893 ok(statstg.type == STGTY_STORAGE, "Statstg type should have been STGTY_STORAGE instead of %d\n", statstg.type);
894 ok(U(statstg.cbSize).LowPart == 0, "Statstg cbSize.LowPart should have been 0 instead of %d\n", U(statstg.cbSize).LowPart);
895 ok(U(statstg.cbSize).HighPart == 0, "Statstg cbSize.HighPart should have been 0 instead of %d\n", U(statstg.cbSize).HighPart);
896 ok(statstg.grfMode == (STGM_TRANSACTED|STGM_SHARE_DENY_WRITE|STGM_READWRITE),
897 "Statstg grfMode should have been 0x10022 instead of 0x%x\n", statstg.grfMode);
898 ok(statstg.grfLocksSupported == 0, "Statstg grfLocksSupported should have been 0 instead of %d\n", statstg.grfLocksSupported);
899 ok(IsEqualCLSID(&statstg.clsid, &test_stg_cls), "Statstg clsid is not test_stg_cls\n");
900 ok(statstg.grfStateBits == 0, "Statstg grfStateBits should have been 0 instead of %d\n", statstg.grfStateBits);
901 ok(statstg.reserved == 0, "Statstg reserved should have been 0 instead of %d\n", statstg.reserved);
903 r = IStorage_CreateStorage( stg, stgname, STGM_SHARE_EXCLUSIVE, 0, 0, &stg2 );
904 ok(r == S_OK, "CreateStorage should have succeeded instead of returning 0x%08x\n", r);
906 r = IStorage_Stat( stg2, &statstg, STATFLAG_DEFAULT );
907 ok(r == S_OK, "Stat should have succeeded instead of returning 0x%08x\n", r);
908 ok(!memcmp(statstg.pwcsName, stgname, sizeof(stgname)),
909 "Statstg pwcsName should have been the name the storage was created with\n");
910 ok(statstg.type == STGTY_STORAGE, "Statstg type should have been STGTY_STORAGE instead of %d\n", statstg.type);
911 ok(U(statstg.cbSize).LowPart == 0, "Statstg cbSize.LowPart should have been 0 instead of %d\n", U(statstg.cbSize).LowPart);
912 ok(U(statstg.cbSize).HighPart == 0, "Statstg cbSize.HighPart should have been 0 instead of %d\n", U(statstg.cbSize).HighPart);
913 ok(statstg.grfMode == STGM_SHARE_EXCLUSIVE,
914 "Statstg grfMode should have been STGM_SHARE_EXCLUSIVE instead of 0x%x\n", statstg.grfMode);
915 ok(statstg.grfLocksSupported == 0, "Statstg grfLocksSupported should have been 0 instead of %d\n", statstg.grfLocksSupported);
916 ok(IsEqualCLSID(&statstg.clsid, &CLSID_NULL), "Statstg clsid is not CLSID_NULL\n");
917 ok(statstg.grfStateBits == 0, "Statstg grfStateBits should have been 0 instead of %d\n", statstg.grfStateBits);
918 ok(statstg.reserved == 0, "Statstg reserved should have been 0 instead of %d\n", statstg.reserved);
919 CoTaskMemFree(statstg.pwcsName);
921 r = IStorage_CreateStorage( stg2, stgname2, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, 0, &stg3 );
922 ok(r == STG_E_ACCESSDENIED, "CreateStorage should have returned STG_E_ACCESSDENIED instead of 0x%08x\n", r);
924 r = IStorage_CreateStream( stg2, stmname2, STGM_CREATE|STGM_SHARE_EXCLUSIVE, 0, 0, &stm );
925 ok(r == STG_E_ACCESSDENIED, "CreateStream should have returned STG_E_ACCESSDENIED instead of 0x%08x\n", r);
927 IStorage_Release(stg2);
929 r = IStorage_Release(stg);
930 ok(r == 0, "wrong ref count\n");
933 /* Multiple STGM_PRIORITY opens are possible. */
934 r = StgOpenStorage( filename, NULL, STGM_PRIORITY, NULL, 0, &stg);
935 ok(r==S_OK, "StgOpenStorage failed with error 0x%08x\n", r);
936 if(stg)
938 r = IStorage_Release(stg);
939 ok(r == 0, "wrong ref count\n");
942 r = StgOpenStorage( NULL, stgprio, STGM_TRANSACTED|STGM_SHARE_DENY_WRITE|STGM_READWRITE, NULL, 0, &stg);
943 ok(r==S_OK, "StgOpenStorage failed with error 0x%08x\n", r);
944 if(stg)
946 static const WCHAR stgname[] = { ' ',' ',' ','2','9',0 };
947 IStorage *stg2;
948 STATSTG statstg;
950 r = IStorage_Stat( stg, &statstg, STATFLAG_NONAME );
951 ok(r == S_OK, "Stat should have succeeded instead of returning 0x%08x\n", r);
952 ok(statstg.type == STGTY_STORAGE, "Statstg type should have been STGTY_STORAGE instead of %d\n", statstg.type);
953 ok(U(statstg.cbSize).LowPart == 0, "Statstg cbSize.LowPart should have been 0 instead of %d\n", U(statstg.cbSize).LowPart);
954 ok(U(statstg.cbSize).HighPart == 0, "Statstg cbSize.HighPart should have been 0 instead of %d\n", U(statstg.cbSize).HighPart);
955 ok(statstg.grfMode == (STGM_TRANSACTED|STGM_SHARE_DENY_WRITE|STGM_READWRITE),
956 "Statstg grfMode should have been 0x10022 instead of 0x%x\n", statstg.grfMode);
957 ok(statstg.grfLocksSupported == 0, "Statstg grfLocksSupported should have been 0 instead of %d\n", statstg.grfLocksSupported);
958 ok(IsEqualCLSID(&statstg.clsid, &test_stg_cls), "Statstg clsid is not test_stg_cls\n");
959 ok(statstg.grfStateBits == 0, "Statstg grfStateBits should have been 0 instead of %d\n", statstg.grfStateBits);
960 ok(statstg.reserved == 0, "Statstg reserved should have been 0 instead of %d\n", statstg.reserved);
962 r = IStorage_CreateStorage( stg, stgname, STGM_SHARE_EXCLUSIVE, 0, 0, &stg2 );
963 ok(r == S_OK, "CreateStorage should have succeeded instead of returning 0x%08x\n", r);
965 IStorage_Release(stg2);
967 r = IStorage_Commit( stg, 0 );
968 ok(r == S_OK, "Commit should have succeeded instead of returning 0x%08x\n", r);
970 r = IStorage_Release(stg);
971 ok(r == 0, "wrong ref count\n");
973 /* IStorage_Release(stgprio) not necessary because StgOpenStorage released it. */
975 DeleteFileA(filenameA);
978 static void test_writeclassstg(void)
980 IStorage *stg = NULL;
981 HRESULT r;
982 CLSID temp_cls;
984 DeleteFileA(filenameA);
986 /* create the file */
987 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
988 STGM_READWRITE, 0, &stg);
989 ok(r==S_OK, "StgCreateDocfile failed\n");
991 r = ReadClassStg( NULL, NULL );
992 ok(r == E_INVALIDARG, "ReadClassStg should return E_INVALIDARG instead of 0x%08X\n", r);
994 r = ReadClassStg( stg, NULL );
995 ok(r == E_INVALIDARG, "ReadClassStg should return E_INVALIDARG instead of 0x%08X\n", r);
997 temp_cls.Data1 = 0xdeadbeef;
998 r = ReadClassStg( stg, &temp_cls );
999 ok(r == S_OK, "ReadClassStg failed with 0x%08X\n", r);
1001 ok(IsEqualCLSID(&temp_cls, &CLSID_NULL), "ReadClassStg returned wrong clsid\n");
1003 r = WriteClassStg( NULL, NULL );
1004 ok(r == E_INVALIDARG, "WriteClassStg should return E_INVALIDARG instead of 0x%08X\n", r);
1006 r = WriteClassStg( stg, NULL );
1007 ok(r == STG_E_INVALIDPOINTER, "WriteClassStg should return STG_E_INVALIDPOINTER instead of 0x%08X\n", r);
1009 r = WriteClassStg( stg, &test_stg_cls );
1010 ok( r == S_OK, "WriteClassStg failed with 0x%08X\n", r);
1012 r = ReadClassStg( stg, &temp_cls );
1013 ok( r == S_OK, "ReadClassStg failed with 0x%08X\n", r);
1014 ok(IsEqualCLSID(&temp_cls, &test_stg_cls), "ReadClassStg returned wrong clsid\n");
1016 r = IStorage_Release( stg );
1017 ok (r == 0, "storage not released\n");
1019 DeleteFileA(filenameA);
1022 static void test_streamenum(void)
1024 IStorage *stg = NULL;
1025 HRESULT r;
1026 IStream *stm = NULL;
1027 static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 };
1028 static const WCHAR stmname2[] = { 'A','B','C','D','E','F','G','H','I',0 };
1029 static const WCHAR stmname3[] = { 'A','B','C','D','E','F','G','H','I','J',0 };
1030 STATSTG stat;
1031 IEnumSTATSTG *ee = NULL;
1032 ULONG count;
1034 DeleteFileA(filenameA);
1036 /* create the file */
1037 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
1038 STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
1039 ok(r==S_OK, "StgCreateDocfile failed\n");
1041 r = WriteClassStg( stg, &test_stg_cls );
1042 ok( r == S_OK, "WriteClassStg failed\n");
1044 r = IStorage_Commit( stg, STGC_DEFAULT );
1045 ok( r == S_OK, "IStorage_Commit failed\n");
1047 /* now create a stream */
1048 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1049 ok(r==S_OK, "IStorage->CreateStream failed\n");
1051 r = IStream_Release(stm);
1053 /* first enum ... should be 1 stream */
1054 r = IStorage_EnumElements(stg, 0, NULL, 0, &ee);
1055 ok(r==S_OK, "IStorage->EnumElements failed\n");
1057 count = 0xf00;
1058 r = IEnumSTATSTG_Next(ee, 1, &stat, &count);
1059 ok(r==S_OK, "IEnumSTATSTG->Next failed\n");
1060 ok(count == 1, "count wrong\n");
1062 if (r == S_OK)
1063 CoTaskMemFree(stat.pwcsName);
1065 r = IEnumSTATSTG_Release(ee);
1066 ok(r==S_OK, "EnumSTATSTG_Release failed with error 0x%08x\n", r);
1068 /* second enum... destroy the stream before reading */
1069 r = IStorage_EnumElements(stg, 0, NULL, 0, &ee);
1070 ok(r==S_OK, "IStorage->EnumElements failed\n");
1072 r = IStorage_DestroyElement(stg, stmname);
1073 ok(r==S_OK, "IStorage->DestroyElement failed\n");
1075 count = 0xf00;
1076 r = IEnumSTATSTG_Next(ee, 1, &stat, &count);
1077 ok(r==S_FALSE, "IEnumSTATSTG->Next failed\n");
1078 ok(count == 0, "count wrong\n");
1080 /* reset and try again */
1081 r = IEnumSTATSTG_Reset(ee);
1082 ok(r==S_OK, "IEnumSTATSTG->Reset failed\n");
1084 count = 0xf00;
1085 r = IEnumSTATSTG_Next(ee, 1, &stat, &count);
1086 ok(r==S_FALSE, "IEnumSTATSTG->Next failed\n");
1087 ok(count == 0, "count wrong\n");
1089 /* add a stream before reading */
1090 r = IEnumSTATSTG_Reset(ee);
1091 ok(r==S_OK, "IEnumSTATSTG->Reset failed\n");
1093 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1094 ok(r==S_OK, "IStorage->CreateStream failed\n");
1096 r = IStream_Release(stm);
1097 ok(r==S_OK, "Stream_Release failed with error 0x%08x\n", r);
1099 count = 0xf00;
1100 r = IEnumSTATSTG_Next(ee, 1, &stat, &count);
1101 ok(r==S_OK, "IEnumSTATSTG->Next failed\n");
1102 ok(count == 1, "count wrong\n");
1104 if (r == S_OK)
1106 ok(lstrcmpiW(stat.pwcsName, stmname) == 0, "expected CONTENTS, got %s\n", wine_dbgstr_w(stat.pwcsName));
1107 CoTaskMemFree(stat.pwcsName);
1110 r = IStorage_CreateStream(stg, stmname2, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1111 ok(r==S_OK, "IStorage->CreateStream failed\n");
1113 r = IStream_Release(stm);
1114 ok(r==S_OK, "Stream_Release failed with error 0x%08x\n", r);
1116 count = 0xf00;
1117 r = IEnumSTATSTG_Next(ee, 1, &stat, &count);
1118 ok(r==S_OK, "IEnumSTATSTG->Next failed\n");
1119 ok(count == 1, "count wrong\n");
1121 if (r == S_OK)
1123 ok(lstrcmpiW(stat.pwcsName, stmname2) == 0, "expected ABCDEFGHI, got %s\n", wine_dbgstr_w(stat.pwcsName));
1124 CoTaskMemFree(stat.pwcsName);
1127 /* delete previous and next stream after reading */
1128 r = IStorage_CreateStream(stg, stmname3, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1129 ok(r==S_OK, "IStorage->CreateStream failed\n");
1131 r = IStream_Release(stm);
1132 ok(r==S_OK, "Stream_Release failed with error 0x%08x\n", r);
1134 r = IEnumSTATSTG_Reset(ee);
1135 ok(r==S_OK, "IEnumSTATSTG->Reset failed\n");
1137 count = 0xf00;
1138 r = IEnumSTATSTG_Next(ee, 1, &stat, &count);
1139 ok(r==S_OK, "IEnumSTATSTG->Next failed\n");
1140 ok(count == 1, "count wrong\n");
1142 if (r == S_OK)
1144 ok(lstrcmpiW(stat.pwcsName, stmname) == 0, "expected CONTENTS, got %s\n", wine_dbgstr_w(stat.pwcsName));
1145 CoTaskMemFree(stat.pwcsName);
1148 r = IStorage_DestroyElement(stg, stmname);
1149 ok(r==S_OK, "IStorage->DestroyElement failed\n");
1151 r = IStorage_DestroyElement(stg, stmname2);
1152 ok(r==S_OK, "IStorage->DestroyElement failed\n");
1154 count = 0xf00;
1155 r = IEnumSTATSTG_Next(ee, 1, &stat, &count);
1156 ok(r==S_OK, "IEnumSTATSTG->Next failed\n");
1157 ok(count == 1, "count wrong\n");
1159 if (r == S_OK)
1161 ok(lstrcmpiW(stat.pwcsName, stmname3) == 0, "expected ABCDEFGHIJ, got %s\n", wine_dbgstr_w(stat.pwcsName));
1162 CoTaskMemFree(stat.pwcsName);
1165 r = IStorage_Release( stg );
1166 todo_wine ok (r == 0, "storage not released\n");
1168 /* enumerator is still valid and working after the storage is released */
1169 r = IEnumSTATSTG_Reset(ee);
1170 ok(r==S_OK, "IEnumSTATSTG->Reset failed\n");
1172 count = 0xf00;
1173 r = IEnumSTATSTG_Next(ee, 1, &stat, &count);
1174 ok(r==S_OK, "IEnumSTATSTG->Next failed\n");
1175 ok(count == 1, "count wrong\n");
1177 if (r == S_OK)
1179 ok(lstrcmpiW(stat.pwcsName, stmname3) == 0, "expected ABCDEFGHIJ, got %s\n", wine_dbgstr_w(stat.pwcsName));
1180 CoTaskMemFree(stat.pwcsName);
1183 /* the storage is left open until the enumerator is freed */
1184 r = StgOpenStorage( filename, NULL, STGM_SHARE_EXCLUSIVE |
1185 STGM_READWRITE |STGM_TRANSACTED, NULL, 0, &stg);
1186 ok(r==STG_E_SHAREVIOLATION ||
1187 r==STG_E_LOCKVIOLATION, /* XP-SP2/W2K3-SP1 and below */
1188 "StgCreateDocfile failed, res=%x\n", r);
1190 r = IEnumSTATSTG_Release(ee);
1191 ok (r == 0, "enum not released\n");
1193 DeleteFileA(filenameA);
1196 static void test_transact(void)
1198 IStorage *stg = NULL, *stg2 = NULL, *stg3 = NULL;
1199 HRESULT r;
1200 IStream *stm = NULL;
1201 static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 };
1202 static const WCHAR stmname2[] = { 'F','O','O',0 };
1203 static const WCHAR stgname[] = { 'P','E','R','M','S','T','G',0 };
1204 static const WCHAR stgname2[] = { 'T','E','M','P','S','T','G',0 };
1206 DeleteFileA(filenameA);
1208 /* create the file */
1209 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
1210 STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
1211 ok(r==S_OK, "StgCreateDocfile failed\n");
1213 /* commit a new stream and storage */
1214 r = IStorage_CreateStream(stg, stmname2, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1215 ok(r==S_OK, "IStorage->CreateStream failed\n");
1217 r = IStream_Write(stm, "this is stream 1\n", 16, NULL);
1218 ok(r==S_OK, "IStream->Write failed\n");
1220 IStream_Release(stm);
1222 r = IStorage_CreateStorage(stg, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg2);
1223 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1225 if (r == S_OK)
1227 /* Create two substorages but only commit one */
1228 r = IStorage_CreateStorage(stg2, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg3);
1229 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1231 if (r == S_OK)
1232 IStorage_Release(stg3);
1234 r = IStorage_Commit(stg, 0);
1235 ok(r==S_OK, "IStorage->Commit failed\n");
1237 r = IStorage_CreateStorage(stg2, stgname2, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg3);
1238 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1240 if (r == S_OK)
1241 IStorage_Release(stg3);
1243 IStorage_Release(stg2);
1246 /* now create a stream and storage, but don't commit them */
1247 stm = NULL;
1248 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1249 ok(r==S_OK, "IStorage->CreateStream failed\n");
1251 r = IStream_Write(stm, "this is stream 2\n", 16, NULL);
1252 ok(r==S_OK, "IStream->Write failed\n");
1254 /* IStream::Commit does nothing for OLE storage streams */
1255 r = IStream_Commit(stm, STGC_ONLYIFCURRENT | STGC_DANGEROUSLYCOMMITMERELYTODISKCACHE);
1256 ok(r==S_OK, "IStream->Commit failed\n");
1258 r = IStorage_CreateStorage(stg, stgname2, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg2);
1259 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1261 if (r == S_OK)
1262 IStorage_Release(stg2);
1264 IStream_Release(stm);
1266 IStorage_Release(stg);
1268 stm = NULL;
1269 stg = NULL;
1270 r = StgOpenStorage( filename, NULL, STGM_SHARE_DENY_NONE | STGM_READ | STGM_TRANSACTED, NULL, 0, &stg);
1271 ok(r==S_OK, "StgOpenStorage failed\n");
1273 if (!stg)
1274 return;
1276 r = IStorage_OpenStream(stg, stmname, NULL, STGM_SHARE_DENY_NONE|STGM_READ, 0, &stm );
1277 ok(r==STG_E_INVALIDFLAG, "IStorage->OpenStream failed %08x\n", r);
1279 r = IStorage_OpenStream(stg, stmname, NULL, STGM_DELETEONRELEASE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
1280 ok(r==STG_E_INVALIDFUNCTION, "IStorage->OpenStream failed %08x\n", r);
1282 r = IStorage_OpenStream(stg, stmname, NULL, STGM_TRANSACTED|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
1283 ok(r==STG_E_INVALIDFUNCTION, "IStorage->OpenStream failed %08x\n", r);
1285 r = IStorage_OpenStorage(stg, stmname, NULL, STGM_TRANSACTED|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg2 );
1286 ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStream failed %08x\n", r);
1288 r = IStorage_OpenStream(stg, stmname, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
1289 ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStream should fail %08x\n", r);
1290 if (r == S_OK)
1291 IStream_Release(stm);
1293 r = IStorage_OpenStorage(stg, stgname2, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg2 );
1294 ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStorage should fail %08x\n", r);
1295 if (r == S_OK)
1296 IStorage_Release(stg2);
1298 r = IStorage_OpenStorage(stg, stmname2, NULL, STGM_TRANSACTED|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg2 );
1299 ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStream failed %08x\n", r);
1301 r = IStorage_OpenStream(stg, stmname2, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
1302 ok(r==S_OK, "IStorage->OpenStream should succeed %08x\n", r);
1303 if (r == S_OK)
1304 IStream_Release(stm);
1306 r = IStorage_OpenStorage(stg, stgname, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg2 );
1307 ok(r==S_OK, "IStorage->OpenStorage should succeed %08x\n", r);
1308 if (r == S_OK)
1310 r = IStorage_OpenStorage(stg2, stgname, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg3 );
1311 ok(r==S_OK, "IStorage->OpenStorage should succeed %08x\n", r);
1312 if (r == S_OK)
1313 IStorage_Release(stg3);
1315 r = IStorage_OpenStorage(stg2, stgname2, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg3 );
1316 ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStorage should fail %08x\n", r);
1317 if (r == S_OK)
1318 IStorage_Release(stg3);
1320 IStorage_Release(stg2);
1323 IStorage_Release(stg);
1325 r = DeleteFileA(filenameA);
1326 ok( r == TRUE, "deleted file\n");
1329 static void test_substorage_share(void)
1331 IStorage *stg, *stg2, *stg3;
1332 IStream *stm, *stm2;
1333 HRESULT r;
1334 static const WCHAR stgname[] = { 'P','E','R','M','S','T','G',0 };
1335 static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 };
1336 static const WCHAR othername[] = { 'N','E','W','N','A','M','E',0 };
1338 DeleteFileA(filenameA);
1340 /* create the file */
1341 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
1342 STGM_READWRITE, 0, &stg);
1343 ok(r==S_OK, "StgCreateDocfile failed\n");
1345 /* create a read/write storage and try to open it again */
1346 r = IStorage_CreateStorage(stg, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg2);
1347 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1349 if (r == S_OK)
1351 r = IStorage_OpenStorage(stg, stgname, NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg3);
1352 ok(r==STG_E_ACCESSDENIED, "IStorage->OpenStorage should fail %08x\n", r);
1354 if (r == S_OK)
1355 IStorage_Release(stg3);
1357 r = IStorage_OpenStorage(stg, stgname, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, 0, &stg3);
1358 ok(r==STG_E_ACCESSDENIED, "IStorage->OpenStorage should fail %08x\n", r);
1360 if (r == S_OK)
1361 IStorage_Release(stg3);
1363 /* cannot rename the storage while it's open */
1364 r = IStorage_RenameElement(stg, stgname, othername);
1365 ok(r==STG_E_ACCESSDENIED, "IStorage->RenameElement should fail %08x\n", r);
1366 if (SUCCEEDED(r)) IStorage_RenameElement(stg, othername, stgname);
1368 /* destroying an object while it's open invalidates it */
1369 r = IStorage_DestroyElement(stg, stgname);
1370 ok(r==S_OK, "IStorage->DestroyElement failed, hr=%08x\n", r);
1372 r = IStorage_CreateStream(stg2, stmname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm);
1373 ok(r==STG_E_REVERTED, "IStorage->CreateStream failed, hr=%08x\n", r);
1375 if (r == S_OK)
1376 IStream_Release(stm);
1378 IStorage_Release(stg2);
1381 /* create a read/write stream and try to open it again */
1382 r = IStorage_CreateStream(stg, stmname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm);
1383 ok(r==S_OK, "IStorage->CreateStream failed, hr=%08x\n", r);
1385 if (r == S_OK)
1387 r = IStorage_OpenStream(stg, stmname, NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &stm2);
1388 ok(r==STG_E_ACCESSDENIED, "IStorage->OpenStream should fail %08x\n", r);
1390 if (r == S_OK)
1391 IStream_Release(stm2);
1393 r = IStorage_OpenStream(stg, stmname, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm2);
1394 ok(r==STG_E_ACCESSDENIED, "IStorage->OpenStream should fail %08x\n", r);
1396 if (r == S_OK)
1397 IStream_Release(stm2);
1399 /* cannot rename the stream while it's open */
1400 r = IStorage_RenameElement(stg, stmname, othername);
1401 ok(r==STG_E_ACCESSDENIED, "IStorage->RenameElement should fail %08x\n", r);
1402 if (SUCCEEDED(r)) IStorage_RenameElement(stg, othername, stmname);
1404 /* destroying an object while it's open invalidates it */
1405 r = IStorage_DestroyElement(stg, stmname);
1406 ok(r==S_OK, "IStorage->DestroyElement failed, hr=%08x\n", r);
1408 r = IStream_Write(stm, "this shouldn't work\n", 20, NULL);
1409 ok(r==STG_E_REVERTED, "IStream_Write should fail %08x\n", r);
1411 IStream_Release(stm);
1414 IStorage_Release(stg);
1416 r = DeleteFileA(filenameA);
1417 ok( r == TRUE, "deleted file\n");
1420 static void test_revert(void)
1422 IStorage *stg = NULL, *stg2 = NULL, *stg3 = NULL;
1423 HRESULT r;
1424 IStream *stm = NULL, *stm2 = NULL;
1425 static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 };
1426 static const WCHAR stmname2[] = { 'F','O','O',0 };
1427 static const WCHAR stgname[] = { 'P','E','R','M','S','T','G',0 };
1428 static const WCHAR stgname2[] = { 'T','E','M','P','S','T','G',0 };
1429 STATSTG statstg;
1431 DeleteFileA(filenameA);
1433 /* create the file */
1434 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
1435 STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
1436 ok(r==S_OK, "StgCreateDocfile failed\n");
1438 /* commit a new stream and storage */
1439 r = IStorage_CreateStream(stg, stmname2, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1440 ok(r==S_OK, "IStorage->CreateStream failed\n");
1442 r = IStream_Write(stm, "this is stream 1\n", 16, NULL);
1443 ok(r==S_OK, "IStream->Write failed\n");
1445 r = IStorage_CreateStorage(stg, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg2);
1446 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1448 if (r == S_OK)
1450 /* Create two substorages but only commit one */
1451 r = IStorage_CreateStorage(stg2, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg3);
1452 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1454 if (r == S_OK)
1455 IStorage_Release(stg3);
1457 r = IStorage_Commit(stg, 0);
1458 ok(r==S_OK, "IStorage->Commit failed\n");
1460 r = IStorage_CreateStorage(stg2, stgname2, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg3);
1461 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1463 if (r == S_OK)
1464 IStorage_Release(stg3);
1467 /* now create a stream and storage, then revert */
1468 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm2 );
1469 ok(r==S_OK, "IStorage->CreateStream failed\n");
1471 r = IStream_Write(stm2, "this is stream 2\n", 16, NULL);
1472 ok(r==S_OK, "IStream->Write failed\n");
1474 r = IStorage_CreateStorage(stg, stgname2, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg3);
1475 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1477 r = IStorage_Revert(stg);
1478 ok(r==S_OK, "Storage_Revert failed with error 0x%08x\n", r);
1480 /* all open objects become invalid */
1481 r = IStream_Write(stm, "this shouldn't work\n", 20, NULL);
1482 ok(r==STG_E_REVERTED, "IStream_Write should fail %08x\n", r);
1484 r = IStream_Write(stm2, "this shouldn't work\n", 20, NULL);
1485 ok(r==STG_E_REVERTED, "IStream_Write should fail %08x\n", r);
1487 r = IStorage_Stat(stg2, &statstg, STATFLAG_NONAME);
1488 ok(r==STG_E_REVERTED, "IStorage_Stat should fail %08x\n", r);
1490 r = IStorage_Stat(stg3, &statstg, STATFLAG_NONAME);
1491 ok(r==STG_E_REVERTED, "IStorage_Stat should fail %08x\n", r);
1493 IStream_Release(stm);
1494 IStream_Release(stm2);
1495 IStorage_Release(stg2);
1496 IStorage_Release(stg3);
1498 r = IStorage_OpenStream(stg, stmname, NULL, STGM_SHARE_DENY_NONE|STGM_READ, 0, &stm );
1499 ok(r==STG_E_INVALIDFLAG, "IStorage->OpenStream failed %08x\n", r);
1501 r = IStorage_OpenStream(stg, stmname, NULL, STGM_DELETEONRELEASE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
1502 ok(r==STG_E_INVALIDFUNCTION, "IStorage->OpenStream failed %08x\n", r);
1504 r = IStorage_OpenStream(stg, stmname, NULL, STGM_TRANSACTED|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
1505 ok(r==STG_E_INVALIDFUNCTION, "IStorage->OpenStream failed %08x\n", r);
1507 r = IStorage_OpenStorage(stg, stmname, NULL, STGM_TRANSACTED|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg2 );
1508 ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStream failed %08x\n", r);
1510 r = IStorage_OpenStream(stg, stmname, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
1511 ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStream should fail %08x\n", r);
1512 if (r == S_OK)
1513 IStream_Release(stm);
1515 r = IStorage_OpenStorage(stg, stgname2, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg2 );
1516 ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStorage should fail %08x\n", r);
1517 if (r == S_OK)
1518 IStorage_Release(stg2);
1520 r = IStorage_OpenStorage(stg, stmname2, NULL, STGM_TRANSACTED|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg2 );
1521 ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStream failed %08x\n", r);
1523 r = IStorage_OpenStream(stg, stmname2, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
1524 ok(r==S_OK, "IStorage->OpenStream should succeed %08x\n", r);
1525 if (r == S_OK)
1526 IStream_Release(stm);
1528 r = IStorage_OpenStorage(stg, stgname, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg2 );
1529 ok(r==S_OK, "IStorage->OpenStorage should succeed %08x\n", r);
1530 if (r == S_OK)
1532 r = IStorage_OpenStorage(stg2, stgname, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg3 );
1533 ok(r==S_OK, "IStorage->OpenStorage should succeed %08x\n", r);
1534 if (r == S_OK)
1535 IStorage_Release(stg3);
1537 r = IStorage_OpenStorage(stg2, stgname2, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg3 );
1538 ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStorage should fail %08x\n", r);
1539 if (r == S_OK)
1540 IStorage_Release(stg3);
1542 IStorage_Release(stg2);
1545 IStorage_Release(stg);
1547 r = DeleteFileA(filenameA);
1548 ok( r == TRUE, "deleted file\n");
1550 /* Revert only invalidates objects in transacted mode */
1551 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
1552 STGM_READWRITE, 0, &stg);
1553 ok(r==S_OK, "StgCreateDocfile failed\n");
1555 r = IStorage_CreateStream(stg, stmname2, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1556 ok(r==S_OK, "IStorage->CreateStream failed\n");
1558 r = IStorage_Revert(stg);
1559 ok(r==S_OK, "IStorage->Revert failed %08x\n", r);
1561 r = IStream_Write(stm, "this works\n", 11, NULL);
1562 ok(r==S_OK, "IStream_Write should succeed %08x\n", r);
1564 IStream_Release(stm);
1565 IStorage_Release(stg);
1567 r = DeleteFileA(filenameA);
1568 ok( r == TRUE, "deleted file\n");
1571 static void test_parent_free(void)
1573 IStorage *stg = NULL, *stg2 = NULL, *stg3 = NULL;
1574 HRESULT r;
1575 IStream *stm = NULL;
1576 static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 };
1577 static const WCHAR stgname[] = { 'P','E','R','M','S','T','G',0 };
1578 ULONG ref;
1579 STATSTG statstg;
1581 DeleteFileA(filenameA);
1583 /* create the file */
1584 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
1585 STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
1586 ok(r==S_OK, "StgCreateDocfile failed\n");
1588 /* create a new storage */
1589 r = IStorage_CreateStorage(stg, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg2);
1590 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1592 if (r == S_OK)
1594 /* now create a stream inside the new storage */
1595 r = IStorage_CreateStream(stg2, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1596 ok(r==S_OK, "IStorage->CreateStream failed\n");
1598 if (r == S_OK)
1600 /* create a storage inside the new storage */
1601 r = IStorage_CreateStorage(stg2, stgname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stg3 );
1602 ok(r==S_OK, "IStorage->CreateStorage failed\n");
1605 /* free the parent */
1606 ref = IStorage_Release(stg2);
1607 ok(ref == 0, "IStorage still has %u references\n", ref);
1609 /* child objects are invalid */
1610 if (r == S_OK)
1612 r = IStream_Write(stm, "this should fail\n", 17, NULL);
1613 ok(r==STG_E_REVERTED, "IStream->Write should fail, hr=%x\n", r);
1615 IStream_Release(stm);
1617 r = IStorage_Stat(stg3, &statstg, STATFLAG_NONAME);
1618 ok(r==STG_E_REVERTED, "IStorage_Stat should fail %08x\n", r);
1620 r = IStorage_SetStateBits(stg3, 1, 1);
1621 ok(r==STG_E_REVERTED, "IStorage_Stat should fail %08x\n", r);
1623 IStorage_Release(stg3);
1627 IStorage_Release(stg);
1629 r = DeleteFileA(filenameA);
1630 ok( r == TRUE, "deleted file\n");
1633 static void test_nonroot_transacted(void)
1635 IStorage *stg = NULL, *stg2 = NULL, *stg3 = NULL;
1636 HRESULT r;
1637 IStream *stm = NULL;
1638 static const WCHAR stgname[] = { 'P','E','R','M','S','T','G',0 };
1639 static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 };
1640 static const WCHAR stmname2[] = { 'F','O','O',0 };
1642 DeleteFileA(filenameA);
1644 /* create a transacted file */
1645 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
1646 STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
1647 ok(r==S_OK, "StgCreateDocfile failed\n");
1649 /* create a transacted substorage */
1650 r = IStorage_CreateStorage(stg, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_TRANSACTED, 0, 0, &stg2);
1651 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1653 if (r == S_OK)
1655 /* create and commit stmname */
1656 r = IStorage_CreateStream(stg2, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1657 ok(r==S_OK, "IStorage->CreateStream failed\n");
1658 if (r == S_OK)
1659 IStream_Release(stm);
1661 IStorage_Commit(stg2, 0);
1663 /* create and revert stmname2 */
1664 r = IStorage_CreateStream(stg2, stmname2, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1665 ok(r==S_OK, "IStorage->CreateStream failed\n");
1666 if (r == S_OK)
1667 IStream_Release(stm);
1669 IStorage_Revert(stg2);
1671 /* check that Commit and Revert really worked */
1672 r = IStorage_OpenStream(stg2, stmname, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
1673 ok(r==S_OK, "IStorage->OpenStream should succeed %08x\n", r);
1674 if (r == S_OK)
1675 IStream_Release(stm);
1677 r = IStorage_OpenStream(stg2, stmname2, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
1678 ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStream should fail %08x\n", r);
1679 if (r == S_OK)
1680 IStream_Release(stm);
1682 IStorage_Release(stg2);
1685 /* create a read-only transacted substorage */
1686 r = IStorage_OpenStorage(stg, stgname, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE | STGM_TRANSACTED, NULL, 0, &stg2);
1687 ok(r==S_OK, "IStorage->OpenStorage failed, hr=%08x\n", r);
1689 if (r == S_OK)
1691 /* The storage can be modified. */
1692 r = IStorage_CreateStorage(stg2, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg3);
1693 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1694 if (r == S_OK)
1695 IStorage_Release(stg3);
1697 /* But changes cannot be committed. */
1698 r = IStorage_Commit(stg2, 0);
1699 ok(r==STG_E_ACCESSDENIED, "IStorage->Commit should fail, hr=%08x\n", r);
1701 IStorage_Release(stg2);
1704 IStorage_Release(stg);
1706 /* create a non-transacted file */
1707 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
1708 STGM_READWRITE, 0, &stg);
1709 ok(r==S_OK, "StgCreateDocfile failed\n");
1711 /* create a transacted substorage */
1712 r = IStorage_CreateStorage(stg, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_TRANSACTED, 0, 0, &stg2);
1713 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1715 if (r == S_OK)
1717 /* create and commit stmname */
1718 r = IStorage_CreateStream(stg2, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1719 ok(r==S_OK, "IStorage->CreateStream failed\n");
1720 if (r == S_OK)
1721 IStream_Release(stm);
1723 IStorage_Commit(stg2, 0);
1725 /* create and revert stmname2 */
1726 r = IStorage_CreateStream(stg2, stmname2, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1727 ok(r==S_OK, "IStorage->CreateStream failed\n");
1728 if (r == S_OK)
1729 IStream_Release(stm);
1731 IStorage_Revert(stg2);
1733 /* check that Commit and Revert really worked */
1734 r = IStorage_OpenStream(stg2, stmname, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
1735 ok(r==S_OK, "IStorage->OpenStream should succeed %08x\n", r);
1736 if (r == S_OK)
1737 IStream_Release(stm);
1739 r = IStorage_OpenStream(stg2, stmname2, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
1740 ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStream should fail %08x\n", r);
1741 if (r == S_OK)
1742 IStream_Release(stm);
1744 IStorage_Release(stg2);
1747 IStorage_Release(stg);
1749 r = DeleteFileA(filenameA);
1750 ok( r == TRUE, "deleted file\n");
1753 static void test_ReadClassStm(void)
1755 CLSID clsid;
1756 HRESULT hr;
1757 IStream *pStream;
1758 static const LARGE_INTEGER llZero;
1760 hr = ReadClassStm(NULL, &clsid);
1761 ok(hr == E_INVALIDARG, "ReadClassStm should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1763 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1764 ok_ole_success(hr, "CreateStreamOnHGlobal");
1765 hr = WriteClassStm(pStream, &test_stg_cls);
1766 ok_ole_success(hr, "WriteClassStm");
1768 hr = ReadClassStm(pStream, NULL);
1769 ok(hr == E_INVALIDARG, "ReadClassStm should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1771 /* test not rewound stream */
1772 hr = ReadClassStm(pStream, &clsid);
1773 ok(hr == STG_E_READFAULT, "ReadClassStm should have returned STG_E_READFAULT instead of 0x%08x\n", hr);
1774 ok(IsEqualCLSID(&clsid, &CLSID_NULL), "clsid should have been zeroed\n");
1776 hr = IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1777 ok_ole_success(hr, "IStream_Seek");
1778 hr = ReadClassStm(pStream, &clsid);
1779 ok_ole_success(hr, "ReadClassStm");
1780 ok(IsEqualCLSID(&clsid, &test_stg_cls), "clsid should have been set to CLSID_WineTest\n");
1782 IStream_Release(pStream);
1785 struct access_res
1787 BOOL gothandle;
1788 DWORD lasterr;
1789 BOOL ignore;
1792 static const struct access_res create[16] =
1794 { TRUE, ERROR_SUCCESS, TRUE },
1795 { TRUE, ERROR_SUCCESS, TRUE },
1796 { TRUE, ERROR_SUCCESS, FALSE },
1797 { TRUE, ERROR_SUCCESS, FALSE },
1798 { FALSE, ERROR_SHARING_VIOLATION, FALSE },
1799 { FALSE, ERROR_SHARING_VIOLATION, FALSE },
1800 { FALSE, ERROR_SHARING_VIOLATION, FALSE },
1801 { TRUE, ERROR_SUCCESS, FALSE },
1802 { FALSE, ERROR_SHARING_VIOLATION, FALSE },
1803 { FALSE, ERROR_SHARING_VIOLATION, FALSE },
1804 { FALSE, ERROR_SHARING_VIOLATION, FALSE },
1805 { TRUE, ERROR_SUCCESS, TRUE },
1806 { FALSE, ERROR_SHARING_VIOLATION, FALSE },
1807 { FALSE, ERROR_SHARING_VIOLATION, FALSE },
1808 { FALSE, ERROR_SHARING_VIOLATION, FALSE },
1809 { TRUE, ERROR_SUCCESS, TRUE }
1812 static const struct access_res create_commit[16] =
1814 { TRUE, ERROR_SUCCESS, TRUE },
1815 { TRUE, ERROR_SUCCESS, TRUE },
1816 { TRUE, ERROR_SUCCESS, FALSE },
1817 { TRUE, ERROR_SUCCESS, FALSE },
1818 { FALSE, ERROR_SHARING_VIOLATION, FALSE },
1819 { FALSE, ERROR_SHARING_VIOLATION, FALSE },
1820 { FALSE, ERROR_SHARING_VIOLATION, FALSE },
1821 { TRUE, ERROR_SUCCESS, FALSE },
1822 { FALSE, ERROR_SHARING_VIOLATION, FALSE },
1823 { FALSE, ERROR_SHARING_VIOLATION, FALSE },
1824 { FALSE, ERROR_SHARING_VIOLATION, FALSE },
1825 { TRUE, ERROR_SUCCESS, TRUE },
1826 { FALSE, ERROR_SHARING_VIOLATION, FALSE },
1827 { FALSE, ERROR_SHARING_VIOLATION, FALSE },
1828 { FALSE, ERROR_SHARING_VIOLATION, FALSE },
1829 { TRUE, ERROR_SUCCESS, TRUE }
1832 static const struct access_res create_close[16] =
1834 { TRUE, ERROR_SUCCESS, FALSE },
1835 { TRUE, ERROR_SUCCESS, FALSE },
1836 { TRUE, ERROR_SUCCESS, FALSE },
1837 { TRUE, ERROR_SUCCESS, FALSE },
1838 { TRUE, ERROR_SUCCESS, FALSE },
1839 { TRUE, ERROR_SUCCESS, FALSE },
1840 { TRUE, ERROR_SUCCESS, FALSE },
1841 { TRUE, ERROR_SUCCESS, FALSE },
1842 { TRUE, ERROR_SUCCESS, FALSE },
1843 { TRUE, ERROR_SUCCESS, FALSE },
1844 { TRUE, ERROR_SUCCESS, FALSE },
1845 { TRUE, ERROR_SUCCESS, FALSE },
1846 { TRUE, ERROR_SUCCESS, FALSE },
1847 { TRUE, ERROR_SUCCESS, FALSE },
1848 { TRUE, ERROR_SUCCESS, FALSE },
1849 { TRUE, ERROR_SUCCESS }
1852 static const DWORD access_modes[4] = {
1854 GENERIC_READ,
1855 GENERIC_WRITE,
1856 GENERIC_READ | GENERIC_WRITE
1859 static const DWORD share_modes[4] = {
1861 FILE_SHARE_READ,
1862 FILE_SHARE_WRITE,
1863 FILE_SHARE_READ | FILE_SHARE_WRITE
1866 static void _test_file_access(LPCSTR file, const struct access_res *ares, DWORD line)
1868 int i, j, idx = 0;
1870 for (i = 0; i < sizeof(access_modes)/sizeof(access_modes[0]); i++)
1872 for (j = 0; j < sizeof(share_modes)/sizeof(share_modes[0]); j++)
1874 DWORD lasterr;
1875 HANDLE hfile;
1877 if (ares[idx].ignore)
1878 continue;
1880 SetLastError(0xdeadbeef);
1881 hfile = CreateFileA(file, access_modes[i], share_modes[j], NULL, OPEN_EXISTING,
1882 FILE_ATTRIBUTE_NORMAL, 0);
1883 lasterr = GetLastError();
1885 ok((hfile != INVALID_HANDLE_VALUE) == ares[idx].gothandle,
1886 "(%d, handle, %d): Expected %d, got %d\n",
1887 line, idx, ares[idx].gothandle,
1888 (hfile != INVALID_HANDLE_VALUE));
1890 ok(lasterr == ares[idx].lasterr ||
1891 broken(lasterr == 0xdeadbeef) /* win9x */,
1892 "(%d, lasterr, %d): Expected %d, got %d\n",
1893 line, idx, ares[idx].lasterr, lasterr);
1895 CloseHandle(hfile);
1896 idx++;
1901 #define test_file_access(file, ares) _test_file_access(file, ares, __LINE__)
1903 static void test_access(void)
1905 static const WCHAR fileW[] = {'w','i','n','e','t','e','s','t',0};
1906 static const char fileA[] = "winetest";
1907 IStorage *stg;
1908 HRESULT hr;
1910 /* STGM_TRANSACTED */
1911 hr = StgCreateDocfile(fileW, STGM_CREATE | STGM_READWRITE |
1912 STGM_SHARE_EXCLUSIVE | STGM_TRANSACTED, 0, &stg);
1913 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1915 test_file_access(fileA, create);
1917 hr = IStorage_Commit(stg, STGC_DEFAULT);
1918 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1920 test_file_access(fileA, create_commit);
1922 IStorage_Release(stg);
1924 test_file_access(fileA, create_close);
1926 DeleteFileA(fileA);
1928 /* STGM_DIRECT */
1929 hr = StgCreateDocfile(fileW, STGM_CREATE | STGM_READWRITE |
1930 STGM_SHARE_EXCLUSIVE | STGM_DIRECT, 0, &stg);
1931 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1933 test_file_access(fileA, create);
1935 hr = IStorage_Commit(stg, STGC_DEFAULT);
1936 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1938 test_file_access(fileA, create_commit);
1940 IStorage_Release(stg);
1942 test_file_access(fileA, create_close);
1944 DeleteFileA(fileA);
1946 /* STGM_SHARE_DENY_NONE */
1947 hr = StgCreateDocfile(fileW, STGM_CREATE | STGM_READWRITE |
1948 STGM_SHARE_DENY_NONE | STGM_TRANSACTED, 0, &stg);
1949 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1951 test_file_access(fileA, create);
1953 hr = IStorage_Commit(stg, STGC_DEFAULT);
1954 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1956 test_file_access(fileA, create_commit);
1958 IStorage_Release(stg);
1960 test_file_access(fileA, create_close);
1962 DeleteFileA(fileA);
1964 /* STGM_SHARE_DENY_READ */
1965 hr = StgCreateDocfile(fileW, STGM_CREATE | STGM_READWRITE |
1966 STGM_SHARE_DENY_READ | STGM_TRANSACTED, 0, &stg);
1967 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1969 test_file_access(fileA, create);
1971 hr = IStorage_Commit(stg, STGC_DEFAULT);
1972 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1974 test_file_access(fileA, create_commit);
1976 IStorage_Release(stg);
1978 test_file_access(fileA, create_close);
1980 DeleteFileA(fileA);
1982 /* STGM_SHARE_DENY_WRITE */
1983 hr = StgCreateDocfile(fileW, STGM_CREATE | STGM_READWRITE |
1984 STGM_SHARE_DENY_WRITE | STGM_TRANSACTED, 0, &stg);
1985 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1987 test_file_access(fileA, create);
1989 hr = IStorage_Commit(stg, STGC_DEFAULT);
1990 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1992 test_file_access(fileA, create_commit);
1994 IStorage_Release(stg);
1996 test_file_access(fileA, create_close);
1998 DeleteFileA(fileA);
2000 /* STGM_DIRECT_SWMR | STGM_READ | STGM_SHARE_DENY_NONE - reader mode for direct SWMR mode */
2001 hr = StgCreateDocfile(fileW, STGM_CREATE | STGM_READWRITE | STGM_SHARE_DENY_WRITE | STGM_TRANSACTED, 0, &stg);
2002 ok(hr == S_OK, "got %08x\n", hr);
2003 IStorage_Release(stg);
2005 hr = StgOpenStorage(fileW, NULL, STGM_DIRECT_SWMR | STGM_READ | STGM_SHARE_DENY_NONE, NULL, 0, &stg);
2006 ok(hr == S_OK || broken(hr == STG_E_INVALIDFLAG), "got %08x\n", hr);
2007 if(hr != S_OK)
2008 return;
2010 test_file_access(fileA, create);
2012 IStorage_Release(stg);
2013 test_file_access(fileA, create_close);
2015 DeleteFileA(fileA);
2018 static void test_readonly(void)
2020 IStorage *stg, *stg2, *stg3;
2021 IStream *stream;
2022 HRESULT hr;
2023 static const WCHAR fileW[] = {'w','i','n','e','t','e','s','t',0};
2024 static const WCHAR storageW[] = {'s','t','o','r','a','g','e',0};
2025 static const WCHAR streamW[] = {'s','t','r','e','a','m',0};
2027 hr = StgCreateDocfile( fileW, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &stg);
2028 ok(hr == S_OK, "should succeed, res=%x\n", hr);
2029 if (SUCCEEDED(hr))
2031 hr = IStorage_CreateStorage( stg, storageW, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stg2 );
2032 ok(hr == S_OK, "should succeed, res=%x\n", hr);
2033 if (SUCCEEDED(hr))
2035 hr = IStorage_CreateStream( stg2, streamW, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stream );
2036 ok(hr == S_OK, "should succeed, res=%x\n", hr);
2037 if (SUCCEEDED(hr))
2038 IStream_Release(stream);
2039 IStorage_Release(stg2);
2041 IStorage_Release(stg);
2044 /* re-open read only */
2045 hr = StgOpenStorage( fileW, NULL, STGM_TRANSACTED | STGM_SHARE_DENY_NONE | STGM_READ, NULL, 0, &stg);
2046 ok(hr == S_OK, "should succeed, res=%x\n", hr);
2047 if (SUCCEEDED(hr))
2049 hr = IStorage_OpenStorage( stg, storageW, NULL, STGM_SHARE_EXCLUSIVE | STGM_READ, NULL, 0, &stg2 );
2050 ok(hr == S_OK, "should succeed, res=%x\n", hr);
2051 if (SUCCEEDED(hr))
2053 /* CreateStream on read-only storage, name exists */
2054 hr = IStorage_CreateStream( stg2, streamW, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READ, 0, 0, &stream );
2055 ok(hr == STG_E_ACCESSDENIED, "should fail, res=%x\n", hr);
2056 if (SUCCEEDED(hr))
2057 IStream_Release(stream);
2059 /* CreateStream on read-only storage, name does not exist */
2060 hr = IStorage_CreateStream( stg2, storageW, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READ, 0, 0, &stream );
2061 ok(hr == STG_E_ACCESSDENIED, "should fail, res=%x\n", hr);
2062 if (SUCCEEDED(hr))
2063 IStream_Release(stream);
2065 /* CreateStorage on read-only storage, name exists */
2066 hr = IStorage_CreateStorage( stg2, streamW, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READ, 0, 0, &stg3 );
2067 ok(hr == STG_E_FILEALREADYEXISTS, "should fail, res=%x\n", hr);
2068 if (SUCCEEDED(hr))
2069 IStorage_Release(stg3);
2071 /* CreateStorage on read-only storage, name does not exist */
2072 hr = IStorage_CreateStorage( stg2, storageW, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READ, 0, 0, &stg3 );
2073 ok(hr == STG_E_ACCESSDENIED, "should fail, res=%x\n", hr);
2074 if (SUCCEEDED(hr))
2075 IStorage_Release(stg3);
2077 /* DestroyElement on read-only storage, name exists */
2078 hr = IStorage_DestroyElement( stg2, streamW );
2079 ok(hr == STG_E_ACCESSDENIED, "should fail, res=%x\n", hr);
2081 /* DestroyElement on read-only storage, name does not exist */
2082 hr = IStorage_DestroyElement( stg2, storageW );
2083 ok(hr == STG_E_ACCESSDENIED, "should fail, res=%x\n", hr);
2085 IStorage_Release(stg2);
2088 IStorage_Release(stg);
2091 DeleteFileA("winetest");
2094 static void test_simple(void)
2096 /* Tests for STGM_SIMPLE mode */
2098 IStorage *stg, *stg2;
2099 HRESULT r;
2100 IStream *stm;
2101 static const WCHAR stgname[] = { 'S','t','g',0 };
2102 static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 };
2103 static const WCHAR stmname2[] = { 'S','m','a','l','l',0 };
2104 LARGE_INTEGER pos;
2105 ULARGE_INTEGER upos;
2106 DWORD count;
2107 STATSTG stat;
2109 DeleteFileA(filenameA);
2111 r = StgCreateDocfile( filename, STGM_SIMPLE | STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &stg);
2112 ok(r == S_OK, "got %08x\n", r);
2114 r = IStorage_CreateStorage(stg, stgname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stg2);
2115 ok(r == STG_E_INVALIDFUNCTION, "got %08x\n", r);
2116 if (SUCCEEDED(r)) IStorage_Release(stg2);
2118 r = IStorage_CreateStream(stg, stmname, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm);
2119 ok(r == STG_E_INVALIDFLAG, "got %08x\n", r);
2120 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm);
2121 ok(r == S_OK, "got %08x\n", r);
2123 upos.QuadPart = 6000;
2124 r = IStream_SetSize(stm, upos);
2125 ok(r == S_OK, "got %08x\n", r);
2127 r = IStream_Write(stm, "foo", 3, &count);
2128 ok(r == S_OK, "got %08x\n", r);
2129 ok(count == 3, "got %d\n", count);
2131 pos.QuadPart = 0;
2132 r = IStream_Seek(stm, pos, STREAM_SEEK_CUR, &upos);
2133 ok(r == S_OK, "got %08x\n", r);
2134 ok(upos.QuadPart == 3, "got %d\n", upos.u.LowPart);
2136 r = IStream_Stat(stm, &stat, STATFLAG_NONAME);
2137 ok(r == S_OK ||
2138 broken(r == STG_E_INVALIDFUNCTION), /* NT4 and below */
2139 "got %08x\n", r);
2140 if (r == S_OK)
2141 ok(stat.cbSize.QuadPart == 3, "got %d\n", stat.cbSize.u.LowPart);
2143 pos.QuadPart = 1;
2144 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &upos);
2145 ok(r == S_OK, "got %08x\n", r);
2146 ok(upos.QuadPart == 1, "got %d\n", upos.u.LowPart);
2148 r = IStream_Stat(stm, &stat, STATFLAG_NONAME);
2149 ok(r == S_OK ||
2150 broken(r == STG_E_INVALIDFUNCTION), /* NT4 and below */
2151 "got %08x\n", r);
2152 if (r == S_OK)
2153 ok(stat.cbSize.QuadPart == 1, "got %d\n", stat.cbSize.u.LowPart);
2155 IStream_Release(stm);
2157 r = IStorage_CreateStream(stg, stmname2, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm);
2158 ok(r == S_OK, "got %08x\n", r);
2160 upos.QuadPart = 100;
2161 r = IStream_SetSize(stm, upos);
2162 ok(r == S_OK, "got %08x\n", r);
2164 r = IStream_Write(stm, "foo", 3, &count);
2165 ok(r == S_OK, "got %08x\n", r);
2166 ok(count == 3, "got %d\n", count);
2168 IStream_Release(stm);
2170 IStorage_Commit(stg, STGC_DEFAULT);
2171 IStorage_Release(stg);
2173 r = StgOpenStorage( filename, NULL, STGM_SIMPLE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, NULL, 0, &stg);
2174 if (r == STG_E_INVALIDFLAG)
2176 win_skip("Flag combination is not supported on NT4 and below\n");
2177 DeleteFileA(filenameA);
2178 return;
2180 ok(r == S_OK, "got %08x\n", r);
2182 r = IStorage_OpenStorage(stg, stgname, NULL, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, NULL, 0, &stg2);
2183 ok(r == STG_E_INVALIDFUNCTION, "got %08x\n", r);
2184 if (SUCCEEDED(r)) IStorage_Release(stg2);
2186 r = IStorage_OpenStream(stg, stmname, NULL, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &stm);
2187 ok(r == S_OK, "got %08x\n", r);
2189 r = IStream_Stat(stm, &stat, STATFLAG_NONAME);
2190 ok(r == S_OK, "got %08x\n", r);
2191 ok(stat.cbSize.QuadPart == 6000, "got %d\n", stat.cbSize.u.LowPart);
2193 IStream_Release(stm);
2195 r = IStorage_OpenStream(stg, stmname2, NULL, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &stm);
2196 ok(r == S_OK, "got %08x\n", r);
2198 r = IStream_Stat(stm, &stat, STATFLAG_NONAME);
2199 ok(r == S_OK, "got %08x\n", r);
2200 ok(stat.cbSize.QuadPart == 4096, "got %d\n", stat.cbSize.u.LowPart);
2202 IStream_Release(stm);
2205 IStorage_Release(stg);
2207 DeleteFileA(filenameA);
2210 static void test_fmtusertypestg(void)
2212 IStorage *stg;
2213 IEnumSTATSTG *stat;
2214 HRESULT hr;
2215 static const char fileA[] = {'f','m','t','t','e','s','t',0};
2216 static const WCHAR fileW[] = {'f','m','t','t','e','s','t',0};
2217 static WCHAR userTypeW[] = {'S','t','g','U','s','r','T','y','p','e',0};
2218 static const WCHAR strmNameW[] = {1,'C','o','m','p','O','b','j',0};
2220 hr = StgCreateDocfile( fileW, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &stg);
2221 ok(hr == S_OK, "should succeed, res=%x\n", hr);
2223 if (SUCCEEDED(hr))
2225 /* try to write the stream */
2226 hr = WriteFmtUserTypeStg(stg, 0, userTypeW);
2227 ok(hr == S_OK, "should succeed, res=%x\n", hr);
2229 /* check that the stream was created */
2230 hr = IStorage_EnumElements(stg, 0, NULL, 0, &stat);
2231 ok(hr == S_OK, "should succeed, res=%x\n", hr);
2232 if (SUCCEEDED(hr))
2234 BOOL found = FALSE;
2235 STATSTG statstg;
2236 DWORD got;
2237 while ((hr = IEnumSTATSTG_Next(stat, 1, &statstg, &got)) == S_OK && got == 1)
2239 if (strcmp_ww(statstg.pwcsName, strmNameW) == 0)
2240 found = TRUE;
2241 else
2242 ok(0, "found unexpected stream or storage\n");
2243 CoTaskMemFree(statstg.pwcsName);
2245 ok(found == TRUE, "expected storage to contain stream \\0001CompObj\n");
2246 IEnumSTATSTG_Release(stat);
2249 /* re-write the stream */
2250 hr = WriteFmtUserTypeStg(stg, 0, userTypeW);
2251 ok(hr == S_OK, "should succeed, res=%x\n", hr);
2253 /* check that the stream is still there */
2254 hr = IStorage_EnumElements(stg, 0, NULL, 0, &stat);
2255 ok(hr == S_OK, "should succeed, res=%x\n", hr);
2256 if (SUCCEEDED(hr))
2258 BOOL found = FALSE;
2259 STATSTG statstg;
2260 DWORD got;
2261 while ((hr = IEnumSTATSTG_Next(stat, 1, &statstg, &got)) == S_OK && got == 1)
2263 if (strcmp_ww(statstg.pwcsName, strmNameW) == 0)
2264 found = TRUE;
2265 else
2266 ok(0, "found unexpected stream or storage\n");
2267 CoTaskMemFree(statstg.pwcsName);
2269 ok(found == TRUE, "expected storage to contain stream \\0001CompObj\n");
2270 IEnumSTATSTG_Release(stat);
2273 IStorage_Release(stg);
2274 DeleteFileA( fileA );
2278 static void test_references(void)
2280 IStorage *stg,*stg2;
2281 HRESULT hr;
2282 unsigned c1,c2;
2283 static const WCHAR StorName[] = { 'D','a','t','a','S','p','a','c','e','I','n','f','o',0 };
2285 DeleteFileA(filenameA);
2287 hr = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
2288 ok(hr==S_OK, "StgCreateDocfile failed\n");
2290 if (SUCCEEDED(hr))
2292 IStorage_Release(stg);
2294 hr = StgOpenStorage( filename, NULL, STGM_TRANSACTED | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, NULL, 0, &stg);
2295 ok(hr==S_OK, "StgOpenStorage failed (result=%x)\n",hr);
2297 if (SUCCEEDED(hr))
2299 hr = IStorage_CreateStorage(stg,StorName,STGM_READWRITE | STGM_SHARE_EXCLUSIVE,0,0,&stg2);
2300 ok(hr == S_OK, "IStorage_CreateStorage failed (result=%x)\n",hr);
2302 if (SUCCEEDED(hr))
2304 c1 = IStorage_AddRef(stg);
2305 ok(c1 == 2, "creating internal storage added references to ancestor\n");
2306 c1 = IStorage_AddRef(stg);
2307 IStorage_Release(stg2);
2308 c2 = IStorage_AddRef(stg) - 1;
2309 ok(c1 == c2, "releasing internal storage removed references to ancestor\n");
2311 c1 = IStorage_Release(stg);
2312 while ( c1 ) c1 = IStorage_Release(stg);
2316 DeleteFileA(filenameA);
2319 /* dest
2320 * |-StorageA
2321 * | `StreamA: "StreamA"
2322 * |-StorageB
2323 * | `StreamB: "StreamB"
2324 * `StreamC: "StreamC"
2326 static HRESULT create_test_file(IStorage *dest)
2328 IStorage *stgA = NULL, *stgB = NULL;
2329 IStream *strmA = NULL, *strmB = NULL, *strmC = NULL;
2330 const ULONG strmA_name_size = lstrlenW(strmA_name) * sizeof(WCHAR);
2331 const ULONG strmB_name_size = lstrlenW(strmB_name) * sizeof(WCHAR);
2332 const ULONG strmC_name_size = lstrlenW(strmC_name) * sizeof(WCHAR);
2333 ULONG bytes;
2334 HRESULT hr;
2336 hr = IStorage_CreateStorage(dest, stgA_name, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stgA);
2337 ok(hr == S_OK, "IStorage_CreateStorage failed: 0x%08x\n", hr);
2338 if(FAILED(hr))
2339 goto cleanup;
2341 hr = IStorage_CreateStream(stgA, strmA_name, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &strmA);
2342 ok(hr == S_OK, "IStorage_CreateStream failed: 0x%08x\n", hr);
2343 if(FAILED(hr))
2344 goto cleanup;
2346 hr = IStream_Write(strmA, strmA_name, strmA_name_size, &bytes);
2347 ok(hr == S_OK && bytes == strmA_name_size, "IStream_Write failed: 0x%08x, %d of %d bytes written\n", hr, bytes, strmA_name_size);
2349 hr = IStorage_CreateStorage(dest, stgB_name, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stgB);
2350 ok(hr == S_OK, "IStorage_CreateStorage failed: 0x%08x\n", hr);
2351 if(FAILED(hr))
2352 goto cleanup;
2354 hr = IStorage_CreateStream(stgB, strmB_name, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &strmB);
2355 ok(hr == S_OK, "IStorage_CreateStream failed: 0x%08x\n", hr);
2356 if(FAILED(hr))
2357 goto cleanup;
2359 hr = IStream_Write(strmB, strmB_name, strmB_name_size, &bytes);
2360 ok(hr == S_OK && bytes == strmB_name_size, "IStream_Write failed: 0x%08x, %d of %d bytes written\n", hr, bytes, strmB_name_size);
2362 hr = IStorage_CreateStream(dest, strmC_name, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &strmC);
2363 ok(hr == S_OK, "IStorage_CreateStream failed: 0x%08x\n", hr);
2364 if(FAILED(hr))
2365 goto cleanup;
2367 hr = IStream_Write(strmC, strmC_name, strmC_name_size, &bytes);
2368 ok(hr == S_OK && bytes == strmC_name_size, "IStream_Write failed: 0x%08x, %d of %d bytes written\n", hr, bytes, strmC_name_size);
2370 cleanup:
2371 if(strmC)
2372 IStream_Release(strmC);
2373 if(strmB)
2374 IStream_Release(strmB);
2375 if(stgB)
2376 IStorage_Release(stgB);
2377 if(strmA)
2378 IStream_Release(strmA);
2379 if(stgA)
2380 IStorage_Release(stgA);
2382 return hr;
2385 static void test_copyto(void)
2387 IStorage *file1 = NULL, *file2 = NULL, *stg_tmp;
2388 IStream *strm_tmp;
2389 WCHAR buf[64];
2390 HRESULT hr;
2392 /* create & populate file1 */
2393 hr = StgCreateDocfile(file1_name, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &file1);
2394 ok(hr == S_OK, "StgCreateDocfile failed: 0x%08x\n", hr);
2395 if(FAILED(hr))
2396 goto cleanup;
2398 hr = create_test_file(file1);
2399 if(FAILED(hr))
2400 goto cleanup;
2402 /* create file2 */
2403 hr = StgCreateDocfile(file2_name, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &file2);
2404 ok(hr == S_OK, "StgCreateDocfile failed: 0x%08x\n", hr);
2405 if(FAILED(hr))
2406 goto cleanup;
2408 /* copy file1 into file2 */
2409 hr = IStorage_CopyTo(file1, 0, NULL, NULL, NULL);
2410 ok(hr == STG_E_INVALIDPOINTER, "CopyTo should give STG_E_INVALIDPONITER, gave: 0x%08x\n", hr);
2412 hr = IStorage_CopyTo(file1, 0, NULL, NULL, file2);
2413 ok(hr == S_OK, "CopyTo failed: 0x%08x\n", hr);
2414 if(FAILED(hr))
2415 goto cleanup;
2417 /* verify that all of file1 was copied */
2418 hr = IStorage_OpenStorage(file2, stgA_name, NULL,
2419 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg_tmp);
2420 ok(hr == S_OK, "OpenStorage failed: 0x%08x\n", hr);
2422 if(SUCCEEDED(hr)){
2423 hr = IStorage_OpenStream(stg_tmp, strmA_name, NULL,
2424 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp);
2425 ok(hr == S_OK, "OpenStream failed: 0x%08x\n", hr);
2427 if(SUCCEEDED(hr)){
2428 memset(buf, 0, sizeof(buf));
2429 hr = IStream_Read(strm_tmp, buf, sizeof(buf), NULL);
2430 ok(hr == S_OK, "Read failed: 0x%08x\n", hr);
2431 if(SUCCEEDED(hr))
2432 ok(strcmp_ww(buf, strmA_name) == 0,
2433 "Expected %s to be read, got %s\n", wine_dbgstr_w(strmA_name), wine_dbgstr_w(buf));
2435 IStream_Release(strm_tmp);
2438 IStorage_Release(stg_tmp);
2441 hr = IStorage_OpenStorage(file2, stgB_name, NULL,
2442 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg_tmp);
2443 ok(hr == S_OK, "OpenStorage failed: 0x%08x\n", hr);
2445 if(SUCCEEDED(hr)){
2446 hr = IStorage_OpenStream(stg_tmp, strmB_name, NULL,
2447 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp);
2448 ok(hr == S_OK, "OpenStream failed: 0x%08x\n", hr);
2450 if(SUCCEEDED(hr)){
2451 memset(buf, 0, sizeof(buf));
2452 hr = IStream_Read(strm_tmp, buf, sizeof(buf), NULL);
2453 ok(hr == S_OK, "Read failed: 0x%08x\n", hr);
2454 if(SUCCEEDED(hr))
2455 ok(strcmp_ww(buf, strmB_name) == 0,
2456 "Expected %s to be read, got %s\n", wine_dbgstr_w(strmB_name), wine_dbgstr_w(buf));
2458 IStream_Release(strm_tmp);
2461 IStorage_Release(stg_tmp);
2464 hr = IStorage_OpenStream(file2, strmC_name, NULL,
2465 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp);
2466 ok(hr == S_OK, "OpenStream failed: 0x%08x\n", hr);
2468 if(SUCCEEDED(hr)){
2469 memset(buf, 0, sizeof(buf));
2470 hr = IStream_Read(strm_tmp, buf, sizeof(buf), NULL);
2471 ok(hr == S_OK, "Read failed: 0x%08x\n", hr);
2472 if(SUCCEEDED(hr))
2473 ok(strcmp_ww(buf, strmC_name) == 0,
2474 "Expected %s to be read, got %s\n", wine_dbgstr_w(strmC_name), wine_dbgstr_w(buf));
2476 IStream_Release(strm_tmp);
2479 cleanup:
2480 if(file1)
2481 IStorage_Release(file1);
2482 if(file2)
2483 IStorage_Release(file2);
2485 DeleteFileA(file1_nameA);
2486 DeleteFileA(file2_nameA);
2489 static void test_copyto_snbexclusions(void)
2491 static const WCHAR *snb_exclude[] = {stgA_name, strmB_name, strmC_name, 0};
2493 IStorage *file1 = NULL, *file2 = NULL, *stg_tmp;
2494 IStream *strm_tmp;
2495 WCHAR buf[64];
2496 HRESULT hr;
2498 /* create & populate file1 */
2499 hr = StgCreateDocfile(file1_name, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &file1);
2500 ok(hr == S_OK, "StgCreateDocfile failed: 0x%08x\n", hr);
2501 if(FAILED(hr))
2502 goto cleanup;
2504 hr = create_test_file(file1);
2505 if(FAILED(hr))
2506 goto cleanup;
2508 /* create file2 */
2509 hr = StgCreateDocfile(file2_name, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &file2);
2510 ok(hr == S_OK, "StgCreateDocfile failed: 0x%08x\n", hr);
2511 if(FAILED(hr))
2512 goto cleanup;
2514 /* copy file1 to file2 with name exclusions */
2515 hr = IStorage_CopyTo(file1, 0, NULL, (SNB)snb_exclude, file2);
2516 ok(hr == S_OK, "CopyTo failed: 0x%08x\n", hr);
2517 if(FAILED(hr))
2518 goto cleanup;
2520 /* verify that file1 copied over, respecting exclusions */
2521 hr = IStorage_OpenStorage(file2, stgA_name, NULL,
2522 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg_tmp);
2523 ok(hr == STG_E_FILENOTFOUND, "OpenStorage should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr);
2524 if(SUCCEEDED(hr))
2525 IStorage_Release(stg_tmp);
2527 hr = IStorage_OpenStream(file2, strmA_name, NULL,
2528 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp);
2529 ok(hr == STG_E_FILENOTFOUND, "OpenStream should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr);
2530 if(SUCCEEDED(hr))
2531 IStream_Release(strm_tmp);
2533 hr = IStorage_OpenStorage(file2, stgB_name, NULL,
2534 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg_tmp);
2535 ok(hr == S_OK, "OpenStorage failed: 0x%08x\n", hr);
2537 if(SUCCEEDED(hr)){
2538 hr = IStorage_OpenStream(stg_tmp, strmB_name, NULL,
2539 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp);
2540 ok(hr == S_OK, "OpenStream failed: 0x%08x\n", hr);
2542 if(SUCCEEDED(hr)){
2543 memset(buf, 0, sizeof(buf));
2544 hr = IStream_Read(strm_tmp, buf, sizeof(buf), NULL);
2545 ok(hr == S_OK, "Read failed: 0x%08x\n", hr);
2546 if(SUCCEEDED(hr))
2547 ok(strcmp_ww(buf, strmB_name) == 0,
2548 "Expected %s to be read, got %s\n", wine_dbgstr_w(strmB_name), wine_dbgstr_w(buf));
2550 IStream_Release(strm_tmp);
2553 IStorage_Release(stg_tmp);
2556 hr = IStorage_OpenStream(file2, strmC_name, NULL,
2557 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp);
2558 ok(hr == STG_E_FILENOTFOUND, "OpenStream should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr);
2559 if(SUCCEEDED(hr))
2560 IStream_Release(strm_tmp);
2562 cleanup:
2563 if(file1)
2564 IStorage_Release(file1);
2565 if(file2)
2566 IStorage_Release(file2);
2568 DeleteFileA(file1_nameA);
2569 DeleteFileA(file2_nameA);
2572 static void test_copyto_iidexclusions_storage(void)
2574 IStorage *file1 = NULL, *file2 = NULL, *stg_tmp;
2575 IStream *strm_tmp;
2576 WCHAR buf[64];
2577 HRESULT hr;
2579 /* create & populate file1 */
2580 hr = StgCreateDocfile(file1_name, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &file1);
2581 ok(hr == S_OK, "StgCreateDocfile failed: 0x%08x\n", hr);
2582 if(FAILED(hr))
2583 goto cleanup;
2585 hr = create_test_file(file1);
2586 if(FAILED(hr))
2587 goto cleanup;
2589 /* create file2 */
2590 hr = StgCreateDocfile(file2_name, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &file2);
2591 ok(hr == S_OK, "StgCreateDocfile failed: 0x%08x\n", hr);
2592 if(FAILED(hr))
2593 goto cleanup;
2595 /* copy file1 to file2 with iid exclusions */
2596 hr = IStorage_CopyTo(file1, 1, &IID_IStorage, NULL, file2);
2597 ok(hr == S_OK, "CopyTo failed: 0x%08x\n", hr);
2598 if(FAILED(hr))
2599 goto cleanup;
2601 /* verify that file1 copied over, respecting exclusions */
2602 hr = IStorage_OpenStorage(file2, stgA_name, NULL,
2603 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg_tmp);
2604 ok(hr == STG_E_FILENOTFOUND, "OpenStorage should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr);
2605 if(SUCCEEDED(hr))
2606 IStorage_Release(stg_tmp);
2608 hr = IStorage_OpenStream(file2, strmA_name, NULL,
2609 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp);
2610 ok(hr == STG_E_FILENOTFOUND, "OpenStream should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr);
2611 if(SUCCEEDED(hr))
2612 IStream_Release(strm_tmp);
2614 hr = IStorage_OpenStorage(file2, stgB_name, NULL,
2615 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg_tmp);
2616 ok(hr == STG_E_FILENOTFOUND, "OpenStorage should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr);
2617 if(SUCCEEDED(hr))
2618 IStorage_Release(stg_tmp);
2620 hr = IStorage_OpenStream(file2, strmB_name, NULL,
2621 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp);
2622 ok(hr == STG_E_FILENOTFOUND, "OpenStream should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr);
2623 if(SUCCEEDED(hr))
2624 IStream_Release(strm_tmp);
2626 hr = IStorage_OpenStream(file2, strmC_name, NULL,
2627 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp);
2628 ok(hr == S_OK, "OpenStream failed: 0x%08x\n", hr);
2630 if(SUCCEEDED(hr)){
2631 memset(buf, 0, sizeof(buf));
2632 hr = IStream_Read(strm_tmp, buf, sizeof(buf), NULL);
2633 ok(hr == S_OK, "Read failed: 0x%08x\n", hr);
2634 if(SUCCEEDED(hr))
2635 ok(strcmp_ww(buf, strmC_name) == 0,
2636 "Expected %s to be read, got %s\n", wine_dbgstr_w(strmC_name), wine_dbgstr_w(buf));
2638 IStream_Release(strm_tmp);
2641 cleanup:
2642 if(file1)
2643 IStorage_Release(file1);
2644 if(file2)
2645 IStorage_Release(file2);
2647 DeleteFileA(file1_nameA);
2648 DeleteFileA(file2_nameA);
2651 static void test_copyto_iidexclusions_stream(void)
2653 IStorage *file1 = NULL, *file2 = NULL, *stg_tmp;
2654 IStream *strm_tmp;
2655 HRESULT hr;
2657 /* create & populate file1 */
2658 hr = StgCreateDocfile(file1_name, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &file1);
2659 ok(hr == S_OK, "StgCreateDocfile failed: 0x%08x\n", hr);
2660 if(FAILED(hr))
2661 goto cleanup;
2663 hr = create_test_file(file1);
2664 if(FAILED(hr))
2665 goto cleanup;
2667 /* create file2 */
2668 hr = StgCreateDocfile(file2_name, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &file2);
2669 ok(hr == S_OK, "StgCreateDocfile failed: 0x%08x\n", hr);
2670 if(FAILED(hr))
2671 goto cleanup;
2673 /* copy file1 to file2 with iid exclusions */
2674 hr = IStorage_CopyTo(file1, 1, &IID_IStream, NULL, file2);
2675 ok(hr == S_OK, "CopyTo failed: 0x%08x\n", hr);
2676 if(FAILED(hr))
2677 goto cleanup;
2679 /* verify that file1 copied over, respecting exclusions */
2680 hr = IStorage_OpenStorage(file2, stgA_name, NULL,
2681 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg_tmp);
2682 ok(hr == S_OK, "OpenStorage failed: 0x%08x\n", hr);
2684 if(SUCCEEDED(hr)){
2685 hr = IStorage_OpenStream(stg_tmp, strmA_name, NULL,
2686 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp);
2687 ok(hr == STG_E_FILENOTFOUND, "OpenStream should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr);
2688 if(SUCCEEDED(hr))
2689 IStream_Release(strm_tmp);
2691 IStorage_Release(stg_tmp);
2694 hr = IStorage_OpenStorage(file2, stgB_name, NULL,
2695 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg_tmp);
2696 ok(hr == S_OK, "OpenStorage failed: 0x%08x\n", hr);
2698 if(SUCCEEDED(hr)){
2699 hr = IStorage_OpenStream(stg_tmp, strmB_name, NULL,
2700 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp);
2701 ok(hr == STG_E_FILENOTFOUND, "OpenStream should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr);
2702 if(SUCCEEDED(hr))
2703 IStream_Release(strm_tmp);
2705 IStorage_Release(stg_tmp);
2708 hr = IStorage_OpenStream(file2, strmC_name, NULL,
2709 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp);
2710 ok(hr == STG_E_FILENOTFOUND, "OpenStream should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr);
2711 if(SUCCEEDED(hr))
2712 IStream_Release(strm_tmp);
2714 cleanup:
2715 if(file1)
2716 IStorage_Release(file1);
2717 if(file2)
2718 IStorage_Release(file2);
2720 DeleteFileA(file1_nameA);
2721 DeleteFileA(file2_nameA);
2724 static void test_rename(void)
2726 IStorage *stg, *stg2;
2727 IStream *stm;
2728 HRESULT r;
2729 static const WCHAR stgname[] = { 'P','E','R','M','S','T','G',0 };
2730 static const WCHAR stgname2[] = { 'S','T','G',0 };
2731 static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 };
2732 static const WCHAR stmname2[] = { 'E','N','T','S',0 };
2734 DeleteFileA(filenameA);
2736 /* create the file */
2737 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
2738 STGM_READWRITE, 0, &stg);
2739 ok(r==S_OK, "StgCreateDocfile failed\n");
2741 /* create a substorage */
2742 r = IStorage_CreateStorage(stg, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg2);
2743 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
2745 /* create a stream in the substorage */
2746 r = IStorage_CreateStream(stg2, stmname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm);
2747 ok(r==S_OK, "IStorage->CreateStream failed, hr=%08x\n", r);
2748 IStream_Release(stm);
2750 /* rename the stream */
2751 r = IStorage_RenameElement(stg2, stmname, stmname2);
2752 ok(r==S_OK, "IStorage->RenameElement failed, hr=%08x\n", r);
2754 /* cannot open stream with old name */
2755 r = IStorage_OpenStream(stg2, stmname, NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &stm);
2756 ok(r==STG_E_FILENOTFOUND, "IStorage_OpenStream should fail, hr=%08x\n", r);
2757 if (SUCCEEDED(r)) IStream_Release(stm);
2759 /* can open stream with new name */
2760 r = IStorage_OpenStream(stg2, stmname2, NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &stm);
2761 ok(r==S_OK, "IStorage_OpenStream failed, hr=%08x\n", r);
2762 if (SUCCEEDED(r)) IStream_Release(stm);
2764 IStorage_Release(stg2);
2766 /* rename the storage */
2767 IStorage_RenameElement(stg, stgname, stgname2);
2769 /* cannot open storage with old name */
2770 r = IStorage_OpenStorage(stg, stgname, NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg2);
2771 ok(r==STG_E_FILENOTFOUND, "IStorage_OpenStream should fail, hr=%08x\n", r);
2772 if (SUCCEEDED(r)) IStorage_Release(stg2);
2774 /* can open storage with new name */
2775 r = IStorage_OpenStorage(stg, stgname2, NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg2);
2776 ok(r==S_OK, "IStorage_OpenStream should fail, hr=%08x\n", r);
2777 if (SUCCEEDED(r))
2779 /* opened storage still has the stream */
2780 r = IStorage_OpenStream(stg2, stmname2, NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &stm);
2781 ok(r==S_OK, "IStorage_OpenStream failed, hr=%08x\n", r);
2782 if (SUCCEEDED(r)) IStream_Release(stm);
2784 IStorage_Release(stg2);
2787 IStorage_Release(stg);
2789 r = DeleteFileA(filenameA);
2790 ok( r == TRUE, "deleted file\n");
2793 static void test_toplevel_stat(void)
2795 IStorage *stg = NULL;
2796 HRESULT r;
2797 STATSTG stat;
2798 char prev_dir[MAX_PATH];
2799 char temp[MAX_PATH];
2800 char full_path[MAX_PATH];
2801 LPSTR rel_pathA;
2802 WCHAR rel_path[MAX_PATH];
2804 DeleteFileA(filenameA);
2806 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
2807 STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
2808 ok(r==S_OK, "StgCreateDocfile failed\n");
2810 r = IStorage_Stat( stg, &stat, STATFLAG_DEFAULT );
2811 ok(r==S_OK, "Storage_Stat failed with error 0x%08x\n", r);
2812 ok(!strcmp_ww(stat.pwcsName, filename), "expected %s, got %s\n",
2813 wine_dbgstr_w(filename), wine_dbgstr_w(stat.pwcsName));
2814 CoTaskMemFree(stat.pwcsName);
2816 IStorage_Release( stg );
2818 r = StgOpenStorage( filename, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg);
2819 ok(r==S_OK, "StgOpenStorage failed with error 0x%08x\n", r);
2821 r = IStorage_Stat( stg, &stat, STATFLAG_DEFAULT );
2822 ok(r==S_OK, "Storage_Stat failed with error 0x%08x\n", r);
2823 ok(!strcmp_ww(stat.pwcsName, filename), "expected %s, got %s\n",
2824 wine_dbgstr_w(filename), wine_dbgstr_w(stat.pwcsName));
2825 CoTaskMemFree(stat.pwcsName);
2827 IStorage_Release( stg );
2829 DeleteFileA(filenameA);
2831 /* Stat always returns the full path, even for files opened with a relative path. */
2832 GetCurrentDirectoryA(MAX_PATH, prev_dir);
2834 GetTempPathA(MAX_PATH, temp);
2836 SetCurrentDirectoryA(temp);
2838 GetFullPathNameA(filenameA, MAX_PATH, full_path, &rel_pathA);
2839 MultiByteToWideChar(CP_ACP, 0, rel_pathA, -1, rel_path, MAX_PATH);
2841 r = StgCreateDocfile( rel_path, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
2842 STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
2843 ok(r==S_OK, "StgCreateDocfile failed\n");
2845 r = IStorage_Stat( stg, &stat, STATFLAG_DEFAULT );
2846 ok(r==S_OK, "Storage_Stat failed with error 0x%08x\n", r);
2847 ok(!strcmp_ww(stat.pwcsName, filename), "expected %s, got %s\n",
2848 wine_dbgstr_w(filename), wine_dbgstr_w(stat.pwcsName));
2849 CoTaskMemFree(stat.pwcsName);
2851 IStorage_Release( stg );
2853 r = StgOpenStorage( rel_path, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg);
2854 ok(r==S_OK, "StgOpenStorage failed with error 0x%08x\n", r);
2856 r = IStorage_Stat( stg, &stat, STATFLAG_DEFAULT );
2857 ok(r==S_OK, "Storage_Stat failed with error 0x%08x\n", r);
2858 ok(!strcmp_ww(stat.pwcsName, filename), "expected %s, got %s\n",
2859 wine_dbgstr_w(filename), wine_dbgstr_w(stat.pwcsName));
2860 CoTaskMemFree(stat.pwcsName);
2862 IStorage_Release( stg );
2864 SetCurrentDirectoryA(prev_dir);
2866 DeleteFileA(filenameA);
2869 static void test_substorage_enum(void)
2871 IStorage *stg, *stg2;
2872 IEnumSTATSTG *ee;
2873 HRESULT r;
2874 ULONG ref;
2875 static const WCHAR stgname[] = { 'P','E','R','M','S','T','G',0 };
2877 DeleteFileA(filenameA);
2879 /* create the file */
2880 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
2881 STGM_READWRITE, 0, &stg);
2882 ok(r==S_OK, "StgCreateDocfile failed\n");
2884 /* create a substorage */
2885 r = IStorage_CreateStorage(stg, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg2);
2886 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
2888 /* create an enumelements */
2889 r = IStorage_EnumElements(stg2, 0, NULL, 0, &ee);
2890 ok(r==S_OK, "IStorage->EnumElements failed, hr=%08x\n", r);
2892 /* release the substorage */
2893 ref = IStorage_Release(stg2);
2894 todo_wine ok(ref==0, "storage not released\n");
2896 /* reopening fails, because the substorage is really still open */
2897 r = IStorage_OpenStorage(stg, stgname, NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg2);
2898 ok(r==STG_E_ACCESSDENIED, "IStorage->OpenStorage failed, hr=%08x\n", r);
2900 /* destroying the storage invalidates the enumerator */
2901 r = IStorage_DestroyElement(stg, stgname);
2902 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
2904 r = IEnumSTATSTG_Reset(ee);
2905 ok(r==STG_E_REVERTED, "IEnumSTATSTG->Reset failed, hr=%08x\n", r);
2907 IEnumSTATSTG_Release(ee);
2909 IStorage_Release(stg);
2911 r = DeleteFileA(filenameA);
2912 ok( r == TRUE, "deleted file\n");
2915 static void test_copyto_locking(void)
2917 IStorage *stg, *stg2, *stg3, *stg4;
2918 IStream *stm;
2919 HRESULT r;
2920 static const WCHAR stgname[] = { 'S','T','G','1',0 };
2921 static const WCHAR stgname2[] = { 'S','T','G','2',0 };
2922 static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 };
2924 DeleteFileA(filenameA);
2926 /* create the file */
2927 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
2928 STGM_READWRITE, 0, &stg);
2929 ok(r==S_OK, "StgCreateDocfile failed\n");
2931 /* create a substorage */
2932 r = IStorage_CreateStorage(stg, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg2);
2933 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
2935 /* create another substorage */
2936 r = IStorage_CreateStorage(stg, stgname2, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg3);
2937 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
2939 /* add a stream, and leave it open */
2940 r = IStorage_CreateStream(stg2, stmname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm);
2941 ok(r==S_OK, "IStorage->CreateStream failed, hr=%08x\n", r);
2943 /* Try to copy the storage while the stream is open */
2944 r = IStorage_CopyTo(stg2, 0, NULL, NULL, stg3);
2945 ok(r==S_OK, "IStorage->CopyTo failed, hr=%08x\n", r);
2947 IStream_Release(stm);
2949 /* create a substorage */
2950 r = IStorage_CreateStorage(stg2, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg4);
2951 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
2953 /* Try to copy the storage while the substorage is open */
2954 r = IStorage_CopyTo(stg2, 0, NULL, NULL, stg3);
2955 ok(r==S_OK, "IStorage->CopyTo failed, hr=%08x\n", r);
2957 IStorage_Release(stg4);
2958 IStorage_Release(stg3);
2959 IStorage_Release(stg2);
2960 IStorage_Release(stg);
2962 r = DeleteFileA(filenameA);
2963 ok( r == TRUE, "deleted file\n");
2966 static void test_copyto_recursive(void)
2968 IStorage *stg, *stg2, *stg3, *stg4;
2969 HRESULT r;
2970 static const WCHAR stgname[] = { 'S','T','G','1',0 };
2971 static const WCHAR stgname2[] = { 'S','T','G','2',0 };
2973 DeleteFileA(filenameA);
2975 /* create the file */
2976 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
2977 STGM_READWRITE, 0, &stg);
2978 ok(r==S_OK, "StgCreateDocfile failed\n");
2980 /* create a substorage */
2981 r = IStorage_CreateStorage(stg, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg2);
2982 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
2984 /* copy the parent to the child */
2985 r = IStorage_CopyTo(stg, 0, NULL, NULL, stg2);
2986 ok(r==STG_E_ACCESSDENIED, "IStorage->CopyTo failed, hr=%08x\n", r);
2988 /* create a transacted substorage */
2989 r = IStorage_CreateStorage(stg, stgname2, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_TRANSACTED, 0, 0, &stg3);
2990 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
2992 /* copy the parent to the transacted child */
2993 r = IStorage_CopyTo(stg, 0, NULL, NULL, stg2);
2994 ok(r==STG_E_ACCESSDENIED, "IStorage->CopyTo failed, hr=%08x\n", r);
2996 /* create a transacted subsubstorage */
2997 r = IStorage_CreateStorage(stg3, stgname2, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_TRANSACTED, 0, 0, &stg4);
2998 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
3000 /* copy the parent to the transacted child of the transacted child */
3001 r = IStorage_CopyTo(stg, 0, NULL, NULL, stg4);
3002 ok(r==STG_E_ACCESSDENIED, "IStorage->CopyTo failed, hr=%08x\n", r);
3004 /* copy the parent but exclude storage objects */
3005 r = IStorage_CopyTo(stg, 1, &IID_IStorage, NULL, stg4);
3006 ok(r==S_OK, "IStorage->CopyTo failed, hr=%08x\n", r);
3008 IStorage_Release(stg4);
3009 IStorage_Release(stg3);
3010 IStorage_Release(stg2);
3011 IStorage_Release(stg);
3013 r = DeleteFileA(filenameA);
3014 ok( r == TRUE, "deleted file\n");
3017 static void test_hglobal_storage_creation(void)
3019 ILockBytes *ilb = NULL;
3020 IStorage *stg = NULL;
3021 HRESULT r;
3022 STATSTG stat;
3023 char junk[512];
3024 ULARGE_INTEGER offset;
3026 r = CreateILockBytesOnHGlobal(NULL, TRUE, &ilb);
3027 ok(r == S_OK, "CreateILockBytesOnHGlobal failed, hr=%x\n", r);
3029 offset.QuadPart = 0;
3030 memset(junk, 0xaa, 512);
3031 r = ILockBytes_WriteAt(ilb, offset, junk, 512, NULL);
3032 ok(r == S_OK, "ILockBytes_WriteAt failed, hr=%x\n", r);
3034 offset.QuadPart = 2000;
3035 r = ILockBytes_WriteAt(ilb, offset, junk, 512, NULL);
3036 ok(r == S_OK, "ILockBytes_WriteAt failed, hr=%x\n", r);
3038 r = StgCreateDocfileOnILockBytes(ilb, STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stg);
3039 ok(r == S_OK, "StgCreateDocfileOnILockBytes failed, hr=%x\n", r);
3041 IStorage_Release(stg);
3043 r = StgOpenStorageOnILockBytes(ilb, NULL, STGM_READ|STGM_SHARE_EXCLUSIVE,
3044 NULL, 0, &stg);
3045 ok(r == S_OK, "StgOpenStorageOnILockBytes failed, hr=%x\n", r);
3047 if (SUCCEEDED(r))
3049 r = IStorage_Stat(stg, &stat, STATFLAG_NONAME);
3050 ok(r == S_OK, "StgOpenStorageOnILockBytes failed, hr=%x\n", r);
3051 ok(IsEqualCLSID(&stat.clsid, &GUID_NULL), "unexpected CLSID value\n");
3053 IStorage_Release(stg);
3056 r = ILockBytes_Stat(ilb, &stat, STATFLAG_NONAME);
3057 ok(r == S_OK, "ILockBytes_Stat failed, hr=%x\n", r);
3058 ok(stat.cbSize.u.LowPart < 2512, "expected truncated size, got %d\n", stat.cbSize.u.LowPart);
3060 ILockBytes_Release(ilb);
3063 static void test_convert(void)
3065 static const WCHAR filename[] = {'s','t','o','r','a','g','e','.','s','t','g',0};
3066 IStorage *stg;
3067 HRESULT hr;
3069 hr = GetConvertStg(NULL);
3070 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3072 hr = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &stg);
3073 ok(hr == S_OK, "StgCreateDocfile failed\n");
3074 hr = GetConvertStg(stg);
3075 ok(hr == STG_E_FILENOTFOUND, "got 0x%08x\n", hr);
3076 hr = SetConvertStg(stg, TRUE);
3077 ok(hr == S_OK, "got 0x%08x\n", hr);
3078 hr = SetConvertStg(stg, TRUE);
3079 ok(hr == S_OK, "got 0x%08x\n", hr);
3080 hr = GetConvertStg(stg);
3081 ok(hr == S_OK, "got 0x%08x\n", hr);
3082 hr = SetConvertStg(stg, FALSE);
3083 ok(hr == S_OK, "got 0x%08x\n", hr);
3084 hr = GetConvertStg(stg);
3085 ok(hr == S_FALSE, "got 0x%08x\n", hr);
3087 IStorage_Release(stg);
3089 DeleteFileW(filename);
3092 static void test_direct_swmr(void)
3094 static const WCHAR fileW[] = {'w','i','n','e','t','e','s','t',0};
3095 IDirectWriterLock *dwlock;
3096 ULONG ref, ref2;
3097 IStorage *stg;
3098 HRESULT hr;
3100 /* it's possible to create in writer mode */
3101 hr = StgCreateDocfile(fileW, STGM_CREATE | STGM_READWRITE | STGM_SHARE_DENY_WRITE | STGM_DIRECT_SWMR, 0, &stg);
3102 todo_wine
3103 ok(hr == S_OK, "got %08x\n", hr);
3104 if (hr == S_OK) {
3105 IStorage_Release(stg);
3106 DeleteFileW(fileW);
3109 hr = StgCreateDocfile(fileW, STGM_CREATE | STGM_READWRITE | STGM_SHARE_DENY_WRITE | STGM_TRANSACTED, 0, &stg);
3110 ok(hr == S_OK, "got %08x\n", hr);
3111 IStorage_Release(stg);
3113 /* reader mode */
3114 hr = StgOpenStorage(fileW, NULL, STGM_DIRECT_SWMR | STGM_READ | STGM_SHARE_DENY_NONE, NULL, 0, &stg);
3115 ok(hr == S_OK || broken(hr == STG_E_INVALIDFLAG), "got %08x\n", hr);
3116 if(hr == S_OK)
3118 hr = IStorage_QueryInterface(stg, &IID_IDirectWriterLock, (void**)&dwlock);
3119 ok(hr == E_NOINTERFACE, "got %08x\n", hr);
3120 IStorage_Release(stg);
3123 /* writer mode */
3124 hr = StgOpenStorage(fileW, NULL, STGM_DIRECT_SWMR | STGM_READWRITE | STGM_SHARE_DENY_WRITE, NULL, 0, &stg);
3125 ok(hr == S_OK, "got %08x\n", hr);
3126 if(hr == S_OK)
3128 ref = IStorage_AddRef(stg);
3129 IStorage_Release(stg);
3131 hr = IStorage_QueryInterface(stg, &IID_IDirectWriterLock, (void**)&dwlock);
3132 ok(hr == S_OK, "got %08x\n", hr);
3134 ref2 = IStorage_AddRef(stg);
3135 IStorage_Release(stg);
3136 ok(ref2 == ref + 1, "got %u\n", ref2);
3138 IDirectWriterLock_Release(dwlock);
3139 IStorage_Release(stg);
3142 DeleteFileW(fileW);
3145 struct lock_test
3147 DWORD stg_mode;
3148 BOOL create;
3149 DWORD access;
3150 DWORD sharing;
3151 const int *locked_bytes;
3152 const int *fail_ranges;
3153 BOOL todo;
3156 static const int priority_locked_bytes[] = { 0x58, 0x81, 0x93, -1 };
3157 static const int rwex_locked_bytes[] = { 0x93, 0xa7, 0xbb, 0xcf, -1 };
3158 static const int rw_locked_bytes[] = { 0x93, 0xa7, -1 };
3159 static const int rwdw_locked_bytes[] = { 0x93, 0xa7, 0xcf, -1 };
3160 static const int wodw_locked_bytes[] = { 0xa7, 0xcf, -1 };
3161 static const int tr_locked_bytes[] = { 0x93, -1 };
3162 static const int no_locked_bytes[] = { -1 };
3163 static const int roex_locked_bytes[] = { 0x93, 0xbb, 0xcf, -1 };
3165 static const int rwex_fail_ranges[] = { 0x93,0xe3, -1 };
3166 static const int rw_fail_ranges[] = { 0xbb,0xe3, -1 };
3167 static const int dw_fail_ranges[] = { 0xa7,0xcf, -1 };
3168 static const int tr_fail_ranges[] = { 0xbb,0xcf, -1 };
3169 static const int pr_fail_ranges[] = { 0x80,0x81, 0xbb,0xcf, -1 };
3170 static const int roex_fail_ranges[] = { 0x0,-1 };
3172 static const struct lock_test lock_tests[] = {
3173 { STGM_PRIORITY, FALSE, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, priority_locked_bytes, pr_fail_ranges, FALSE },
3174 { STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, TRUE, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, rwex_locked_bytes, 0, FALSE },
3175 { STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE|STGM_TRANSACTED, TRUE, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, rwex_locked_bytes, 0, FALSE },
3176 { STGM_CREATE|STGM_READWRITE|STGM_TRANSACTED, TRUE, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, rw_locked_bytes, 0, FALSE },
3177 { STGM_CREATE|STGM_READWRITE|STGM_SHARE_DENY_WRITE|STGM_TRANSACTED, TRUE, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, rwdw_locked_bytes, 0, FALSE },
3178 { STGM_CREATE|STGM_WRITE|STGM_SHARE_DENY_WRITE|STGM_TRANSACTED, TRUE, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, wodw_locked_bytes, 0, FALSE },
3179 { STGM_SHARE_EXCLUSIVE|STGM_READWRITE, FALSE, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, rwex_locked_bytes, rwex_fail_ranges, FALSE },
3180 { STGM_SHARE_EXCLUSIVE|STGM_READWRITE|STGM_TRANSACTED, FALSE, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, rwex_locked_bytes, rwex_fail_ranges, FALSE },
3181 { STGM_READWRITE|STGM_TRANSACTED, FALSE, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, rw_locked_bytes, rw_fail_ranges, FALSE },
3182 { STGM_READ|STGM_SHARE_DENY_WRITE, FALSE, GENERIC_READ, FILE_SHARE_READ, no_locked_bytes, dw_fail_ranges, TRUE },
3183 { STGM_READ|STGM_TRANSACTED, FALSE, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, tr_locked_bytes, tr_fail_ranges, FALSE },
3184 { STGM_READ|STGM_SHARE_EXCLUSIVE, FALSE, GENERIC_READ, FILE_SHARE_READ, roex_locked_bytes, roex_fail_ranges, TRUE },
3185 { STGM_READ|STGM_SHARE_EXCLUSIVE|STGM_TRANSACTED, FALSE, GENERIC_READ, FILE_SHARE_READ, roex_locked_bytes, roex_fail_ranges, TRUE },
3188 static BOOL can_open(LPCWSTR filename, DWORD access, DWORD sharing)
3190 HANDLE hfile;
3192 hfile = CreateFileW(filename, access, sharing, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
3194 if (hfile == INVALID_HANDLE_VALUE)
3195 return FALSE;
3197 CloseHandle(hfile);
3198 return TRUE;
3201 static void check_sharing(LPCWSTR filename, const struct lock_test *current,
3202 DWORD access, DWORD sharing, const char *desc, DWORD *open_mode, BOOL *any_failure)
3204 if (can_open(filename, access, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE))
3206 *open_mode = access;
3207 if (!current->todo || (current->sharing & sharing))
3208 ok(current->sharing & sharing ||
3209 broken(!(current->sharing & sharing) && access == GENERIC_WRITE && (current->stg_mode & 0xf) != STGM_READ) /* win2k */,
3210 "file with mode %x should not be openable with %s permission\n", current->stg_mode, desc);
3211 else
3213 todo_wine ok(current->sharing & sharing ||
3214 broken(!(current->sharing & sharing) && access == GENERIC_WRITE && (current->stg_mode & 0xf) != STGM_READ) /* win2k */,
3215 "file with mode %x should not be openable with %s permission\n", current->stg_mode, desc);
3216 *any_failure = TRUE;
3219 else
3221 if (!current->todo || !(current->sharing & sharing))
3222 ok(!(current->sharing & sharing), "file with mode %x should be openable with %s permission\n", current->stg_mode, desc);
3223 else
3225 todo_wine ok(!(current->sharing & sharing), "file with mode %x should be openable with %s permission\n", current->stg_mode, desc);
3226 *any_failure = TRUE;
3231 static void check_access(LPCWSTR filename, const struct lock_test *current,
3232 DWORD access, DWORD sharing, const char *desc, DWORD open_mode, BOOL *any_failure)
3234 if (can_open(filename, open_mode, (FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE) & ~sharing))
3236 if (!current->todo || !(current->access & access))
3237 ok(!(current->access & access), "file with mode %x should not be openable without %s sharing\n", current->stg_mode, desc);
3238 else
3240 todo_wine ok(!(current->access & access), "file with mode %x should not be openable without %s sharing\n", current->stg_mode, desc);
3241 *any_failure = TRUE;
3244 else
3246 if (!current->todo || (current->access & access))
3247 ok(current->access & access, "file with mode %x should be openable without %s sharing\n", current->stg_mode, desc);
3248 else
3250 todo_wine ok(current->access & access, "file with mode %x should be openable without %s sharing\n", current->stg_mode, desc);
3251 *any_failure = TRUE;
3256 static void test_locking(void)
3258 static const WCHAR filename[] = {'w','i','n','e','t','e','s','t',0};
3259 int i;
3260 IStorage *stg;
3261 HRESULT hr;
3263 for (i=0; i<sizeof(lock_tests)/sizeof(lock_tests[0]); i++)
3265 const struct lock_test *current = &lock_tests[i];
3266 BOOL any_failure = FALSE;
3267 DWORD open_mode = 0;
3269 if (current->create)
3271 hr = StgCreateDocfile(filename, current->stg_mode, 0, &stg);
3272 ok(SUCCEEDED(hr), "StgCreateDocfile with mode %x failed with hr %x\n", current->stg_mode, hr);
3273 if (FAILED(hr)) continue;
3275 else
3277 hr = StgCreateDocfile(filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &stg);
3278 ok(SUCCEEDED(hr), "StgCreateDocfile failed with hr %x\n", hr);
3279 if (FAILED(hr)) continue;
3280 IStorage_Release(stg);
3282 hr = StgOpenStorage(filename, NULL, current->stg_mode, NULL, 0, &stg);
3283 ok(SUCCEEDED(hr), "StgOpenStorage with mode %x failed with hr %x\n", current->stg_mode, hr);
3284 if (FAILED(hr))
3286 DeleteFileW(filename);
3287 continue;
3291 check_sharing(filename, current, GENERIC_READ, FILE_SHARE_READ, "READ", &open_mode, &any_failure);
3292 check_sharing(filename, current, GENERIC_WRITE, FILE_SHARE_WRITE, "WRITE", &open_mode, &any_failure);
3293 check_sharing(filename, current, DELETE, FILE_SHARE_DELETE, "DELETE", &open_mode, &any_failure);
3295 if (open_mode != 0)
3297 HANDLE hfile;
3298 BOOL locked, expect_locked;
3299 OVERLAPPED ol;
3300 const int* next_lock = current->locked_bytes;
3302 check_access(filename, current, GENERIC_READ, FILE_SHARE_READ, "READ", open_mode, &any_failure);
3303 check_access(filename, current, GENERIC_WRITE, FILE_SHARE_WRITE, "WRITE", open_mode, &any_failure);
3304 check_access(filename, current, DELETE, FILE_SHARE_DELETE, "DELETE", open_mode, &any_failure);
3306 hfile = CreateFileW(filename, open_mode, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
3307 ok(hfile != INVALID_HANDLE_VALUE, "couldn't open file with mode %x\n", current->stg_mode);
3309 ol.u.s.OffsetHigh = 0;
3310 ol.hEvent = NULL;
3312 for (ol.u.s.Offset = 0x7fffff00; ol.u.s.Offset != 0x80000000; ol.u.s.Offset++)
3314 if (LockFileEx(hfile, LOCKFILE_EXCLUSIVE_LOCK|LOCKFILE_FAIL_IMMEDIATELY, 0, 1, 0, &ol))
3315 locked = FALSE;
3316 else
3318 ok(!LockFileEx(hfile, LOCKFILE_FAIL_IMMEDIATELY, 0, 1, 0, &ol), "shared locks should not be used\n");
3319 locked = TRUE;
3322 UnlockFileEx(hfile, 0, 1, 0, &ol);
3324 if ((ol.u.s.Offset&0xff) == *next_lock)
3326 expect_locked = TRUE;
3327 next_lock++;
3329 else
3330 expect_locked = FALSE;
3332 if (!current->todo || locked == expect_locked)
3333 ok(locked == expect_locked, "byte %x of file with mode %x is %slocked but should %sbe\n",
3334 ol.u.s.Offset, current->stg_mode, locked?"":"not ", expect_locked?"":"not ");
3335 else
3337 any_failure = TRUE;
3338 todo_wine ok(locked == expect_locked, "byte %x of file with mode %x is %slocked but should %sbe\n",
3339 ol.u.s.Offset, current->stg_mode, locked?"":"not ", expect_locked?"":"not ");
3343 CloseHandle(hfile);
3346 IStorage_Release( stg );
3348 if (!current->create)
3350 HANDLE hfile;
3351 BOOL failed, expect_failed=FALSE;
3352 OVERLAPPED ol;
3353 const int* next_range = current->fail_ranges;
3355 hfile = CreateFileW(filename, open_mode, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
3356 ok(hfile != INVALID_HANDLE_VALUE, "couldn't open file with mode %x\n", current->stg_mode);
3358 ol.u.s.OffsetHigh = 0;
3359 ol.hEvent = NULL;
3361 for (ol.u.s.Offset = 0x7fffff00; ol.u.s.Offset != 0x80000000; ol.u.s.Offset++)
3363 if (ol.u.s.Offset == 0x7fffff92 ||
3364 (ol.u.s.Offset == 0x7fffff80 && current->stg_mode == (STGM_TRANSACTED|STGM_READWRITE)) ||
3365 (ol.u.s.Offset == 0x7fffff80 && current->stg_mode == (STGM_TRANSACTED|STGM_READ)))
3366 continue; /* This makes opens hang */
3368 LockFileEx(hfile, LOCKFILE_EXCLUSIVE_LOCK, 0, 1, 0, &ol);
3370 hr = StgOpenStorage(filename, NULL, current->stg_mode, NULL, 0, &stg);
3371 ok(hr == S_OK || hr == STG_E_LOCKVIOLATION || hr == STG_E_SHAREVIOLATION, "failed with unexpected hr %x\n", hr);
3372 if (SUCCEEDED(hr)) IStorage_Release(stg);
3374 UnlockFileEx(hfile, 0, 1, 0, &ol);
3376 failed = FAILED(hr);
3378 if (!expect_failed && (ol.u.s.Offset&0xff) == next_range[0])
3380 expect_failed = TRUE;
3382 else if (expect_failed && (ol.u.s.Offset&0xff) == next_range[1])
3384 expect_failed = FALSE;
3385 next_range += 2;
3388 if (!current->todo || failed == expect_failed)
3389 ok(failed == expect_failed, "open with byte %x locked, mode %x %s but should %s\n",
3390 ol.u.s.Offset, current->stg_mode, failed?"failed":"succeeded", expect_failed?"fail":"succeed");
3391 else
3393 any_failure = TRUE;
3394 todo_wine ok(failed == expect_failed, "open with byte %x locked, mode %x %s but should %s\n",
3395 ol.u.s.Offset, current->stg_mode, failed?"failed":"succeeded", expect_failed?"fail":"succeed");
3399 CloseHandle(hfile);
3402 DeleteFileW(filename);
3404 if (current->todo && !any_failure)
3405 todo_wine ok(1, "tests succeeded for mode %x\n", current->stg_mode);
3409 static void test_transacted_shared(void)
3411 IStorage *stg = NULL;
3412 IStorage *stgrw = NULL;
3413 HRESULT r;
3414 IStream *stm = NULL;
3415 static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 };
3416 LARGE_INTEGER pos;
3417 ULARGE_INTEGER upos;
3418 char buffer[10];
3419 ULONG bytesread;
3421 DeleteFileA(filenameA);
3423 /* create a new transacted storage with a stream */
3424 r = StgCreateDocfile(filename, STGM_CREATE |
3425 STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
3426 ok(r==S_OK, "StgCreateDocfile failed %x\n", r);
3428 r = WriteClassStg(stg, &test_stg_cls);
3429 ok(r == S_OK, "WriteClassStg failed %x\n", r);
3431 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm);
3432 ok(r==S_OK, "IStorage->CreateStream failed %x\n", r);
3434 pos.QuadPart = 0;
3435 r = IStream_Seek(stm, pos, 0, &upos);
3436 ok(r==S_OK, "IStream->Seek failed %x\n", r);
3438 r = IStream_Write(stm, "aaa", 3, NULL);
3439 ok(r==S_OK, "IStream->Write failed %x\n", r);
3441 r = IStorage_Commit(stg, STGC_ONLYIFCURRENT);
3442 ok(r==S_OK, "IStorage->Commit failed %x\n", r);
3444 /* open a second transacted read/write storage */
3445 r = StgOpenStorage(filename, NULL, STGM_READWRITE | STGM_TRANSACTED | STGM_SHARE_DENY_NONE, NULL, 0, &stgrw);
3446 ok(r==S_OK, "StgOpenStorage failed %x\n", r);
3448 /* update stream on the first storage and commit */
3449 pos.QuadPart = 0;
3450 r = IStream_Seek(stm, pos, 0, &upos);
3451 ok(r==S_OK, "IStream->Seek failed %x\n", r);
3453 r = IStream_Write(stm, "ccc", 3, NULL);
3454 ok(r==S_OK, "IStream->Write failed %x\n", r);
3456 r = IStorage_Commit(stg, STGC_ONLYIFCURRENT);
3457 ok(r==S_OK, "IStorage->Commit failed %x\n", r);
3459 /* update again without committing */
3460 pos.QuadPart = 0;
3461 r = IStream_Seek(stm, pos, 0, &upos);
3462 ok(r==S_OK, "IStream->Seek failed %x\n", r);
3464 r = IStream_Write(stm, "ddd", 3, NULL);
3465 ok(r==S_OK, "IStream->Write failed %x\n", r);
3467 IStream_Release(stm);
3469 /* we can still read the old content from the second storage */
3470 r = IStorage_OpenStream(stgrw, stmname, NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &stm);
3471 ok(r==S_OK, "IStorage->OpenStream failed %x\n", r);
3473 pos.QuadPart = 0;
3474 r = IStream_Seek(stm, pos, 0, &upos);
3475 ok(r==S_OK, "IStream->Seek failed %x\n", r);
3477 r = IStream_Read(stm, buffer, sizeof(buffer), &bytesread);
3478 ok(r==S_OK, "IStream->Read failed %x\n", r);
3479 ok(bytesread == 3, "read wrong number of bytes %i\n", bytesread);
3480 ok(memcmp(buffer, "aaa", 3) == 0, "wrong data\n");
3482 /* and overwrite the data */
3483 pos.QuadPart = 0;
3484 r = IStream_Seek(stm, pos, 0, &upos);
3485 ok(r==S_OK, "IStream->Seek failed %x\n", r);
3487 r = IStream_Write(stm, "bbb", 3, NULL);
3488 ok(r==S_OK, "IStream->Write failed %x\n", r);
3490 IStream_Release(stm);
3492 /* commit fails because we're out of date */
3493 r = IStorage_Commit(stgrw, STGC_ONLYIFCURRENT);
3494 todo_wine ok(r==STG_E_NOTCURRENT, "IStorage->Commit failed %x\n", r);
3496 /* unless we force it */
3497 r = IStorage_Commit(stgrw, STGC_DEFAULT);
3498 ok(r==S_OK, "IStorage->Commit failed %x\n", r);
3500 /* reverting gets us back to the last commit from the same storage */
3501 r = IStorage_Revert(stg);
3502 ok(r==S_OK, "IStorage->Revert failed %x\n", r);
3504 r = IStorage_OpenStream(stg, stmname, NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &stm);
3505 ok(r==S_OK, "IStorage->CreateStream failed %x\n", r);
3507 pos.QuadPart = 0;
3508 r = IStream_Seek(stm, pos, 0, &upos);
3509 ok(r==S_OK, "IStream->Seek failed %x\n", r);
3511 r = IStream_Read(stm, buffer, sizeof(buffer), &bytesread);
3512 ok(r==S_OK, "IStream->Read failed %x\n", r);
3513 ok(bytesread == 3, "read wrong number of bytes %i\n", bytesread);
3514 ok(memcmp(buffer, "ccc", 3) == 0, "wrong data\n");
3516 /* and committing fails forever */
3517 r = IStorage_Commit(stg, STGC_ONLYIFCURRENT);
3518 todo_wine ok(r==STG_E_NOTCURRENT, "IStorage->Commit failed %x\n", r);
3520 IStream_Release(stm);
3522 IStorage_Release(stg);
3523 IStorage_Release(stgrw);
3525 DeleteFileA(filenameA);
3528 START_TEST(storage32)
3530 CHAR temp[MAX_PATH];
3532 GetTempPathA(MAX_PATH, temp);
3533 if(!GetTempFileNameA(temp, "stg", 0, filenameA))
3535 win_skip("Could not create temp file, %u\n", GetLastError());
3536 return;
3538 MultiByteToWideChar(CP_ACP, 0, filenameA, -1, filename, MAX_PATH);
3539 DeleteFileA(filenameA);
3541 test_hglobal_storage_stat();
3542 test_create_storage_modes();
3543 test_stgcreatestorageex();
3544 test_storage_stream();
3545 test_open_storage();
3546 test_storage_suminfo();
3547 test_storage_refcount();
3548 test_streamenum();
3549 test_transact();
3550 test_substorage_share();
3551 test_revert();
3552 test_parent_free();
3553 test_nonroot_transacted();
3554 test_ReadClassStm();
3555 test_access();
3556 test_writeclassstg();
3557 test_readonly();
3558 test_simple();
3559 test_fmtusertypestg();
3560 test_references();
3561 test_copyto();
3562 test_copyto_snbexclusions();
3563 test_copyto_iidexclusions_storage();
3564 test_copyto_iidexclusions_stream();
3565 test_rename();
3566 test_toplevel_stat();
3567 test_substorage_enum();
3568 test_copyto_locking();
3569 test_copyto_recursive();
3570 test_hglobal_storage_creation();
3571 test_convert();
3572 test_direct_swmr();
3573 test_locking();
3574 test_transacted_shared();