oledb32: Support DBSTATUS_S_ISNULL when converting to VARIANT.
[wine.git] / dlls / ole32 / tests / storage32.c
blob4f12d8b419381b651ce303dc5522bd6d1e28e014
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
25 #include <windows.h>
26 #include "wine/test.h"
28 #include "ole2.h"
29 #include "objidl.h"
30 #include "initguid.h"
32 DEFINE_GUID( test_stg_cls, 0x88888888, 0x0425, 0x0000, 0,0,0,0,0,0,0,0);
34 #define ok_ole_success(hr, func) ok(hr == S_OK, func " failed with error 0x%08x\n", hr)
36 static CHAR filenameA[MAX_PATH];
37 static WCHAR filename[MAX_PATH];
39 static const char file1_nameA[] = {'c','o','p','y','t','e','s','t','A',0};
40 static const WCHAR file1_name[] = {'c','o','p','y','t','e','s','t','A',0};
41 static const char file2_nameA[] = {'c','o','p','y','t','e','s','t','B',0};
42 static const WCHAR file2_name[] = {'c','o','p','y','t','e','s','t','B',0};
43 static const WCHAR stgA_name[] = {'S','t','o','r','a','g','e','A',0};
44 static const WCHAR stgB_name[] = {'S','t','o','r','a','g','e','B',0};
45 static const WCHAR strmA_name[] = {'S','t','r','e','a','m','A',0};
46 static const WCHAR strmB_name[] = {'S','t','r','e','a','m','B',0};
47 static const WCHAR strmC_name[] = {'S','t','r','e','a','m','C',0};
49 /* Win9x and WinMe don't have lstrcmpW */
50 static int strcmp_ww(LPCWSTR strw1, LPCWSTR strw2)
52 CHAR stra1[512], stra2[512];
53 WideCharToMultiByte(CP_ACP, 0, strw1, -1, stra1, sizeof(stra1), NULL, NULL);
54 WideCharToMultiByte(CP_ACP, 0, strw2, -1, stra2, sizeof(stra2), NULL, NULL);
55 return lstrcmpA(stra1, stra2);
58 static void test_hglobal_storage_stat(void)
60 ILockBytes *ilb = NULL;
61 IStorage *stg = NULL;
62 HRESULT r;
63 STATSTG stat;
64 DWORD mode, refcount;
66 r = CreateILockBytesOnHGlobal( NULL, TRUE, &ilb );
67 ok( r == S_OK, "CreateILockBytesOnHGlobal failed\n");
69 r = StgIsStorageILockBytes( ilb );
70 ok( r == S_FALSE, "StgIsStorageILockBytes should have failed\n");
72 mode = STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE;/*0x1012*/
73 r = StgCreateDocfileOnILockBytes( ilb, mode, 0, &stg );
74 ok( r == S_OK, "StgCreateDocfileOnILockBytes failed\n");
76 r = WriteClassStg( stg, &test_stg_cls );
77 ok( r == S_OK, "WriteClassStg failed\n");
79 r = StgIsStorageILockBytes( ilb );
80 ok( r == S_OK, "StgIsStorageILockBytes failed\n");
82 memset( &stat, 0, sizeof stat );
83 r = IStorage_Stat( stg, &stat, 0 );
85 ok( stat.pwcsName == NULL, "storage name not null\n");
86 ok( stat.type == 1, "type is wrong\n");
87 ok( stat.grfMode == 0x12, "grf mode is incorrect\n");
88 ok( !memcmp(&stat.clsid, &test_stg_cls, sizeof test_stg_cls), "CLSID is wrong\n");
90 refcount = IStorage_Release( stg );
91 ok( refcount == 0, "IStorage refcount is wrong\n");
92 refcount = ILockBytes_Release( ilb );
93 ok( refcount == 0, "ILockBytes refcount is wrong\n");
96 static void test_create_storage_modes(void)
98 IStorage *stg = NULL;
99 HRESULT r;
101 DeleteFileA(filenameA);
103 /* test with some invalid parameters */
104 r = StgCreateDocfile( NULL, 0, 0, &stg);
105 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
106 r = StgCreateDocfile( filename, 0, 0, &stg);
107 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
108 r = StgCreateDocfile( filename, STGM_CREATE, 0, &stg);
109 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
110 r = StgCreateDocfile( filename, STGM_CREATE | STGM_READWRITE, 0, &stg);
111 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
112 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE, 0, &stg);
113 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
114 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, NULL);
115 ok(r==STG_E_INVALIDPOINTER, "StgCreateDocfile succeeded\n");
116 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 1, &stg);
117 ok(r==STG_E_INVALIDPARAMETER, "StgCreateDocfile succeeded\n");
118 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_DENY_WRITE | STGM_READWRITE, 0, &stg);
119 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
120 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READ, 0, &stg);
121 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
122 r = StgCreateDocfile( filename, STGM_PRIORITY, 0, &stg);
123 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
125 /* StgCreateDocfile seems to be very particular about the flags it accepts */
126 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED | STGM_WRITE, 0, &stg);
127 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
128 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED | 8, 0, &stg);
129 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
130 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED | 0x80, 0, &stg);
131 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
132 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED | 0x800, 0, &stg);
133 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
134 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED | 0x8000, 0, &stg);
135 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
136 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED | 0x80000, 0, &stg);
137 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
138 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED | 0x800000, 0, &stg);
139 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
140 ok(stg == NULL, "stg was set\n");
142 /* check what happens if the file already exists (which is how it's meant to be used) */
143 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &stg);
144 ok(r==S_OK, "StgCreateDocfile failed\n");
145 r = IStorage_Release(stg);
146 ok(r == 0, "storage not released\n");
147 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
148 ok(r==STG_E_FILEALREADYEXISTS, "StgCreateDocfile wrong error\n"); /* FAILIFTHERE is default */
149 r = StgCreateDocfile( filename, STGM_READ, 0, &stg);
150 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n"); /* need at least readmode and sharemode */
151 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE, 0, &stg);
152 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
153 r = StgCreateDocfile( filename, STGM_SHARE_DENY_WRITE, 0, &stg);
154 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
155 r = StgCreateDocfile( filename, STGM_SHARE_DENY_NONE, 0, &stg);
156 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile failed\n");
157 r = StgCreateDocfile( filename, STGM_SHARE_DENY_NONE | STGM_TRANSACTED, 0, &stg);
158 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile failed\n");
159 r = StgCreateDocfile( filename, STGM_SHARE_DENY_NONE | STGM_READWRITE, 0, &stg);
160 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile failed\n");
161 r = StgCreateDocfile( filename, STGM_SHARE_DENY_NONE | STGM_WRITE, 0, &stg);
162 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile failed\n");
163 r = StgCreateDocfile( filename, STGM_SHARE_DENY_WRITE | STGM_WRITE, 0, &stg);
164 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile failed\n");
165 r = StgCreateDocfile( filename, STGM_SHARE_DENY_WRITE | STGM_READ, 0, &stg);
166 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile wrong error\n");
167 r = StgCreateDocfile( filename, STGM_TRANSACTED | STGM_SHARE_DENY_WRITE | STGM_READ, 0, &stg);
168 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile wrong error\n");
169 ok(DeleteFileA(filenameA), "failed to delete file\n");
171 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
172 ok(r==S_OK, "StgCreateDocfile failed\n");
173 r = IStorage_Release(stg);
174 ok(r == 0, "storage not released\n");
175 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED |STGM_FAILIFTHERE, 0, &stg);
176 ok(r==STG_E_FILEALREADYEXISTS, "StgCreateDocfile wrong error\n");
177 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_WRITE, 0, &stg);
178 ok(r==STG_E_FILEALREADYEXISTS, "StgCreateDocfile wrong error\n");
180 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_DENY_WRITE | STGM_READWRITE, 0, &stg);
181 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
182 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
183 ok(r==S_OK, "StgCreateDocfile failed\n");
184 r = IStorage_Release(stg);
185 ok(r == 0, "storage not released\n");
186 ok(DeleteFileA(filenameA), "failed to delete file\n");
188 r = StgCreateDocfile( filename, STGM_CREATE | STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
189 ok(r==S_OK, "StgCreateDocfile failed\n");
190 r = IStorage_Release(stg);
191 ok(r == 0, "storage not released\n");
192 ok(DeleteFileA(filenameA), "failed to delete file\n");
194 /* test the way excel uses StgCreateDocFile */
195 r = StgCreateDocfile( filename, STGM_TRANSACTED|STGM_CREATE|STGM_SHARE_DENY_WRITE|STGM_READWRITE, 0, &stg);
196 ok(r==S_OK, "StgCreateDocfile the excel way failed\n");
197 if(r == S_OK)
199 r = IStorage_Release(stg);
200 ok(r == 0, "storage not released\n");
201 ok(DeleteFileA(filenameA), "failed to delete file\n");
204 /* and the way windows media uses it ... */
205 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_DENY_NONE | STGM_READWRITE | STGM_TRANSACTED, 0, &stg);
206 ok(r==S_OK, "StgCreateDocfile the windows media way failed\n");
207 if (r == S_OK)
209 r = IStorage_Release(stg);
210 ok(r == 0, "storage not released\n");
211 ok(DeleteFileA(filenameA), "failed to delete file\n");
214 /* looks like we need STGM_TRANSACTED or STGM_CREATE */
215 r = StgCreateDocfile( filename, STGM_TRANSACTED|STGM_SHARE_DENY_WRITE|STGM_READWRITE, 0, &stg);
216 ok(r==S_OK, "StgCreateDocfile the excel way failed\n");
217 if(r == S_OK)
219 r = IStorage_Release(stg);
220 ok(r == 0, "storage not released\n");
221 ok(DeleteFileA(filenameA), "failed to delete file\n");
224 r = StgCreateDocfile( filename, STGM_TRANSACTED|STGM_CREATE|STGM_SHARE_DENY_WRITE|STGM_WRITE, 0, &stg);
225 ok(r==S_OK, "StgCreateDocfile the excel way failed\n");
226 if(r == S_OK)
228 r = IStorage_Release(stg);
229 ok(r == 0, "storage not released\n");
230 ok(DeleteFileA(filenameA), "failed to delete file\n");
233 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &stg);
234 ok(r==S_OK, "StgCreateDocfile the powerpoint way failed\n");
235 if(r == S_OK)
237 r = IStorage_Release(stg);
238 ok(r == 0, "storage not released\n");
239 ok(DeleteFileA(filenameA), "failed to delete file\n");
242 /* test the way msi uses StgCreateDocfile */
243 r = StgCreateDocfile( filename, STGM_DIRECT | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &stg);
244 ok(r==S_OK, "StgCreateDocFile failed\n");
245 r = IStorage_Release(stg);
246 ok(r == 0, "storage not released\n");
247 ok(DeleteFileA(filenameA), "failed to delete file\n");
250 static void test_stgcreatestorageex(void)
252 HRESULT (WINAPI *pStgCreateStorageEx)(const WCHAR* pwcsName, DWORD grfMode, DWORD stgfmt, DWORD grfAttrs, STGOPTIONS* pStgOptions, void* reserved, REFIID riid, void** ppObjectOpen);
253 HMODULE hOle32 = GetModuleHandle("ole32");
254 IStorage *stg = NULL;
255 STGOPTIONS stgoptions = {1, 0, 4096};
256 HRESULT r;
258 pStgCreateStorageEx = (void *) GetProcAddress(hOle32, "StgCreateStorageEx");
259 if (!pStgCreateStorageEx)
261 win_skip("skipping test on NT4\n");
262 return;
265 DeleteFileA(filenameA);
267 /* Verify that StgCreateStorageEx can accept an options param */
268 r = pStgCreateStorageEx( filename,
269 STGM_SHARE_EXCLUSIVE | STGM_READWRITE,
270 STGFMT_DOCFILE,
272 &stgoptions,
273 NULL,
274 &IID_IStorage,
275 (void **) &stg);
276 ok(r==S_OK || r==STG_E_UNIMPLEMENTEDFUNCTION, "StgCreateStorageEx with options failed\n");
277 if (r==STG_E_UNIMPLEMENTEDFUNCTION)
279 /* We're on win98 which means all bets are off. Let's get out of here. */
280 win_skip("skipping test on win9x\n");
281 return;
284 r = IStorage_Release(stg);
285 ok(r == 0, "storage not released\n");
286 ok(DeleteFileA(filenameA), "failed to delete file\n");
288 /* Verify that StgCreateStorageEx can accept a NULL pStgOptions */
289 r = pStgCreateStorageEx( filename,
290 STGM_SHARE_EXCLUSIVE | STGM_READWRITE,
291 STGFMT_STORAGE,
293 NULL,
294 NULL,
295 &IID_IStorage,
296 (void **) &stg);
297 ok(r==S_OK, "StgCreateStorageEx with NULL options failed\n");
298 r = IStorage_Release(stg);
299 ok(r == 0, "storage not released\n");
300 ok(DeleteFileA(filenameA), "failed to delete file\n");
303 static void test_storage_stream(void)
305 static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 };
306 static const WCHAR longname[] = {
307 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
308 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',0
310 IStorage *stg = NULL;
311 HRESULT r;
312 IStream *stm = NULL;
313 IStream *stm2 = NULL;
314 ULONG count = 0;
315 LARGE_INTEGER pos;
316 ULARGE_INTEGER p;
317 unsigned char buffer[0x100];
318 IUnknown *unk;
320 DeleteFileA(filenameA);
322 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
323 ok(r==S_OK, "StgCreateDocfile failed\n");
325 /* try create some invalid streams */
326 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 1, 0, &stm );
327 ok(r==STG_E_INVALIDPARAMETER, "IStorage->CreateStream wrong error\n");
328 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 1, &stm );
329 ok(r==STG_E_INVALIDPARAMETER, "IStorage->CreateStream wrong error\n");
330 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, NULL );
331 ok(r==STG_E_INVALIDPOINTER, "IStorage->CreateStream wrong error\n");
332 r = IStorage_CreateStream(stg, NULL, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
333 ok(r==STG_E_INVALIDNAME, "IStorage->CreateStream wrong error\n");
334 r = IStorage_CreateStream(stg, longname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
335 ok(r==STG_E_INVALIDNAME || broken(r==S_OK) /* nt4 */,
336 "IStorage->CreateStream wrong error, got %d GetLastError()=%d\n", r, GetLastError());
337 r = IStorage_CreateStream(stg, stmname, STGM_READWRITE, 0, 0, &stm );
338 ok(r==STG_E_INVALIDFLAG, "IStorage->CreateStream wrong error\n");
339 r = IStorage_CreateStream(stg, stmname, STGM_READ, 0, 0, &stm );
340 ok(r==STG_E_INVALIDFLAG, "IStorage->CreateStream wrong error\n");
341 r = IStorage_CreateStream(stg, stmname, STGM_WRITE, 0, 0, &stm );
342 ok(r==STG_E_INVALIDFLAG, "IStorage->CreateStream wrong error\n");
343 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_DENY_NONE | STGM_READWRITE, 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_READ, 0, 0, &stm );
346 ok(r==STG_E_INVALIDFLAG, "IStorage->CreateStream wrong error\n");
348 /* now really create a stream and delete it */
349 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
350 ok(r==S_OK, "IStorage->CreateStream failed\n");
352 /* test for support interfaces */
353 r = IStream_QueryInterface(stm, &IID_IPersist, (void**)&unk);
354 ok(r==E_NOINTERFACE, "got 0x%08x\n", r);
355 r = IStream_QueryInterface(stm, &IID_IPersistStream, (void**)&unk);
356 ok(r==E_NOINTERFACE, "got 0x%08x\n", r);
358 r = IStream_Release(stm);
359 ok(r == 0, "wrong ref count\n");
360 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
361 ok(r==STG_E_FILEALREADYEXISTS, "IStorage->CreateStream failed\n");
362 r = IStorage_DestroyElement(stg,stmname);
363 ok(r==S_OK, "IStorage->DestroyElement failed\n");
365 /* create a stream and write to it */
366 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
367 ok(r==S_OK, "IStorage->CreateStream failed\n");
369 r = IStream_Clone(stm, &stm2);
370 ok(r==S_OK, "failed to clone stream\n");
372 r = IStream_Write(stm, NULL, 0, NULL );
373 ok(r==STG_E_INVALIDPOINTER, "IStream->Write wrong error\n");
374 r = IStream_Write(stm, "Hello\n", 0, NULL );
375 ok(r==S_OK, "failed to write stream\n");
376 r = IStream_Write(stm, "Hello\n", 0, &count );
377 ok(r==S_OK, "failed to write stream\n");
378 r = IStream_Write(stm, "Hello\n", 6, &count );
379 ok(r==S_OK, "failed to write stream\n");
380 r = IStream_Commit(stm, STGC_DEFAULT );
381 ok(r==S_OK, "failed to commit stream\n");
382 r = IStream_Commit(stm, STGC_DEFAULT );
383 ok(r==S_OK, "failed to commit stream\n");
385 /* Read past the end of the stream. */
386 pos.QuadPart = 3;
387 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p );
388 ok(r==S_OK, "failed to seek stream\n");
389 ok(p.QuadPart == 3, "at wrong place\n");
390 r = IStream_Read(stm, buffer, sizeof buffer, &count );
391 ok(r==S_OK, "failed to read\n");
392 ok(count == 3, "read bytes past end of stream\n");
393 pos.QuadPart = 10;
394 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p );
395 ok(r==S_OK, "failed to seek stream\n");
396 ok(p.QuadPart == 10, "at wrong place\n");
397 r = IStream_Read(stm, buffer, sizeof buffer, &count );
398 ok(r==S_OK, "failed to read\n");
399 ok(count == 0, "read bytes past end of stream\n");
400 pos.QuadPart = 10000;
401 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p );
402 ok(r==S_OK, "failed to seek stream\n");
403 ok(p.QuadPart == 10000, "at wrong place\n");
404 r = IStream_Read(stm, buffer, sizeof buffer, &count );
405 ok(r==S_OK, "failed to read\n");
406 ok(count == 0, "read bytes past end of stream\n");
408 /* Convert to a big block stream, and read past the end. */
409 p.QuadPart = 5000;
410 r = IStream_SetSize(stm,p);
411 ok(r==S_OK, "failed to set pos\n");
412 pos.QuadPart = 4997;
413 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p );
414 ok(r==S_OK, "failed to seek stream\n");
415 ok(p.QuadPart == 4997, "at wrong place\n");
416 r = IStream_Read(stm, buffer, sizeof buffer, &count );
417 ok(r==S_OK, "failed to read\n");
418 ok(count == 3, "read bytes past end of stream\n");
419 pos.QuadPart = 5001;
420 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p );
421 ok(r==S_OK, "failed to seek stream\n");
422 ok(p.QuadPart == 5001, "at wrong place\n");
423 r = IStream_Read(stm, buffer, sizeof buffer, &count );
424 ok(r==S_OK, "failed to read\n");
425 ok(count == 0, "read bytes past end of stream\n");
426 pos.QuadPart = 10000;
427 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p );
428 ok(r==S_OK, "failed to seek stream\n");
429 ok(p.QuadPart == 10000, "at wrong place\n");
430 r = IStream_Read(stm, buffer, sizeof buffer, &count );
431 ok(r==S_OK, "failed to read\n");
432 ok(count == 0, "read bytes past end of stream\n");
434 /* seek round a bit, reset the stream size */
435 pos.QuadPart = 0;
436 r = IStream_Seek(stm, pos, 3, &p );
437 ok(r==STG_E_INVALIDFUNCTION, "IStream->Seek returned wrong error\n");
438 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, NULL);
439 ok(r==S_OK, "failed to seek stream\n");
440 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p );
441 ok(r==S_OK, "failed to seek stream\n");
442 r = IStream_SetSize(stm,p);
443 ok(r==S_OK, "failed to set pos\n");
444 pos.QuadPart = 10;
445 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p );
446 ok(r==S_OK, "failed to seek stream\n");
447 ok(p.QuadPart == 10, "at wrong place\n");
448 r = IStream_Read(stm, buffer, sizeof buffer, &count );
449 ok(r==S_OK, "failed to set pos\n");
450 ok(count == 0, "read bytes from empty stream\n");
451 pos.QuadPart = 10000;
452 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p );
453 ok(r==S_OK, "failed to seek stream\n");
454 ok(p.QuadPart == 10000, "at wrong place\n");
455 r = IStream_Read(stm, buffer, sizeof buffer, &count );
456 ok(r==S_OK, "failed to set pos\n");
457 ok(count == 0, "read bytes from empty stream\n");
458 pos.QuadPart = 0;
459 r = IStream_Seek(stm, pos, STREAM_SEEK_END, &p );
460 ok(r==S_OK, "failed to seek stream\n");
461 ok(p.QuadPart == 0, "at wrong place\n");
462 r = IStream_Read(stm, buffer, sizeof buffer, &count );
463 ok(r==S_OK, "failed to set pos\n");
464 ok(count == 0, "read bytes from empty stream\n");
466 /* wrap up */
467 r = IStream_Release(stm2);
468 ok(r == 0, "wrong ref count\n");
470 /* create a stream and write to it */
471 r = IStorage_CreateStream(stg, stmname, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm2 );
472 ok(r==S_OK, "IStorage->CreateStream failed\n");
474 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p);
475 ok(r==STG_E_REVERTED, "overwritten stream should return STG_E_REVERTED instead of 0x%08x\n", r);
477 r = IStream_Release(stm2);
478 ok(r == 0, "wrong ref count\n");
479 r = IStream_Release(stm);
480 ok(r == 0, "wrong ref count\n");
482 r = IStorage_Release(stg);
483 ok(r == 0, "wrong ref count\n");
485 /* try create some invalid streams */
486 stg = NULL;
487 stm = NULL;
488 r = StgOpenStorage(filename, NULL, STGM_READ | STGM_SHARE_DENY_WRITE, NULL, 0, &stg);
489 ok(r == S_OK, "should succeed\n");
490 if (stg)
492 r = IStorage_OpenStream(stg, stmname, NULL, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &stm);
493 ok(r == STG_E_INVALIDFLAG, "IStorage->OpenStream should return STG_E_INVALIDFLAG instead of 0x%08x\n", r);
494 IStorage_Release(stg);
497 r = DeleteFileA(filenameA);
498 ok(r, "file should exist\n");
501 static BOOL touch_file(LPCSTR filename)
503 HANDLE file;
505 file = CreateFileA(filename, GENERIC_READ|GENERIC_WRITE, 0, NULL,
506 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
507 if (file==INVALID_HANDLE_VALUE)
508 return FALSE;
509 CloseHandle(file);
510 return TRUE;
513 static BOOL is_zero_length(LPCSTR filename)
515 HANDLE file;
516 DWORD len;
518 file = CreateFileA(filename, GENERIC_READ, 0, NULL,
519 OPEN_EXISTING, 0, NULL);
520 if (file==INVALID_HANDLE_VALUE)
521 return FALSE;
522 len = GetFileSize(file, NULL);
523 CloseHandle(file);
524 return len == 0;
527 static BOOL is_existing_file(LPCSTR filename)
529 HANDLE file;
531 file = CreateFileA(filename, GENERIC_READ, 0, NULL,
532 OPEN_EXISTING, 0, NULL);
533 if (file==INVALID_HANDLE_VALUE)
534 return FALSE;
535 CloseHandle(file);
536 return TRUE;
539 static void test_open_storage(void)
541 static const WCHAR szNonExist[] = { 'n','o','n','e','x','i','s','t',0 };
542 IStorage *stg = NULL, *stg2 = NULL;
543 HRESULT r;
544 DWORD stgm;
546 /* try opening a zero length file - it should stay zero length */
547 DeleteFileA(filenameA);
548 touch_file(filenameA);
549 stgm = STGM_NOSCRATCH | STGM_TRANSACTED | STGM_SHARE_DENY_WRITE | STGM_READWRITE;
550 r = StgOpenStorage( filename, NULL, stgm, NULL, 0, &stg);
551 ok(r==STG_E_FILEALREADYEXISTS, "StgOpenStorage didn't fail\n");
553 stgm = STGM_SHARE_EXCLUSIVE | STGM_READWRITE;
554 r = StgOpenStorage( filename, NULL, stgm, NULL, 0, &stg);
555 ok(r==STG_E_FILEALREADYEXISTS, "StgOpenStorage didn't fail\n");
556 ok(is_zero_length(filenameA), "file length changed\n");
558 DeleteFileA(filenameA);
560 /* try opening a nonexistent file - it should not create it */
561 stgm = STGM_DIRECT | STGM_SHARE_EXCLUSIVE | STGM_READWRITE;
562 r = StgOpenStorage( filename, NULL, stgm, NULL, 0, &stg);
563 ok(r!=S_OK, "StgOpenStorage failed: 0x%08x\n", r);
564 if (r==S_OK) IStorage_Release(stg);
565 ok(!is_existing_file(filenameA), "StgOpenStorage should not create a file\n");
566 DeleteFileA(filenameA);
568 /* create the file */
569 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
570 ok(r==S_OK, "StgCreateDocfile failed\n");
571 IStorage_Release(stg);
573 r = StgOpenStorage( filename, NULL, 0, NULL, 0, &stg);
574 ok(r==STG_E_INVALIDFLAG, "StgOpenStorage wrong error\n");
575 r = StgOpenStorage( NULL, NULL, STGM_SHARE_EXCLUSIVE, NULL, 0, &stg);
576 ok(r==STG_E_INVALIDNAME, "StgOpenStorage wrong error\n");
577 r = StgOpenStorage( filename, NULL, STGM_SHARE_EXCLUSIVE | STGM_READ, NULL, 0, NULL);
578 ok(r==STG_E_INVALIDPOINTER, "StgOpenStorage wrong error\n");
579 r = StgOpenStorage( filename, NULL, STGM_SHARE_EXCLUSIVE | STGM_READ, NULL, 1, &stg);
580 ok(r==STG_E_INVALIDPARAMETER, "StgOpenStorage wrong error\n");
581 r = StgOpenStorage( szNonExist, NULL, STGM_SHARE_EXCLUSIVE | STGM_READ, NULL, 0, &stg);
582 ok(r==STG_E_FILENOTFOUND, "StgOpenStorage failed\n");
583 r = StgOpenStorage( filename, NULL, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READ, NULL, 0, &stg);
584 ok(r==STG_E_INVALIDFLAG, "StgOpenStorage failed\n");
585 r = StgOpenStorage( filename, NULL, STGM_SHARE_DENY_NONE | STGM_READ, NULL, 0, &stg);
586 ok(r==STG_E_INVALIDFLAG, "StgOpenStorage failed\n");
587 r = StgOpenStorage( filename, NULL, STGM_SHARE_DENY_READ | STGM_READ, NULL, 0, &stg);
588 ok(r==STG_E_INVALIDFLAG, "StgOpenStorage failed\n");
589 r = StgOpenStorage( filename, NULL, STGM_SHARE_DENY_WRITE | STGM_READWRITE, NULL, 0, &stg);
590 ok(r==STG_E_INVALIDFLAG, "StgOpenStorage failed\n");
592 /* open it for real */
593 r = StgOpenStorage( filename, NULL, STGM_SHARE_DENY_NONE | STGM_READ | STGM_TRANSACTED, NULL, 0, &stg); /* XLViewer 97/2000 */
594 ok(r==S_OK, "StgOpenStorage failed\n");
595 if(stg)
597 r = IStorage_Release(stg);
598 ok(r == 0, "wrong ref count\n");
601 r = StgOpenStorage( filename, NULL, STGM_SHARE_DENY_WRITE | STGM_READ, NULL, 0, &stg);
602 ok(r==S_OK, "StgOpenStorage failed\n");
603 if(stg)
605 r = IStorage_Release(stg);
606 ok(r == 0, "wrong ref count\n");
609 /* test the way word opens its custom dictionary */
610 r = StgOpenStorage( filename, NULL, STGM_NOSCRATCH | STGM_TRANSACTED |
611 STGM_SHARE_DENY_WRITE | STGM_READWRITE, NULL, 0, &stg);
612 ok(r==S_OK, "StgOpenStorage failed\n");
613 if(stg)
615 r = IStorage_Release(stg);
616 ok(r == 0, "wrong ref count\n");
619 r = StgOpenStorage( filename, NULL, STGM_SHARE_EXCLUSIVE | STGM_READ, NULL, 0, &stg);
620 ok(r==S_OK, "StgOpenStorage failed\n");
621 r = StgOpenStorage( filename, NULL, STGM_SHARE_EXCLUSIVE | STGM_READ, NULL, 0, &stg2);
622 ok(r==STG_E_SHAREVIOLATION, "StgOpenStorage failed\n");
623 if(stg)
625 r = IStorage_Release(stg);
626 ok(r == 0, "wrong ref count\n");
629 /* now try write to a storage file we opened read-only */
630 r = StgOpenStorage( filename, NULL, STGM_SHARE_EXCLUSIVE | STGM_READ, NULL, 0, &stg);
631 ok(r==S_OK, "StgOpenStorage failed\n");
632 if(stg)
634 static const WCHAR stmname[] = { 'w','i','n','e','t','e','s','t',0};
635 IStream *stm = NULL;
636 IStorage *stg2 = NULL;
638 r = IStorage_CreateStream( stg, stmname, STGM_WRITE | STGM_SHARE_EXCLUSIVE,
639 0, 0, &stm );
640 ok(r == STG_E_ACCESSDENIED, "CreateStream should fail\n");
641 r = IStorage_CreateStorage( stg, stmname, STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg2);
642 ok(r == STG_E_ACCESSDENIED, "CreateStream should fail\n");
644 r = IStorage_Release(stg);
645 ok(r == 0, "wrong ref count\n");
648 /* open like visio 2003 */
649 stg = NULL;
650 r = StgOpenStorage( filename, NULL, STGM_PRIORITY | STGM_SHARE_DENY_NONE, NULL, 0, &stg);
651 ok(r == S_OK, "should succeed\n");
652 if (stg)
653 IStorage_Release(stg);
655 /* test other sharing modes with STGM_PRIORITY */
656 stg = NULL;
657 r = StgOpenStorage( filename, NULL, STGM_PRIORITY | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg);
658 ok(r == S_OK, "should succeed\n");
659 if (stg)
660 IStorage_Release(stg);
662 stg = NULL;
663 r = StgOpenStorage( filename, NULL, STGM_PRIORITY | STGM_SHARE_DENY_WRITE, NULL, 0, &stg);
664 ok(r == S_OK, "should succeed\n");
665 if (stg)
666 IStorage_Release(stg);
668 stg = NULL;
669 r = StgOpenStorage( filename, NULL, STGM_PRIORITY | STGM_SHARE_DENY_READ, NULL, 0, &stg);
670 ok(r == S_OK, "should succeed\n");
671 if (stg)
672 IStorage_Release(stg);
674 /* open like Project 2003 */
675 stg = NULL;
676 r = StgOpenStorage( filename, NULL, STGM_PRIORITY, NULL, 0, &stg);
677 ok(r == S_OK, "should succeed\n");
678 r = StgOpenStorage( filename, NULL, STGM_PRIORITY, NULL, 0, &stg2);
679 ok(r == S_OK, "should succeed\n");
680 if (stg2)
681 IStorage_Release(stg2);
682 if (stg)
683 IStorage_Release(stg);
685 stg = NULL;
686 r = StgOpenStorage( filename, NULL, STGM_PRIORITY | STGM_READWRITE, NULL, 0, &stg);
687 ok(r == STG_E_INVALIDFLAG, "should fail\n");
689 r = StgOpenStorage( filename, NULL, STGM_TRANSACTED | STGM_PRIORITY, NULL, 0, &stg);
690 ok(r == STG_E_INVALIDFLAG, "should fail\n");
692 r = StgOpenStorage( filename, NULL, STGM_SIMPLE | STGM_PRIORITY, NULL, 0, &stg);
693 ok(r == STG_E_INVALIDFLAG, "should fail\n");
695 r = StgOpenStorage( filename, NULL, STGM_DELETEONRELEASE | STGM_PRIORITY, NULL, 0, &stg);
696 ok(r == STG_E_INVALIDFUNCTION, "should fail\n");
698 r = StgOpenStorage( filename, NULL, STGM_NOSCRATCH | STGM_PRIORITY, NULL, 0, &stg);
699 ok(r == STG_E_INVALIDFLAG, "should fail\n");
701 r = StgOpenStorage( filename, NULL, STGM_NOSNAPSHOT | STGM_PRIORITY, NULL, 0, &stg);
702 ok(r == STG_E_INVALIDFLAG, "should fail\n");
704 r = DeleteFileA(filenameA);
705 ok(r, "file didn't exist\n");
708 static void test_storage_suminfo(void)
710 IStorage *stg = NULL;
711 IPropertySetStorage *propset = NULL;
712 IPropertyStorage *ps = NULL;
713 HRESULT r;
715 DeleteFileA(filenameA);
717 /* create the file */
718 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
719 STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
720 ok(r==S_OK, "StgCreateDocfile failed\n");
722 r = IStorage_QueryInterface( stg, &IID_IPropertySetStorage, (LPVOID) &propset );
723 ok(r == S_OK, "query interface failed\n");
725 /* delete it */
726 r = IPropertySetStorage_Delete( propset, &FMTID_SummaryInformation );
727 ok(r == STG_E_FILENOTFOUND, "deleted property set storage\n");
729 r = IPropertySetStorage_Open( propset, &FMTID_SummaryInformation,
730 STGM_READ | STGM_SHARE_EXCLUSIVE, &ps );
731 ok(r == STG_E_FILENOTFOUND, "opened property set storage\n");
733 r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0,
734 STGM_READ | STGM_SHARE_EXCLUSIVE, &ps );
735 ok(r == STG_E_INVALIDFLAG, "created property set storage\n");
737 r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0,
738 STGM_READ, &ps );
739 ok(r == STG_E_INVALIDFLAG, "created property set storage\n");
741 r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0, 0, &ps );
742 ok(r == STG_E_INVALIDFLAG, "created property set storage\n");
744 r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0,
745 STGM_WRITE|STGM_SHARE_EXCLUSIVE, &ps );
746 ok(r == STG_E_INVALIDFLAG, "created property set storage\n");
748 r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0,
749 STGM_CREATE|STGM_WRITE|STGM_SHARE_EXCLUSIVE, &ps );
750 ok(r == STG_E_INVALIDFLAG, "created property set storage\n");
752 /* now try really creating a property set */
753 r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0,
754 STGM_CREATE|STGM_READWRITE|STGM_SHARE_EXCLUSIVE, &ps );
755 ok(r == S_OK, "failed to create property set storage\n");
757 if( ps )
758 IPropertyStorage_Release(ps);
760 /* now try creating the same thing again */
761 r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0,
762 STGM_CREATE|STGM_READWRITE|STGM_SHARE_EXCLUSIVE, &ps );
763 ok(r == S_OK, "failed to create property set storage\n");
764 if( ps )
765 IPropertyStorage_Release(ps);
767 /* should be able to open it */
768 r = IPropertySetStorage_Open( propset, &FMTID_SummaryInformation,
769 STGM_READWRITE|STGM_SHARE_EXCLUSIVE, &ps);
770 ok(r == S_OK, "open failed\n");
771 if(r == S_OK)
772 IPropertyStorage_Release(ps);
774 /* delete it */
775 r = IPropertySetStorage_Delete( propset, &FMTID_SummaryInformation );
776 ok(r == S_OK, "failed to delete property set storage\n");
778 /* try opening with an invalid FMTID */
779 r = IPropertySetStorage_Open( propset, NULL,
780 STGM_READWRITE|STGM_SHARE_EXCLUSIVE, &ps);
781 ok(r == E_INVALIDARG, "open succeeded\n");
782 if(r == S_OK)
783 IPropertyStorage_Release(ps);
785 /* try a bad guid */
786 r = IPropertySetStorage_Open( propset, &IID_IStorage,
787 STGM_READWRITE|STGM_SHARE_EXCLUSIVE, &ps);
788 ok(r == STG_E_FILENOTFOUND, "open succeeded\n");
789 if(r == S_OK)
790 IPropertyStorage_Release(ps);
793 /* try some invalid flags */
794 r = IPropertySetStorage_Open( propset, &FMTID_SummaryInformation,
795 STGM_CREATE | STGM_READWRITE|STGM_SHARE_EXCLUSIVE, &ps);
796 ok(r == STG_E_INVALIDFLAG, "open succeeded\n");
797 if(r == S_OK)
798 IPropertyStorage_Release(ps);
800 /* after deleting it, it should be gone */
801 r = IPropertySetStorage_Open( propset, &FMTID_SummaryInformation,
802 STGM_READWRITE|STGM_SHARE_EXCLUSIVE, &ps);
803 ok(r == STG_E_FILENOTFOUND, "open failed\n");
804 if(r == S_OK)
805 IPropertyStorage_Release(ps);
807 r = IPropertySetStorage_Release( propset );
808 ok(r == 1, "ref count wrong\n");
810 r = IStorage_Release(stg);
811 ok(r == 0, "ref count wrong\n");
813 DeleteFileA(filenameA);
816 static void test_storage_refcount(void)
818 IStorage *stg = NULL;
819 IStorage *stgprio = NULL;
820 HRESULT r;
821 IStream *stm = NULL;
822 static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 };
823 LARGE_INTEGER pos;
824 ULARGE_INTEGER upos;
825 STATSTG stat;
826 char buffer[10];
828 DeleteFileA(filenameA);
830 /* create the file */
831 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
832 STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
833 ok(r==S_OK, "StgCreateDocfile failed\n");
835 r = WriteClassStg( stg, &test_stg_cls );
836 ok( r == S_OK, "WriteClassStg failed\n");
838 r = IStorage_Commit( stg, STGC_DEFAULT );
839 ok( r == S_OK, "IStorage_Commit failed\n");
841 /* now create a stream */
842 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
843 ok(r==S_OK, "IStorage->CreateStream failed\n");
845 r = IStorage_Release( stg );
846 ok (r == 0, "storage not released\n");
848 pos.QuadPart = 0;
849 r = IStream_Seek( stm, pos, 0, &upos );
850 ok (r == STG_E_REVERTED, "seek should fail\n");
852 r = IStream_Stat( stm, &stat, STATFLAG_DEFAULT );
853 ok (r == STG_E_REVERTED, "stat should fail\n");
855 r = IStream_Write( stm, "Test string", strlen("Test string"), NULL);
856 ok (r == STG_E_REVERTED, "IStream_Write should return STG_E_REVERTED instead of 0x%08x\n", r);
858 r = IStream_Read( stm, buffer, sizeof(buffer), NULL);
859 ok (r == STG_E_REVERTED, "IStream_Read should return STG_E_REVERTED instead of 0x%08x\n", r);
861 r = IStream_Release(stm);
862 ok (r == 0, "stream not released\n");
864 /* tests that STGM_PRIORITY doesn't prevent readwrite access from other
865 * StgOpenStorage calls in transacted mode */
866 r = StgOpenStorage( filename, NULL, STGM_PRIORITY, NULL, 0, &stgprio);
867 ok(r==S_OK, "StgOpenStorage failed with error 0x%08x\n", r);
869 todo_wine {
870 /* non-transacted mode read/write fails */
871 r = StgOpenStorage( filename, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg);
872 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");
932 IStorage_Release(stgprio);
934 DeleteFileA(filenameA);
937 static void test_writeclassstg(void)
939 IStorage *stg = NULL;
940 HRESULT r;
941 CLSID temp_cls;
943 DeleteFileA(filenameA);
945 /* create the file */
946 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
947 STGM_READWRITE, 0, &stg);
948 ok(r==S_OK, "StgCreateDocfile failed\n");
950 r = ReadClassStg( NULL, NULL );
951 ok(r == E_INVALIDARG, "ReadClassStg should return E_INVALIDARG instead of 0x%08X\n", r);
953 r = ReadClassStg( stg, NULL );
954 ok(r == E_INVALIDARG, "ReadClassStg should return E_INVALIDARG instead of 0x%08X\n", r);
956 temp_cls.Data1 = 0xdeadbeef;
957 r = ReadClassStg( stg, &temp_cls );
958 ok(r == S_OK, "ReadClassStg failed with 0x%08X\n", r);
960 ok(IsEqualCLSID(&temp_cls, &CLSID_NULL), "ReadClassStg returned wrong clsid\n");
962 r = WriteClassStg( NULL, NULL );
963 ok(r == E_INVALIDARG, "WriteClassStg should return E_INVALIDARG instead of 0x%08X\n", r);
965 r = WriteClassStg( stg, NULL );
966 ok(r == STG_E_INVALIDPOINTER, "WriteClassStg should return STG_E_INVALIDPOINTER instead of 0x%08X\n", r);
968 r = WriteClassStg( stg, &test_stg_cls );
969 ok( r == S_OK, "WriteClassStg failed with 0x%08X\n", r);
971 r = ReadClassStg( stg, &temp_cls );
972 ok( r == S_OK, "ReadClassStg failed with 0x%08X\n", r);
973 ok(IsEqualCLSID(&temp_cls, &test_stg_cls), "ReadClassStg returned wrong clsid\n");
975 r = IStorage_Release( stg );
976 ok (r == 0, "storage not released\n");
978 DeleteFileA(filenameA);
981 static void test_streamenum(void)
983 IStorage *stg = NULL;
984 HRESULT r;
985 IStream *stm = NULL;
986 static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 };
987 static const WCHAR stmname2[] = { 'A','B','C','D','E','F','G','H','I',0 };
988 static const WCHAR stmname3[] = { 'A','B','C','D','E','F','G','H','I','J',0 };
989 STATSTG stat;
990 IEnumSTATSTG *ee = NULL;
991 ULONG count;
993 DeleteFileA(filenameA);
995 /* create the file */
996 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
997 STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
998 ok(r==S_OK, "StgCreateDocfile failed\n");
1000 r = WriteClassStg( stg, &test_stg_cls );
1001 ok( r == S_OK, "WriteClassStg failed\n");
1003 r = IStorage_Commit( stg, STGC_DEFAULT );
1004 ok( r == S_OK, "IStorage_Commit failed\n");
1006 /* now create a stream */
1007 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1008 ok(r==S_OK, "IStorage->CreateStream failed\n");
1010 r = IStream_Release(stm);
1012 /* first enum ... should be 1 stream */
1013 r = IStorage_EnumElements(stg, 0, NULL, 0, &ee);
1014 ok(r==S_OK, "IStorage->EnumElements failed\n");
1016 count = 0xf00;
1017 r = IEnumSTATSTG_Next(ee, 1, &stat, &count);
1018 ok(r==S_OK, "IEnumSTATSTG->Next failed\n");
1019 ok(count == 1, "count wrong\n");
1021 if (r == S_OK)
1022 CoTaskMemFree(stat.pwcsName);
1024 r = IEnumSTATSTG_Release(ee);
1025 ok(r==S_OK, "EnumSTATSTG_Release failed with error 0x%08x\n", r);
1027 /* second enum... destroy the stream before reading */
1028 r = IStorage_EnumElements(stg, 0, NULL, 0, &ee);
1029 ok(r==S_OK, "IStorage->EnumElements failed\n");
1031 r = IStorage_DestroyElement(stg, stmname);
1032 ok(r==S_OK, "IStorage->DestroyElement failed\n");
1034 count = 0xf00;
1035 r = IEnumSTATSTG_Next(ee, 1, &stat, &count);
1036 ok(r==S_FALSE, "IEnumSTATSTG->Next failed\n");
1037 ok(count == 0, "count wrong\n");
1039 /* reset and try again */
1040 r = IEnumSTATSTG_Reset(ee);
1041 ok(r==S_OK, "IEnumSTATSTG->Reset failed\n");
1043 count = 0xf00;
1044 r = IEnumSTATSTG_Next(ee, 1, &stat, &count);
1045 ok(r==S_FALSE, "IEnumSTATSTG->Next failed\n");
1046 ok(count == 0, "count wrong\n");
1048 /* add a stream before reading */
1049 r = IEnumSTATSTG_Reset(ee);
1050 ok(r==S_OK, "IEnumSTATSTG->Reset failed\n");
1052 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1053 ok(r==S_OK, "IStorage->CreateStream failed\n");
1055 r = IStream_Release(stm);
1056 ok(r==S_OK, "Stream_Release failed with error 0x%08x\n", r);
1058 count = 0xf00;
1059 r = IEnumSTATSTG_Next(ee, 1, &stat, &count);
1060 ok(r==S_OK, "IEnumSTATSTG->Next failed\n");
1061 ok(count == 1, "count wrong\n");
1063 if (r == S_OK)
1065 ok(lstrcmpiW(stat.pwcsName, stmname) == 0, "expected CONTENTS, got %s\n", wine_dbgstr_w(stat.pwcsName));
1066 CoTaskMemFree(stat.pwcsName);
1069 r = IStorage_CreateStream(stg, stmname2, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1070 ok(r==S_OK, "IStorage->CreateStream failed\n");
1072 r = IStream_Release(stm);
1073 ok(r==S_OK, "Stream_Release failed with error 0x%08x\n", r);
1075 count = 0xf00;
1076 r = IEnumSTATSTG_Next(ee, 1, &stat, &count);
1077 ok(r==S_OK, "IEnumSTATSTG->Next failed\n");
1078 ok(count == 1, "count wrong\n");
1080 if (r == S_OK)
1082 ok(lstrcmpiW(stat.pwcsName, stmname2) == 0, "expected ABCDEFGHI, got %s\n", wine_dbgstr_w(stat.pwcsName));
1083 CoTaskMemFree(stat.pwcsName);
1086 /* delete previous and next stream after reading */
1087 r = IStorage_CreateStream(stg, stmname3, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1088 ok(r==S_OK, "IStorage->CreateStream failed\n");
1090 r = IStream_Release(stm);
1091 ok(r==S_OK, "Stream_Release failed with error 0x%08x\n", r);
1093 r = IEnumSTATSTG_Reset(ee);
1094 ok(r==S_OK, "IEnumSTATSTG->Reset failed\n");
1096 count = 0xf00;
1097 r = IEnumSTATSTG_Next(ee, 1, &stat, &count);
1098 ok(r==S_OK, "IEnumSTATSTG->Next failed\n");
1099 ok(count == 1, "count wrong\n");
1101 if (r == S_OK)
1103 ok(lstrcmpiW(stat.pwcsName, stmname) == 0, "expected CONTENTS, got %s\n", wine_dbgstr_w(stat.pwcsName));
1104 CoTaskMemFree(stat.pwcsName);
1107 r = IStorage_DestroyElement(stg, stmname);
1108 ok(r==S_OK, "IStorage->DestroyElement failed\n");
1110 r = IStorage_DestroyElement(stg, stmname2);
1111 ok(r==S_OK, "IStorage->DestroyElement failed\n");
1113 count = 0xf00;
1114 r = IEnumSTATSTG_Next(ee, 1, &stat, &count);
1115 ok(r==S_OK, "IEnumSTATSTG->Next failed\n");
1116 ok(count == 1, "count wrong\n");
1118 if (r == S_OK)
1120 ok(lstrcmpiW(stat.pwcsName, stmname3) == 0, "expected ABCDEFGHIJ, got %s\n", wine_dbgstr_w(stat.pwcsName));
1121 CoTaskMemFree(stat.pwcsName);
1124 r = IStorage_Release( stg );
1125 todo_wine ok (r == 0, "storage not released\n");
1127 /* enumerator is still valid and working after the storage is released */
1128 r = IEnumSTATSTG_Reset(ee);
1129 ok(r==S_OK, "IEnumSTATSTG->Reset failed\n");
1131 count = 0xf00;
1132 r = IEnumSTATSTG_Next(ee, 1, &stat, &count);
1133 ok(r==S_OK, "IEnumSTATSTG->Next failed\n");
1134 ok(count == 1, "count wrong\n");
1136 if (r == S_OK)
1138 ok(lstrcmpiW(stat.pwcsName, stmname3) == 0, "expected ABCDEFGHIJ, got %s\n", wine_dbgstr_w(stat.pwcsName));
1139 CoTaskMemFree(stat.pwcsName);
1142 /* the storage is left open until the enumerator is freed */
1143 r = StgOpenStorage( filename, NULL, STGM_SHARE_EXCLUSIVE |
1144 STGM_READWRITE |STGM_TRANSACTED, NULL, 0, &stg);
1145 ok(r==STG_E_SHAREVIOLATION ||
1146 r==STG_E_LOCKVIOLATION, /* XP-SP2/W2K3-SP1 and below */
1147 "StgCreateDocfile failed, res=%x\n", r);
1149 r = IEnumSTATSTG_Release(ee);
1150 ok (r == 0, "enum not released\n");
1152 DeleteFileA(filenameA);
1155 static void test_transact(void)
1157 IStorage *stg = NULL, *stg2 = NULL, *stg3 = NULL;
1158 HRESULT r;
1159 IStream *stm = NULL;
1160 static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 };
1161 static const WCHAR stmname2[] = { 'F','O','O',0 };
1162 static const WCHAR stgname[] = { 'P','E','R','M','S','T','G',0 };
1163 static const WCHAR stgname2[] = { 'T','E','M','P','S','T','G',0 };
1165 DeleteFileA(filenameA);
1167 /* create the file */
1168 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
1169 STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
1170 ok(r==S_OK, "StgCreateDocfile failed\n");
1172 /* commit a new stream and storage */
1173 r = IStorage_CreateStream(stg, stmname2, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1174 ok(r==S_OK, "IStorage->CreateStream failed\n");
1176 r = IStream_Write(stm, "this is stream 1\n", 16, NULL);
1177 ok(r==S_OK, "IStream->Write failed\n");
1179 IStream_Release(stm);
1181 r = IStorage_CreateStorage(stg, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg2);
1182 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1184 if (r == S_OK)
1186 /* Create two substorages but only commit one */
1187 r = IStorage_CreateStorage(stg2, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg3);
1188 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1190 if (r == S_OK)
1191 IStorage_Release(stg3);
1193 r = IStorage_Commit(stg, 0);
1194 ok(r==S_OK, "IStorage->Commit failed\n");
1196 r = IStorage_CreateStorage(stg2, stgname2, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg3);
1197 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1199 if (r == S_OK)
1200 IStorage_Release(stg3);
1202 IStorage_Release(stg2);
1205 /* now create a stream and storage, but don't commit them */
1206 stm = NULL;
1207 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1208 ok(r==S_OK, "IStorage->CreateStream failed\n");
1210 r = IStream_Write(stm, "this is stream 2\n", 16, NULL);
1211 ok(r==S_OK, "IStream->Write failed\n");
1213 /* IStream::Commit does nothing for OLE storage streams */
1214 r = IStream_Commit(stm, STGC_ONLYIFCURRENT | STGC_DANGEROUSLYCOMMITMERELYTODISKCACHE);
1215 ok(r==S_OK, "IStream->Commit failed\n");
1217 r = IStorage_CreateStorage(stg, stgname2, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg2);
1218 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1220 if (r == S_OK)
1221 IStorage_Release(stg2);
1223 IStream_Release(stm);
1225 IStorage_Release(stg);
1227 stm = NULL;
1228 stg = NULL;
1229 r = StgOpenStorage( filename, NULL, STGM_SHARE_DENY_NONE | STGM_READ | STGM_TRANSACTED, NULL, 0, &stg);
1230 ok(r==S_OK, "StgOpenStorage failed\n");
1232 if (!stg)
1233 return;
1235 r = IStorage_OpenStream(stg, stmname, NULL, STGM_SHARE_DENY_NONE|STGM_READ, 0, &stm );
1236 ok(r==STG_E_INVALIDFLAG, "IStorage->OpenStream failed %08x\n", r);
1238 r = IStorage_OpenStream(stg, stmname, NULL, STGM_DELETEONRELEASE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
1239 ok(r==STG_E_INVALIDFUNCTION, "IStorage->OpenStream failed %08x\n", r);
1241 r = IStorage_OpenStream(stg, stmname, NULL, STGM_TRANSACTED|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
1242 ok(r==STG_E_INVALIDFUNCTION, "IStorage->OpenStream failed %08x\n", r);
1244 r = IStorage_OpenStorage(stg, stmname, NULL, STGM_TRANSACTED|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg2 );
1245 ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStream failed %08x\n", r);
1247 r = IStorage_OpenStream(stg, stmname, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
1248 ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStream should fail %08x\n", r);
1249 if (r == S_OK)
1250 IStream_Release(stm);
1252 r = IStorage_OpenStorage(stg, stgname2, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg2 );
1253 ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStorage should fail %08x\n", r);
1254 if (r == S_OK)
1255 IStorage_Release(stg2);
1257 r = IStorage_OpenStorage(stg, stmname2, NULL, STGM_TRANSACTED|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg2 );
1258 ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStream failed %08x\n", r);
1260 r = IStorage_OpenStream(stg, stmname2, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
1261 ok(r==S_OK, "IStorage->OpenStream should succeed %08x\n", r);
1262 if (r == S_OK)
1263 IStream_Release(stm);
1265 r = IStorage_OpenStorage(stg, stgname, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg2 );
1266 ok(r==S_OK, "IStorage->OpenStorage should succeed %08x\n", r);
1267 if (r == S_OK)
1269 r = IStorage_OpenStorage(stg2, stgname, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg3 );
1270 ok(r==S_OK, "IStorage->OpenStorage should succeed %08x\n", r);
1271 if (r == S_OK)
1272 IStorage_Release(stg3);
1274 r = IStorage_OpenStorage(stg2, stgname2, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg3 );
1275 ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStorage should fail %08x\n", r);
1276 if (r == S_OK)
1277 IStorage_Release(stg3);
1279 IStorage_Release(stg2);
1282 IStorage_Release(stg);
1284 r = DeleteFileA(filenameA);
1285 ok( r == TRUE, "deleted file\n");
1288 static void test_substorage_share(void)
1290 IStorage *stg, *stg2, *stg3;
1291 IStream *stm, *stm2;
1292 HRESULT r;
1293 static const WCHAR stgname[] = { 'P','E','R','M','S','T','G',0 };
1294 static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 };
1295 static const WCHAR othername[] = { 'N','E','W','N','A','M','E',0 };
1297 DeleteFileA(filenameA);
1299 /* create the file */
1300 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
1301 STGM_READWRITE, 0, &stg);
1302 ok(r==S_OK, "StgCreateDocfile failed\n");
1304 /* create a read/write storage and try to open it again */
1305 r = IStorage_CreateStorage(stg, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg2);
1306 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1308 if (r == S_OK)
1310 r = IStorage_OpenStorage(stg, stgname, NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg3);
1311 ok(r==STG_E_ACCESSDENIED, "IStorage->OpenStorage should fail %08x\n", r);
1313 if (r == S_OK)
1314 IStorage_Release(stg3);
1316 r = IStorage_OpenStorage(stg, stgname, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, 0, &stg3);
1317 ok(r==STG_E_ACCESSDENIED, "IStorage->OpenStorage should fail %08x\n", r);
1319 if (r == S_OK)
1320 IStorage_Release(stg3);
1322 /* cannot rename the storage while it's open */
1323 r = IStorage_RenameElement(stg, stgname, othername);
1324 ok(r==STG_E_ACCESSDENIED, "IStorage->RenameElement should fail %08x\n", r);
1325 if (SUCCEEDED(r)) IStorage_RenameElement(stg, othername, stgname);
1327 /* destroying an object while it's open invalidates it */
1328 r = IStorage_DestroyElement(stg, stgname);
1329 ok(r==S_OK, "IStorage->DestroyElement failed, hr=%08x\n", r);
1331 r = IStorage_CreateStream(stg2, stmname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm);
1332 ok(r==STG_E_REVERTED, "IStorage->CreateStream failed, hr=%08x\n", r);
1334 if (r == S_OK)
1335 IStream_Release(stm);
1337 IStorage_Release(stg2);
1340 /* create a read/write stream and try to open it again */
1341 r = IStorage_CreateStream(stg, stmname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm);
1342 ok(r==S_OK, "IStorage->CreateStream failed, hr=%08x\n", r);
1344 if (r == S_OK)
1346 r = IStorage_OpenStream(stg, stmname, NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &stm2);
1347 ok(r==STG_E_ACCESSDENIED, "IStorage->OpenStream should fail %08x\n", r);
1349 if (r == S_OK)
1350 IStream_Release(stm2);
1352 r = IStorage_OpenStream(stg, stmname, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm2);
1353 ok(r==STG_E_ACCESSDENIED, "IStorage->OpenStream should fail %08x\n", r);
1355 if (r == S_OK)
1356 IStream_Release(stm2);
1358 /* cannot rename the stream while it's open */
1359 r = IStorage_RenameElement(stg, stmname, othername);
1360 ok(r==STG_E_ACCESSDENIED, "IStorage->RenameElement should fail %08x\n", r);
1361 if (SUCCEEDED(r)) IStorage_RenameElement(stg, othername, stmname);
1363 /* destroying an object while it's open invalidates it */
1364 r = IStorage_DestroyElement(stg, stmname);
1365 ok(r==S_OK, "IStorage->DestroyElement failed, hr=%08x\n", r);
1367 r = IStream_Write(stm, "this shouldn't work\n", 20, NULL);
1368 ok(r==STG_E_REVERTED, "IStream_Write should fail %08x\n", r);
1370 IStream_Release(stm);
1373 IStorage_Release(stg);
1375 r = DeleteFileA(filenameA);
1376 ok( r == TRUE, "deleted file\n");
1379 static void test_revert(void)
1381 IStorage *stg = NULL, *stg2 = NULL, *stg3 = NULL;
1382 HRESULT r;
1383 IStream *stm = NULL, *stm2 = NULL;
1384 static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 };
1385 static const WCHAR stmname2[] = { 'F','O','O',0 };
1386 static const WCHAR stgname[] = { 'P','E','R','M','S','T','G',0 };
1387 static const WCHAR stgname2[] = { 'T','E','M','P','S','T','G',0 };
1388 STATSTG statstg;
1390 DeleteFileA(filenameA);
1392 /* create the file */
1393 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
1394 STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
1395 ok(r==S_OK, "StgCreateDocfile failed\n");
1397 /* commit a new stream and storage */
1398 r = IStorage_CreateStream(stg, stmname2, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1399 ok(r==S_OK, "IStorage->CreateStream failed\n");
1401 r = IStream_Write(stm, "this is stream 1\n", 16, NULL);
1402 ok(r==S_OK, "IStream->Write failed\n");
1404 r = IStorage_CreateStorage(stg, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg2);
1405 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1407 if (r == S_OK)
1409 /* Create two substorages but only commit one */
1410 r = IStorage_CreateStorage(stg2, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg3);
1411 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1413 if (r == S_OK)
1414 IStorage_Release(stg3);
1416 r = IStorage_Commit(stg, 0);
1417 ok(r==S_OK, "IStorage->Commit failed\n");
1419 r = IStorage_CreateStorage(stg2, stgname2, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg3);
1420 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1422 if (r == S_OK)
1423 IStorage_Release(stg3);
1426 /* now create a stream and storage, then revert */
1427 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm2 );
1428 ok(r==S_OK, "IStorage->CreateStream failed\n");
1430 r = IStream_Write(stm2, "this is stream 2\n", 16, NULL);
1431 ok(r==S_OK, "IStream->Write failed\n");
1433 r = IStorage_CreateStorage(stg, stgname2, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg3);
1434 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1436 r = IStorage_Revert(stg);
1437 ok(r==S_OK, "Storage_Revert failed with error 0x%08x\n", r);
1439 /* all open objects become invalid */
1440 r = IStream_Write(stm, "this shouldn't work\n", 20, NULL);
1441 ok(r==STG_E_REVERTED, "IStream_Write should fail %08x\n", r);
1443 r = IStream_Write(stm2, "this shouldn't work\n", 20, NULL);
1444 ok(r==STG_E_REVERTED, "IStream_Write should fail %08x\n", r);
1446 r = IStorage_Stat(stg2, &statstg, STATFLAG_NONAME);
1447 ok(r==STG_E_REVERTED, "IStorage_Stat should fail %08x\n", r);
1449 r = IStorage_Stat(stg3, &statstg, STATFLAG_NONAME);
1450 ok(r==STG_E_REVERTED, "IStorage_Stat should fail %08x\n", r);
1452 IStream_Release(stm);
1453 IStream_Release(stm2);
1454 IStorage_Release(stg2);
1455 IStorage_Release(stg3);
1457 r = IStorage_OpenStream(stg, stmname, NULL, STGM_SHARE_DENY_NONE|STGM_READ, 0, &stm );
1458 ok(r==STG_E_INVALIDFLAG, "IStorage->OpenStream failed %08x\n", r);
1460 r = IStorage_OpenStream(stg, stmname, NULL, STGM_DELETEONRELEASE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
1461 ok(r==STG_E_INVALIDFUNCTION, "IStorage->OpenStream failed %08x\n", r);
1463 r = IStorage_OpenStream(stg, stmname, NULL, STGM_TRANSACTED|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
1464 ok(r==STG_E_INVALIDFUNCTION, "IStorage->OpenStream failed %08x\n", r);
1466 r = IStorage_OpenStorage(stg, stmname, NULL, STGM_TRANSACTED|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg2 );
1467 ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStream failed %08x\n", r);
1469 r = IStorage_OpenStream(stg, stmname, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
1470 ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStream should fail %08x\n", r);
1471 if (r == S_OK)
1472 IStream_Release(stm);
1474 r = IStorage_OpenStorage(stg, stgname2, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg2 );
1475 ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStorage should fail %08x\n", r);
1476 if (r == S_OK)
1477 IStorage_Release(stg2);
1479 r = IStorage_OpenStorage(stg, stmname2, NULL, STGM_TRANSACTED|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg2 );
1480 ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStream failed %08x\n", r);
1482 r = IStorage_OpenStream(stg, stmname2, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
1483 ok(r==S_OK, "IStorage->OpenStream should succeed %08x\n", r);
1484 if (r == S_OK)
1485 IStream_Release(stm);
1487 r = IStorage_OpenStorage(stg, stgname, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg2 );
1488 ok(r==S_OK, "IStorage->OpenStorage should succeed %08x\n", r);
1489 if (r == S_OK)
1491 r = IStorage_OpenStorage(stg2, stgname, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg3 );
1492 ok(r==S_OK, "IStorage->OpenStorage should succeed %08x\n", r);
1493 if (r == S_OK)
1494 IStorage_Release(stg3);
1496 r = IStorage_OpenStorage(stg2, stgname2, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg3 );
1497 ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStorage should fail %08x\n", r);
1498 if (r == S_OK)
1499 IStorage_Release(stg3);
1501 IStorage_Release(stg2);
1504 IStorage_Release(stg);
1506 r = DeleteFileA(filenameA);
1507 ok( r == TRUE, "deleted file\n");
1509 /* Revert only invalidates objects in transacted mode */
1510 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
1511 STGM_READWRITE, 0, &stg);
1512 ok(r==S_OK, "StgCreateDocfile failed\n");
1514 r = IStorage_CreateStream(stg, stmname2, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1515 ok(r==S_OK, "IStorage->CreateStream failed\n");
1517 r = IStorage_Revert(stg);
1518 ok(r==S_OK, "IStorage->Revert failed %08x\n", r);
1520 r = IStream_Write(stm, "this works\n", 11, NULL);
1521 ok(r==S_OK, "IStream_Write should succeed %08x\n", r);
1523 IStream_Release(stm);
1524 IStorage_Release(stg);
1526 r = DeleteFileA(filenameA);
1527 ok( r == TRUE, "deleted file\n");
1530 static void test_parent_free(void)
1532 IStorage *stg = NULL, *stg2 = NULL, *stg3 = NULL;
1533 HRESULT r;
1534 IStream *stm = NULL;
1535 static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 };
1536 static const WCHAR stgname[] = { 'P','E','R','M','S','T','G',0 };
1537 ULONG ref;
1538 STATSTG statstg;
1540 DeleteFileA(filenameA);
1542 /* create the file */
1543 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
1544 STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
1545 ok(r==S_OK, "StgCreateDocfile failed\n");
1547 /* create a new storage */
1548 r = IStorage_CreateStorage(stg, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg2);
1549 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1551 if (r == S_OK)
1553 /* now create a stream inside the new storage */
1554 r = IStorage_CreateStream(stg2, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1555 ok(r==S_OK, "IStorage->CreateStream failed\n");
1557 if (r == S_OK)
1559 /* create a storage inside the new storage */
1560 r = IStorage_CreateStorage(stg2, stgname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stg3 );
1561 ok(r==S_OK, "IStorage->CreateStorage failed\n");
1564 /* free the parent */
1565 ref = IStorage_Release(stg2);
1566 ok(ref == 0, "IStorage still has %u references\n", ref);
1568 /* child objects are invalid */
1569 if (r == S_OK)
1571 r = IStream_Write(stm, "this should fail\n", 17, NULL);
1572 ok(r==STG_E_REVERTED, "IStream->Write should fail, hr=%x\n", r);
1574 IStream_Release(stm);
1576 r = IStorage_Stat(stg3, &statstg, STATFLAG_NONAME);
1577 ok(r==STG_E_REVERTED, "IStorage_Stat should fail %08x\n", r);
1579 r = IStorage_SetStateBits(stg3, 1, 1);
1580 ok(r==STG_E_REVERTED, "IStorage_Stat should fail %08x\n", r);
1582 IStorage_Release(stg3);
1586 IStorage_Release(stg);
1588 r = DeleteFileA(filenameA);
1589 ok( r == TRUE, "deleted file\n");
1592 static void test_nonroot_transacted(void)
1594 IStorage *stg = NULL, *stg2 = NULL, *stg3 = NULL;
1595 HRESULT r;
1596 IStream *stm = NULL;
1597 static const WCHAR stgname[] = { 'P','E','R','M','S','T','G',0 };
1598 static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 };
1599 static const WCHAR stmname2[] = { 'F','O','O',0 };
1601 DeleteFileA(filenameA);
1603 /* create a transacted file */
1604 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
1605 STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
1606 ok(r==S_OK, "StgCreateDocfile failed\n");
1608 /* create a transacted substorage */
1609 r = IStorage_CreateStorage(stg, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_TRANSACTED, 0, 0, &stg2);
1610 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1612 if (r == S_OK)
1614 /* create and commit stmname */
1615 r = IStorage_CreateStream(stg2, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1616 ok(r==S_OK, "IStorage->CreateStream failed\n");
1617 if (r == S_OK)
1618 IStream_Release(stm);
1620 IStorage_Commit(stg2, 0);
1622 /* create and revert stmname2 */
1623 r = IStorage_CreateStream(stg2, stmname2, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1624 ok(r==S_OK, "IStorage->CreateStream failed\n");
1625 if (r == S_OK)
1626 IStream_Release(stm);
1628 IStorage_Revert(stg2);
1630 /* check that Commit and Revert really worked */
1631 r = IStorage_OpenStream(stg2, stmname, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
1632 ok(r==S_OK, "IStorage->OpenStream should succeed %08x\n", r);
1633 if (r == S_OK)
1634 IStream_Release(stm);
1636 r = IStorage_OpenStream(stg2, stmname2, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
1637 ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStream should fail %08x\n", r);
1638 if (r == S_OK)
1639 IStream_Release(stm);
1641 IStorage_Release(stg2);
1644 /* create a read-only transacted substorage */
1645 r = IStorage_OpenStorage(stg, stgname, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE | STGM_TRANSACTED, NULL, 0, &stg2);
1646 ok(r==S_OK, "IStorage->OpenStorage failed, hr=%08x\n", r);
1648 if (r == S_OK)
1650 /* The storage can be modified. */
1651 r = IStorage_CreateStorage(stg2, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg3);
1652 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1653 if (r == S_OK)
1654 IStorage_Release(stg3);
1656 /* But changes cannot be committed. */
1657 r = IStorage_Commit(stg2, 0);
1658 ok(r==STG_E_ACCESSDENIED, "IStorage->Commit should fail, hr=%08x\n", r);
1660 IStorage_Release(stg2);
1663 IStorage_Release(stg);
1665 /* create a non-transacted file */
1666 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
1667 STGM_READWRITE, 0, &stg);
1668 ok(r==S_OK, "StgCreateDocfile failed\n");
1670 /* create a transacted substorage */
1671 r = IStorage_CreateStorage(stg, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_TRANSACTED, 0, 0, &stg2);
1672 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1674 if (r == S_OK)
1676 /* create and commit stmname */
1677 r = IStorage_CreateStream(stg2, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1678 ok(r==S_OK, "IStorage->CreateStream failed\n");
1679 if (r == S_OK)
1680 IStream_Release(stm);
1682 IStorage_Commit(stg2, 0);
1684 /* create and revert stmname2 */
1685 r = IStorage_CreateStream(stg2, stmname2, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1686 ok(r==S_OK, "IStorage->CreateStream failed\n");
1687 if (r == S_OK)
1688 IStream_Release(stm);
1690 IStorage_Revert(stg2);
1692 /* check that Commit and Revert really worked */
1693 r = IStorage_OpenStream(stg2, stmname, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
1694 ok(r==S_OK, "IStorage->OpenStream should succeed %08x\n", r);
1695 if (r == S_OK)
1696 IStream_Release(stm);
1698 r = IStorage_OpenStream(stg2, stmname2, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
1699 ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStream should fail %08x\n", r);
1700 if (r == S_OK)
1701 IStream_Release(stm);
1703 IStorage_Release(stg2);
1706 IStorage_Release(stg);
1708 r = DeleteFileA(filenameA);
1709 ok( r == TRUE, "deleted file\n");
1712 static void test_ReadClassStm(void)
1714 CLSID clsid;
1715 HRESULT hr;
1716 IStream *pStream;
1717 static const LARGE_INTEGER llZero;
1719 hr = ReadClassStm(NULL, &clsid);
1720 ok(hr == E_INVALIDARG, "ReadClassStm should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1722 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1723 ok_ole_success(hr, "CreateStreamOnHGlobal");
1724 hr = WriteClassStm(pStream, &test_stg_cls);
1725 ok_ole_success(hr, "WriteClassStm");
1727 hr = ReadClassStm(pStream, NULL);
1728 ok(hr == E_INVALIDARG, "ReadClassStm should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1730 /* test not rewound stream */
1731 hr = ReadClassStm(pStream, &clsid);
1732 ok(hr == STG_E_READFAULT, "ReadClassStm should have returned STG_E_READFAULT instead of 0x%08x\n", hr);
1733 ok(IsEqualCLSID(&clsid, &CLSID_NULL), "clsid should have been zeroed\n");
1735 hr = IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1736 ok_ole_success(hr, "IStream_Seek");
1737 hr = ReadClassStm(pStream, &clsid);
1738 ok_ole_success(hr, "ReadClassStm");
1739 ok(IsEqualCLSID(&clsid, &test_stg_cls), "clsid should have been set to CLSID_WineTest\n");
1741 IStream_Release(pStream);
1744 struct access_res
1746 BOOL gothandle;
1747 DWORD lasterr;
1748 BOOL ignore;
1751 static const struct access_res create[16] =
1753 { TRUE, ERROR_SUCCESS, TRUE },
1754 { TRUE, ERROR_SUCCESS, TRUE },
1755 { TRUE, ERROR_SUCCESS, FALSE },
1756 { TRUE, ERROR_SUCCESS, FALSE },
1757 { FALSE, ERROR_SHARING_VIOLATION, FALSE },
1758 { FALSE, ERROR_SHARING_VIOLATION, FALSE },
1759 { FALSE, ERROR_SHARING_VIOLATION, FALSE },
1760 { TRUE, ERROR_SUCCESS, FALSE },
1761 { FALSE, ERROR_SHARING_VIOLATION, FALSE },
1762 { FALSE, ERROR_SHARING_VIOLATION, FALSE },
1763 { FALSE, ERROR_SHARING_VIOLATION, FALSE },
1764 { TRUE, ERROR_SUCCESS, TRUE },
1765 { FALSE, ERROR_SHARING_VIOLATION, FALSE },
1766 { FALSE, ERROR_SHARING_VIOLATION, FALSE },
1767 { FALSE, ERROR_SHARING_VIOLATION, FALSE },
1768 { TRUE, ERROR_SUCCESS, TRUE }
1771 static const struct access_res create_commit[16] =
1773 { TRUE, ERROR_SUCCESS, TRUE },
1774 { TRUE, ERROR_SUCCESS, TRUE },
1775 { TRUE, ERROR_SUCCESS, FALSE },
1776 { TRUE, ERROR_SUCCESS, FALSE },
1777 { FALSE, ERROR_SHARING_VIOLATION, FALSE },
1778 { FALSE, ERROR_SHARING_VIOLATION, FALSE },
1779 { FALSE, ERROR_SHARING_VIOLATION, FALSE },
1780 { TRUE, ERROR_SUCCESS, FALSE },
1781 { FALSE, ERROR_SHARING_VIOLATION, FALSE },
1782 { FALSE, ERROR_SHARING_VIOLATION, FALSE },
1783 { FALSE, ERROR_SHARING_VIOLATION, FALSE },
1784 { TRUE, ERROR_SUCCESS, TRUE },
1785 { FALSE, ERROR_SHARING_VIOLATION, FALSE },
1786 { FALSE, ERROR_SHARING_VIOLATION, FALSE },
1787 { FALSE, ERROR_SHARING_VIOLATION, FALSE },
1788 { TRUE, ERROR_SUCCESS, TRUE }
1791 static const struct access_res create_close[16] =
1793 { TRUE, ERROR_SUCCESS, FALSE },
1794 { TRUE, ERROR_SUCCESS, FALSE },
1795 { TRUE, ERROR_SUCCESS, FALSE },
1796 { TRUE, ERROR_SUCCESS, FALSE },
1797 { TRUE, ERROR_SUCCESS, FALSE },
1798 { TRUE, ERROR_SUCCESS, FALSE },
1799 { TRUE, ERROR_SUCCESS, FALSE },
1800 { TRUE, ERROR_SUCCESS, FALSE },
1801 { TRUE, ERROR_SUCCESS, FALSE },
1802 { TRUE, ERROR_SUCCESS, FALSE },
1803 { TRUE, ERROR_SUCCESS, FALSE },
1804 { TRUE, ERROR_SUCCESS, FALSE },
1805 { TRUE, ERROR_SUCCESS, FALSE },
1806 { TRUE, ERROR_SUCCESS, FALSE },
1807 { TRUE, ERROR_SUCCESS, FALSE },
1808 { TRUE, ERROR_SUCCESS }
1811 static const DWORD access_modes[4] = {
1813 GENERIC_READ,
1814 GENERIC_WRITE,
1815 GENERIC_READ | GENERIC_WRITE
1818 static const DWORD share_modes[4] = {
1820 FILE_SHARE_READ,
1821 FILE_SHARE_WRITE,
1822 FILE_SHARE_READ | FILE_SHARE_WRITE
1825 static void _test_file_access(LPCSTR file, const struct access_res *ares, DWORD line)
1827 int i, j, idx = 0;
1829 for (i = 0; i < sizeof(access_modes)/sizeof(access_modes[0]); i++)
1831 for (j = 0; j < sizeof(share_modes)/sizeof(share_modes[0]); j++)
1833 DWORD lasterr;
1834 HANDLE hfile;
1836 if (ares[idx].ignore)
1837 continue;
1839 SetLastError(0xdeadbeef);
1840 hfile = CreateFileA(file, access_modes[i], share_modes[j], NULL, OPEN_EXISTING,
1841 FILE_ATTRIBUTE_NORMAL, 0);
1842 lasterr = GetLastError();
1844 ok((hfile != INVALID_HANDLE_VALUE) == ares[idx].gothandle,
1845 "(%d, handle, %d): Expected %d, got %d\n",
1846 line, idx, ares[idx].gothandle,
1847 (hfile != INVALID_HANDLE_VALUE));
1849 ok(lasterr == ares[idx].lasterr ||
1850 broken(lasterr == 0xdeadbeef) /* win9x */,
1851 "(%d, lasterr, %d): Expected %d, got %d\n",
1852 line, idx, ares[idx].lasterr, lasterr);
1854 CloseHandle(hfile);
1855 idx++;
1860 #define test_file_access(file, ares) _test_file_access(file, ares, __LINE__)
1862 static void test_access(void)
1864 static const WCHAR fileW[] = {'w','i','n','e','t','e','s','t',0};
1865 static const char fileA[] = "winetest";
1866 IStorage *stg;
1867 HRESULT hr;
1869 /* STGM_TRANSACTED */
1870 hr = StgCreateDocfile(fileW, STGM_CREATE | STGM_READWRITE |
1871 STGM_SHARE_EXCLUSIVE | STGM_TRANSACTED, 0, &stg);
1872 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1874 test_file_access(fileA, create);
1876 hr = IStorage_Commit(stg, STGC_DEFAULT);
1877 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1879 test_file_access(fileA, create_commit);
1881 IStorage_Release(stg);
1883 test_file_access(fileA, create_close);
1885 DeleteFileA(fileA);
1887 /* STGM_DIRECT */
1888 hr = StgCreateDocfile(fileW, STGM_CREATE | STGM_READWRITE |
1889 STGM_SHARE_EXCLUSIVE | STGM_DIRECT, 0, &stg);
1890 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1892 test_file_access(fileA, create);
1894 hr = IStorage_Commit(stg, STGC_DEFAULT);
1895 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1897 test_file_access(fileA, create_commit);
1899 IStorage_Release(stg);
1901 test_file_access(fileA, create_close);
1903 DeleteFileA(fileA);
1905 /* STGM_SHARE_DENY_NONE */
1906 hr = StgCreateDocfile(fileW, STGM_CREATE | STGM_READWRITE |
1907 STGM_SHARE_DENY_NONE | STGM_TRANSACTED, 0, &stg);
1908 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1910 test_file_access(fileA, create);
1912 hr = IStorage_Commit(stg, STGC_DEFAULT);
1913 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1915 test_file_access(fileA, create_commit);
1917 IStorage_Release(stg);
1919 test_file_access(fileA, create_close);
1921 DeleteFileA(fileA);
1923 /* STGM_SHARE_DENY_READ */
1924 hr = StgCreateDocfile(fileW, STGM_CREATE | STGM_READWRITE |
1925 STGM_SHARE_DENY_READ | STGM_TRANSACTED, 0, &stg);
1926 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1928 test_file_access(fileA, create);
1930 hr = IStorage_Commit(stg, STGC_DEFAULT);
1931 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1933 test_file_access(fileA, create_commit);
1935 IStorage_Release(stg);
1937 test_file_access(fileA, create_close);
1939 DeleteFileA(fileA);
1941 /* STGM_SHARE_DENY_WRITE */
1942 hr = StgCreateDocfile(fileW, STGM_CREATE | STGM_READWRITE |
1943 STGM_SHARE_DENY_WRITE | STGM_TRANSACTED, 0, &stg);
1944 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1946 test_file_access(fileA, create);
1948 hr = IStorage_Commit(stg, STGC_DEFAULT);
1949 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1951 test_file_access(fileA, create_commit);
1953 IStorage_Release(stg);
1955 test_file_access(fileA, create_close);
1957 DeleteFileA(fileA);
1959 /* STGM_DIRECT_SWMR | STGM_READ | STGM_SHARE_DENY_NONE - reader mode for direct SWMR mode */
1960 hr = StgCreateDocfile(fileW, STGM_CREATE | STGM_READWRITE | STGM_SHARE_DENY_WRITE | STGM_TRANSACTED, 0, &stg);
1961 ok(hr == S_OK, "got %08x\n", hr);
1962 IStorage_Release(stg);
1964 hr = StgOpenStorage(fileW, NULL, STGM_DIRECT_SWMR | STGM_READ | STGM_SHARE_DENY_NONE, NULL, 0, &stg);
1965 ok(hr == S_OK, "got %08x\n", hr);
1967 test_file_access(fileA, create);
1969 IStorage_Release(stg);
1970 test_file_access(fileA, create_close);
1972 DeleteFileA(fileA);
1975 static void test_readonly(void)
1977 IStorage *stg, *stg2, *stg3;
1978 IStream *stream;
1979 HRESULT hr;
1980 static const WCHAR fileW[] = {'w','i','n','e','t','e','s','t',0};
1981 static const WCHAR storageW[] = {'s','t','o','r','a','g','e',0};
1982 static const WCHAR streamW[] = {'s','t','r','e','a','m',0};
1984 hr = StgCreateDocfile( fileW, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &stg);
1985 ok(hr == S_OK, "should succeed, res=%x\n", hr);
1986 if (SUCCEEDED(hr))
1988 hr = IStorage_CreateStorage( stg, storageW, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stg2 );
1989 ok(hr == S_OK, "should succeed, res=%x\n", hr);
1990 if (SUCCEEDED(hr))
1992 hr = IStorage_CreateStream( stg2, streamW, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stream );
1993 ok(hr == S_OK, "should succeed, res=%x\n", hr);
1994 if (SUCCEEDED(hr))
1995 IStream_Release(stream);
1996 IStorage_Release(stg2);
1998 IStorage_Release(stg);
2001 /* re-open read only */
2002 hr = StgOpenStorage( fileW, NULL, STGM_TRANSACTED | STGM_SHARE_DENY_NONE | STGM_READ, NULL, 0, &stg);
2003 ok(hr == S_OK, "should succeed, res=%x\n", hr);
2004 if (SUCCEEDED(hr))
2006 hr = IStorage_OpenStorage( stg, storageW, NULL, STGM_SHARE_EXCLUSIVE | STGM_READ, NULL, 0, &stg2 );
2007 ok(hr == S_OK, "should succeed, res=%x\n", hr);
2008 if (SUCCEEDED(hr))
2010 /* CreateStream on read-only storage, name exists */
2011 hr = IStorage_CreateStream( stg2, streamW, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READ, 0, 0, &stream );
2012 ok(hr == STG_E_ACCESSDENIED, "should fail, res=%x\n", hr);
2013 if (SUCCEEDED(hr))
2014 IStream_Release(stream);
2016 /* CreateStream on read-only storage, name does not exist */
2017 hr = IStorage_CreateStream( stg2, storageW, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READ, 0, 0, &stream );
2018 ok(hr == STG_E_ACCESSDENIED, "should fail, res=%x\n", hr);
2019 if (SUCCEEDED(hr))
2020 IStream_Release(stream);
2022 /* CreateStorage on read-only storage, name exists */
2023 hr = IStorage_CreateStorage( stg2, streamW, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READ, 0, 0, &stg3 );
2024 ok(hr == STG_E_FILEALREADYEXISTS, "should fail, res=%x\n", hr);
2025 if (SUCCEEDED(hr))
2026 IStorage_Release(stg3);
2028 /* CreateStorage on read-only storage, name does not exist */
2029 hr = IStorage_CreateStorage( stg2, storageW, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READ, 0, 0, &stg3 );
2030 ok(hr == STG_E_ACCESSDENIED, "should fail, res=%x\n", hr);
2031 if (SUCCEEDED(hr))
2032 IStorage_Release(stg3);
2034 /* DestroyElement on read-only storage, name exists */
2035 hr = IStorage_DestroyElement( stg2, streamW );
2036 ok(hr == STG_E_ACCESSDENIED, "should fail, res=%x\n", hr);
2038 /* DestroyElement on read-only storage, name does not exist */
2039 hr = IStorage_DestroyElement( stg2, storageW );
2040 ok(hr == STG_E_ACCESSDENIED, "should fail, res=%x\n", hr);
2042 IStorage_Release(stg2);
2045 IStorage_Release(stg);
2048 DeleteFileA("winetest");
2051 static void test_simple(void)
2053 /* Tests for STGM_SIMPLE mode */
2055 IStorage *stg, *stg2;
2056 HRESULT r;
2057 IStream *stm;
2058 static const WCHAR stgname[] = { 'S','t','g',0 };
2059 static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 };
2060 static const WCHAR stmname2[] = { 'S','m','a','l','l',0 };
2061 LARGE_INTEGER pos;
2062 ULARGE_INTEGER upos;
2063 DWORD count;
2064 STATSTG stat;
2066 DeleteFileA(filenameA);
2068 r = StgCreateDocfile( filename, STGM_SIMPLE | STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &stg);
2069 ok(r == S_OK, "got %08x\n", r);
2071 r = IStorage_CreateStorage(stg, stgname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stg2);
2072 ok(r == STG_E_INVALIDFUNCTION, "got %08x\n", r);
2073 if (SUCCEEDED(r)) IStorage_Release(stg2);
2075 r = IStorage_CreateStream(stg, stmname, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm);
2076 ok(r == STG_E_INVALIDFLAG, "got %08x\n", r);
2077 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm);
2078 ok(r == S_OK, "got %08x\n", r);
2080 upos.QuadPart = 6000;
2081 r = IStream_SetSize(stm, upos);
2082 ok(r == S_OK, "got %08x\n", r);
2084 r = IStream_Write(stm, "foo", 3, &count);
2085 ok(r == S_OK, "got %08x\n", r);
2086 ok(count == 3, "got %d\n", count);
2088 pos.QuadPart = 0;
2089 r = IStream_Seek(stm, pos, STREAM_SEEK_CUR, &upos);
2090 ok(r == S_OK, "got %08x\n", r);
2091 ok(upos.QuadPart == 3, "got %d\n", upos.u.LowPart);
2093 r = IStream_Stat(stm, &stat, STATFLAG_NONAME);
2094 ok(r == S_OK ||
2095 broken(r == STG_E_INVALIDFUNCTION), /* NT4 and below */
2096 "got %08x\n", r);
2097 if (r == S_OK)
2098 ok(stat.cbSize.QuadPart == 3, "got %d\n", stat.cbSize.u.LowPart);
2100 pos.QuadPart = 1;
2101 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &upos);
2102 ok(r == S_OK, "got %08x\n", r);
2103 ok(upos.QuadPart == 1, "got %d\n", upos.u.LowPart);
2105 r = IStream_Stat(stm, &stat, STATFLAG_NONAME);
2106 ok(r == S_OK ||
2107 broken(r == STG_E_INVALIDFUNCTION), /* NT4 and below */
2108 "got %08x\n", r);
2109 if (r == S_OK)
2110 ok(stat.cbSize.QuadPart == 1, "got %d\n", stat.cbSize.u.LowPart);
2112 IStream_Release(stm);
2114 r = IStorage_CreateStream(stg, stmname2, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm);
2115 ok(r == S_OK, "got %08x\n", r);
2117 upos.QuadPart = 100;
2118 r = IStream_SetSize(stm, upos);
2119 ok(r == S_OK, "got %08x\n", r);
2121 r = IStream_Write(stm, "foo", 3, &count);
2122 ok(r == S_OK, "got %08x\n", r);
2123 ok(count == 3, "got %d\n", count);
2125 IStream_Release(stm);
2127 IStorage_Commit(stg, STGC_DEFAULT);
2128 IStorage_Release(stg);
2130 r = StgOpenStorage( filename, NULL, STGM_SIMPLE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, NULL, 0, &stg);
2131 if (r == STG_E_INVALIDFLAG)
2133 win_skip("Flag combination is not supported on NT4 and below\n");
2134 DeleteFileA(filenameA);
2135 return;
2137 ok(r == S_OK, "got %08x\n", r);
2139 r = IStorage_OpenStorage(stg, stgname, NULL, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, NULL, 0, &stg2);
2140 ok(r == STG_E_INVALIDFUNCTION, "got %08x\n", r);
2141 if (SUCCEEDED(r)) IStorage_Release(stg2);
2143 r = IStorage_OpenStream(stg, stmname, NULL, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &stm);
2144 ok(r == S_OK, "got %08x\n", r);
2146 r = IStream_Stat(stm, &stat, STATFLAG_NONAME);
2147 ok(r == S_OK, "got %08x\n", r);
2148 ok(stat.cbSize.QuadPart == 6000, "got %d\n", stat.cbSize.u.LowPart);
2150 IStream_Release(stm);
2152 r = IStorage_OpenStream(stg, stmname2, NULL, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &stm);
2153 ok(r == S_OK, "got %08x\n", r);
2155 r = IStream_Stat(stm, &stat, STATFLAG_NONAME);
2156 ok(r == S_OK, "got %08x\n", r);
2157 ok(stat.cbSize.QuadPart == 4096, "got %d\n", stat.cbSize.u.LowPart);
2159 IStream_Release(stm);
2162 IStorage_Release(stg);
2164 DeleteFileA(filenameA);
2167 static void test_fmtusertypestg(void)
2169 IStorage *stg;
2170 IEnumSTATSTG *stat;
2171 HRESULT hr;
2172 static const char fileA[] = {'f','m','t','t','e','s','t',0};
2173 static const WCHAR fileW[] = {'f','m','t','t','e','s','t',0};
2174 static WCHAR userTypeW[] = {'S','t','g','U','s','r','T','y','p','e',0};
2175 static WCHAR strmNameW[] = {1,'C','o','m','p','O','b','j',0};
2177 hr = StgCreateDocfile( fileW, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &stg);
2178 ok(hr == S_OK, "should succeed, res=%x\n", hr);
2180 if (SUCCEEDED(hr))
2182 /* try to write the stream */
2183 hr = WriteFmtUserTypeStg(stg, 0, userTypeW);
2184 ok(hr == S_OK, "should succeed, res=%x\n", hr);
2186 /* check that the stream was created */
2187 hr = IStorage_EnumElements(stg, 0, NULL, 0, &stat);
2188 ok(hr == S_OK, "should succeed, res=%x\n", hr);
2189 if (SUCCEEDED(hr))
2191 BOOL found = FALSE;
2192 STATSTG statstg;
2193 DWORD got;
2194 while ((hr = IEnumSTATSTG_Next(stat, 1, &statstg, &got)) == S_OK && got == 1)
2196 if (strcmp_ww(statstg.pwcsName, strmNameW) == 0)
2197 found = TRUE;
2198 else
2199 ok(0, "found unexpected stream or storage\n");
2200 CoTaskMemFree(statstg.pwcsName);
2202 ok(found == TRUE, "expected storage to contain stream \\0001CompObj\n");
2203 IEnumSTATSTG_Release(stat);
2206 /* re-write the stream */
2207 hr = WriteFmtUserTypeStg(stg, 0, userTypeW);
2208 ok(hr == S_OK, "should succeed, res=%x\n", hr);
2210 /* check that the stream is still there */
2211 hr = IStorage_EnumElements(stg, 0, NULL, 0, &stat);
2212 ok(hr == S_OK, "should succeed, res=%x\n", hr);
2213 if (SUCCEEDED(hr))
2215 BOOL found = FALSE;
2216 STATSTG statstg;
2217 DWORD got;
2218 while ((hr = IEnumSTATSTG_Next(stat, 1, &statstg, &got)) == S_OK && got == 1)
2220 if (strcmp_ww(statstg.pwcsName, strmNameW) == 0)
2221 found = TRUE;
2222 else
2223 ok(0, "found unexpected stream or storage\n");
2224 CoTaskMemFree(statstg.pwcsName);
2226 ok(found == TRUE, "expected storage to contain stream \\0001CompObj\n");
2227 IEnumSTATSTG_Release(stat);
2230 IStorage_Release(stg);
2231 DeleteFileA( fileA );
2235 static void test_references(void)
2237 IStorage *stg,*stg2;
2238 HRESULT hr;
2239 unsigned c1,c2;
2240 static const WCHAR StorName[] = { 'D','a','t','a','S','p','a','c','e','I','n','f','o',0 };
2242 DeleteFileA(filenameA);
2244 hr = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
2245 ok(hr==S_OK, "StgCreateDocfile failed\n");
2247 if (SUCCEEDED(hr))
2249 IStorage_Release(stg);
2251 hr = StgOpenStorage( filename, NULL, STGM_TRANSACTED | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, NULL, 0, &stg);
2252 ok(hr==S_OK, "StgOpenStorage failed (result=%x)\n",hr);
2254 if (SUCCEEDED(hr))
2256 hr = IStorage_CreateStorage(stg,StorName,STGM_READWRITE | STGM_SHARE_EXCLUSIVE,0,0,&stg2);
2257 ok(hr == S_OK, "IStorage_CreateStorage failed (result=%x)\n",hr);
2259 if (SUCCEEDED(hr))
2261 c1 = IStorage_AddRef(stg);
2262 ok(c1 == 2, "creating internal storage added references to ancestor\n");
2263 c1 = IStorage_AddRef(stg);
2264 IStorage_Release(stg2);
2265 c2 = IStorage_AddRef(stg) - 1;
2266 ok(c1 == c2, "releasing internal storage removed references to ancestor\n");
2268 c1 = IStorage_Release(stg);
2269 while ( c1 ) c1 = IStorage_Release(stg);
2273 DeleteFileA(filenameA);
2276 /* dest
2277 * |-StorageA
2278 * | `StreamA: "StreamA"
2279 * |-StorageB
2280 * | `StreamB: "StreamB"
2281 * `StreamC: "StreamC"
2283 static HRESULT create_test_file(IStorage *dest)
2285 IStorage *stgA = NULL, *stgB = NULL;
2286 IStream *strmA = NULL, *strmB = NULL, *strmC = NULL;
2287 const ULONG strmA_name_size = lstrlenW(strmA_name) * sizeof(WCHAR);
2288 const ULONG strmB_name_size = lstrlenW(strmB_name) * sizeof(WCHAR);
2289 const ULONG strmC_name_size = lstrlenW(strmC_name) * sizeof(WCHAR);
2290 ULONG bytes;
2291 HRESULT hr;
2293 hr = IStorage_CreateStorage(dest, stgA_name, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stgA);
2294 ok(hr == S_OK, "IStorage_CreateStorage failed: 0x%08x\n", hr);
2295 if(FAILED(hr))
2296 goto cleanup;
2298 hr = IStorage_CreateStream(stgA, strmA_name, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &strmA);
2299 ok(hr == S_OK, "IStorage_CreateStream failed: 0x%08x\n", hr);
2300 if(FAILED(hr))
2301 goto cleanup;
2303 hr = IStream_Write(strmA, strmA_name, strmA_name_size, &bytes);
2304 ok(hr == S_OK && bytes == strmA_name_size, "IStream_Write failed: 0x%08x, %d of %d bytes written\n", hr, bytes, strmA_name_size);
2306 hr = IStorage_CreateStorage(dest, stgB_name, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stgB);
2307 ok(hr == S_OK, "IStorage_CreateStorage failed: 0x%08x\n", hr);
2308 if(FAILED(hr))
2309 goto cleanup;
2311 hr = IStorage_CreateStream(stgB, strmB_name, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &strmB);
2312 ok(hr == S_OK, "IStorage_CreateStream failed: 0x%08x\n", hr);
2313 if(FAILED(hr))
2314 goto cleanup;
2316 hr = IStream_Write(strmB, strmB_name, strmB_name_size, &bytes);
2317 ok(hr == S_OK && bytes == strmB_name_size, "IStream_Write failed: 0x%08x, %d of %d bytes written\n", hr, bytes, strmB_name_size);
2319 hr = IStorage_CreateStream(dest, strmC_name, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &strmC);
2320 ok(hr == S_OK, "IStorage_CreateStream failed: 0x%08x\n", hr);
2321 if(FAILED(hr))
2322 goto cleanup;
2324 hr = IStream_Write(strmC, strmC_name, strmC_name_size, &bytes);
2325 ok(hr == S_OK && bytes == strmC_name_size, "IStream_Write failed: 0x%08x, %d of %d bytes written\n", hr, bytes, strmC_name_size);
2327 cleanup:
2328 if(strmC)
2329 IStream_Release(strmC);
2330 if(strmB)
2331 IStream_Release(strmB);
2332 if(stgB)
2333 IStorage_Release(stgB);
2334 if(strmA)
2335 IStream_Release(strmA);
2336 if(stgA)
2337 IStorage_Release(stgA);
2339 return hr;
2342 static void test_copyto(void)
2344 IStorage *file1 = NULL, *file2 = NULL, *stg_tmp;
2345 IStream *strm_tmp;
2346 WCHAR buf[64];
2347 HRESULT hr;
2349 /* create & populate file1 */
2350 hr = StgCreateDocfile(file1_name, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &file1);
2351 ok(hr == S_OK, "StgCreateDocfile failed: 0x%08x\n", hr);
2352 if(FAILED(hr))
2353 goto cleanup;
2355 hr = create_test_file(file1);
2356 if(FAILED(hr))
2357 goto cleanup;
2359 /* create file2 */
2360 hr = StgCreateDocfile(file2_name, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &file2);
2361 ok(hr == S_OK, "StgCreateDocfile failed: 0x%08x\n", hr);
2362 if(FAILED(hr))
2363 goto cleanup;
2365 /* copy file1 into file2 */
2366 hr = IStorage_CopyTo(file1, 0, NULL, NULL, NULL);
2367 ok(hr == STG_E_INVALIDPOINTER, "CopyTo should give STG_E_INVALIDPONITER, gave: 0x%08x\n", hr);
2369 hr = IStorage_CopyTo(file1, 0, NULL, NULL, file2);
2370 ok(hr == S_OK, "CopyTo failed: 0x%08x\n", hr);
2371 if(FAILED(hr))
2372 goto cleanup;
2374 /* verify that all of file1 was copied */
2375 hr = IStorage_OpenStorage(file2, stgA_name, NULL,
2376 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg_tmp);
2377 ok(hr == S_OK, "OpenStorage failed: 0x%08x\n", hr);
2379 if(SUCCEEDED(hr)){
2380 hr = IStorage_OpenStream(stg_tmp, strmA_name, NULL,
2381 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp);
2382 ok(hr == S_OK, "OpenStream failed: 0x%08x\n", hr);
2384 if(SUCCEEDED(hr)){
2385 memset(buf, 0, sizeof(buf));
2386 hr = IStream_Read(strm_tmp, buf, sizeof(buf), NULL);
2387 ok(hr == S_OK, "Read failed: 0x%08x\n", hr);
2388 if(SUCCEEDED(hr))
2389 ok(strcmp_ww(buf, strmA_name) == 0,
2390 "Expected %s to be read, got %s\n", wine_dbgstr_w(strmA_name), wine_dbgstr_w(buf));
2392 IStream_Release(strm_tmp);
2395 IStorage_Release(stg_tmp);
2398 hr = IStorage_OpenStorage(file2, stgB_name, NULL,
2399 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg_tmp);
2400 ok(hr == S_OK, "OpenStorage failed: 0x%08x\n", hr);
2402 if(SUCCEEDED(hr)){
2403 hr = IStorage_OpenStream(stg_tmp, strmB_name, NULL,
2404 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp);
2405 ok(hr == S_OK, "OpenStream failed: 0x%08x\n", hr);
2407 if(SUCCEEDED(hr)){
2408 memset(buf, 0, sizeof(buf));
2409 hr = IStream_Read(strm_tmp, buf, sizeof(buf), NULL);
2410 ok(hr == S_OK, "Read failed: 0x%08x\n", hr);
2411 if(SUCCEEDED(hr))
2412 ok(strcmp_ww(buf, strmB_name) == 0,
2413 "Expected %s to be read, got %s\n", wine_dbgstr_w(strmB_name), wine_dbgstr_w(buf));
2415 IStream_Release(strm_tmp);
2418 IStorage_Release(stg_tmp);
2421 hr = IStorage_OpenStream(file2, strmC_name, NULL,
2422 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp);
2423 ok(hr == S_OK, "OpenStream failed: 0x%08x\n", hr);
2425 if(SUCCEEDED(hr)){
2426 memset(buf, 0, sizeof(buf));
2427 hr = IStream_Read(strm_tmp, buf, sizeof(buf), NULL);
2428 ok(hr == S_OK, "Read failed: 0x%08x\n", hr);
2429 if(SUCCEEDED(hr))
2430 ok(strcmp_ww(buf, strmC_name) == 0,
2431 "Expected %s to be read, got %s\n", wine_dbgstr_w(strmC_name), wine_dbgstr_w(buf));
2433 IStream_Release(strm_tmp);
2436 cleanup:
2437 if(file1)
2438 IStorage_Release(file1);
2439 if(file2)
2440 IStorage_Release(file2);
2442 DeleteFileA(file1_nameA);
2443 DeleteFileA(file2_nameA);
2446 static void test_copyto_snbexclusions(void)
2448 static const WCHAR *snb_exclude[] = {stgA_name, strmB_name, strmC_name, 0};
2450 IStorage *file1 = NULL, *file2 = NULL, *stg_tmp;
2451 IStream *strm_tmp;
2452 WCHAR buf[64];
2453 HRESULT hr;
2455 /* create & populate file1 */
2456 hr = StgCreateDocfile(file1_name, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &file1);
2457 ok(hr == S_OK, "StgCreateDocfile failed: 0x%08x\n", hr);
2458 if(FAILED(hr))
2459 goto cleanup;
2461 hr = create_test_file(file1);
2462 if(FAILED(hr))
2463 goto cleanup;
2465 /* create file2 */
2466 hr = StgCreateDocfile(file2_name, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &file2);
2467 ok(hr == S_OK, "StgCreateDocfile failed: 0x%08x\n", hr);
2468 if(FAILED(hr))
2469 goto cleanup;
2471 /* copy file1 to file2 with name exclusions */
2472 hr = IStorage_CopyTo(file1, 0, NULL, (SNB)snb_exclude, file2);
2473 ok(hr == S_OK, "CopyTo failed: 0x%08x\n", hr);
2474 if(FAILED(hr))
2475 goto cleanup;
2477 /* verify that file1 copied over, respecting exclusions */
2478 hr = IStorage_OpenStorage(file2, stgA_name, NULL,
2479 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg_tmp);
2480 ok(hr == STG_E_FILENOTFOUND, "OpenStorage should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr);
2481 if(SUCCEEDED(hr))
2482 IStorage_Release(stg_tmp);
2484 hr = IStorage_OpenStream(file2, strmA_name, NULL,
2485 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp);
2486 ok(hr == STG_E_FILENOTFOUND, "OpenStream should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr);
2487 if(SUCCEEDED(hr))
2488 IStream_Release(strm_tmp);
2490 hr = IStorage_OpenStorage(file2, stgB_name, NULL,
2491 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg_tmp);
2492 ok(hr == S_OK, "OpenStorage failed: 0x%08x\n", hr);
2494 if(SUCCEEDED(hr)){
2495 hr = IStorage_OpenStream(stg_tmp, strmB_name, NULL,
2496 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp);
2497 ok(hr == S_OK, "OpenStream failed: 0x%08x\n", hr);
2499 if(SUCCEEDED(hr)){
2500 memset(buf, 0, sizeof(buf));
2501 hr = IStream_Read(strm_tmp, buf, sizeof(buf), NULL);
2502 ok(hr == S_OK, "Read failed: 0x%08x\n", hr);
2503 if(SUCCEEDED(hr))
2504 ok(strcmp_ww(buf, strmB_name) == 0,
2505 "Expected %s to be read, got %s\n", wine_dbgstr_w(strmB_name), wine_dbgstr_w(buf));
2507 IStream_Release(strm_tmp);
2510 IStorage_Release(stg_tmp);
2513 hr = IStorage_OpenStream(file2, strmC_name, NULL,
2514 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp);
2515 ok(hr == STG_E_FILENOTFOUND, "OpenStream should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr);
2516 if(SUCCEEDED(hr))
2517 IStream_Release(strm_tmp);
2519 cleanup:
2520 if(file1)
2521 IStorage_Release(file1);
2522 if(file2)
2523 IStorage_Release(file2);
2525 DeleteFileA(file1_nameA);
2526 DeleteFileA(file2_nameA);
2529 static void test_copyto_iidexclusions_storage(void)
2531 IStorage *file1 = NULL, *file2 = NULL, *stg_tmp;
2532 IStream *strm_tmp;
2533 WCHAR buf[64];
2534 HRESULT hr;
2536 /* create & populate file1 */
2537 hr = StgCreateDocfile(file1_name, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &file1);
2538 ok(hr == S_OK, "StgCreateDocfile failed: 0x%08x\n", hr);
2539 if(FAILED(hr))
2540 goto cleanup;
2542 hr = create_test_file(file1);
2543 if(FAILED(hr))
2544 goto cleanup;
2546 /* create file2 */
2547 hr = StgCreateDocfile(file2_name, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &file2);
2548 ok(hr == S_OK, "StgCreateDocfile failed: 0x%08x\n", hr);
2549 if(FAILED(hr))
2550 goto cleanup;
2552 /* copy file1 to file2 with iid exclusions */
2553 hr = IStorage_CopyTo(file1, 1, &IID_IStorage, NULL, file2);
2554 ok(hr == S_OK, "CopyTo failed: 0x%08x\n", hr);
2555 if(FAILED(hr))
2556 goto cleanup;
2558 /* verify that file1 copied over, respecting exclusions */
2559 hr = IStorage_OpenStorage(file2, stgA_name, NULL,
2560 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg_tmp);
2561 ok(hr == STG_E_FILENOTFOUND, "OpenStorage should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr);
2562 if(SUCCEEDED(hr))
2563 IStorage_Release(stg_tmp);
2565 hr = IStorage_OpenStream(file2, strmA_name, NULL,
2566 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp);
2567 ok(hr == STG_E_FILENOTFOUND, "OpenStream should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr);
2568 if(SUCCEEDED(hr))
2569 IStream_Release(strm_tmp);
2571 hr = IStorage_OpenStorage(file2, stgB_name, NULL,
2572 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg_tmp);
2573 ok(hr == STG_E_FILENOTFOUND, "OpenStorage should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr);
2574 if(SUCCEEDED(hr))
2575 IStorage_Release(stg_tmp);
2577 hr = IStorage_OpenStream(file2, strmB_name, NULL,
2578 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp);
2579 ok(hr == STG_E_FILENOTFOUND, "OpenStream should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr);
2580 if(SUCCEEDED(hr))
2581 IStream_Release(strm_tmp);
2583 hr = IStorage_OpenStream(file2, strmC_name, NULL,
2584 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp);
2585 ok(hr == S_OK, "OpenStream failed: 0x%08x\n", hr);
2587 if(SUCCEEDED(hr)){
2588 memset(buf, 0, sizeof(buf));
2589 hr = IStream_Read(strm_tmp, buf, sizeof(buf), NULL);
2590 ok(hr == S_OK, "Read failed: 0x%08x\n", hr);
2591 if(SUCCEEDED(hr))
2592 ok(strcmp_ww(buf, strmC_name) == 0,
2593 "Expected %s to be read, got %s\n", wine_dbgstr_w(strmC_name), wine_dbgstr_w(buf));
2595 IStream_Release(strm_tmp);
2598 cleanup:
2599 if(file1)
2600 IStorage_Release(file1);
2601 if(file2)
2602 IStorage_Release(file2);
2604 DeleteFileA(file1_nameA);
2605 DeleteFileA(file2_nameA);
2608 static void test_copyto_iidexclusions_stream(void)
2610 IStorage *file1 = NULL, *file2 = NULL, *stg_tmp;
2611 IStream *strm_tmp;
2612 HRESULT hr;
2614 /* create & populate file1 */
2615 hr = StgCreateDocfile(file1_name, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &file1);
2616 ok(hr == S_OK, "StgCreateDocfile failed: 0x%08x\n", hr);
2617 if(FAILED(hr))
2618 goto cleanup;
2620 hr = create_test_file(file1);
2621 if(FAILED(hr))
2622 goto cleanup;
2624 /* create file2 */
2625 hr = StgCreateDocfile(file2_name, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &file2);
2626 ok(hr == S_OK, "StgCreateDocfile failed: 0x%08x\n", hr);
2627 if(FAILED(hr))
2628 goto cleanup;
2630 /* copy file1 to file2 with iid exclusions */
2631 hr = IStorage_CopyTo(file1, 1, &IID_IStream, NULL, file2);
2632 ok(hr == S_OK, "CopyTo failed: 0x%08x\n", hr);
2633 if(FAILED(hr))
2634 goto cleanup;
2636 /* verify that file1 copied over, respecting exclusions */
2637 hr = IStorage_OpenStorage(file2, stgA_name, NULL,
2638 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg_tmp);
2639 ok(hr == S_OK, "OpenStorage failed: 0x%08x\n", hr);
2641 if(SUCCEEDED(hr)){
2642 hr = IStorage_OpenStream(stg_tmp, strmA_name, NULL,
2643 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp);
2644 ok(hr == STG_E_FILENOTFOUND, "OpenStream should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr);
2645 if(SUCCEEDED(hr))
2646 IStream_Release(strm_tmp);
2648 IStorage_Release(stg_tmp);
2651 hr = IStorage_OpenStorage(file2, stgB_name, NULL,
2652 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg_tmp);
2653 ok(hr == S_OK, "OpenStorage failed: 0x%08x\n", hr);
2655 if(SUCCEEDED(hr)){
2656 hr = IStorage_OpenStream(stg_tmp, strmB_name, NULL,
2657 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp);
2658 ok(hr == STG_E_FILENOTFOUND, "OpenStream should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr);
2659 if(SUCCEEDED(hr))
2660 IStream_Release(strm_tmp);
2662 IStorage_Release(stg_tmp);
2665 hr = IStorage_OpenStream(file2, strmC_name, NULL,
2666 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp);
2667 ok(hr == STG_E_FILENOTFOUND, "OpenStream should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr);
2668 if(SUCCEEDED(hr))
2669 IStream_Release(strm_tmp);
2671 cleanup:
2672 if(file1)
2673 IStorage_Release(file1);
2674 if(file2)
2675 IStorage_Release(file2);
2677 DeleteFileA(file1_nameA);
2678 DeleteFileA(file2_nameA);
2681 static void test_rename(void)
2683 IStorage *stg, *stg2;
2684 IStream *stm;
2685 HRESULT r;
2686 static const WCHAR stgname[] = { 'P','E','R','M','S','T','G',0 };
2687 static const WCHAR stgname2[] = { 'S','T','G',0 };
2688 static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 };
2689 static const WCHAR stmname2[] = { 'E','N','T','S',0 };
2691 DeleteFileA(filenameA);
2693 /* create the file */
2694 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
2695 STGM_READWRITE, 0, &stg);
2696 ok(r==S_OK, "StgCreateDocfile failed\n");
2698 /* create a substorage */
2699 r = IStorage_CreateStorage(stg, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg2);
2700 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
2702 /* create a stream in the substorage */
2703 r = IStorage_CreateStream(stg2, stmname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm);
2704 ok(r==S_OK, "IStorage->CreateStream failed, hr=%08x\n", r);
2705 IStream_Release(stm);
2707 /* rename the stream */
2708 r = IStorage_RenameElement(stg2, stmname, stmname2);
2709 ok(r==S_OK, "IStorage->RenameElement failed, hr=%08x\n", r);
2711 /* cannot open stream with old name */
2712 r = IStorage_OpenStream(stg2, stmname, NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &stm);
2713 ok(r==STG_E_FILENOTFOUND, "IStorage_OpenStream should fail, hr=%08x\n", r);
2714 if (SUCCEEDED(r)) IStream_Release(stm);
2716 /* can open stream with new name */
2717 r = IStorage_OpenStream(stg2, stmname2, NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &stm);
2718 ok(r==S_OK, "IStorage_OpenStream failed, hr=%08x\n", r);
2719 if (SUCCEEDED(r)) IStream_Release(stm);
2721 IStorage_Release(stg2);
2723 /* rename the storage */
2724 IStorage_RenameElement(stg, stgname, stgname2);
2726 /* cannot open storage with old name */
2727 r = IStorage_OpenStorage(stg, stgname, NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg2);
2728 ok(r==STG_E_FILENOTFOUND, "IStorage_OpenStream should fail, hr=%08x\n", r);
2729 if (SUCCEEDED(r)) IStorage_Release(stg2);
2731 /* can open storage with new name */
2732 r = IStorage_OpenStorage(stg, stgname2, NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg2);
2733 ok(r==S_OK, "IStorage_OpenStream should fail, hr=%08x\n", r);
2734 if (SUCCEEDED(r))
2736 /* opened storage still has the stream */
2737 r = IStorage_OpenStream(stg2, stmname2, NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &stm);
2738 ok(r==S_OK, "IStorage_OpenStream failed, hr=%08x\n", r);
2739 if (SUCCEEDED(r)) IStream_Release(stm);
2741 IStorage_Release(stg2);
2744 IStorage_Release(stg);
2746 r = DeleteFileA(filenameA);
2747 ok( r == TRUE, "deleted file\n");
2750 static void test_toplevel_stat(void)
2752 IStorage *stg = NULL;
2753 HRESULT r;
2754 STATSTG stat;
2755 char prev_dir[MAX_PATH];
2756 char temp[MAX_PATH];
2757 char full_path[MAX_PATH];
2758 LPSTR rel_pathA;
2759 WCHAR rel_path[MAX_PATH];
2761 DeleteFileA(filenameA);
2763 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
2764 STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
2765 ok(r==S_OK, "StgCreateDocfile failed\n");
2767 r = IStorage_Stat( stg, &stat, STATFLAG_DEFAULT );
2768 ok(r==S_OK, "Storage_Stat failed with error 0x%08x\n", r);
2769 ok(!strcmp_ww(stat.pwcsName, filename), "expected %s, got %s\n",
2770 wine_dbgstr_w(filename), wine_dbgstr_w(stat.pwcsName));
2771 CoTaskMemFree(stat.pwcsName);
2773 IStorage_Release( stg );
2775 r = StgOpenStorage( filename, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg);
2776 ok(r==S_OK, "StgOpenStorage failed with error 0x%08x\n", r);
2778 r = IStorage_Stat( stg, &stat, STATFLAG_DEFAULT );
2779 ok(r==S_OK, "Storage_Stat failed with error 0x%08x\n", r);
2780 ok(!strcmp_ww(stat.pwcsName, filename), "expected %s, got %s\n",
2781 wine_dbgstr_w(filename), wine_dbgstr_w(stat.pwcsName));
2782 CoTaskMemFree(stat.pwcsName);
2784 IStorage_Release( stg );
2786 DeleteFileA(filenameA);
2788 /* Stat always returns the full path, even for files opened with a relative path. */
2789 GetCurrentDirectoryA(MAX_PATH, prev_dir);
2791 GetTempPathA(MAX_PATH, temp);
2793 SetCurrentDirectoryA(temp);
2795 GetFullPathNameA(filenameA, MAX_PATH, full_path, &rel_pathA);
2796 MultiByteToWideChar(CP_ACP, 0, rel_pathA, -1, rel_path, MAX_PATH);
2798 r = StgCreateDocfile( rel_path, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
2799 STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
2800 ok(r==S_OK, "StgCreateDocfile failed\n");
2802 r = IStorage_Stat( stg, &stat, STATFLAG_DEFAULT );
2803 ok(r==S_OK, "Storage_Stat failed with error 0x%08x\n", r);
2804 ok(!strcmp_ww(stat.pwcsName, filename), "expected %s, got %s\n",
2805 wine_dbgstr_w(filename), wine_dbgstr_w(stat.pwcsName));
2806 CoTaskMemFree(stat.pwcsName);
2808 IStorage_Release( stg );
2810 r = StgOpenStorage( rel_path, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg);
2811 ok(r==S_OK, "StgOpenStorage failed with error 0x%08x\n", r);
2813 r = IStorage_Stat( stg, &stat, STATFLAG_DEFAULT );
2814 ok(r==S_OK, "Storage_Stat failed with error 0x%08x\n", r);
2815 ok(!strcmp_ww(stat.pwcsName, filename), "expected %s, got %s\n",
2816 wine_dbgstr_w(filename), wine_dbgstr_w(stat.pwcsName));
2817 CoTaskMemFree(stat.pwcsName);
2819 IStorage_Release( stg );
2821 SetCurrentDirectoryA(prev_dir);
2823 DeleteFileA(filenameA);
2826 static void test_substorage_enum(void)
2828 IStorage *stg, *stg2;
2829 IEnumSTATSTG *ee;
2830 HRESULT r;
2831 ULONG ref;
2832 static const WCHAR stgname[] = { 'P','E','R','M','S','T','G',0 };
2834 DeleteFileA(filenameA);
2836 /* create the file */
2837 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
2838 STGM_READWRITE, 0, &stg);
2839 ok(r==S_OK, "StgCreateDocfile failed\n");
2841 /* create a substorage */
2842 r = IStorage_CreateStorage(stg, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg2);
2843 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
2845 /* create an enumelements */
2846 r = IStorage_EnumElements(stg2, 0, NULL, 0, &ee);
2847 ok(r==S_OK, "IStorage->EnumElements failed, hr=%08x\n", r);
2849 /* release the substorage */
2850 ref = IStorage_Release(stg2);
2851 todo_wine ok(ref==0, "storage not released\n");
2853 /* reopening fails, because the substorage is really still open */
2854 r = IStorage_OpenStorage(stg, stgname, NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg2);
2855 ok(r==STG_E_ACCESSDENIED, "IStorage->OpenStorage failed, hr=%08x\n", r);
2857 /* destroying the storage invalidates the enumerator */
2858 r = IStorage_DestroyElement(stg, stgname);
2859 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
2861 r = IEnumSTATSTG_Reset(ee);
2862 ok(r==STG_E_REVERTED, "IEnumSTATSTG->Reset failed, hr=%08x\n", r);
2864 IEnumSTATSTG_Release(ee);
2866 IStorage_Release(stg);
2868 r = DeleteFileA(filenameA);
2869 ok( r == TRUE, "deleted file\n");
2872 static void test_copyto_locking(void)
2874 IStorage *stg, *stg2, *stg3, *stg4;
2875 IStream *stm;
2876 HRESULT r;
2877 static const WCHAR stgname[] = { 'S','T','G','1',0 };
2878 static const WCHAR stgname2[] = { 'S','T','G','2',0 };
2879 static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 };
2881 DeleteFileA(filenameA);
2883 /* create the file */
2884 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
2885 STGM_READWRITE, 0, &stg);
2886 ok(r==S_OK, "StgCreateDocfile failed\n");
2888 /* create a substorage */
2889 r = IStorage_CreateStorage(stg, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg2);
2890 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
2892 /* create another substorage */
2893 r = IStorage_CreateStorage(stg, stgname2, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg3);
2894 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
2896 /* add a stream, and leave it open */
2897 r = IStorage_CreateStream(stg2, stmname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm);
2898 ok(r==S_OK, "IStorage->CreateStream failed, hr=%08x\n", r);
2900 /* Try to copy the storage while the stream is open */
2901 r = IStorage_CopyTo(stg2, 0, NULL, NULL, stg3);
2902 ok(r==S_OK, "IStorage->CopyTo failed, hr=%08x\n", r);
2904 IStream_Release(stm);
2906 /* create a substorage */
2907 r = IStorage_CreateStorage(stg2, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg4);
2908 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
2910 /* Try to copy the storage while the substorage is open */
2911 r = IStorage_CopyTo(stg2, 0, NULL, NULL, stg3);
2912 ok(r==S_OK, "IStorage->CopyTo failed, hr=%08x\n", r);
2914 IStorage_Release(stg4);
2915 IStorage_Release(stg3);
2916 IStorage_Release(stg2);
2917 IStorage_Release(stg);
2919 r = DeleteFileA(filenameA);
2920 ok( r == TRUE, "deleted file\n");
2923 static void test_copyto_recursive(void)
2925 IStorage *stg, *stg2, *stg3, *stg4;
2926 HRESULT r;
2927 static const WCHAR stgname[] = { 'S','T','G','1',0 };
2928 static const WCHAR stgname2[] = { 'S','T','G','2',0 };
2930 DeleteFileA(filenameA);
2932 /* create the file */
2933 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
2934 STGM_READWRITE, 0, &stg);
2935 ok(r==S_OK, "StgCreateDocfile failed\n");
2937 /* create a substorage */
2938 r = IStorage_CreateStorage(stg, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg2);
2939 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
2941 /* copy the parent to the child */
2942 r = IStorage_CopyTo(stg, 0, NULL, NULL, stg2);
2943 ok(r==STG_E_ACCESSDENIED, "IStorage->CopyTo failed, hr=%08x\n", r);
2945 /* create a transacted substorage */
2946 r = IStorage_CreateStorage(stg, stgname2, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_TRANSACTED, 0, 0, &stg3);
2947 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
2949 /* copy the parent to the transacted child */
2950 r = IStorage_CopyTo(stg, 0, NULL, NULL, stg2);
2951 ok(r==STG_E_ACCESSDENIED, "IStorage->CopyTo failed, hr=%08x\n", r);
2953 /* create a transacted subsubstorage */
2954 r = IStorage_CreateStorage(stg3, stgname2, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_TRANSACTED, 0, 0, &stg4);
2955 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
2957 /* copy the parent to the transacted child of the transacted child */
2958 r = IStorage_CopyTo(stg, 0, NULL, NULL, stg4);
2959 ok(r==STG_E_ACCESSDENIED, "IStorage->CopyTo failed, hr=%08x\n", r);
2961 /* copy the parent but exclude storage objects */
2962 r = IStorage_CopyTo(stg, 1, &IID_IStorage, NULL, stg4);
2963 ok(r==S_OK, "IStorage->CopyTo failed, hr=%08x\n", r);
2965 IStorage_Release(stg4);
2966 IStorage_Release(stg3);
2967 IStorage_Release(stg2);
2968 IStorage_Release(stg);
2970 r = DeleteFileA(filenameA);
2971 ok( r == TRUE, "deleted file\n");
2974 static void test_hglobal_storage_creation(void)
2976 ILockBytes *ilb = NULL;
2977 IStorage *stg = NULL;
2978 HRESULT r;
2979 STATSTG stat;
2980 char junk[512];
2981 ULARGE_INTEGER offset;
2983 r = CreateILockBytesOnHGlobal(NULL, TRUE, &ilb);
2984 ok(r == S_OK, "CreateILockBytesOnHGlobal failed, hr=%x\n", r);
2986 offset.QuadPart = 0;
2987 memset(junk, 0xaa, 512);
2988 r = ILockBytes_WriteAt(ilb, offset, junk, 512, NULL);
2989 ok(r == S_OK, "ILockBytes_WriteAt failed, hr=%x\n", r);
2991 offset.QuadPart = 2000;
2992 r = ILockBytes_WriteAt(ilb, offset, junk, 512, NULL);
2993 ok(r == S_OK, "ILockBytes_WriteAt failed, hr=%x\n", r);
2995 r = StgCreateDocfileOnILockBytes(ilb, STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stg);
2996 ok(r == S_OK, "StgCreateDocfileOnILockBytes failed, hr=%x\n", r);
2998 IStorage_Release(stg);
3000 r = StgOpenStorageOnILockBytes(ilb, NULL, STGM_READ|STGM_SHARE_EXCLUSIVE,
3001 NULL, 0, &stg);
3002 ok(r == S_OK, "StgOpenStorageOnILockBytes failed, hr=%x\n", r);
3004 if (SUCCEEDED(r))
3006 r = IStorage_Stat(stg, &stat, STATFLAG_NONAME);
3007 ok(r == S_OK, "StgOpenStorageOnILockBytes failed, hr=%x\n", r);
3008 ok(IsEqualCLSID(&stat.clsid, &GUID_NULL), "unexpected CLSID value\n");
3010 IStorage_Release(stg);
3013 r = ILockBytes_Stat(ilb, &stat, STATFLAG_NONAME);
3014 ok(r == S_OK, "ILockBytes_Stat failed, hr=%x\n", r);
3015 ok(stat.cbSize.u.LowPart < 2512, "expected truncated size, got %d\n", stat.cbSize.u.LowPart);
3017 ILockBytes_Release(ilb);
3020 static void test_convert(void)
3022 static const WCHAR filename[] = {'s','t','o','r','a','g','e','.','s','t','g',0};
3023 IStorage *stg;
3024 HRESULT hr;
3026 hr = GetConvertStg(NULL);
3027 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3029 hr = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &stg);
3030 ok(hr == S_OK, "StgCreateDocfile failed\n");
3031 hr = GetConvertStg(stg);
3032 ok(hr == STG_E_FILENOTFOUND, "got 0x%08x\n", hr);
3033 hr = SetConvertStg(stg, TRUE);
3034 ok(hr == S_OK, "got 0x%08x\n", hr);
3035 hr = SetConvertStg(stg, TRUE);
3036 ok(hr == S_OK, "got 0x%08x\n", hr);
3037 hr = GetConvertStg(stg);
3038 ok(hr == S_OK, "got 0x%08x\n", hr);
3039 hr = SetConvertStg(stg, FALSE);
3040 ok(hr == S_OK, "got 0x%08x\n", hr);
3041 hr = GetConvertStg(stg);
3042 ok(hr == S_FALSE, "got 0x%08x\n", hr);
3044 IStorage_Release(stg);
3046 DeleteFileW(filename);
3049 static void test_direct_swmr(void)
3051 static const WCHAR fileW[] = {'w','i','n','e','t','e','s','t',0};
3052 IDirectWriterLock *dwlock;
3053 ULONG ref, ref2;
3054 IStorage *stg;
3055 HRESULT hr;
3057 /* it's possible to create in writer mode */
3058 hr = StgCreateDocfile(fileW, STGM_CREATE | STGM_READWRITE | STGM_SHARE_DENY_WRITE | STGM_DIRECT_SWMR, 0, &stg);
3059 todo_wine
3060 ok(hr == S_OK, "got %08x\n", hr);
3061 if (hr == S_OK) {
3062 IStorage_Release(stg);
3063 DeleteFileW(fileW);
3066 hr = StgCreateDocfile(fileW, STGM_CREATE | STGM_READWRITE | STGM_SHARE_DENY_WRITE | STGM_TRANSACTED, 0, &stg);
3067 ok(hr == S_OK, "got %08x\n", hr);
3068 IStorage_Release(stg);
3070 /* reader mode */
3071 hr = StgOpenStorage(fileW, NULL, STGM_DIRECT_SWMR | STGM_READ | STGM_SHARE_DENY_NONE, NULL, 0, &stg);
3072 ok(hr == S_OK, "got %08x\n", hr);
3074 hr = IStorage_QueryInterface(stg, &IID_IDirectWriterLock, (void**)&dwlock);
3075 ok(hr == E_NOINTERFACE, "got %08x\n", hr);
3076 IStorage_Release(stg);
3078 /* writer mode */
3079 hr = StgOpenStorage(fileW, NULL, STGM_DIRECT_SWMR | STGM_READWRITE | STGM_SHARE_DENY_WRITE, NULL, 0, &stg);
3080 ok(hr == S_OK, "got %08x\n", hr);
3082 ref = IStorage_AddRef(stg);
3083 IStorage_Release(stg);
3085 hr = IStorage_QueryInterface(stg, &IID_IDirectWriterLock, (void**)&dwlock);
3086 ok(hr == S_OK, "got %08x\n", hr);
3088 ref2 = IStorage_AddRef(stg);
3089 IStorage_Release(stg);
3090 ok(ref2 == ref + 1, "got %u\n", ref2);
3092 IDirectWriterLock_Release(dwlock);
3093 IStorage_Release(stg);
3095 DeleteFileW(fileW);
3098 START_TEST(storage32)
3100 CHAR temp[MAX_PATH];
3102 GetTempPathA(MAX_PATH, temp);
3103 if(!GetTempFileNameA(temp, "stg", 0, filenameA))
3105 win_skip("Could not create temp file, %u\n", GetLastError());
3106 return;
3108 MultiByteToWideChar(CP_ACP, 0, filenameA, -1, filename, MAX_PATH);
3109 DeleteFileA(filenameA);
3111 test_hglobal_storage_stat();
3112 test_create_storage_modes();
3113 test_stgcreatestorageex();
3114 test_storage_stream();
3115 test_open_storage();
3116 test_storage_suminfo();
3117 test_storage_refcount();
3118 test_streamenum();
3119 test_transact();
3120 test_substorage_share();
3121 test_revert();
3122 test_parent_free();
3123 test_nonroot_transacted();
3124 test_ReadClassStm();
3125 test_access();
3126 test_writeclassstg();
3127 test_readonly();
3128 test_simple();
3129 test_fmtusertypestg();
3130 test_references();
3131 test_copyto();
3132 test_copyto_snbexclusions();
3133 test_copyto_iidexclusions_storage();
3134 test_copyto_iidexclusions_stream();
3135 test_rename();
3136 test_toplevel_stat();
3137 test_substorage_enum();
3138 test_copyto_locking();
3139 test_copyto_recursive();
3140 test_hglobal_storage_creation();
3141 test_convert();
3142 test_direct_swmr();