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