[OLE32_WINETEST]
[reactos.git] / rostests / winetests / ole32 / storage32.c
1 /*
2 * Unit tests for OLE storage
3 *
4 * Copyright (c) 2004 Mike McCormack
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21 #define WIN32_NO_STATUS
22 #define _INC_WINDOWS
23 #define COM_NO_WINDOWS_H
24
25 //#include <stdio.h>
26
27 #define COBJMACROS
28
29 //#include <windows.h>
30 #include <wine/test.h>
31 #include <winnls.h>
32 #include <ole2.h>
33 //#include "objidl.h"
34 #include <initguid.h>
35
36 DEFINE_GUID( test_stg_cls, 0x88888888, 0x0425, 0x0000, 0,0,0,0,0,0,0,0);
37
38 #define ok_ole_success(hr, func) ok(hr == S_OK, func " failed with error 0x%08x\n", hr)
39
40 static CHAR filenameA[MAX_PATH];
41 static WCHAR filename[MAX_PATH];
42
43 static const char file1_nameA[] = {'c','o','p','y','t','e','s','t','A',0};
44 static const WCHAR file1_name[] = {'c','o','p','y','t','e','s','t','A',0};
45 static const char file2_nameA[] = {'c','o','p','y','t','e','s','t','B',0};
46 static const WCHAR file2_name[] = {'c','o','p','y','t','e','s','t','B',0};
47 static const WCHAR stgA_name[] = {'S','t','o','r','a','g','e','A',0};
48 static const WCHAR stgB_name[] = {'S','t','o','r','a','g','e','B',0};
49 static const WCHAR strmA_name[] = {'S','t','r','e','a','m','A',0};
50 static const WCHAR strmB_name[] = {'S','t','r','e','a','m','B',0};
51 static const WCHAR strmC_name[] = {'S','t','r','e','a','m','C',0};
52
53 /* Win9x and WinMe don't have lstrcmpW */
54 static int strcmp_ww(LPCWSTR strw1, LPCWSTR strw2)
55 {
56 CHAR stra1[512], stra2[512];
57 WideCharToMultiByte(CP_ACP, 0, strw1, -1, stra1, sizeof(stra1), NULL, NULL);
58 WideCharToMultiByte(CP_ACP, 0, strw2, -1, stra2, sizeof(stra2), NULL, NULL);
59 return lstrcmpA(stra1, stra2);
60 }
61
62 static void test_hglobal_storage_stat(void)
63 {
64 ILockBytes *ilb = NULL;
65 IStorage *stg = NULL;
66 HRESULT r;
67 STATSTG stat;
68 DWORD mode, refcount;
69
70 r = CreateILockBytesOnHGlobal( NULL, TRUE, &ilb );
71 ok( r == S_OK, "CreateILockBytesOnHGlobal failed\n");
72
73 r = StgIsStorageILockBytes( ilb );
74 ok( r == S_FALSE, "StgIsStorageILockBytes should have failed\n");
75
76 mode = STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE;/*0x1012*/
77 r = StgCreateDocfileOnILockBytes( ilb, mode, 0, &stg );
78 ok( r == S_OK, "StgCreateDocfileOnILockBytes failed\n");
79
80 r = WriteClassStg( stg, &test_stg_cls );
81 ok( r == S_OK, "WriteClassStg failed\n");
82
83 r = StgIsStorageILockBytes( ilb );
84 ok( r == S_OK, "StgIsStorageILockBytes failed\n");
85
86 memset( &stat, 0, sizeof stat );
87 r = IStorage_Stat( stg, &stat, 0 );
88
89 ok( stat.pwcsName == NULL, "storage name not null\n");
90 ok( stat.type == 1, "type is wrong\n");
91 ok( stat.grfMode == 0x12, "grf mode is incorrect\n");
92 ok( !memcmp(&stat.clsid, &test_stg_cls, sizeof test_stg_cls), "CLSID is wrong\n");
93
94 refcount = IStorage_Release( stg );
95 ok( refcount == 0, "IStorage refcount is wrong\n");
96 refcount = ILockBytes_Release( ilb );
97 ok( refcount == 0, "ILockBytes refcount is wrong\n");
98 }
99
100 static void test_create_storage_modes(void)
101 {
102 IStorage *stg = NULL;
103 HRESULT r;
104
105 DeleteFileA(filenameA);
106
107 /* test with some invalid parameters */
108 r = StgCreateDocfile( NULL, 0, 0, &stg);
109 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
110 r = StgCreateDocfile( filename, 0, 0, &stg);
111 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
112 r = StgCreateDocfile( filename, STGM_CREATE, 0, &stg);
113 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
114 r = StgCreateDocfile( filename, STGM_CREATE | STGM_READWRITE, 0, &stg);
115 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
116 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE, 0, &stg);
117 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
118 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, NULL);
119 ok(r==STG_E_INVALIDPOINTER, "StgCreateDocfile succeeded\n");
120 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 1, &stg);
121 ok(r==STG_E_INVALIDPARAMETER, "StgCreateDocfile succeeded\n");
122 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_DENY_WRITE | STGM_READWRITE, 0, &stg);
123 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
124 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READ, 0, &stg);
125 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
126 r = StgCreateDocfile( filename, STGM_PRIORITY, 0, &stg);
127 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
128
129 /* StgCreateDocfile seems to be very particular about the flags it accepts */
130 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED | STGM_WRITE, 0, &stg);
131 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
132 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED | 8, 0, &stg);
133 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
134 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED | 0x80, 0, &stg);
135 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
136 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED | 0x800, 0, &stg);
137 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
138 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED | 0x8000, 0, &stg);
139 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
140 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED | 0x80000, 0, &stg);
141 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
142 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED | 0x800000, 0, &stg);
143 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
144 ok(stg == NULL, "stg was set\n");
145
146 /* check what happens if the file already exists (which is how it's meant to be used) */
147 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &stg);
148 ok(r==S_OK, "StgCreateDocfile failed\n");
149 r = IStorage_Release(stg);
150 ok(r == 0, "storage not released\n");
151 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
152 ok(r==STG_E_FILEALREADYEXISTS, "StgCreateDocfile wrong error\n"); /* FAILIFTHERE is default */
153 r = StgCreateDocfile( filename, STGM_READ, 0, &stg);
154 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n"); /* need at least readmode and sharemode */
155 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE, 0, &stg);
156 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
157 r = StgCreateDocfile( filename, STGM_SHARE_DENY_WRITE, 0, &stg);
158 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
159 r = StgCreateDocfile( filename, STGM_SHARE_DENY_NONE, 0, &stg);
160 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile failed\n");
161 r = StgCreateDocfile( filename, STGM_SHARE_DENY_NONE | STGM_TRANSACTED, 0, &stg);
162 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile failed\n");
163 r = StgCreateDocfile( filename, STGM_SHARE_DENY_NONE | STGM_READWRITE, 0, &stg);
164 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile failed\n");
165 r = StgCreateDocfile( filename, STGM_SHARE_DENY_NONE | STGM_WRITE, 0, &stg);
166 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile failed\n");
167 r = StgCreateDocfile( filename, STGM_SHARE_DENY_WRITE | STGM_WRITE, 0, &stg);
168 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile failed\n");
169 r = StgCreateDocfile( filename, STGM_SHARE_DENY_WRITE | STGM_READ, 0, &stg);
170 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile wrong error\n");
171 r = StgCreateDocfile( filename, STGM_TRANSACTED | STGM_SHARE_DENY_WRITE | STGM_READ, 0, &stg);
172 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile wrong error\n");
173 ok(DeleteFileA(filenameA), "failed to delete file\n");
174
175 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
176 ok(r==S_OK, "StgCreateDocfile failed\n");
177 r = IStorage_Release(stg);
178 ok(r == 0, "storage not released\n");
179 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED |STGM_FAILIFTHERE, 0, &stg);
180 ok(r==STG_E_FILEALREADYEXISTS, "StgCreateDocfile wrong error\n");
181 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_WRITE, 0, &stg);
182 ok(r==STG_E_FILEALREADYEXISTS, "StgCreateDocfile wrong error\n");
183
184 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_DENY_WRITE | STGM_READWRITE, 0, &stg);
185 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
186 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
187 ok(r==S_OK, "StgCreateDocfile failed\n");
188 r = IStorage_Release(stg);
189 ok(r == 0, "storage not released\n");
190 ok(DeleteFileA(filenameA), "failed to delete file\n");
191
192 r = StgCreateDocfile( filename, STGM_CREATE | STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
193 ok(r==S_OK, "StgCreateDocfile failed\n");
194 r = IStorage_Release(stg);
195 ok(r == 0, "storage not released\n");
196 ok(DeleteFileA(filenameA), "failed to delete file\n");
197
198 /* test the way excel uses StgCreateDocFile */
199 r = StgCreateDocfile( filename, STGM_TRANSACTED|STGM_CREATE|STGM_SHARE_DENY_WRITE|STGM_READWRITE, 0, &stg);
200 ok(r==S_OK, "StgCreateDocfile the excel way failed\n");
201 if(r == S_OK)
202 {
203 r = IStorage_Release(stg);
204 ok(r == 0, "storage not released\n");
205 ok(DeleteFileA(filenameA), "failed to delete file\n");
206 }
207
208 /* and the way windows media uses it ... */
209 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_DENY_NONE | STGM_READWRITE | STGM_TRANSACTED, 0, &stg);
210 ok(r==S_OK, "StgCreateDocfile the windows media way failed\n");
211 if (r == S_OK)
212 {
213 r = IStorage_Release(stg);
214 ok(r == 0, "storage not released\n");
215 ok(DeleteFileA(filenameA), "failed to delete file\n");
216 }
217
218 /* looks like we need STGM_TRANSACTED or STGM_CREATE */
219 r = StgCreateDocfile( filename, STGM_TRANSACTED|STGM_SHARE_DENY_WRITE|STGM_READWRITE, 0, &stg);
220 ok(r==S_OK, "StgCreateDocfile the excel way failed\n");
221 if(r == S_OK)
222 {
223 r = IStorage_Release(stg);
224 ok(r == 0, "storage not released\n");
225 ok(DeleteFileA(filenameA), "failed to delete file\n");
226 }
227
228 r = StgCreateDocfile( filename, STGM_TRANSACTED|STGM_CREATE|STGM_SHARE_DENY_WRITE|STGM_WRITE, 0, &stg);
229 ok(r==S_OK, "StgCreateDocfile the excel way failed\n");
230 if(r == S_OK)
231 {
232 r = IStorage_Release(stg);
233 ok(r == 0, "storage not released\n");
234 ok(DeleteFileA(filenameA), "failed to delete file\n");
235 }
236
237 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &stg);
238 ok(r==S_OK, "StgCreateDocfile the powerpoint way failed\n");
239 if(r == S_OK)
240 {
241 r = IStorage_Release(stg);
242 ok(r == 0, "storage not released\n");
243 ok(DeleteFileA(filenameA), "failed to delete file\n");
244 }
245
246 /* test the way msi uses StgCreateDocfile */
247 r = StgCreateDocfile( filename, STGM_DIRECT | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &stg);
248 ok(r==S_OK, "StgCreateDocFile failed\n");
249 r = IStorage_Release(stg);
250 ok(r == 0, "storage not released\n");
251 ok(DeleteFileA(filenameA), "failed to delete file\n");
252 }
253
254 static void test_stgcreatestorageex(void)
255 {
256 HRESULT (WINAPI *pStgCreateStorageEx)(const WCHAR* pwcsName, DWORD grfMode, DWORD stgfmt, DWORD grfAttrs, STGOPTIONS* pStgOptions, void* reserved, REFIID riid, void** ppObjectOpen);
257 HMODULE hOle32 = GetModuleHandle("ole32");
258 IStorage *stg = NULL;
259 STGOPTIONS stgoptions = {1, 0, 4096};
260 HRESULT r;
261
262 pStgCreateStorageEx = (void *) GetProcAddress(hOle32, "StgCreateStorageEx");
263 if (!pStgCreateStorageEx)
264 {
265 win_skip("skipping test on NT4\n");
266 return;
267 }
268
269 DeleteFileA(filenameA);
270
271 /* Verify that StgCreateStorageEx can accept an options param */
272 r = pStgCreateStorageEx( filename,
273 STGM_SHARE_EXCLUSIVE | STGM_READWRITE,
274 STGFMT_DOCFILE,
275 0,
276 &stgoptions,
277 NULL,
278 &IID_IStorage,
279 (void **) &stg);
280 ok(r==S_OK || r==STG_E_UNIMPLEMENTEDFUNCTION, "StgCreateStorageEx with options failed\n");
281 if (r==STG_E_UNIMPLEMENTEDFUNCTION)
282 {
283 /* We're on win98 which means all bets are off. Let's get out of here. */
284 win_skip("skipping test on win9x\n");
285 return;
286 }
287
288 r = IStorage_Release(stg);
289 ok(r == 0, "storage not released\n");
290 ok(DeleteFileA(filenameA), "failed to delete file\n");
291
292 /* Verify that StgCreateStorageEx can accept a NULL pStgOptions */
293 r = pStgCreateStorageEx( filename,
294 STGM_SHARE_EXCLUSIVE | STGM_READWRITE,
295 STGFMT_STORAGE,
296 0,
297 NULL,
298 NULL,
299 &IID_IStorage,
300 (void **) &stg);
301 ok(r==S_OK, "StgCreateStorageEx with NULL options failed\n");
302 r = IStorage_Release(stg);
303 ok(r == 0, "storage not released\n");
304 ok(DeleteFileA(filenameA), "failed to delete file\n");
305 }
306
307 static void test_storage_stream(void)
308 {
309 static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 };
310 static const WCHAR longname[] = {
311 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
312 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',0
313 };
314 IStorage *stg = NULL;
315 HRESULT r;
316 IStream *stm = NULL;
317 IStream *stm2 = NULL;
318 ULONG count = 0;
319 LARGE_INTEGER pos;
320 ULARGE_INTEGER p;
321 unsigned char buffer[0x100];
322 IUnknown *unk;
323
324 DeleteFileA(filenameA);
325
326 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
327 ok(r==S_OK, "StgCreateDocfile failed\n");
328
329 /* try create some invalid streams */
330 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 1, 0, &stm );
331 ok(r==STG_E_INVALIDPARAMETER, "IStorage->CreateStream wrong error\n");
332 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 1, &stm );
333 ok(r==STG_E_INVALIDPARAMETER, "IStorage->CreateStream wrong error\n");
334 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, NULL );
335 ok(r==STG_E_INVALIDPOINTER, "IStorage->CreateStream wrong error\n");
336 r = IStorage_CreateStream(stg, NULL, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
337 ok(r==STG_E_INVALIDNAME, "IStorage->CreateStream wrong error\n");
338 r = IStorage_CreateStream(stg, longname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
339 ok(r==STG_E_INVALIDNAME || broken(r==S_OK) /* nt4 */,
340 "IStorage->CreateStream wrong error, got %d GetLastError()=%d\n", r, GetLastError());
341 r = IStorage_CreateStream(stg, stmname, STGM_READWRITE, 0, 0, &stm );
342 ok(r==STG_E_INVALIDFLAG, "IStorage->CreateStream wrong error\n");
343 r = IStorage_CreateStream(stg, stmname, STGM_READ, 0, 0, &stm );
344 ok(r==STG_E_INVALIDFLAG, "IStorage->CreateStream wrong error\n");
345 r = IStorage_CreateStream(stg, stmname, STGM_WRITE, 0, 0, &stm );
346 ok(r==STG_E_INVALIDFLAG, "IStorage->CreateStream wrong error\n");
347 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_DENY_NONE | STGM_READWRITE, 0, 0, &stm );
348 ok(r==STG_E_INVALIDFLAG, "IStorage->CreateStream wrong error\n");
349 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_DENY_NONE | STGM_READ, 0, 0, &stm );
350 ok(r==STG_E_INVALIDFLAG, "IStorage->CreateStream wrong error\n");
351
352 /* now really create a stream and delete it */
353 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
354 ok(r==S_OK, "IStorage->CreateStream failed\n");
355
356 /* test for support interfaces */
357 r = IStream_QueryInterface(stm, &IID_IPersist, (void**)&unk);
358 ok(r==E_NOINTERFACE, "got 0x%08x\n", r);
359 r = IStream_QueryInterface(stm, &IID_IPersistStream, (void**)&unk);
360 ok(r==E_NOINTERFACE, "got 0x%08x\n", r);
361
362 r = IStream_Release(stm);
363 ok(r == 0, "wrong ref count\n");
364 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
365 ok(r==STG_E_FILEALREADYEXISTS, "IStorage->CreateStream failed\n");
366 r = IStorage_DestroyElement(stg,stmname);
367 ok(r==S_OK, "IStorage->DestroyElement failed\n");
368
369 /* create a stream and write to it */
370 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
371 ok(r==S_OK, "IStorage->CreateStream failed\n");
372
373 r = IStream_Clone(stm, &stm2);
374 ok(r==S_OK, "failed to clone stream\n");
375
376 r = IStream_Write(stm, NULL, 0, NULL );
377 ok(r==STG_E_INVALIDPOINTER, "IStream->Write wrong error\n");
378 r = IStream_Write(stm, "Hello\n", 0, NULL );
379 ok(r==S_OK, "failed to write stream\n");
380 r = IStream_Write(stm, "Hello\n", 0, &count );
381 ok(r==S_OK, "failed to write stream\n");
382 r = IStream_Write(stm, "Hello\n", 6, &count );
383 ok(r==S_OK, "failed to write stream\n");
384 r = IStream_Commit(stm, STGC_DEFAULT );
385 ok(r==S_OK, "failed to commit stream\n");
386 r = IStream_Commit(stm, STGC_DEFAULT );
387 ok(r==S_OK, "failed to commit stream\n");
388
389 /* Read past the end of the stream. */
390 pos.QuadPart = 3;
391 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p );
392 ok(r==S_OK, "failed to seek stream\n");
393 ok(p.QuadPart == 3, "at wrong place\n");
394 r = IStream_Read(stm, buffer, sizeof buffer, &count );
395 ok(r==S_OK, "failed to read\n");
396 ok(count == 3, "read bytes past end of stream\n");
397 pos.QuadPart = 10;
398 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p );
399 ok(r==S_OK, "failed to seek stream\n");
400 ok(p.QuadPart == 10, "at wrong place\n");
401 r = IStream_Read(stm, buffer, sizeof buffer, &count );
402 ok(r==S_OK, "failed to read\n");
403 ok(count == 0, "read bytes past end of stream\n");
404 pos.QuadPart = 10000;
405 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p );
406 ok(r==S_OK, "failed to seek stream\n");
407 ok(p.QuadPart == 10000, "at wrong place\n");
408 r = IStream_Read(stm, buffer, sizeof buffer, &count );
409 ok(r==S_OK, "failed to read\n");
410 ok(count == 0, "read bytes past end of stream\n");
411
412 /* Convert to a big block stream, and read past the end. */
413 p.QuadPart = 5000;
414 r = IStream_SetSize(stm,p);
415 ok(r==S_OK, "failed to set pos\n");
416 pos.QuadPart = 4997;
417 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p );
418 ok(r==S_OK, "failed to seek stream\n");
419 ok(p.QuadPart == 4997, "at wrong place\n");
420 r = IStream_Read(stm, buffer, sizeof buffer, &count );
421 ok(r==S_OK, "failed to read\n");
422 ok(count == 3, "read bytes past end of stream\n");
423 pos.QuadPart = 5001;
424 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p );
425 ok(r==S_OK, "failed to seek stream\n");
426 ok(p.QuadPart == 5001, "at wrong place\n");
427 r = IStream_Read(stm, buffer, sizeof buffer, &count );
428 ok(r==S_OK, "failed to read\n");
429 ok(count == 0, "read bytes past end of stream\n");
430 pos.QuadPart = 10000;
431 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p );
432 ok(r==S_OK, "failed to seek stream\n");
433 ok(p.QuadPart == 10000, "at wrong place\n");
434 r = IStream_Read(stm, buffer, sizeof buffer, &count );
435 ok(r==S_OK, "failed to read\n");
436 ok(count == 0, "read bytes past end of stream\n");
437
438 /* seek round a bit, reset the stream size */
439 pos.QuadPart = 0;
440 r = IStream_Seek(stm, pos, 3, &p );
441 ok(r==STG_E_INVALIDFUNCTION, "IStream->Seek returned wrong error\n");
442 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, NULL);
443 ok(r==S_OK, "failed to seek stream\n");
444 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p );
445 ok(r==S_OK, "failed to seek stream\n");
446 r = IStream_SetSize(stm,p);
447 ok(r==S_OK, "failed to set pos\n");
448 pos.QuadPart = 10;
449 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p );
450 ok(r==S_OK, "failed to seek stream\n");
451 ok(p.QuadPart == 10, "at wrong place\n");
452 r = IStream_Read(stm, buffer, sizeof buffer, &count );
453 ok(r==S_OK, "failed to set pos\n");
454 ok(count == 0, "read bytes from empty stream\n");
455 pos.QuadPart = 10000;
456 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p );
457 ok(r==S_OK, "failed to seek stream\n");
458 ok(p.QuadPart == 10000, "at wrong place\n");
459 r = IStream_Read(stm, buffer, sizeof buffer, &count );
460 ok(r==S_OK, "failed to set pos\n");
461 ok(count == 0, "read bytes from empty stream\n");
462 pos.QuadPart = 0;
463 r = IStream_Seek(stm, pos, STREAM_SEEK_END, &p );
464 ok(r==S_OK, "failed to seek stream\n");
465 ok(p.QuadPart == 0, "at wrong place\n");
466 r = IStream_Read(stm, buffer, sizeof buffer, &count );
467 ok(r==S_OK, "failed to set pos\n");
468 ok(count == 0, "read bytes from empty stream\n");
469
470 /* wrap up */
471 r = IStream_Release(stm2);
472 ok(r == 0, "wrong ref count\n");
473
474 /* create a stream and write to it */
475 r = IStorage_CreateStream(stg, stmname, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm2 );
476 ok(r==S_OK, "IStorage->CreateStream failed\n");
477
478 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p);
479 ok(r==STG_E_REVERTED, "overwritten stream should return STG_E_REVERTED instead of 0x%08x\n", r);
480
481 r = IStream_Release(stm2);
482 ok(r == 0, "wrong ref count\n");
483 r = IStream_Release(stm);
484 ok(r == 0, "wrong ref count\n");
485
486 r = IStorage_Release(stg);
487 ok(r == 0, "wrong ref count\n");
488
489 /* try create some invalid streams */
490 stg = NULL;
491 stm = NULL;
492 r = StgOpenStorage(filename, NULL, STGM_READ | STGM_SHARE_DENY_WRITE, NULL, 0, &stg);
493 ok(r == S_OK, "should succeed\n");
494 if (stg)
495 {
496 r = IStorage_OpenStream(stg, stmname, NULL, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &stm);
497 ok(r == STG_E_INVALIDFLAG, "IStorage->OpenStream should return STG_E_INVALIDFLAG instead of 0x%08x\n", r);
498 IStorage_Release(stg);
499 }
500
501 r = DeleteFileA(filenameA);
502 ok(r, "file should exist\n");
503 }
504
505 static BOOL touch_file(LPCSTR filename)
506 {
507 HANDLE file;
508
509 file = CreateFileA(filename, GENERIC_READ|GENERIC_WRITE, 0, NULL,
510 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
511 if (file==INVALID_HANDLE_VALUE)
512 return FALSE;
513 CloseHandle(file);
514 return TRUE;
515 }
516
517 static BOOL is_zero_length(LPCSTR filename)
518 {
519 HANDLE file;
520 DWORD len;
521
522 file = CreateFileA(filename, GENERIC_READ, 0, NULL,
523 OPEN_EXISTING, 0, NULL);
524 if (file==INVALID_HANDLE_VALUE)
525 return FALSE;
526 len = GetFileSize(file, NULL);
527 CloseHandle(file);
528 return len == 0;
529 }
530
531 static BOOL is_existing_file(LPCSTR filename)
532 {
533 HANDLE file;
534
535 file = CreateFileA(filename, GENERIC_READ, 0, NULL,
536 OPEN_EXISTING, 0, NULL);
537 if (file==INVALID_HANDLE_VALUE)
538 return FALSE;
539 CloseHandle(file);
540 return TRUE;
541 }
542
543 static void test_open_storage(void)
544 {
545 static const WCHAR szNonExist[] = { 'n','o','n','e','x','i','s','t',0 };
546 IStorage *stg = NULL, *stg2 = NULL;
547 HRESULT r;
548 DWORD stgm;
549
550 /* try opening a zero length file - it should stay zero length */
551 DeleteFileA(filenameA);
552 touch_file(filenameA);
553 stgm = STGM_NOSCRATCH | STGM_TRANSACTED | STGM_SHARE_DENY_WRITE | STGM_READWRITE;
554 r = StgOpenStorage( filename, NULL, stgm, NULL, 0, &stg);
555 ok(r==STG_E_FILEALREADYEXISTS, "StgOpenStorage didn't fail\n");
556
557 stgm = STGM_SHARE_EXCLUSIVE | STGM_READWRITE;
558 r = StgOpenStorage( filename, NULL, stgm, NULL, 0, &stg);
559 ok(r==STG_E_FILEALREADYEXISTS, "StgOpenStorage didn't fail\n");
560 ok(is_zero_length(filenameA), "file length changed\n");
561
562 DeleteFileA(filenameA);
563
564 /* try opening a nonexistent file - it should not create it */
565 stgm = STGM_DIRECT | STGM_SHARE_EXCLUSIVE | STGM_READWRITE;
566 r = StgOpenStorage( filename, NULL, stgm, NULL, 0, &stg);
567 ok(r!=S_OK, "StgOpenStorage failed: 0x%08x\n", r);
568 if (r==S_OK) IStorage_Release(stg);
569 ok(!is_existing_file(filenameA), "StgOpenStorage should not create a file\n");
570 DeleteFileA(filenameA);
571
572 /* create the file */
573 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
574 ok(r==S_OK, "StgCreateDocfile failed\n");
575 IStorage_Release(stg);
576
577 r = StgOpenStorage( filename, NULL, 0, NULL, 0, &stg);
578 ok(r==STG_E_INVALIDFLAG, "StgOpenStorage wrong error\n");
579 r = StgOpenStorage( NULL, NULL, STGM_SHARE_EXCLUSIVE, NULL, 0, &stg);
580 ok(r==STG_E_INVALIDNAME, "StgOpenStorage wrong error\n");
581 r = StgOpenStorage( filename, NULL, STGM_SHARE_EXCLUSIVE | STGM_READ, NULL, 0, NULL);
582 ok(r==STG_E_INVALIDPOINTER, "StgOpenStorage wrong error\n");
583 r = StgOpenStorage( filename, NULL, STGM_SHARE_EXCLUSIVE | STGM_READ, NULL, 1, &stg);
584 ok(r==STG_E_INVALIDPARAMETER, "StgOpenStorage wrong error\n");
585 r = StgOpenStorage( szNonExist, NULL, STGM_SHARE_EXCLUSIVE | STGM_READ, NULL, 0, &stg);
586 ok(r==STG_E_FILENOTFOUND, "StgOpenStorage failed\n");
587 r = StgOpenStorage( filename, NULL, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READ, NULL, 0, &stg);
588 ok(r==STG_E_INVALIDFLAG, "StgOpenStorage failed\n");
589 r = StgOpenStorage( filename, NULL, STGM_SHARE_DENY_NONE | STGM_READ, NULL, 0, &stg);
590 ok(r==STG_E_INVALIDFLAG, "StgOpenStorage failed\n");
591 r = StgOpenStorage( filename, NULL, STGM_SHARE_DENY_READ | STGM_READ, NULL, 0, &stg);
592 ok(r==STG_E_INVALIDFLAG, "StgOpenStorage failed\n");
593 r = StgOpenStorage( filename, NULL, STGM_SHARE_DENY_WRITE | STGM_READWRITE, NULL, 0, &stg);
594 ok(r==STG_E_INVALIDFLAG, "StgOpenStorage failed\n");
595
596 /* open it for real */
597 r = StgOpenStorage( filename, NULL, STGM_SHARE_DENY_NONE | STGM_READ | STGM_TRANSACTED, NULL, 0, &stg); /* XLViewer 97/2000 */
598 ok(r==S_OK, "StgOpenStorage failed\n");
599 if(stg)
600 {
601 r = IStorage_Release(stg);
602 ok(r == 0, "wrong ref count\n");
603 }
604
605 r = StgOpenStorage( filename, NULL, STGM_SHARE_DENY_WRITE | STGM_READ, NULL, 0, &stg);
606 ok(r==S_OK, "StgOpenStorage failed\n");
607 if(stg)
608 {
609 r = IStorage_Release(stg);
610 ok(r == 0, "wrong ref count\n");
611 }
612
613 /* test the way word opens its custom dictionary */
614 r = StgOpenStorage( filename, NULL, STGM_NOSCRATCH | STGM_TRANSACTED |
615 STGM_SHARE_DENY_WRITE | STGM_READWRITE, NULL, 0, &stg);
616 ok(r==S_OK, "StgOpenStorage failed\n");
617 if(stg)
618 {
619 r = IStorage_Release(stg);
620 ok(r == 0, "wrong ref count\n");
621 }
622
623 r = StgOpenStorage( filename, NULL, STGM_SHARE_EXCLUSIVE | STGM_READ, NULL, 0, &stg);
624 ok(r==S_OK, "StgOpenStorage failed\n");
625 r = StgOpenStorage( filename, NULL, STGM_SHARE_EXCLUSIVE | STGM_READ, NULL, 0, &stg2);
626 ok(r==STG_E_SHAREVIOLATION, "StgOpenStorage failed\n");
627 if(stg)
628 {
629 r = IStorage_Release(stg);
630 ok(r == 0, "wrong ref count\n");
631 }
632
633 /* now try write to a storage file we opened read-only */
634 r = StgOpenStorage( filename, NULL, STGM_SHARE_EXCLUSIVE | STGM_READ, NULL, 0, &stg);
635 ok(r==S_OK, "StgOpenStorage failed\n");
636 if(stg)
637 {
638 static const WCHAR stmname[] = { 'w','i','n','e','t','e','s','t',0};
639 IStream *stm = NULL;
640 IStorage *stg2 = NULL;
641
642 r = IStorage_CreateStream( stg, stmname, STGM_WRITE | STGM_SHARE_EXCLUSIVE,
643 0, 0, &stm );
644 ok(r == STG_E_ACCESSDENIED, "CreateStream should fail\n");
645 r = IStorage_CreateStorage( stg, stmname, STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg2);
646 ok(r == STG_E_ACCESSDENIED, "CreateStream should fail\n");
647
648 r = IStorage_Release(stg);
649 ok(r == 0, "wrong ref count\n");
650 }
651
652 /* open like visio 2003 */
653 stg = NULL;
654 r = StgOpenStorage( filename, NULL, STGM_PRIORITY | STGM_SHARE_DENY_NONE, NULL, 0, &stg);
655 ok(r == S_OK, "should succeed\n");
656 if (stg)
657 IStorage_Release(stg);
658
659 /* test other sharing modes with STGM_PRIORITY */
660 stg = NULL;
661 r = StgOpenStorage( filename, NULL, STGM_PRIORITY | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg);
662 ok(r == S_OK, "should succeed\n");
663 if (stg)
664 IStorage_Release(stg);
665
666 stg = NULL;
667 r = StgOpenStorage( filename, NULL, STGM_PRIORITY | STGM_SHARE_DENY_WRITE, NULL, 0, &stg);
668 ok(r == S_OK, "should succeed\n");
669 if (stg)
670 IStorage_Release(stg);
671
672 stg = NULL;
673 r = StgOpenStorage( filename, NULL, STGM_PRIORITY | STGM_SHARE_DENY_READ, NULL, 0, &stg);
674 ok(r == S_OK, "should succeed\n");
675 if (stg)
676 IStorage_Release(stg);
677
678 /* open like Project 2003 */
679 stg = NULL;
680 r = StgOpenStorage( filename, NULL, STGM_PRIORITY, NULL, 0, &stg);
681 ok(r == S_OK, "should succeed\n");
682 r = StgOpenStorage( filename, NULL, STGM_PRIORITY, NULL, 0, &stg2);
683 ok(r == S_OK, "should succeed\n");
684 if (stg2)
685 IStorage_Release(stg2);
686 if (stg)
687 IStorage_Release(stg);
688
689 stg = NULL;
690 r = StgOpenStorage( filename, NULL, STGM_PRIORITY | STGM_READWRITE, NULL, 0, &stg);
691 ok(r == STG_E_INVALIDFLAG, "should fail\n");
692
693 r = StgOpenStorage( filename, NULL, STGM_TRANSACTED | STGM_PRIORITY, NULL, 0, &stg);
694 ok(r == STG_E_INVALIDFLAG, "should fail\n");
695
696 r = StgOpenStorage( filename, NULL, STGM_SIMPLE | STGM_PRIORITY, NULL, 0, &stg);
697 ok(r == STG_E_INVALIDFLAG, "should fail\n");
698
699 r = StgOpenStorage( filename, NULL, STGM_DELETEONRELEASE | STGM_PRIORITY, NULL, 0, &stg);
700 ok(r == STG_E_INVALIDFUNCTION, "should fail\n");
701
702 r = StgOpenStorage( filename, NULL, STGM_NOSCRATCH | STGM_PRIORITY, NULL, 0, &stg);
703 ok(r == STG_E_INVALIDFLAG, "should fail\n");
704
705 r = StgOpenStorage( filename, NULL, STGM_NOSNAPSHOT | STGM_PRIORITY, NULL, 0, &stg);
706 ok(r == STG_E_INVALIDFLAG, "should fail\n");
707
708 r = DeleteFileA(filenameA);
709 ok(r, "file didn't exist\n");
710 }
711
712 static void test_storage_suminfo(void)
713 {
714 IStorage *stg = NULL;
715 IPropertySetStorage *propset = NULL;
716 IPropertyStorage *ps = NULL;
717 HRESULT r;
718
719 DeleteFileA(filenameA);
720
721 /* create the file */
722 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
723 STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
724 ok(r==S_OK, "StgCreateDocfile failed\n");
725
726 r = IStorage_QueryInterface( stg, &IID_IPropertySetStorage, (LPVOID) &propset );
727 ok(r == S_OK, "query interface failed\n");
728
729 /* delete it */
730 r = IPropertySetStorage_Delete( propset, &FMTID_SummaryInformation );
731 ok(r == STG_E_FILENOTFOUND, "deleted property set storage\n");
732
733 r = IPropertySetStorage_Open( propset, &FMTID_SummaryInformation,
734 STGM_READ | STGM_SHARE_EXCLUSIVE, &ps );
735 ok(r == STG_E_FILENOTFOUND, "opened property set storage\n");
736
737 r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0,
738 STGM_READ | STGM_SHARE_EXCLUSIVE, &ps );
739 ok(r == STG_E_INVALIDFLAG, "created property set storage\n");
740
741 r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0,
742 STGM_READ, &ps );
743 ok(r == STG_E_INVALIDFLAG, "created property set storage\n");
744
745 r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0, 0, &ps );
746 ok(r == STG_E_INVALIDFLAG, "created property set storage\n");
747
748 r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0,
749 STGM_WRITE|STGM_SHARE_EXCLUSIVE, &ps );
750 ok(r == STG_E_INVALIDFLAG, "created property set storage\n");
751
752 r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0,
753 STGM_CREATE|STGM_WRITE|STGM_SHARE_EXCLUSIVE, &ps );
754 ok(r == STG_E_INVALIDFLAG, "created property set storage\n");
755
756 /* now try really creating a property set */
757 r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0,
758 STGM_CREATE|STGM_READWRITE|STGM_SHARE_EXCLUSIVE, &ps );
759 ok(r == S_OK, "failed to create property set storage\n");
760
761 if( ps )
762 IPropertyStorage_Release(ps);
763
764 /* now try creating the same thing again */
765 r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0,
766 STGM_CREATE|STGM_READWRITE|STGM_SHARE_EXCLUSIVE, &ps );
767 ok(r == S_OK, "failed to create property set storage\n");
768 if( ps )
769 IPropertyStorage_Release(ps);
770
771 /* should be able to open it */
772 r = IPropertySetStorage_Open( propset, &FMTID_SummaryInformation,
773 STGM_READWRITE|STGM_SHARE_EXCLUSIVE, &ps);
774 ok(r == S_OK, "open failed\n");
775 if(r == S_OK)
776 IPropertyStorage_Release(ps);
777
778 /* delete it */
779 r = IPropertySetStorage_Delete( propset, &FMTID_SummaryInformation );
780 ok(r == S_OK, "failed to delete property set storage\n");
781
782 /* try opening with an invalid FMTID */
783 r = IPropertySetStorage_Open( propset, NULL,
784 STGM_READWRITE|STGM_SHARE_EXCLUSIVE, &ps);
785 ok(r == E_INVALIDARG, "open succeeded\n");
786 if(r == S_OK)
787 IPropertyStorage_Release(ps);
788
789 /* try a bad guid */
790 r = IPropertySetStorage_Open( propset, &IID_IStorage,
791 STGM_READWRITE|STGM_SHARE_EXCLUSIVE, &ps);
792 ok(r == STG_E_FILENOTFOUND, "open succeeded\n");
793 if(r == S_OK)
794 IPropertyStorage_Release(ps);
795
796
797 /* try some invalid flags */
798 r = IPropertySetStorage_Open( propset, &FMTID_SummaryInformation,
799 STGM_CREATE | STGM_READWRITE|STGM_SHARE_EXCLUSIVE, &ps);
800 ok(r == STG_E_INVALIDFLAG, "open succeeded\n");
801 if(r == S_OK)
802 IPropertyStorage_Release(ps);
803
804 /* after deleting it, it should be gone */
805 r = IPropertySetStorage_Open( propset, &FMTID_SummaryInformation,
806 STGM_READWRITE|STGM_SHARE_EXCLUSIVE, &ps);
807 ok(r == STG_E_FILENOTFOUND, "open failed\n");
808 if(r == S_OK)
809 IPropertyStorage_Release(ps);
810
811 r = IPropertySetStorage_Release( propset );
812 ok(r == 1, "ref count wrong\n");
813
814 r = IStorage_Release(stg);
815 ok(r == 0, "ref count wrong\n");
816
817 DeleteFileA(filenameA);
818 }
819
820 static void test_storage_refcount(void)
821 {
822 IStorage *stg = NULL;
823 IStorage *stgprio = NULL;
824 HRESULT r;
825 IStream *stm = NULL;
826 static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 };
827 LARGE_INTEGER pos;
828 ULARGE_INTEGER upos;
829 STATSTG stat;
830 char buffer[10];
831
832 DeleteFileA(filenameA);
833
834 /* create the file */
835 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
836 STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
837 ok(r==S_OK, "StgCreateDocfile failed\n");
838
839 r = WriteClassStg( stg, &test_stg_cls );
840 ok( r == S_OK, "WriteClassStg failed\n");
841
842 r = IStorage_Commit( stg, STGC_DEFAULT );
843 ok( r == S_OK, "IStorage_Commit failed\n");
844
845 /* now create a stream */
846 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
847 ok(r==S_OK, "IStorage->CreateStream failed\n");
848
849 r = IStorage_Release( stg );
850 ok (r == 0, "storage not released\n");
851
852 pos.QuadPart = 0;
853 r = IStream_Seek( stm, pos, 0, &upos );
854 ok (r == STG_E_REVERTED, "seek should fail\n");
855
856 r = IStream_Stat( stm, &stat, STATFLAG_DEFAULT );
857 ok (r == STG_E_REVERTED, "stat should fail\n");
858
859 r = IStream_Write( stm, "Test string", strlen("Test string"), NULL);
860 ok (r == STG_E_REVERTED, "IStream_Write should return STG_E_REVERTED instead of 0x%08x\n", r);
861
862 r = IStream_Read( stm, buffer, sizeof(buffer), NULL);
863 ok (r == STG_E_REVERTED, "IStream_Read should return STG_E_REVERTED instead of 0x%08x\n", r);
864
865 r = IStream_Release(stm);
866 ok (r == 0, "stream not released\n");
867
868 /* tests that STGM_PRIORITY doesn't prevent readwrite access from other
869 * StgOpenStorage calls in transacted mode */
870 r = StgOpenStorage( filename, NULL, STGM_PRIORITY, NULL, 0, &stgprio);
871 ok(r==S_OK, "StgOpenStorage failed with error 0x%08x\n", r);
872
873 todo_wine {
874 /* non-transacted mode read/write fails */
875 r = StgOpenStorage( filename, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg);
876 ok(r==STG_E_LOCKVIOLATION, "StgOpenStorage should return STG_E_LOCKVIOLATION instead of 0x%08x\n", r);
877 }
878
879 /* non-transacted mode read-only succeeds */
880 r = StgOpenStorage( filename, NULL, STGM_SHARE_DENY_WRITE|STGM_READ, NULL, 0, &stg);
881 ok(r==S_OK, "StgOpenStorage failed with error 0x%08x\n", r);
882 IStorage_Release(stg);
883
884 r = StgOpenStorage( filename, NULL, STGM_TRANSACTED|STGM_SHARE_DENY_WRITE|STGM_READWRITE, NULL, 0, &stg);
885 ok(r==S_OK, "StgOpenStorage failed with error 0x%08x\n", r);
886 if(stg)
887 {
888 static const WCHAR stgname[] = { ' ',' ',' ','2','9',0 };
889 static const WCHAR stgname2[] = { 'C','V','_','i','e','w',0 };
890 static const WCHAR stmname2[] = { 'V','a','r','2','D','a','t','a',0 };
891 IStorage *stg2;
892 IStorage *stg3;
893 STATSTG statstg;
894
895 r = IStorage_Stat( stg, &statstg, STATFLAG_NONAME );
896 ok(r == S_OK, "Stat should have succeeded instead of returning 0x%08x\n", r);
897 ok(statstg.type == STGTY_STORAGE, "Statstg type should have been STGTY_STORAGE instead of %d\n", statstg.type);
898 ok(U(statstg.cbSize).LowPart == 0, "Statstg cbSize.LowPart should have been 0 instead of %d\n", U(statstg.cbSize).LowPart);
899 ok(U(statstg.cbSize).HighPart == 0, "Statstg cbSize.HighPart should have been 0 instead of %d\n", U(statstg.cbSize).HighPart);
900 ok(statstg.grfMode == (STGM_TRANSACTED|STGM_SHARE_DENY_WRITE|STGM_READWRITE),
901 "Statstg grfMode should have been 0x10022 instead of 0x%x\n", statstg.grfMode);
902 ok(statstg.grfLocksSupported == 0, "Statstg grfLocksSupported should have been 0 instead of %d\n", statstg.grfLocksSupported);
903 ok(IsEqualCLSID(&statstg.clsid, &test_stg_cls), "Statstg clsid is not test_stg_cls\n");
904 ok(statstg.grfStateBits == 0, "Statstg grfStateBits should have been 0 instead of %d\n", statstg.grfStateBits);
905 ok(statstg.reserved == 0, "Statstg reserved should have been 0 instead of %d\n", statstg.reserved);
906
907 r = IStorage_CreateStorage( stg, stgname, STGM_SHARE_EXCLUSIVE, 0, 0, &stg2 );
908 ok(r == S_OK, "CreateStorage should have succeeded instead of returning 0x%08x\n", r);
909
910 r = IStorage_Stat( stg2, &statstg, STATFLAG_DEFAULT );
911 ok(r == S_OK, "Stat should have succeeded instead of returning 0x%08x\n", r);
912 ok(!memcmp(statstg.pwcsName, stgname, sizeof(stgname)),
913 "Statstg pwcsName should have been the name the storage was created with\n");
914 ok(statstg.type == STGTY_STORAGE, "Statstg type should have been STGTY_STORAGE instead of %d\n", statstg.type);
915 ok(U(statstg.cbSize).LowPart == 0, "Statstg cbSize.LowPart should have been 0 instead of %d\n", U(statstg.cbSize).LowPart);
916 ok(U(statstg.cbSize).HighPart == 0, "Statstg cbSize.HighPart should have been 0 instead of %d\n", U(statstg.cbSize).HighPart);
917 ok(statstg.grfMode == STGM_SHARE_EXCLUSIVE,
918 "Statstg grfMode should have been STGM_SHARE_EXCLUSIVE instead of 0x%x\n", statstg.grfMode);
919 ok(statstg.grfLocksSupported == 0, "Statstg grfLocksSupported should have been 0 instead of %d\n", statstg.grfLocksSupported);
920 ok(IsEqualCLSID(&statstg.clsid, &CLSID_NULL), "Statstg clsid is not CLSID_NULL\n");
921 ok(statstg.grfStateBits == 0, "Statstg grfStateBits should have been 0 instead of %d\n", statstg.grfStateBits);
922 ok(statstg.reserved == 0, "Statstg reserved should have been 0 instead of %d\n", statstg.reserved);
923 CoTaskMemFree(statstg.pwcsName);
924
925 r = IStorage_CreateStorage( stg2, stgname2, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, 0, &stg3 );
926 ok(r == STG_E_ACCESSDENIED, "CreateStorage should have returned STG_E_ACCESSDENIED instead of 0x%08x\n", r);
927
928 r = IStorage_CreateStream( stg2, stmname2, STGM_CREATE|STGM_SHARE_EXCLUSIVE, 0, 0, &stm );
929 ok(r == STG_E_ACCESSDENIED, "CreateStream should have returned STG_E_ACCESSDENIED instead of 0x%08x\n", r);
930
931 IStorage_Release(stg2);
932
933 r = IStorage_Release(stg);
934 ok(r == 0, "wrong ref count\n");
935 }
936 IStorage_Release(stgprio);
937
938 DeleteFileA(filenameA);
939 }
940
941 static void test_writeclassstg(void)
942 {
943 IStorage *stg = NULL;
944 HRESULT r;
945 CLSID temp_cls;
946
947 DeleteFileA(filenameA);
948
949 /* create the file */
950 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
951 STGM_READWRITE, 0, &stg);
952 ok(r==S_OK, "StgCreateDocfile failed\n");
953
954 r = ReadClassStg( NULL, NULL );
955 ok(r == E_INVALIDARG, "ReadClassStg should return E_INVALIDARG instead of 0x%08X\n", r);
956
957 r = ReadClassStg( stg, NULL );
958 ok(r == E_INVALIDARG, "ReadClassStg should return E_INVALIDARG instead of 0x%08X\n", r);
959
960 temp_cls.Data1 = 0xdeadbeef;
961 r = ReadClassStg( stg, &temp_cls );
962 ok(r == S_OK, "ReadClassStg failed with 0x%08X\n", r);
963
964 ok(IsEqualCLSID(&temp_cls, &CLSID_NULL), "ReadClassStg returned wrong clsid\n");
965
966 r = WriteClassStg( NULL, NULL );
967 ok(r == E_INVALIDARG, "WriteClassStg should return E_INVALIDARG instead of 0x%08X\n", r);
968
969 r = WriteClassStg( stg, NULL );
970 ok(r == STG_E_INVALIDPOINTER, "WriteClassStg should return STG_E_INVALIDPOINTER instead of 0x%08X\n", r);
971
972 r = WriteClassStg( stg, &test_stg_cls );
973 ok( r == S_OK, "WriteClassStg failed with 0x%08X\n", r);
974
975 r = ReadClassStg( stg, &temp_cls );
976 ok( r == S_OK, "ReadClassStg failed with 0x%08X\n", r);
977 ok(IsEqualCLSID(&temp_cls, &test_stg_cls), "ReadClassStg returned wrong clsid\n");
978
979 r = IStorage_Release( stg );
980 ok (r == 0, "storage not released\n");
981
982 DeleteFileA(filenameA);
983 }
984
985 static void test_streamenum(void)
986 {
987 IStorage *stg = NULL;
988 HRESULT r;
989 IStream *stm = NULL;
990 static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 };
991 static const WCHAR stmname2[] = { 'A','B','C','D','E','F','G','H','I',0 };
992 static const WCHAR stmname3[] = { 'A','B','C','D','E','F','G','H','I','J',0 };
993 STATSTG stat;
994 IEnumSTATSTG *ee = NULL;
995 ULONG count;
996
997 DeleteFileA(filenameA);
998
999 /* create the file */
1000 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
1001 STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
1002 ok(r==S_OK, "StgCreateDocfile failed\n");
1003
1004 r = WriteClassStg( stg, &test_stg_cls );
1005 ok( r == S_OK, "WriteClassStg failed\n");
1006
1007 r = IStorage_Commit( stg, STGC_DEFAULT );
1008 ok( r == S_OK, "IStorage_Commit failed\n");
1009
1010 /* now create a stream */
1011 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1012 ok(r==S_OK, "IStorage->CreateStream failed\n");
1013
1014 r = IStream_Release(stm);
1015
1016 /* first enum ... should be 1 stream */
1017 r = IStorage_EnumElements(stg, 0, NULL, 0, &ee);
1018 ok(r==S_OK, "IStorage->EnumElements failed\n");
1019
1020 count = 0xf00;
1021 r = IEnumSTATSTG_Next(ee, 1, &stat, &count);
1022 ok(r==S_OK, "IEnumSTATSTG->Next failed\n");
1023 ok(count == 1, "count wrong\n");
1024
1025 if (r == S_OK)
1026 CoTaskMemFree(stat.pwcsName);
1027
1028 r = IEnumSTATSTG_Release(ee);
1029 ok(r==S_OK, "EnumSTATSTG_Release failed with error 0x%08x\n", r);
1030
1031 /* second enum... destroy the stream before reading */
1032 r = IStorage_EnumElements(stg, 0, NULL, 0, &ee);
1033 ok(r==S_OK, "IStorage->EnumElements failed\n");
1034
1035 r = IStorage_DestroyElement(stg, stmname);
1036 ok(r==S_OK, "IStorage->DestroyElement failed\n");
1037
1038 count = 0xf00;
1039 r = IEnumSTATSTG_Next(ee, 1, &stat, &count);
1040 ok(r==S_FALSE, "IEnumSTATSTG->Next failed\n");
1041 ok(count == 0, "count wrong\n");
1042
1043 /* reset and try again */
1044 r = IEnumSTATSTG_Reset(ee);
1045 ok(r==S_OK, "IEnumSTATSTG->Reset failed\n");
1046
1047 count = 0xf00;
1048 r = IEnumSTATSTG_Next(ee, 1, &stat, &count);
1049 ok(r==S_FALSE, "IEnumSTATSTG->Next failed\n");
1050 ok(count == 0, "count wrong\n");
1051
1052 /* add a stream before reading */
1053 r = IEnumSTATSTG_Reset(ee);
1054 ok(r==S_OK, "IEnumSTATSTG->Reset failed\n");
1055
1056 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1057 ok(r==S_OK, "IStorage->CreateStream failed\n");
1058
1059 r = IStream_Release(stm);
1060 ok(r==S_OK, "Stream_Release failed with error 0x%08x\n", r);
1061
1062 count = 0xf00;
1063 r = IEnumSTATSTG_Next(ee, 1, &stat, &count);
1064 ok(r==S_OK, "IEnumSTATSTG->Next failed\n");
1065 ok(count == 1, "count wrong\n");
1066
1067 if (r == S_OK)
1068 {
1069 ok(lstrcmpiW(stat.pwcsName, stmname) == 0, "expected CONTENTS, got %s\n", wine_dbgstr_w(stat.pwcsName));
1070 CoTaskMemFree(stat.pwcsName);
1071 }
1072
1073 r = IStorage_CreateStream(stg, stmname2, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1074 ok(r==S_OK, "IStorage->CreateStream failed\n");
1075
1076 r = IStream_Release(stm);
1077 ok(r==S_OK, "Stream_Release failed with error 0x%08x\n", r);
1078
1079 count = 0xf00;
1080 r = IEnumSTATSTG_Next(ee, 1, &stat, &count);
1081 ok(r==S_OK, "IEnumSTATSTG->Next failed\n");
1082 ok(count == 1, "count wrong\n");
1083
1084 if (r == S_OK)
1085 {
1086 ok(lstrcmpiW(stat.pwcsName, stmname2) == 0, "expected ABCDEFGHI, got %s\n", wine_dbgstr_w(stat.pwcsName));
1087 CoTaskMemFree(stat.pwcsName);
1088 }
1089
1090 /* delete previous and next stream after reading */
1091 r = IStorage_CreateStream(stg, stmname3, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1092 ok(r==S_OK, "IStorage->CreateStream failed\n");
1093
1094 r = IStream_Release(stm);
1095 ok(r==S_OK, "Stream_Release failed with error 0x%08x\n", r);
1096
1097 r = IEnumSTATSTG_Reset(ee);
1098 ok(r==S_OK, "IEnumSTATSTG->Reset failed\n");
1099
1100 count = 0xf00;
1101 r = IEnumSTATSTG_Next(ee, 1, &stat, &count);
1102 ok(r==S_OK, "IEnumSTATSTG->Next failed\n");
1103 ok(count == 1, "count wrong\n");
1104
1105 if (r == S_OK)
1106 {
1107 ok(lstrcmpiW(stat.pwcsName, stmname) == 0, "expected CONTENTS, got %s\n", wine_dbgstr_w(stat.pwcsName));
1108 CoTaskMemFree(stat.pwcsName);
1109 }
1110
1111 r = IStorage_DestroyElement(stg, stmname);
1112 ok(r==S_OK, "IStorage->DestroyElement failed\n");
1113
1114 r = IStorage_DestroyElement(stg, stmname2);
1115 ok(r==S_OK, "IStorage->DestroyElement failed\n");
1116
1117 count = 0xf00;
1118 r = IEnumSTATSTG_Next(ee, 1, &stat, &count);
1119 ok(r==S_OK, "IEnumSTATSTG->Next failed\n");
1120 ok(count == 1, "count wrong\n");
1121
1122 if (r == S_OK)
1123 {
1124 ok(lstrcmpiW(stat.pwcsName, stmname3) == 0, "expected ABCDEFGHIJ, got %s\n", wine_dbgstr_w(stat.pwcsName));
1125 CoTaskMemFree(stat.pwcsName);
1126 }
1127
1128 r = IStorage_Release( stg );
1129 todo_wine ok (r == 0, "storage not released\n");
1130
1131 /* enumerator is still valid and working after the storage is released */
1132 r = IEnumSTATSTG_Reset(ee);
1133 ok(r==S_OK, "IEnumSTATSTG->Reset failed\n");
1134
1135 count = 0xf00;
1136 r = IEnumSTATSTG_Next(ee, 1, &stat, &count);
1137 ok(r==S_OK, "IEnumSTATSTG->Next failed\n");
1138 ok(count == 1, "count wrong\n");
1139
1140 if (r == S_OK)
1141 {
1142 ok(lstrcmpiW(stat.pwcsName, stmname3) == 0, "expected ABCDEFGHIJ, got %s\n", wine_dbgstr_w(stat.pwcsName));
1143 CoTaskMemFree(stat.pwcsName);
1144 }
1145
1146 /* the storage is left open until the enumerator is freed */
1147 r = StgOpenStorage( filename, NULL, STGM_SHARE_EXCLUSIVE |
1148 STGM_READWRITE |STGM_TRANSACTED, NULL, 0, &stg);
1149 ok(r==STG_E_SHAREVIOLATION ||
1150 r==STG_E_LOCKVIOLATION, /* XP-SP2/W2K3-SP1 and below */
1151 "StgCreateDocfile failed, res=%x\n", r);
1152
1153 r = IEnumSTATSTG_Release(ee);
1154 ok (r == 0, "enum not released\n");
1155
1156 DeleteFileA(filenameA);
1157 }
1158
1159 static void test_transact(void)
1160 {
1161 IStorage *stg = NULL, *stg2 = NULL, *stg3 = NULL;
1162 HRESULT r;
1163 IStream *stm = NULL;
1164 static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 };
1165 static const WCHAR stmname2[] = { 'F','O','O',0 };
1166 static const WCHAR stgname[] = { 'P','E','R','M','S','T','G',0 };
1167 static const WCHAR stgname2[] = { 'T','E','M','P','S','T','G',0 };
1168
1169 DeleteFileA(filenameA);
1170
1171 /* create the file */
1172 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
1173 STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
1174 ok(r==S_OK, "StgCreateDocfile failed\n");
1175
1176 /* commit a new stream and storage */
1177 r = IStorage_CreateStream(stg, stmname2, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1178 ok(r==S_OK, "IStorage->CreateStream failed\n");
1179
1180 r = IStream_Write(stm, "this is stream 1\n", 16, NULL);
1181 ok(r==S_OK, "IStream->Write failed\n");
1182
1183 IStream_Release(stm);
1184
1185 r = IStorage_CreateStorage(stg, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg2);
1186 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1187
1188 if (r == S_OK)
1189 {
1190 /* Create two substorages but only commit one */
1191 r = IStorage_CreateStorage(stg2, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg3);
1192 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1193
1194 if (r == S_OK)
1195 IStorage_Release(stg3);
1196
1197 r = IStorage_Commit(stg, 0);
1198 ok(r==S_OK, "IStorage->Commit failed\n");
1199
1200 r = IStorage_CreateStorage(stg2, stgname2, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg3);
1201 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1202
1203 if (r == S_OK)
1204 IStorage_Release(stg3);
1205
1206 IStorage_Release(stg2);
1207 }
1208
1209 /* now create a stream and storage, but don't commit them */
1210 stm = NULL;
1211 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1212 ok(r==S_OK, "IStorage->CreateStream failed\n");
1213
1214 r = IStream_Write(stm, "this is stream 2\n", 16, NULL);
1215 ok(r==S_OK, "IStream->Write failed\n");
1216
1217 /* IStream::Commit does nothing for OLE storage streams */
1218 r = IStream_Commit(stm, STGC_ONLYIFCURRENT | STGC_DANGEROUSLYCOMMITMERELYTODISKCACHE);
1219 ok(r==S_OK, "IStream->Commit failed\n");
1220
1221 r = IStorage_CreateStorage(stg, stgname2, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg2);
1222 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1223
1224 if (r == S_OK)
1225 IStorage_Release(stg2);
1226
1227 IStream_Release(stm);
1228
1229 IStorage_Release(stg);
1230
1231 stm = NULL;
1232 stg = NULL;
1233 r = StgOpenStorage( filename, NULL, STGM_SHARE_DENY_NONE | STGM_READ | STGM_TRANSACTED, NULL, 0, &stg);
1234 ok(r==S_OK, "StgOpenStorage failed\n");
1235
1236 if (!stg)
1237 return;
1238
1239 r = IStorage_OpenStream(stg, stmname, NULL, STGM_SHARE_DENY_NONE|STGM_READ, 0, &stm );
1240 ok(r==STG_E_INVALIDFLAG, "IStorage->OpenStream failed %08x\n", r);
1241
1242 r = IStorage_OpenStream(stg, stmname, NULL, STGM_DELETEONRELEASE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
1243 ok(r==STG_E_INVALIDFUNCTION, "IStorage->OpenStream failed %08x\n", r);
1244
1245 r = IStorage_OpenStream(stg, stmname, NULL, STGM_TRANSACTED|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
1246 ok(r==STG_E_INVALIDFUNCTION, "IStorage->OpenStream failed %08x\n", r);
1247
1248 r = IStorage_OpenStorage(stg, stmname, NULL, STGM_TRANSACTED|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg2 );
1249 ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStream failed %08x\n", r);
1250
1251 r = IStorage_OpenStream(stg, stmname, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
1252 ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStream should fail %08x\n", r);
1253 if (r == S_OK)
1254 IStream_Release(stm);
1255
1256 r = IStorage_OpenStorage(stg, stgname2, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg2 );
1257 ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStorage should fail %08x\n", r);
1258 if (r == S_OK)
1259 IStorage_Release(stg2);
1260
1261 r = IStorage_OpenStorage(stg, stmname2, NULL, STGM_TRANSACTED|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg2 );
1262 ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStream failed %08x\n", r);
1263
1264 r = IStorage_OpenStream(stg, stmname2, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
1265 ok(r==S_OK, "IStorage->OpenStream should succeed %08x\n", r);
1266 if (r == S_OK)
1267 IStream_Release(stm);
1268
1269 r = IStorage_OpenStorage(stg, stgname, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg2 );
1270 ok(r==S_OK, "IStorage->OpenStorage should succeed %08x\n", r);
1271 if (r == S_OK)
1272 {
1273 r = IStorage_OpenStorage(stg2, stgname, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg3 );
1274 ok(r==S_OK, "IStorage->OpenStorage should succeed %08x\n", r);
1275 if (r == S_OK)
1276 IStorage_Release(stg3);
1277
1278 r = IStorage_OpenStorage(stg2, stgname2, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg3 );
1279 ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStorage should fail %08x\n", r);
1280 if (r == S_OK)
1281 IStorage_Release(stg3);
1282
1283 IStorage_Release(stg2);
1284 }
1285
1286 IStorage_Release(stg);
1287
1288 r = DeleteFileA(filenameA);
1289 ok( r == TRUE, "deleted file\n");
1290 }
1291
1292 static void test_substorage_share(void)
1293 {
1294 IStorage *stg, *stg2, *stg3;
1295 IStream *stm, *stm2;
1296 HRESULT r;
1297 static const WCHAR stgname[] = { 'P','E','R','M','S','T','G',0 };
1298 static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 };
1299 static const WCHAR othername[] = { 'N','E','W','N','A','M','E',0 };
1300
1301 DeleteFileA(filenameA);
1302
1303 /* create the file */
1304 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
1305 STGM_READWRITE, 0, &stg);
1306 ok(r==S_OK, "StgCreateDocfile failed\n");
1307
1308 /* create a read/write storage and try to open it again */
1309 r = IStorage_CreateStorage(stg, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg2);
1310 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1311
1312 if (r == S_OK)
1313 {
1314 r = IStorage_OpenStorage(stg, stgname, NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg3);
1315 ok(r==STG_E_ACCESSDENIED, "IStorage->OpenStorage should fail %08x\n", r);
1316
1317 if (r == S_OK)
1318 IStorage_Release(stg3);
1319
1320 r = IStorage_OpenStorage(stg, stgname, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, 0, &stg3);
1321 ok(r==STG_E_ACCESSDENIED, "IStorage->OpenStorage should fail %08x\n", r);
1322
1323 if (r == S_OK)
1324 IStorage_Release(stg3);
1325
1326 /* cannot rename the storage while it's open */
1327 r = IStorage_RenameElement(stg, stgname, othername);
1328 ok(r==STG_E_ACCESSDENIED, "IStorage->RenameElement should fail %08x\n", r);
1329 if (SUCCEEDED(r)) IStorage_RenameElement(stg, othername, stgname);
1330
1331 /* destroying an object while it's open invalidates it */
1332 r = IStorage_DestroyElement(stg, stgname);
1333 ok(r==S_OK, "IStorage->DestroyElement failed, hr=%08x\n", r);
1334
1335 r = IStorage_CreateStream(stg2, stmname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm);
1336 ok(r==STG_E_REVERTED, "IStorage->CreateStream failed, hr=%08x\n", r);
1337
1338 if (r == S_OK)
1339 IStream_Release(stm);
1340
1341 IStorage_Release(stg2);
1342 }
1343
1344 /* create a read/write stream and try to open it again */
1345 r = IStorage_CreateStream(stg, stmname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm);
1346 ok(r==S_OK, "IStorage->CreateStream failed, hr=%08x\n", r);
1347
1348 if (r == S_OK)
1349 {
1350 r = IStorage_OpenStream(stg, stmname, NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &stm2);
1351 ok(r==STG_E_ACCESSDENIED, "IStorage->OpenStream should fail %08x\n", r);
1352
1353 if (r == S_OK)
1354 IStream_Release(stm2);
1355
1356 r = IStorage_OpenStream(stg, stmname, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm2);
1357 ok(r==STG_E_ACCESSDENIED, "IStorage->OpenStream should fail %08x\n", r);
1358
1359 if (r == S_OK)
1360 IStream_Release(stm2);
1361
1362 /* cannot rename the stream while it's open */
1363 r = IStorage_RenameElement(stg, stmname, othername);
1364 ok(r==STG_E_ACCESSDENIED, "IStorage->RenameElement should fail %08x\n", r);
1365 if (SUCCEEDED(r)) IStorage_RenameElement(stg, othername, stmname);
1366
1367 /* destroying an object while it's open invalidates it */
1368 r = IStorage_DestroyElement(stg, stmname);
1369 ok(r==S_OK, "IStorage->DestroyElement failed, hr=%08x\n", r);
1370
1371 r = IStream_Write(stm, "this shouldn't work\n", 20, NULL);
1372 ok(r==STG_E_REVERTED, "IStream_Write should fail %08x\n", r);
1373
1374 IStream_Release(stm);
1375 }
1376
1377 IStorage_Release(stg);
1378
1379 r = DeleteFileA(filenameA);
1380 ok( r == TRUE, "deleted file\n");
1381 }
1382
1383 static void test_revert(void)
1384 {
1385 IStorage *stg = NULL, *stg2 = NULL, *stg3 = NULL;
1386 HRESULT r;
1387 IStream *stm = NULL, *stm2 = NULL;
1388 static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 };
1389 static const WCHAR stmname2[] = { 'F','O','O',0 };
1390 static const WCHAR stgname[] = { 'P','E','R','M','S','T','G',0 };
1391 static const WCHAR stgname2[] = { 'T','E','M','P','S','T','G',0 };
1392 STATSTG statstg;
1393
1394 DeleteFileA(filenameA);
1395
1396 /* create the file */
1397 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
1398 STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
1399 ok(r==S_OK, "StgCreateDocfile failed\n");
1400
1401 /* commit a new stream and storage */
1402 r = IStorage_CreateStream(stg, stmname2, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1403 ok(r==S_OK, "IStorage->CreateStream failed\n");
1404
1405 r = IStream_Write(stm, "this is stream 1\n", 16, NULL);
1406 ok(r==S_OK, "IStream->Write failed\n");
1407
1408 r = IStorage_CreateStorage(stg, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg2);
1409 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1410
1411 if (r == S_OK)
1412 {
1413 /* Create two substorages but only commit one */
1414 r = IStorage_CreateStorage(stg2, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg3);
1415 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1416
1417 if (r == S_OK)
1418 IStorage_Release(stg3);
1419
1420 r = IStorage_Commit(stg, 0);
1421 ok(r==S_OK, "IStorage->Commit failed\n");
1422
1423 r = IStorage_CreateStorage(stg2, stgname2, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg3);
1424 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1425
1426 if (r == S_OK)
1427 IStorage_Release(stg3);
1428 }
1429
1430 /* now create a stream and storage, then revert */
1431 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm2 );
1432 ok(r==S_OK, "IStorage->CreateStream failed\n");
1433
1434 r = IStream_Write(stm2, "this is stream 2\n", 16, NULL);
1435 ok(r==S_OK, "IStream->Write failed\n");
1436
1437 r = IStorage_CreateStorage(stg, stgname2, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg3);
1438 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1439
1440 r = IStorage_Revert(stg);
1441 ok(r==S_OK, "Storage_Revert failed with error 0x%08x\n", r);
1442
1443 /* all open objects become invalid */
1444 r = IStream_Write(stm, "this shouldn't work\n", 20, NULL);
1445 ok(r==STG_E_REVERTED, "IStream_Write should fail %08x\n", r);
1446
1447 r = IStream_Write(stm2, "this shouldn't work\n", 20, NULL);
1448 ok(r==STG_E_REVERTED, "IStream_Write should fail %08x\n", r);
1449
1450 r = IStorage_Stat(stg2, &statstg, STATFLAG_NONAME);
1451 ok(r==STG_E_REVERTED, "IStorage_Stat should fail %08x\n", r);
1452
1453 r = IStorage_Stat(stg3, &statstg, STATFLAG_NONAME);
1454 ok(r==STG_E_REVERTED, "IStorage_Stat should fail %08x\n", r);
1455
1456 IStream_Release(stm);
1457 IStream_Release(stm2);
1458 IStorage_Release(stg2);
1459 IStorage_Release(stg3);
1460
1461 r = IStorage_OpenStream(stg, stmname, NULL, STGM_SHARE_DENY_NONE|STGM_READ, 0, &stm );
1462 ok(r==STG_E_INVALIDFLAG, "IStorage->OpenStream failed %08x\n", r);
1463
1464 r = IStorage_OpenStream(stg, stmname, NULL, STGM_DELETEONRELEASE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
1465 ok(r==STG_E_INVALIDFUNCTION, "IStorage->OpenStream failed %08x\n", r);
1466
1467 r = IStorage_OpenStream(stg, stmname, NULL, STGM_TRANSACTED|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
1468 ok(r==STG_E_INVALIDFUNCTION, "IStorage->OpenStream failed %08x\n", r);
1469
1470 r = IStorage_OpenStorage(stg, stmname, NULL, STGM_TRANSACTED|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg2 );
1471 ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStream failed %08x\n", r);
1472
1473 r = IStorage_OpenStream(stg, stmname, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
1474 ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStream should fail %08x\n", r);
1475 if (r == S_OK)
1476 IStream_Release(stm);
1477
1478 r = IStorage_OpenStorage(stg, stgname2, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg2 );
1479 ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStorage should fail %08x\n", r);
1480 if (r == S_OK)
1481 IStorage_Release(stg2);
1482
1483 r = IStorage_OpenStorage(stg, stmname2, NULL, STGM_TRANSACTED|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg2 );
1484 ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStream failed %08x\n", r);
1485
1486 r = IStorage_OpenStream(stg, stmname2, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
1487 ok(r==S_OK, "IStorage->OpenStream should succeed %08x\n", r);
1488 if (r == S_OK)
1489 IStream_Release(stm);
1490
1491 r = IStorage_OpenStorage(stg, stgname, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg2 );
1492 ok(r==S_OK, "IStorage->OpenStorage should succeed %08x\n", r);
1493 if (r == S_OK)
1494 {
1495 r = IStorage_OpenStorage(stg2, stgname, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg3 );
1496 ok(r==S_OK, "IStorage->OpenStorage should succeed %08x\n", r);
1497 if (r == S_OK)
1498 IStorage_Release(stg3);
1499
1500 r = IStorage_OpenStorage(stg2, stgname2, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg3 );
1501 ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStorage should fail %08x\n", r);
1502 if (r == S_OK)
1503 IStorage_Release(stg3);
1504
1505 IStorage_Release(stg2);
1506 }
1507
1508 IStorage_Release(stg);
1509
1510 r = DeleteFileA(filenameA);
1511 ok( r == TRUE, "deleted file\n");
1512
1513 /* Revert only invalidates objects in transacted mode */
1514 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
1515 STGM_READWRITE, 0, &stg);
1516 ok(r==S_OK, "StgCreateDocfile failed\n");
1517
1518 r = IStorage_CreateStream(stg, stmname2, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1519 ok(r==S_OK, "IStorage->CreateStream failed\n");
1520
1521 r = IStorage_Revert(stg);
1522 ok(r==S_OK, "IStorage->Revert failed %08x\n", r);
1523
1524 r = IStream_Write(stm, "this works\n", 11, NULL);
1525 ok(r==S_OK, "IStream_Write should succeed %08x\n", r);
1526
1527 IStream_Release(stm);
1528 IStorage_Release(stg);
1529
1530 r = DeleteFileA(filenameA);
1531 ok( r == TRUE, "deleted file\n");
1532 }
1533
1534 static void test_parent_free(void)
1535 {
1536 IStorage *stg = NULL, *stg2 = NULL, *stg3 = NULL;
1537 HRESULT r;
1538 IStream *stm = NULL;
1539 static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 };
1540 static const WCHAR stgname[] = { 'P','E','R','M','S','T','G',0 };
1541 ULONG ref;
1542 STATSTG statstg;
1543
1544 DeleteFileA(filenameA);
1545
1546 /* create the file */
1547 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
1548 STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
1549 ok(r==S_OK, "StgCreateDocfile failed\n");
1550
1551 /* create a new storage */
1552 r = IStorage_CreateStorage(stg, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg2);
1553 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1554
1555 if (r == S_OK)
1556 {
1557 /* now create a stream inside the new storage */
1558 r = IStorage_CreateStream(stg2, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1559 ok(r==S_OK, "IStorage->CreateStream failed\n");
1560
1561 if (r == S_OK)
1562 {
1563 /* create a storage inside the new storage */
1564 r = IStorage_CreateStorage(stg2, stgname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stg3 );
1565 ok(r==S_OK, "IStorage->CreateStorage failed\n");
1566 }
1567
1568 /* free the parent */
1569 ref = IStorage_Release(stg2);
1570 ok(ref == 0, "IStorage still has %u references\n", ref);
1571
1572 /* child objects are invalid */
1573 if (r == S_OK)
1574 {
1575 r = IStream_Write(stm, "this should fail\n", 17, NULL);
1576 ok(r==STG_E_REVERTED, "IStream->Write should fail, hr=%x\n", r);
1577
1578 IStream_Release(stm);
1579
1580 r = IStorage_Stat(stg3, &statstg, STATFLAG_NONAME);
1581 ok(r==STG_E_REVERTED, "IStorage_Stat should fail %08x\n", r);
1582
1583 r = IStorage_SetStateBits(stg3, 1, 1);
1584 ok(r==STG_E_REVERTED, "IStorage_Stat should fail %08x\n", r);
1585
1586 IStorage_Release(stg3);
1587 }
1588 }
1589
1590 IStorage_Release(stg);
1591
1592 r = DeleteFileA(filenameA);
1593 ok( r == TRUE, "deleted file\n");
1594 }
1595
1596 static void test_nonroot_transacted(void)
1597 {
1598 IStorage *stg = NULL, *stg2 = NULL, *stg3 = NULL;
1599 HRESULT r;
1600 IStream *stm = NULL;
1601 static const WCHAR stgname[] = { 'P','E','R','M','S','T','G',0 };
1602 static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 };
1603 static const WCHAR stmname2[] = { 'F','O','O',0 };
1604
1605 DeleteFileA(filenameA);
1606
1607 /* create a transacted file */
1608 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
1609 STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
1610 ok(r==S_OK, "StgCreateDocfile failed\n");
1611
1612 /* create a transacted substorage */
1613 r = IStorage_CreateStorage(stg, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_TRANSACTED, 0, 0, &stg2);
1614 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1615
1616 if (r == S_OK)
1617 {
1618 /* create and commit stmname */
1619 r = IStorage_CreateStream(stg2, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1620 ok(r==S_OK, "IStorage->CreateStream failed\n");
1621 if (r == S_OK)
1622 IStream_Release(stm);
1623
1624 IStorage_Commit(stg2, 0);
1625
1626 /* create and revert stmname2 */
1627 r = IStorage_CreateStream(stg2, stmname2, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1628 ok(r==S_OK, "IStorage->CreateStream failed\n");
1629 if (r == S_OK)
1630 IStream_Release(stm);
1631
1632 IStorage_Revert(stg2);
1633
1634 /* check that Commit and Revert really worked */
1635 r = IStorage_OpenStream(stg2, stmname, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
1636 ok(r==S_OK, "IStorage->OpenStream should succeed %08x\n", r);
1637 if (r == S_OK)
1638 IStream_Release(stm);
1639
1640 r = IStorage_OpenStream(stg2, stmname2, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
1641 ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStream should fail %08x\n", r);
1642 if (r == S_OK)
1643 IStream_Release(stm);
1644
1645 IStorage_Release(stg2);
1646 }
1647
1648 /* create a read-only transacted substorage */
1649 r = IStorage_OpenStorage(stg, stgname, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE | STGM_TRANSACTED, NULL, 0, &stg2);
1650 ok(r==S_OK, "IStorage->OpenStorage failed, hr=%08x\n", r);
1651
1652 if (r == S_OK)
1653 {
1654 /* The storage can be modified. */
1655 r = IStorage_CreateStorage(stg2, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg3);
1656 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1657 if (r == S_OK)
1658 IStorage_Release(stg3);
1659
1660 /* But changes cannot be committed. */
1661 r = IStorage_Commit(stg2, 0);
1662 ok(r==STG_E_ACCESSDENIED, "IStorage->Commit should fail, hr=%08x\n", r);
1663
1664 IStorage_Release(stg2);
1665 }
1666
1667 IStorage_Release(stg);
1668
1669 /* create a non-transacted file */
1670 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
1671 STGM_READWRITE, 0, &stg);
1672 ok(r==S_OK, "StgCreateDocfile failed\n");
1673
1674 /* create a transacted substorage */
1675 r = IStorage_CreateStorage(stg, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_TRANSACTED, 0, 0, &stg2);
1676 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1677
1678 if (r == S_OK)
1679 {
1680 /* create and commit stmname */
1681 r = IStorage_CreateStream(stg2, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1682 ok(r==S_OK, "IStorage->CreateStream failed\n");
1683 if (r == S_OK)
1684 IStream_Release(stm);
1685
1686 IStorage_Commit(stg2, 0);
1687
1688 /* create and revert stmname2 */
1689 r = IStorage_CreateStream(stg2, stmname2, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1690 ok(r==S_OK, "IStorage->CreateStream failed\n");
1691 if (r == S_OK)
1692 IStream_Release(stm);
1693
1694 IStorage_Revert(stg2);
1695
1696 /* check that Commit and Revert really worked */
1697 r = IStorage_OpenStream(stg2, stmname, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
1698 ok(r==S_OK, "IStorage->OpenStream should succeed %08x\n", r);
1699 if (r == S_OK)
1700 IStream_Release(stm);
1701
1702 r = IStorage_OpenStream(stg2, stmname2, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
1703 ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStream should fail %08x\n", r);
1704 if (r == S_OK)
1705 IStream_Release(stm);
1706
1707 IStorage_Release(stg2);
1708 }
1709
1710 IStorage_Release(stg);
1711
1712 r = DeleteFileA(filenameA);
1713 ok( r == TRUE, "deleted file\n");
1714 }
1715
1716 static void test_ReadClassStm(void)
1717 {
1718 CLSID clsid;
1719 HRESULT hr;
1720 IStream *pStream;
1721 static const LARGE_INTEGER llZero;
1722
1723 hr = ReadClassStm(NULL, &clsid);
1724 ok(hr == E_INVALIDARG, "ReadClassStm should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1725
1726 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1727 ok_ole_success(hr, "CreateStreamOnHGlobal");
1728 hr = WriteClassStm(pStream, &test_stg_cls);
1729 ok_ole_success(hr, "WriteClassStm");
1730
1731 hr = ReadClassStm(pStream, NULL);
1732 ok(hr == E_INVALIDARG, "ReadClassStm should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1733
1734 /* test not rewound stream */
1735 hr = ReadClassStm(pStream, &clsid);
1736 ok(hr == STG_E_READFAULT, "ReadClassStm should have returned STG_E_READFAULT instead of 0x%08x\n", hr);
1737 ok(IsEqualCLSID(&clsid, &CLSID_NULL), "clsid should have been zeroed\n");
1738
1739 hr = IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1740 ok_ole_success(hr, "IStream_Seek");
1741 hr = ReadClassStm(pStream, &clsid);
1742 ok_ole_success(hr, "ReadClassStm");
1743 ok(IsEqualCLSID(&clsid, &test_stg_cls), "clsid should have been set to CLSID_WineTest\n");
1744
1745 IStream_Release(pStream);
1746 }
1747
1748 struct access_res
1749 {
1750 BOOL gothandle;
1751 DWORD lasterr;
1752 BOOL ignore;
1753 };
1754
1755 static const struct access_res create[16] =
1756 {
1757 { TRUE, ERROR_SUCCESS, TRUE },
1758 { TRUE, ERROR_SUCCESS, TRUE },
1759 { TRUE, ERROR_SUCCESS, 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, FALSE },
1765 { FALSE, ERROR_SHARING_VIOLATION, FALSE },
1766 { FALSE, ERROR_SHARING_VIOLATION, FALSE },
1767 { FALSE, ERROR_SHARING_VIOLATION, FALSE },
1768 { TRUE, ERROR_SUCCESS, TRUE },
1769 { FALSE, ERROR_SHARING_VIOLATION, FALSE },
1770 { FALSE, ERROR_SHARING_VIOLATION, FALSE },
1771 { FALSE, ERROR_SHARING_VIOLATION, FALSE },
1772 { TRUE, ERROR_SUCCESS, TRUE }
1773 };
1774
1775 static const struct access_res create_commit[16] =
1776 {
1777 { TRUE, ERROR_SUCCESS, TRUE },
1778 { TRUE, ERROR_SUCCESS, TRUE },
1779 { TRUE, ERROR_SUCCESS, 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, FALSE },
1785 { FALSE, ERROR_SHARING_VIOLATION, FALSE },
1786 { FALSE, ERROR_SHARING_VIOLATION, FALSE },
1787 { FALSE, ERROR_SHARING_VIOLATION, FALSE },
1788 { TRUE, ERROR_SUCCESS, TRUE },
1789 { FALSE, ERROR_SHARING_VIOLATION, FALSE },
1790 { FALSE, ERROR_SHARING_VIOLATION, FALSE },
1791 { FALSE, ERROR_SHARING_VIOLATION, FALSE },
1792 { TRUE, ERROR_SUCCESS, TRUE }
1793 };
1794
1795 static const struct access_res create_close[16] =
1796 {
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, FALSE },
1809 { TRUE, ERROR_SUCCESS, FALSE },
1810 { TRUE, ERROR_SUCCESS, FALSE },
1811 { TRUE, ERROR_SUCCESS, FALSE },
1812 { TRUE, ERROR_SUCCESS }
1813 };
1814
1815 static const DWORD access_modes[4] = {
1816 0,
1817 GENERIC_READ,
1818 GENERIC_WRITE,
1819 GENERIC_READ | GENERIC_WRITE
1820 };
1821
1822 static const DWORD share_modes[4] = {
1823 0,
1824 FILE_SHARE_READ,
1825 FILE_SHARE_WRITE,
1826 FILE_SHARE_READ | FILE_SHARE_WRITE
1827 };
1828
1829 static void _test_file_access(LPCSTR file, const struct access_res *ares, DWORD line)
1830 {
1831 int i, j, idx = 0;
1832
1833 for (i = 0; i < sizeof(access_modes)/sizeof(access_modes[0]); i++)
1834 {
1835 for (j = 0; j < sizeof(share_modes)/sizeof(share_modes[0]); j++)
1836 {
1837 DWORD lasterr;
1838 HANDLE hfile;
1839
1840 if (ares[idx].ignore)
1841 continue;
1842
1843 SetLastError(0xdeadbeef);
1844 hfile = CreateFileA(file, access_modes[i], share_modes[j], NULL, OPEN_EXISTING,
1845 FILE_ATTRIBUTE_NORMAL, 0);
1846 lasterr = GetLastError();
1847
1848 ok((hfile != INVALID_HANDLE_VALUE) == ares[idx].gothandle,
1849 "(%d, handle, %d): Expected %d, got %d\n",
1850 line, idx, ares[idx].gothandle,
1851 (hfile != INVALID_HANDLE_VALUE));
1852
1853 ok(lasterr == ares[idx].lasterr ||
1854 broken(lasterr == 0xdeadbeef) /* win9x */,
1855 "(%d, lasterr, %d): Expected %d, got %d\n",
1856 line, idx, ares[idx].lasterr, lasterr);
1857
1858 CloseHandle(hfile);
1859 idx++;
1860 }
1861 }
1862 }
1863
1864 #define test_file_access(file, ares) _test_file_access(file, ares, __LINE__)
1865
1866 static void test_access(void)
1867 {
1868 static const WCHAR fileW[] = {'w','i','n','e','t','e','s','t',0};
1869 static const char fileA[] = "winetest";
1870 IStorage *stg;
1871 HRESULT hr;
1872
1873 /* STGM_TRANSACTED */
1874 hr = StgCreateDocfile(fileW, STGM_CREATE | STGM_READWRITE |
1875 STGM_SHARE_EXCLUSIVE | STGM_TRANSACTED, 0, &stg);
1876 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1877
1878 test_file_access(fileA, create);
1879
1880 hr = IStorage_Commit(stg, STGC_DEFAULT);
1881 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1882
1883 test_file_access(fileA, create_commit);
1884
1885 IStorage_Release(stg);
1886
1887 test_file_access(fileA, create_close);
1888
1889 DeleteFileA(fileA);
1890
1891 /* STGM_DIRECT */
1892 hr = StgCreateDocfile(fileW, STGM_CREATE | STGM_READWRITE |
1893 STGM_SHARE_EXCLUSIVE | STGM_DIRECT, 0, &stg);
1894 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1895
1896 test_file_access(fileA, create);
1897
1898 hr = IStorage_Commit(stg, STGC_DEFAULT);
1899 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1900
1901 test_file_access(fileA, create_commit);
1902
1903 IStorage_Release(stg);
1904
1905 test_file_access(fileA, create_close);
1906
1907 DeleteFileA(fileA);
1908
1909 /* STGM_SHARE_DENY_NONE */
1910 hr = StgCreateDocfile(fileW, STGM_CREATE | STGM_READWRITE |
1911 STGM_SHARE_DENY_NONE | STGM_TRANSACTED, 0, &stg);
1912 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1913
1914 test_file_access(fileA, create);
1915
1916 hr = IStorage_Commit(stg, STGC_DEFAULT);
1917 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1918
1919 test_file_access(fileA, create_commit);
1920
1921 IStorage_Release(stg);
1922
1923 test_file_access(fileA, create_close);
1924
1925 DeleteFileA(fileA);
1926
1927 /* STGM_SHARE_DENY_READ */
1928 hr = StgCreateDocfile(fileW, STGM_CREATE | STGM_READWRITE |
1929 STGM_SHARE_DENY_READ | STGM_TRANSACTED, 0, &stg);
1930 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1931
1932 test_file_access(fileA, create);
1933
1934 hr = IStorage_Commit(stg, STGC_DEFAULT);
1935 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1936
1937 test_file_access(fileA, create_commit);
1938
1939 IStorage_Release(stg);
1940
1941 test_file_access(fileA, create_close);
1942
1943 DeleteFileA(fileA);
1944
1945 /* STGM_SHARE_DENY_WRITE */
1946 hr = StgCreateDocfile(fileW, STGM_CREATE | STGM_READWRITE |
1947 STGM_SHARE_DENY_WRITE | STGM_TRANSACTED, 0, &stg);
1948 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1949
1950 test_file_access(fileA, create);
1951
1952 hr = IStorage_Commit(stg, STGC_DEFAULT);
1953 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1954
1955 test_file_access(fileA, create_commit);
1956
1957 IStorage_Release(stg);
1958
1959 test_file_access(fileA, create_close);
1960
1961 DeleteFileA(fileA);
1962
1963 /* STGM_DIRECT_SWMR | STGM_READ | STGM_SHARE_DENY_NONE - reader mode for direct SWMR mode */
1964 hr = StgCreateDocfile(fileW, STGM_CREATE | STGM_READWRITE | STGM_SHARE_DENY_WRITE | STGM_TRANSACTED, 0, &stg);
1965 ok(hr == S_OK, "got %08x\n", hr);
1966 IStorage_Release(stg);
1967
1968 hr = StgOpenStorage(fileW, NULL, STGM_DIRECT_SWMR | STGM_READ | STGM_SHARE_DENY_NONE, NULL, 0, &stg);
1969 ok(hr == S_OK || broken(hr == STG_E_INVALIDFLAG), "got %08x\n", hr);
1970 if(hr != S_OK)
1971 return;
1972
1973 test_file_access(fileA, create);
1974
1975 IStorage_Release(stg);
1976 test_file_access(fileA, create_close);
1977
1978 DeleteFileA(fileA);
1979 }
1980
1981 static void test_readonly(void)
1982 {
1983 IStorage *stg, *stg2, *stg3;
1984 IStream *stream;
1985 HRESULT hr;
1986 static const WCHAR fileW[] = {'w','i','n','e','t','e','s','t',0};
1987 static const WCHAR storageW[] = {'s','t','o','r','a','g','e',0};
1988 static const WCHAR streamW[] = {'s','t','r','e','a','m',0};
1989
1990 hr = StgCreateDocfile( fileW, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &stg);
1991 ok(hr == S_OK, "should succeed, res=%x\n", hr);
1992 if (SUCCEEDED(hr))
1993 {
1994 hr = IStorage_CreateStorage( stg, storageW, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stg2 );
1995 ok(hr == S_OK, "should succeed, res=%x\n", hr);
1996 if (SUCCEEDED(hr))
1997 {
1998 hr = IStorage_CreateStream( stg2, streamW, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stream );
1999 ok(hr == S_OK, "should succeed, res=%x\n", hr);
2000 if (SUCCEEDED(hr))
2001 IStream_Release(stream);
2002 IStorage_Release(stg2);
2003 }
2004 IStorage_Release(stg);
2005 }
2006
2007 /* re-open read only */
2008 hr = StgOpenStorage( fileW, NULL, STGM_TRANSACTED | STGM_SHARE_DENY_NONE | STGM_READ, NULL, 0, &stg);
2009 ok(hr == S_OK, "should succeed, res=%x\n", hr);
2010 if (SUCCEEDED(hr))
2011 {
2012 hr = IStorage_OpenStorage( stg, storageW, NULL, STGM_SHARE_EXCLUSIVE | STGM_READ, NULL, 0, &stg2 );
2013 ok(hr == S_OK, "should succeed, res=%x\n", hr);
2014 if (SUCCEEDED(hr))
2015 {
2016 /* CreateStream on read-only storage, name exists */
2017 hr = IStorage_CreateStream( stg2, streamW, 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);
2021
2022 /* CreateStream on read-only storage, name does not exist */
2023 hr = IStorage_CreateStream( stg2, storageW, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READ, 0, 0, &stream );
2024 ok(hr == STG_E_ACCESSDENIED, "should fail, res=%x\n", hr);
2025 if (SUCCEEDED(hr))
2026 IStream_Release(stream);
2027
2028 /* CreateStorage on read-only storage, name exists */
2029 hr = IStorage_CreateStorage( stg2, streamW, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READ, 0, 0, &stg3 );
2030 ok(hr == STG_E_FILEALREADYEXISTS, "should fail, res=%x\n", hr);
2031 if (SUCCEEDED(hr))
2032 IStorage_Release(stg3);
2033
2034 /* CreateStorage on read-only storage, name does not exist */
2035 hr = IStorage_CreateStorage( stg2, storageW, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READ, 0, 0, &stg3 );
2036 ok(hr == STG_E_ACCESSDENIED, "should fail, res=%x\n", hr);
2037 if (SUCCEEDED(hr))
2038 IStorage_Release(stg3);
2039
2040 /* DestroyElement on read-only storage, name exists */
2041 hr = IStorage_DestroyElement( stg2, streamW );
2042 ok(hr == STG_E_ACCESSDENIED, "should fail, res=%x\n", hr);
2043
2044 /* DestroyElement on read-only storage, name does not exist */
2045 hr = IStorage_DestroyElement( stg2, storageW );
2046 ok(hr == STG_E_ACCESSDENIED, "should fail, res=%x\n", hr);
2047
2048 IStorage_Release(stg2);
2049 }
2050
2051 IStorage_Release(stg);
2052 }
2053
2054 DeleteFileA("winetest");
2055 }
2056
2057 static void test_simple(void)
2058 {
2059 /* Tests for STGM_SIMPLE mode */
2060
2061 IStorage *stg, *stg2;
2062 HRESULT r;
2063 IStream *stm;
2064 static const WCHAR stgname[] = { 'S','t','g',0 };
2065 static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 };
2066 static const WCHAR stmname2[] = { 'S','m','a','l','l',0 };
2067 LARGE_INTEGER pos;
2068 ULARGE_INTEGER upos;
2069 DWORD count;
2070 STATSTG stat;
2071
2072 DeleteFileA(filenameA);
2073
2074 r = StgCreateDocfile( filename, STGM_SIMPLE | STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &stg);
2075 ok(r == S_OK, "got %08x\n", r);
2076
2077 r = IStorage_CreateStorage(stg, stgname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stg2);
2078 ok(r == STG_E_INVALIDFUNCTION, "got %08x\n", r);
2079 if (SUCCEEDED(r)) IStorage_Release(stg2);
2080
2081 r = IStorage_CreateStream(stg, stmname, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm);
2082 ok(r == STG_E_INVALIDFLAG, "got %08x\n", r);
2083 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm);
2084 ok(r == S_OK, "got %08x\n", r);
2085
2086 upos.QuadPart = 6000;
2087 r = IStream_SetSize(stm, upos);
2088 ok(r == S_OK, "got %08x\n", r);
2089
2090 r = IStream_Write(stm, "foo", 3, &count);
2091 ok(r == S_OK, "got %08x\n", r);
2092 ok(count == 3, "got %d\n", count);
2093
2094 pos.QuadPart = 0;
2095 r = IStream_Seek(stm, pos, STREAM_SEEK_CUR, &upos);
2096 ok(r == S_OK, "got %08x\n", r);
2097 ok(upos.QuadPart == 3, "got %d\n", upos.u.LowPart);
2098
2099 r = IStream_Stat(stm, &stat, STATFLAG_NONAME);
2100 ok(r == S_OK ||
2101 broken(r == STG_E_INVALIDFUNCTION), /* NT4 and below */
2102 "got %08x\n", r);
2103 if (r == S_OK)
2104 ok(stat.cbSize.QuadPart == 3, "got %d\n", stat.cbSize.u.LowPart);
2105
2106 pos.QuadPart = 1;
2107 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &upos);
2108 ok(r == S_OK, "got %08x\n", r);
2109 ok(upos.QuadPart == 1, "got %d\n", upos.u.LowPart);
2110
2111 r = IStream_Stat(stm, &stat, STATFLAG_NONAME);
2112 ok(r == S_OK ||
2113 broken(r == STG_E_INVALIDFUNCTION), /* NT4 and below */
2114 "got %08x\n", r);
2115 if (r == S_OK)
2116 ok(stat.cbSize.QuadPart == 1, "got %d\n", stat.cbSize.u.LowPart);
2117
2118 IStream_Release(stm);
2119
2120 r = IStorage_CreateStream(stg, stmname2, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm);
2121 ok(r == S_OK, "got %08x\n", r);
2122
2123 upos.QuadPart = 100;
2124 r = IStream_SetSize(stm, upos);
2125 ok(r == S_OK, "got %08x\n", r);
2126
2127 r = IStream_Write(stm, "foo", 3, &count);
2128 ok(r == S_OK, "got %08x\n", r);
2129 ok(count == 3, "got %d\n", count);
2130
2131 IStream_Release(stm);
2132
2133 IStorage_Commit(stg, STGC_DEFAULT);
2134 IStorage_Release(stg);
2135
2136 r = StgOpenStorage( filename, NULL, STGM_SIMPLE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, NULL, 0, &stg);
2137 if (r == STG_E_INVALIDFLAG)
2138 {
2139 win_skip("Flag combination is not supported on NT4 and below\n");
2140 DeleteFileA(filenameA);
2141 return;
2142 }
2143 ok(r == S_OK, "got %08x\n", r);
2144
2145 r = IStorage_OpenStorage(stg, stgname, NULL, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, NULL, 0, &stg2);
2146 ok(r == STG_E_INVALIDFUNCTION, "got %08x\n", r);
2147 if (SUCCEEDED(r)) IStorage_Release(stg2);
2148
2149 r = IStorage_OpenStream(stg, stmname, NULL, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &stm);
2150 ok(r == S_OK, "got %08x\n", r);
2151
2152 r = IStream_Stat(stm, &stat, STATFLAG_NONAME);
2153 ok(r == S_OK, "got %08x\n", r);
2154 ok(stat.cbSize.QuadPart == 6000, "got %d\n", stat.cbSize.u.LowPart);
2155
2156 IStream_Release(stm);
2157
2158 r = IStorage_OpenStream(stg, stmname2, NULL, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &stm);
2159 ok(r == S_OK, "got %08x\n", r);
2160
2161 r = IStream_Stat(stm, &stat, STATFLAG_NONAME);
2162 ok(r == S_OK, "got %08x\n", r);
2163 ok(stat.cbSize.QuadPart == 4096, "got %d\n", stat.cbSize.u.LowPart);
2164
2165 IStream_Release(stm);
2166
2167
2168 IStorage_Release(stg);
2169
2170 DeleteFileA(filenameA);
2171 }
2172
2173 static void test_fmtusertypestg(void)
2174 {
2175 IStorage *stg;
2176 IEnumSTATSTG *stat;
2177 HRESULT hr;
2178 static const char fileA[] = {'f','m','t','t','e','s','t',0};
2179 static const WCHAR fileW[] = {'f','m','t','t','e','s','t',0};
2180 static WCHAR userTypeW[] = {'S','t','g','U','s','r','T','y','p','e',0};
2181 static WCHAR strmNameW[] = {1,'C','o','m','p','O','b','j',0};
2182
2183 hr = StgCreateDocfile( fileW, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &stg);
2184 ok(hr == S_OK, "should succeed, res=%x\n", hr);
2185
2186 if (SUCCEEDED(hr))
2187 {
2188 /* try to write the stream */
2189 hr = WriteFmtUserTypeStg(stg, 0, userTypeW);
2190 ok(hr == S_OK, "should succeed, res=%x\n", hr);
2191
2192 /* check that the stream was created */
2193 hr = IStorage_EnumElements(stg, 0, NULL, 0, &stat);
2194 ok(hr == S_OK, "should succeed, res=%x\n", hr);
2195 if (SUCCEEDED(hr))
2196 {
2197 BOOL found = FALSE;
2198 STATSTG statstg;
2199 DWORD got;
2200 while ((hr = IEnumSTATSTG_Next(stat, 1, &statstg, &got)) == S_OK && got == 1)
2201 {
2202 if (strcmp_ww(statstg.pwcsName, strmNameW) == 0)
2203 found = TRUE;
2204 else
2205 ok(0, "found unexpected stream or storage\n");
2206 CoTaskMemFree(statstg.pwcsName);
2207 }
2208 ok(found == TRUE, "expected storage to contain stream \\0001CompObj\n");
2209 IEnumSTATSTG_Release(stat);
2210 }
2211
2212 /* re-write the stream */
2213 hr = WriteFmtUserTypeStg(stg, 0, userTypeW);
2214 ok(hr == S_OK, "should succeed, res=%x\n", hr);
2215
2216 /* check that the stream is still there */
2217 hr = IStorage_EnumElements(stg, 0, NULL, 0, &stat);
2218 ok(hr == S_OK, "should succeed, res=%x\n", hr);
2219 if (SUCCEEDED(hr))
2220 {
2221 BOOL found = FALSE;
2222 STATSTG statstg;
2223 DWORD got;
2224 while ((hr = IEnumSTATSTG_Next(stat, 1, &statstg, &got)) == S_OK && got == 1)
2225 {
2226 if (strcmp_ww(statstg.pwcsName, strmNameW) == 0)
2227 found = TRUE;
2228 else
2229 ok(0, "found unexpected stream or storage\n");
2230 CoTaskMemFree(statstg.pwcsName);
2231 }
2232 ok(found == TRUE, "expected storage to contain stream \\0001CompObj\n");
2233 IEnumSTATSTG_Release(stat);
2234 }
2235
2236 IStorage_Release(stg);
2237 DeleteFileA( fileA );
2238 }
2239 }
2240
2241 static void test_references(void)
2242 {
2243 IStorage *stg,*stg2;
2244 HRESULT hr;
2245 unsigned c1,c2;
2246 static const WCHAR StorName[] = { 'D','a','t','a','S','p','a','c','e','I','n','f','o',0 };
2247
2248 DeleteFileA(filenameA);
2249
2250 hr = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
2251 ok(hr==S_OK, "StgCreateDocfile failed\n");
2252
2253 if (SUCCEEDED(hr))
2254 {
2255 IStorage_Release(stg);
2256
2257 hr = StgOpenStorage( filename, NULL, STGM_TRANSACTED | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, NULL, 0, &stg);
2258 ok(hr==S_OK, "StgOpenStorage failed (result=%x)\n",hr);
2259
2260 if (SUCCEEDED(hr))
2261 {
2262 hr = IStorage_CreateStorage(stg,StorName,STGM_READWRITE | STGM_SHARE_EXCLUSIVE,0,0,&stg2);
2263 ok(hr == S_OK, "IStorage_CreateStorage failed (result=%x)\n",hr);
2264
2265 if (SUCCEEDED(hr))
2266 {
2267 c1 = IStorage_AddRef(stg);
2268 ok(c1 == 2, "creating internal storage added references to ancestor\n");
2269 c1 = IStorage_AddRef(stg);
2270 IStorage_Release(stg2);
2271 c2 = IStorage_AddRef(stg) - 1;
2272 ok(c1 == c2, "releasing internal storage removed references to ancestor\n");
2273 }
2274 c1 = IStorage_Release(stg);
2275 while ( c1 ) c1 = IStorage_Release(stg);
2276 }
2277 }
2278
2279 DeleteFileA(filenameA);
2280 }
2281
2282 /* dest
2283 * |-StorageA
2284 * | `StreamA: "StreamA"
2285 * |-StorageB
2286 * | `StreamB: "StreamB"
2287 * `StreamC: "StreamC"
2288 */
2289 static HRESULT create_test_file(IStorage *dest)
2290 {
2291 IStorage *stgA = NULL, *stgB = NULL;
2292 IStream *strmA = NULL, *strmB = NULL, *strmC = NULL;
2293 const ULONG strmA_name_size = lstrlenW(strmA_name) * sizeof(WCHAR);
2294 const ULONG strmB_name_size = lstrlenW(strmB_name) * sizeof(WCHAR);
2295 const ULONG strmC_name_size = lstrlenW(strmC_name) * sizeof(WCHAR);
2296 ULONG bytes;
2297 HRESULT hr;
2298
2299 hr = IStorage_CreateStorage(dest, stgA_name, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stgA);
2300 ok(hr == S_OK, "IStorage_CreateStorage failed: 0x%08x\n", hr);
2301 if(FAILED(hr))
2302 goto cleanup;
2303
2304 hr = IStorage_CreateStream(stgA, strmA_name, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &strmA);
2305 ok(hr == S_OK, "IStorage_CreateStream failed: 0x%08x\n", hr);
2306 if(FAILED(hr))
2307 goto cleanup;
2308
2309 hr = IStream_Write(strmA, strmA_name, strmA_name_size, &bytes);
2310 ok(hr == S_OK && bytes == strmA_name_size, "IStream_Write failed: 0x%08x, %d of %d bytes written\n", hr, bytes, strmA_name_size);
2311
2312 hr = IStorage_CreateStorage(dest, stgB_name, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stgB);
2313 ok(hr == S_OK, "IStorage_CreateStorage failed: 0x%08x\n", hr);
2314 if(FAILED(hr))
2315 goto cleanup;
2316
2317 hr = IStorage_CreateStream(stgB, strmB_name, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &strmB);
2318 ok(hr == S_OK, "IStorage_CreateStream failed: 0x%08x\n", hr);
2319 if(FAILED(hr))
2320 goto cleanup;
2321
2322 hr = IStream_Write(strmB, strmB_name, strmB_name_size, &bytes);
2323 ok(hr == S_OK && bytes == strmB_name_size, "IStream_Write failed: 0x%08x, %d of %d bytes written\n", hr, bytes, strmB_name_size);
2324
2325 hr = IStorage_CreateStream(dest, strmC_name, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &strmC);
2326 ok(hr == S_OK, "IStorage_CreateStream failed: 0x%08x\n", hr);
2327 if(FAILED(hr))
2328 goto cleanup;
2329
2330 hr = IStream_Write(strmC, strmC_name, strmC_name_size, &bytes);
2331 ok(hr == S_OK && bytes == strmC_name_size, "IStream_Write failed: 0x%08x, %d of %d bytes written\n", hr, bytes, strmC_name_size);
2332
2333 cleanup:
2334 if(strmC)
2335 IStream_Release(strmC);
2336 if(strmB)
2337 IStream_Release(strmB);
2338 if(stgB)
2339 IStorage_Release(stgB);
2340 if(strmA)
2341 IStream_Release(strmA);
2342 if(stgA)
2343 IStorage_Release(stgA);
2344
2345 return hr;
2346 }
2347
2348 static void test_copyto(void)
2349 {
2350 IStorage *file1 = NULL, *file2 = NULL, *stg_tmp;
2351 IStream *strm_tmp;
2352 WCHAR buf[64];
2353 HRESULT hr;
2354
2355 /* create & populate file1 */
2356 hr = StgCreateDocfile(file1_name, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &file1);
2357 ok(hr == S_OK, "StgCreateDocfile failed: 0x%08x\n", hr);
2358 if(FAILED(hr))
2359 goto cleanup;
2360
2361 hr = create_test_file(file1);
2362 if(FAILED(hr))
2363 goto cleanup;
2364
2365 /* create file2 */
2366 hr = StgCreateDocfile(file2_name, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &file2);
2367 ok(hr == S_OK, "StgCreateDocfile failed: 0x%08x\n", hr);
2368 if(FAILED(hr))
2369 goto cleanup;
2370
2371 /* copy file1 into file2 */
2372 hr = IStorage_CopyTo(file1, 0, NULL, NULL, NULL);
2373 ok(hr == STG_E_INVALIDPOINTER, "CopyTo should give STG_E_INVALIDPONITER, gave: 0x%08x\n", hr);
2374
2375 hr = IStorage_CopyTo(file1, 0, NULL, NULL, file2);
2376 ok(hr == S_OK, "CopyTo failed: 0x%08x\n", hr);
2377 if(FAILED(hr))
2378 goto cleanup;
2379
2380 /* verify that all of file1 was copied */
2381 hr = IStorage_OpenStorage(file2, stgA_name, NULL,
2382 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg_tmp);
2383 ok(hr == S_OK, "OpenStorage failed: 0x%08x\n", hr);
2384
2385 if(SUCCEEDED(hr)){
2386 hr = IStorage_OpenStream(stg_tmp, strmA_name, NULL,
2387 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp);
2388 ok(hr == S_OK, "OpenStream failed: 0x%08x\n", hr);
2389
2390 if(SUCCEEDED(hr)){
2391 memset(buf, 0, sizeof(buf));
2392 hr = IStream_Read(strm_tmp, buf, sizeof(buf), NULL);
2393 ok(hr == S_OK, "Read failed: 0x%08x\n", hr);
2394 if(SUCCEEDED(hr))
2395 ok(strcmp_ww(buf, strmA_name) == 0,
2396 "Expected %s to be read, got %s\n", wine_dbgstr_w(strmA_name), wine_dbgstr_w(buf));
2397
2398 IStream_Release(strm_tmp);
2399 }
2400
2401 IStorage_Release(stg_tmp);
2402 }
2403
2404 hr = IStorage_OpenStorage(file2, stgB_name, NULL,
2405 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg_tmp);
2406 ok(hr == S_OK, "OpenStorage failed: 0x%08x\n", hr);
2407
2408 if(SUCCEEDED(hr)){
2409 hr = IStorage_OpenStream(stg_tmp, strmB_name, NULL,
2410 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp);
2411 ok(hr == S_OK, "OpenStream failed: 0x%08x\n", hr);
2412
2413 if(SUCCEEDED(hr)){
2414 memset(buf, 0, sizeof(buf));
2415 hr = IStream_Read(strm_tmp, buf, sizeof(buf), NULL);
2416 ok(hr == S_OK, "Read failed: 0x%08x\n", hr);
2417 if(SUCCEEDED(hr))
2418 ok(strcmp_ww(buf, strmB_name) == 0,
2419 "Expected %s to be read, got %s\n", wine_dbgstr_w(strmB_name), wine_dbgstr_w(buf));
2420
2421 IStream_Release(strm_tmp);
2422 }
2423
2424 IStorage_Release(stg_tmp);
2425 }
2426
2427 hr = IStorage_OpenStream(file2, strmC_name, NULL,
2428 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp);
2429 ok(hr == S_OK, "OpenStream failed: 0x%08x\n", hr);
2430
2431 if(SUCCEEDED(hr)){
2432 memset(buf, 0, sizeof(buf));
2433 hr = IStream_Read(strm_tmp, buf, sizeof(buf), NULL);
2434 ok(hr == S_OK, "Read failed: 0x%08x\n", hr);
2435 if(SUCCEEDED(hr))
2436 ok(strcmp_ww(buf, strmC_name) == 0,
2437 "Expected %s to be read, got %s\n", wine_dbgstr_w(strmC_name), wine_dbgstr_w(buf));
2438
2439 IStream_Release(strm_tmp);
2440 }
2441
2442 cleanup:
2443 if(file1)
2444 IStorage_Release(file1);
2445 if(file2)
2446 IStorage_Release(file2);
2447
2448 DeleteFileA(file1_nameA);
2449 DeleteFileA(file2_nameA);
2450 }
2451
2452 static void test_copyto_snbexclusions(void)
2453 {
2454 static const WCHAR *snb_exclude[] = {stgA_name, strmB_name, strmC_name, 0};
2455
2456 IStorage *file1 = NULL, *file2 = NULL, *stg_tmp;
2457 IStream *strm_tmp;
2458 WCHAR buf[64];
2459 HRESULT hr;
2460
2461 /* create & populate file1 */
2462 hr = StgCreateDocfile(file1_name, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &file1);
2463 ok(hr == S_OK, "StgCreateDocfile failed: 0x%08x\n", hr);
2464 if(FAILED(hr))
2465 goto cleanup;
2466
2467 hr = create_test_file(file1);
2468 if(FAILED(hr))
2469 goto cleanup;
2470
2471 /* create file2 */
2472 hr = StgCreateDocfile(file2_name, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &file2);
2473 ok(hr == S_OK, "StgCreateDocfile failed: 0x%08x\n", hr);
2474 if(FAILED(hr))
2475 goto cleanup;
2476
2477 /* copy file1 to file2 with name exclusions */
2478 hr = IStorage_CopyTo(file1, 0, NULL, (SNB)snb_exclude, file2);
2479 ok(hr == S_OK, "CopyTo failed: 0x%08x\n", hr);
2480 if(FAILED(hr))
2481 goto cleanup;
2482
2483 /* verify that file1 copied over, respecting exclusions */
2484 hr = IStorage_OpenStorage(file2, stgA_name, NULL,
2485 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg_tmp);
2486 ok(hr == STG_E_FILENOTFOUND, "OpenStorage should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr);
2487 if(SUCCEEDED(hr))
2488 IStorage_Release(stg_tmp);
2489
2490 hr = IStorage_OpenStream(file2, strmA_name, NULL,
2491 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp);
2492 ok(hr == STG_E_FILENOTFOUND, "OpenStream should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr);
2493 if(SUCCEEDED(hr))
2494 IStream_Release(strm_tmp);
2495
2496 hr = IStorage_OpenStorage(file2, stgB_name, NULL,
2497 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg_tmp);
2498 ok(hr == S_OK, "OpenStorage failed: 0x%08x\n", hr);
2499
2500 if(SUCCEEDED(hr)){
2501 hr = IStorage_OpenStream(stg_tmp, strmB_name, NULL,
2502 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp);
2503 ok(hr == S_OK, "OpenStream failed: 0x%08x\n", hr);
2504
2505 if(SUCCEEDED(hr)){
2506 memset(buf, 0, sizeof(buf));
2507 hr = IStream_Read(strm_tmp, buf, sizeof(buf), NULL);
2508 ok(hr == S_OK, "Read failed: 0x%08x\n", hr);
2509 if(SUCCEEDED(hr))
2510 ok(strcmp_ww(buf, strmB_name) == 0,
2511 "Expected %s to be read, got %s\n", wine_dbgstr_w(strmB_name), wine_dbgstr_w(buf));
2512
2513 IStream_Release(strm_tmp);
2514 }
2515
2516 IStorage_Release(stg_tmp);
2517 }
2518
2519 hr = IStorage_OpenStream(file2, strmC_name, NULL,
2520 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp);
2521 ok(hr == STG_E_FILENOTFOUND, "OpenStream should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr);
2522 if(SUCCEEDED(hr))
2523 IStream_Release(strm_tmp);
2524
2525 cleanup:
2526 if(file1)
2527 IStorage_Release(file1);
2528 if(file2)
2529 IStorage_Release(file2);
2530
2531 DeleteFileA(file1_nameA);
2532 DeleteFileA(file2_nameA);
2533 }
2534
2535 static void test_copyto_iidexclusions_storage(void)
2536 {
2537 IStorage *file1 = NULL, *file2 = NULL, *stg_tmp;
2538 IStream *strm_tmp;
2539 WCHAR buf[64];
2540 HRESULT hr;
2541
2542 /* create & populate file1 */
2543 hr = StgCreateDocfile(file1_name, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &file1);
2544 ok(hr == S_OK, "StgCreateDocfile failed: 0x%08x\n", hr);
2545 if(FAILED(hr))
2546 goto cleanup;
2547
2548 hr = create_test_file(file1);
2549 if(FAILED(hr))
2550 goto cleanup;
2551
2552 /* create file2 */
2553 hr = StgCreateDocfile(file2_name, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &file2);
2554 ok(hr == S_OK, "StgCreateDocfile failed: 0x%08x\n", hr);
2555 if(FAILED(hr))
2556 goto cleanup;
2557
2558 /* copy file1 to file2 with iid exclusions */
2559 hr = IStorage_CopyTo(file1, 1, &IID_IStorage, NULL, file2);
2560 ok(hr == S_OK, "CopyTo failed: 0x%08x\n", hr);
2561 if(FAILED(hr))
2562 goto cleanup;
2563
2564 /* verify that file1 copied over, respecting exclusions */
2565 hr = IStorage_OpenStorage(file2, stgA_name, NULL,
2566 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg_tmp);
2567 ok(hr == STG_E_FILENOTFOUND, "OpenStorage should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr);
2568 if(SUCCEEDED(hr))
2569 IStorage_Release(stg_tmp);
2570
2571 hr = IStorage_OpenStream(file2, strmA_name, NULL,
2572 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp);
2573 ok(hr == STG_E_FILENOTFOUND, "OpenStream should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr);
2574 if(SUCCEEDED(hr))
2575 IStream_Release(strm_tmp);
2576
2577 hr = IStorage_OpenStorage(file2, stgB_name, NULL,
2578 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg_tmp);
2579 ok(hr == STG_E_FILENOTFOUND, "OpenStorage should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr);
2580 if(SUCCEEDED(hr))
2581 IStorage_Release(stg_tmp);
2582
2583 hr = IStorage_OpenStream(file2, strmB_name, NULL,
2584 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp);
2585 ok(hr == STG_E_FILENOTFOUND, "OpenStream should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr);
2586 if(SUCCEEDED(hr))
2587 IStream_Release(strm_tmp);
2588
2589 hr = IStorage_OpenStream(file2, strmC_name, NULL,
2590 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp);
2591 ok(hr == S_OK, "OpenStream failed: 0x%08x\n", hr);
2592
2593 if(SUCCEEDED(hr)){
2594 memset(buf, 0, sizeof(buf));
2595 hr = IStream_Read(strm_tmp, buf, sizeof(buf), NULL);
2596 ok(hr == S_OK, "Read failed: 0x%08x\n", hr);
2597 if(SUCCEEDED(hr))
2598 ok(strcmp_ww(buf, strmC_name) == 0,
2599 "Expected %s to be read, got %s\n", wine_dbgstr_w(strmC_name), wine_dbgstr_w(buf));
2600
2601 IStream_Release(strm_tmp);
2602 }
2603
2604 cleanup:
2605 if(file1)
2606 IStorage_Release(file1);
2607 if(file2)
2608 IStorage_Release(file2);
2609
2610 DeleteFileA(file1_nameA);
2611 DeleteFileA(file2_nameA);
2612 }
2613
2614 static void test_copyto_iidexclusions_stream(void)
2615 {
2616 IStorage *file1 = NULL, *file2 = NULL, *stg_tmp;
2617 IStream *strm_tmp;
2618 HRESULT hr;
2619
2620 /* create & populate file1 */
2621 hr = StgCreateDocfile(file1_name, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &file1);
2622 ok(hr == S_OK, "StgCreateDocfile failed: 0x%08x\n", hr);
2623 if(FAILED(hr))
2624 goto cleanup;
2625
2626 hr = create_test_file(file1);
2627 if(FAILED(hr))
2628 goto cleanup;
2629
2630 /* create file2 */
2631 hr = StgCreateDocfile(file2_name, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &file2);
2632 ok(hr == S_OK, "StgCreateDocfile failed: 0x%08x\n", hr);
2633 if(FAILED(hr))
2634 goto cleanup;
2635
2636 /* copy file1 to file2 with iid exclusions */
2637 hr = IStorage_CopyTo(file1, 1, &IID_IStream, NULL, file2);
2638 ok(hr == S_OK, "CopyTo failed: 0x%08x\n", hr);
2639 if(FAILED(hr))
2640 goto cleanup;
2641
2642 /* verify that file1 copied over, respecting exclusions */
2643 hr = IStorage_OpenStorage(file2, stgA_name, NULL,
2644 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg_tmp);
2645 ok(hr == S_OK, "OpenStorage failed: 0x%08x\n", hr);
2646
2647 if(SUCCEEDED(hr)){
2648 hr = IStorage_OpenStream(stg_tmp, strmA_name, NULL,
2649 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp);
2650 ok(hr == STG_E_FILENOTFOUND, "OpenStream should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr);
2651 if(SUCCEEDED(hr))
2652 IStream_Release(strm_tmp);
2653
2654 IStorage_Release(stg_tmp);
2655 }
2656
2657 hr = IStorage_OpenStorage(file2, stgB_name, NULL,
2658 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg_tmp);
2659 ok(hr == S_OK, "OpenStorage failed: 0x%08x\n", hr);
2660
2661 if(SUCCEEDED(hr)){
2662 hr = IStorage_OpenStream(stg_tmp, strmB_name, NULL,
2663 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp);
2664 ok(hr == STG_E_FILENOTFOUND, "OpenStream should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr);
2665 if(SUCCEEDED(hr))
2666 IStream_Release(strm_tmp);
2667
2668 IStorage_Release(stg_tmp);
2669 }
2670
2671 hr = IStorage_OpenStream(file2, strmC_name, NULL,
2672 STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp);
2673 ok(hr == STG_E_FILENOTFOUND, "OpenStream should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr);
2674 if(SUCCEEDED(hr))
2675 IStream_Release(strm_tmp);
2676
2677 cleanup:
2678 if(file1)
2679 IStorage_Release(file1);
2680 if(file2)
2681 IStorage_Release(file2);
2682
2683 DeleteFileA(file1_nameA);
2684 DeleteFileA(file2_nameA);
2685 }
2686
2687 static void test_rename(void)
2688 {
2689 IStorage *stg, *stg2;
2690 IStream *stm;
2691 HRESULT r;
2692 static const WCHAR stgname[] = { 'P','E','R','M','S','T','G',0 };
2693 static const WCHAR stgname2[] = { 'S','T','G',0 };
2694 static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 };
2695 static const WCHAR stmname2[] = { 'E','N','T','S',0 };
2696
2697 DeleteFileA(filenameA);
2698
2699 /* create the file */
2700 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
2701 STGM_READWRITE, 0, &stg);
2702 ok(r==S_OK, "StgCreateDocfile failed\n");
2703
2704 /* create a substorage */
2705 r = IStorage_CreateStorage(stg, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg2);
2706 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
2707
2708 /* create a stream in the substorage */
2709 r = IStorage_CreateStream(stg2, stmname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm);
2710 ok(r==S_OK, "IStorage->CreateStream failed, hr=%08x\n", r);
2711 IStream_Release(stm);
2712
2713 /* rename the stream */
2714 r = IStorage_RenameElement(stg2, stmname, stmname2);
2715 ok(r==S_OK, "IStorage->RenameElement failed, hr=%08x\n", r);
2716
2717 /* cannot open stream with old name */
2718 r = IStorage_OpenStream(stg2, stmname, NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &stm);
2719 ok(r==STG_E_FILENOTFOUND, "IStorage_OpenStream should fail, hr=%08x\n", r);
2720 if (SUCCEEDED(r)) IStream_Release(stm);
2721
2722 /* can open stream with new name */
2723 r = IStorage_OpenStream(stg2, stmname2, NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &stm);
2724 ok(r==S_OK, "IStorage_OpenStream failed, hr=%08x\n", r);
2725 if (SUCCEEDED(r)) IStream_Release(stm);
2726
2727 IStorage_Release(stg2);
2728
2729 /* rename the storage */
2730 IStorage_RenameElement(stg, stgname, stgname2);
2731
2732 /* cannot open storage with old name */
2733 r = IStorage_OpenStorage(stg, stgname, NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg2);
2734 ok(r==STG_E_FILENOTFOUND, "IStorage_OpenStream should fail, hr=%08x\n", r);
2735 if (SUCCEEDED(r)) IStorage_Release(stg2);
2736
2737 /* can open storage with new name */
2738 r = IStorage_OpenStorage(stg, stgname2, NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg2);
2739 ok(r==S_OK, "IStorage_OpenStream should fail, hr=%08x\n", r);
2740 if (SUCCEEDED(r))
2741 {
2742 /* opened storage still has the stream */
2743 r = IStorage_OpenStream(stg2, stmname2, NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &stm);
2744 ok(r==S_OK, "IStorage_OpenStream failed, hr=%08x\n", r);
2745 if (SUCCEEDED(r)) IStream_Release(stm);
2746
2747 IStorage_Release(stg2);
2748 }
2749
2750 IStorage_Release(stg);
2751
2752 r = DeleteFileA(filenameA);
2753 ok( r == TRUE, "deleted file\n");
2754 }
2755
2756 static void test_toplevel_stat(void)
2757 {
2758 IStorage *stg = NULL;
2759 HRESULT r;
2760 STATSTG stat;
2761 char prev_dir[MAX_PATH];
2762 char temp[MAX_PATH];
2763 char full_path[MAX_PATH];
2764 LPSTR rel_pathA;
2765 WCHAR rel_path[MAX_PATH];
2766
2767 DeleteFileA(filenameA);
2768
2769 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
2770 STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
2771 ok(r==S_OK, "StgCreateDocfile failed\n");
2772
2773 r = IStorage_Stat( stg, &stat, STATFLAG_DEFAULT );
2774 ok(r==S_OK, "Storage_Stat failed with error 0x%08x\n", r);
2775 ok(!strcmp_ww(stat.pwcsName, filename), "expected %s, got %s\n",
2776 wine_dbgstr_w(filename), wine_dbgstr_w(stat.pwcsName));
2777 CoTaskMemFree(stat.pwcsName);
2778
2779 IStorage_Release( stg );
2780
2781 r = StgOpenStorage( filename, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg);
2782 ok(r==S_OK, "StgOpenStorage failed with error 0x%08x\n", r);
2783
2784 r = IStorage_Stat( stg, &stat, STATFLAG_DEFAULT );
2785 ok(r==S_OK, "Storage_Stat failed with error 0x%08x\n", r);
2786 ok(!strcmp_ww(stat.pwcsName, filename), "expected %s, got %s\n",
2787 wine_dbgstr_w(filename), wine_dbgstr_w(stat.pwcsName));
2788 CoTaskMemFree(stat.pwcsName);
2789
2790 IStorage_Release( stg );
2791
2792 DeleteFileA(filenameA);
2793
2794 /* Stat always returns the full path, even for files opened with a relative path. */
2795 GetCurrentDirectoryA(MAX_PATH, prev_dir);
2796
2797 GetTempPathA(MAX_PATH, temp);
2798
2799 SetCurrentDirectoryA(temp);
2800
2801 GetFullPathNameA(filenameA, MAX_PATH, full_path, &rel_pathA);
2802 MultiByteToWideChar(CP_ACP, 0, rel_pathA, -1, rel_path, MAX_PATH);
2803
2804 r = StgCreateDocfile( rel_path, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
2805 STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
2806 ok(r==S_OK, "StgCreateDocfile failed\n");
2807
2808 r = IStorage_Stat( stg, &stat, STATFLAG_DEFAULT );
2809 ok(r==S_OK, "Storage_Stat failed with error 0x%08x\n", r);
2810 ok(!strcmp_ww(stat.pwcsName, filename), "expected %s, got %s\n",
2811 wine_dbgstr_w(filename), wine_dbgstr_w(stat.pwcsName));
2812 CoTaskMemFree(stat.pwcsName);
2813
2814 IStorage_Release( stg );
2815
2816 r = StgOpenStorage( rel_path, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg);
2817 ok(r==S_OK, "StgOpenStorage failed with error 0x%08x\n", r);
2818
2819 r = IStorage_Stat( stg, &stat, STATFLAG_DEFAULT );
2820 ok(r==S_OK, "Storage_Stat failed with error 0x%08x\n", r);
2821 ok(!strcmp_ww(stat.pwcsName, filename), "expected %s, got %s\n",
2822 wine_dbgstr_w(filename), wine_dbgstr_w(stat.pwcsName));
2823 CoTaskMemFree(stat.pwcsName);
2824
2825 IStorage_Release( stg );
2826
2827 SetCurrentDirectoryA(prev_dir);
2828
2829 DeleteFileA(filenameA);
2830 }
2831
2832 static void test_substorage_enum(void)
2833 {
2834 IStorage *stg, *stg2;
2835 IEnumSTATSTG *ee;
2836 HRESULT r;
2837 ULONG ref;
2838 static const WCHAR stgname[] = { 'P','E','R','M','S','T','G',0 };
2839
2840 DeleteFileA(filenameA);
2841
2842 /* create the file */
2843 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
2844 STGM_READWRITE, 0, &stg);
2845 ok(r==S_OK, "StgCreateDocfile failed\n");
2846
2847 /* create a substorage */
2848 r = IStorage_CreateStorage(stg, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg2);
2849 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
2850
2851 /* create an enumelements */
2852 r = IStorage_EnumElements(stg2, 0, NULL, 0, &ee);
2853 ok(r==S_OK, "IStorage->EnumElements failed, hr=%08x\n", r);
2854
2855 /* release the substorage */
2856 ref = IStorage_Release(stg2);
2857 todo_wine ok(ref==0, "storage not released\n");
2858
2859 /* reopening fails, because the substorage is really still open */
2860 r = IStorage_OpenStorage(stg, stgname, NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg2);
2861 ok(r==STG_E_ACCESSDENIED, "IStorage->OpenStorage failed, hr=%08x\n", r);
2862
2863 /* destroying the storage invalidates the enumerator */
2864 r = IStorage_DestroyElement(stg, stgname);
2865 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
2866
2867 r = IEnumSTATSTG_Reset(ee);
2868 ok(r==STG_E_REVERTED, "IEnumSTATSTG->Reset failed, hr=%08x\n", r);
2869
2870 IEnumSTATSTG_Release(ee);
2871
2872 IStorage_Release(stg);
2873
2874 r = DeleteFileA(filenameA);
2875 ok( r == TRUE, "deleted file\n");
2876 }
2877
2878 static void test_copyto_locking(void)
2879 {
2880 IStorage *stg, *stg2, *stg3, *stg4;
2881 IStream *stm;
2882 HRESULT r;
2883 static const WCHAR stgname[] = { 'S','T','G','1',0 };
2884 static const WCHAR stgname2[] = { 'S','T','G','2',0 };
2885 static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 };
2886
2887 DeleteFileA(filenameA);
2888
2889 /* create the file */
2890 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
2891 STGM_READWRITE, 0, &stg);
2892 ok(r==S_OK, "StgCreateDocfile failed\n");
2893
2894 /* create a substorage */
2895 r = IStorage_CreateStorage(stg, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg2);
2896 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
2897
2898 /* create another substorage */
2899 r = IStorage_CreateStorage(stg, stgname2, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg3);
2900 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
2901
2902 /* add a stream, and leave it open */
2903 r = IStorage_CreateStream(stg2, stmname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm);
2904 ok(r==S_OK, "IStorage->CreateStream failed, hr=%08x\n", r);
2905
2906 /* Try to copy the storage while the stream is open */
2907 r = IStorage_CopyTo(stg2, 0, NULL, NULL, stg3);
2908 ok(r==S_OK, "IStorage->CopyTo failed, hr=%08x\n", r);
2909
2910 IStream_Release(stm);
2911
2912 /* create a substorage */
2913 r = IStorage_CreateStorage(stg2, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg4);
2914 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
2915
2916 /* Try to copy the storage while the substorage is open */
2917 r = IStorage_CopyTo(stg2, 0, NULL, NULL, stg3);
2918 ok(r==S_OK, "IStorage->CopyTo failed, hr=%08x\n", r);
2919
2920 IStorage_Release(stg4);
2921 IStorage_Release(stg3);
2922 IStorage_Release(stg2);
2923 IStorage_Release(stg);
2924
2925 r = DeleteFileA(filenameA);
2926 ok( r == TRUE, "deleted file\n");
2927 }
2928
2929 static void test_copyto_recursive(void)
2930 {
2931 IStorage *stg, *stg2, *stg3, *stg4;
2932 HRESULT r;
2933 static const WCHAR stgname[] = { 'S','T','G','1',0 };
2934 static const WCHAR stgname2[] = { 'S','T','G','2',0 };
2935
2936 DeleteFileA(filenameA);
2937
2938 /* create the file */
2939 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
2940 STGM_READWRITE, 0, &stg);
2941 ok(r==S_OK, "StgCreateDocfile failed\n");
2942
2943 /* create a substorage */
2944 r = IStorage_CreateStorage(stg, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg2);
2945 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
2946
2947 /* copy the parent to the child */
2948 r = IStorage_CopyTo(stg, 0, NULL, NULL, stg2);
2949 ok(r==STG_E_ACCESSDENIED, "IStorage->CopyTo failed, hr=%08x\n", r);
2950
2951 /* create a transacted substorage */
2952 r = IStorage_CreateStorage(stg, stgname2, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_TRANSACTED, 0, 0, &stg3);
2953 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
2954
2955 /* copy the parent to the transacted child */
2956 r = IStorage_CopyTo(stg, 0, NULL, NULL, stg2);
2957 ok(r==STG_E_ACCESSDENIED, "IStorage->CopyTo failed, hr=%08x\n", r);
2958
2959 /* create a transacted subsubstorage */
2960 r = IStorage_CreateStorage(stg3, stgname2, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_TRANSACTED, 0, 0, &stg4);
2961 ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
2962
2963 /* copy the parent to the transacted child of the transacted child */
2964 r = IStorage_CopyTo(stg, 0, NULL, NULL, stg4);
2965 ok(r==STG_E_ACCESSDENIED, "IStorage->CopyTo failed, hr=%08x\n", r);
2966
2967 /* copy the parent but exclude storage objects */
2968 r = IStorage_CopyTo(stg, 1, &IID_IStorage, NULL, stg4);
2969 ok(r==S_OK, "IStorage->CopyTo failed, hr=%08x\n", r);
2970
2971 IStorage_Release(stg4);
2972 IStorage_Release(stg3);
2973 IStorage_Release(stg2);
2974 IStorage_Release(stg);
2975
2976 r = DeleteFileA(filenameA);
2977 ok( r == TRUE, "deleted file\n");
2978 }
2979
2980 static void test_hglobal_storage_creation(void)
2981 {
2982 ILockBytes *ilb = NULL;
2983 IStorage *stg = NULL;
2984 HRESULT r;
2985 STATSTG stat;
2986 char junk[512];
2987 ULARGE_INTEGER offset;
2988
2989 r = CreateILockBytesOnHGlobal(NULL, TRUE, &ilb);
2990 ok(r == S_OK, "CreateILockBytesOnHGlobal failed, hr=%x\n", r);
2991
2992 offset.QuadPart = 0;
2993 memset(junk, 0xaa, 512);
2994 r = ILockBytes_WriteAt(ilb, offset, junk, 512, NULL);
2995 ok(r == S_OK, "ILockBytes_WriteAt failed, hr=%x\n", r);
2996
2997 offset.QuadPart = 2000;
2998 r = ILockBytes_WriteAt(ilb, offset, junk, 512, NULL);
2999 ok(r == S_OK, "ILockBytes_WriteAt failed, hr=%x\n", r);
3000
3001 r = StgCreateDocfileOnILockBytes(ilb, STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stg);
3002 ok(r == S_OK, "StgCreateDocfileOnILockBytes failed, hr=%x\n", r);
3003
3004 IStorage_Release(stg);
3005
3006 r = StgOpenStorageOnILockBytes(ilb, NULL, STGM_READ|STGM_SHARE_EXCLUSIVE,
3007 NULL, 0, &stg);
3008 ok(r == S_OK, "StgOpenStorageOnILockBytes failed, hr=%x\n", r);
3009
3010 if (SUCCEEDED(r))
3011 {
3012 r = IStorage_Stat(stg, &stat, STATFLAG_NONAME);
3013 ok(r == S_OK, "StgOpenStorageOnILockBytes failed, hr=%x\n", r);
3014 ok(IsEqualCLSID(&stat.clsid, &GUID_NULL), "unexpected CLSID value\n");
3015
3016 IStorage_Release(stg);
3017 }
3018
3019 r = ILockBytes_Stat(ilb, &stat, STATFLAG_NONAME);
3020 ok(r == S_OK, "ILockBytes_Stat failed, hr=%x\n", r);
3021 ok(stat.cbSize.u.LowPart < 2512, "expected truncated size, got %d\n", stat.cbSize.u.LowPart);
3022
3023 ILockBytes_Release(ilb);
3024 }
3025
3026 static void test_convert(void)
3027 {
3028 static const WCHAR filename[] = {'s','t','o','r','a','g','e','.','s','t','g',0};
3029 IStorage *stg;
3030 HRESULT hr;
3031
3032 hr = GetConvertStg(NULL);
3033 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3034
3035 hr = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &stg);
3036 ok(hr == S_OK, "StgCreateDocfile failed\n");
3037 hr = GetConvertStg(stg);
3038 ok(hr == STG_E_FILENOTFOUND, "got 0x%08x\n", hr);
3039 hr = SetConvertStg(stg, TRUE);
3040 ok(hr == S_OK, "got 0x%08x\n", hr);
3041 hr = SetConvertStg(stg, TRUE);
3042 ok(hr == S_OK, "got 0x%08x\n", hr);
3043 hr = GetConvertStg(stg);
3044 ok(hr == S_OK, "got 0x%08x\n", hr);
3045 hr = SetConvertStg(stg, FALSE);
3046 ok(hr == S_OK, "got 0x%08x\n", hr);
3047 hr = GetConvertStg(stg);
3048 ok(hr == S_FALSE, "got 0x%08x\n", hr);
3049
3050 IStorage_Release(stg);
3051
3052 DeleteFileW(filename);
3053 }
3054
3055 static void test_direct_swmr(void)
3056 {
3057 static const WCHAR fileW[] = {'w','i','n','e','t','e','s','t',0};
3058 IDirectWriterLock *dwlock;
3059 ULONG ref, ref2;
3060 IStorage *stg;
3061 HRESULT hr;
3062
3063 /* it's possible to create in writer mode */
3064 hr = StgCreateDocfile(fileW, STGM_CREATE | STGM_READWRITE | STGM_SHARE_DENY_WRITE | STGM_DIRECT_SWMR, 0, &stg);
3065 todo_wine
3066 ok(hr == S_OK, "got %08x\n", hr);
3067 if (hr == S_OK) {
3068 IStorage_Release(stg);
3069 DeleteFileW(fileW);
3070 }
3071
3072 hr = StgCreateDocfile(fileW, STGM_CREATE | STGM_READWRITE | STGM_SHARE_DENY_WRITE | STGM_TRANSACTED, 0, &stg);
3073 ok(hr == S_OK, "got %08x\n", hr);
3074 IStorage_Release(stg);
3075
3076 /* reader mode */
3077 hr = StgOpenStorage(fileW, NULL, STGM_DIRECT_SWMR | STGM_READ | STGM_SHARE_DENY_NONE, NULL, 0, &stg);
3078 ok(hr == S_OK || broken(hr == STG_E_INVALIDFLAG), "got %08x\n", hr);
3079 if(hr == S_OK)
3080 {
3081 hr = IStorage_QueryInterface(stg, &IID_IDirectWriterLock, (void**)&dwlock);
3082 ok(hr == E_NOINTERFACE, "got %08x\n", hr);
3083 IStorage_Release(stg);
3084 }
3085
3086 /* writer mode */
3087 hr = StgOpenStorage(fileW, NULL, STGM_DIRECT_SWMR | STGM_READWRITE | STGM_SHARE_DENY_WRITE, NULL, 0, &stg);
3088 ok(hr == S_OK, "got %08x\n", hr);
3089
3090 ref = IStorage_AddRef(stg);
3091 IStorage_Release(stg);
3092
3093 hr = IStorage_QueryInterface(stg, &IID_IDirectWriterLock, (void**)&dwlock);
3094 ok(hr == S_OK, "got %08x\n", hr);
3095
3096 ref2 = IStorage_AddRef(stg);
3097 IStorage_Release(stg);
3098 ok(ref2 == ref + 1, "got %u\n", ref2);
3099
3100 IDirectWriterLock_Release(dwlock);
3101 IStorage_Release(stg);
3102
3103 DeleteFileW(fileW);
3104 }
3105
3106 START_TEST(storage32)
3107 {
3108 CHAR temp[MAX_PATH];
3109
3110 GetTempPathA(MAX_PATH, temp);
3111 if(!GetTempFileNameA(temp, "stg", 0, filenameA))
3112 {
3113 win_skip("Could not create temp file, %u\n", GetLastError());
3114 return;
3115 }
3116 MultiByteToWideChar(CP_ACP, 0, filenameA, -1, filename, MAX_PATH);
3117 DeleteFileA(filenameA);
3118
3119 test_hglobal_storage_stat();
3120 test_create_storage_modes();
3121 test_stgcreatestorageex();
3122 test_storage_stream();
3123 test_open_storage();
3124 test_storage_suminfo();
3125 test_storage_refcount();
3126 test_streamenum();
3127 test_transact();
3128 test_substorage_share();
3129 test_revert();
3130 test_parent_free();
3131 test_nonroot_transacted();
3132 test_ReadClassStm();
3133 test_access();
3134 test_writeclassstg();
3135 test_readonly();
3136 test_simple();
3137 test_fmtusertypestg();
3138 test_references();
3139 test_copyto();
3140 test_copyto_snbexclusions();
3141 test_copyto_iidexclusions_storage();
3142 test_copyto_iidexclusions_stream();
3143 test_rename();
3144 test_toplevel_stat();
3145 test_substorage_enum();
3146 test_copyto_locking();
3147 test_copyto_recursive();
3148 test_hglobal_storage_creation();
3149 test_convert();
3150 test_direct_swmr();
3151 }