[OLE32_WINETEST]
[reactos.git] / rostests / winetests / ole32 / storage32.c
1 /*
2 * Unit tests for OLE storage
3 *
4 * Copyright (c) 2004 Mike McCormack
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21 #define WIN32_NO_STATUS
22 #define _INC_WINDOWS
23 #define COM_NO_WINDOWS_H
24
25 //#include <stdio.h>
26
27 #define COBJMACROS
28
29 //#include <windows.h>
30 #include <wine/test.h>
31 #include <winnls.h>
32 #include <ole2.h>
33 //#include "objidl.h"
34 #include <initguid.h>
35
36 DEFINE_GUID( test_stg_cls, 0x88888888, 0x0425, 0x0000, 0,0,0,0,0,0,0,0);
37
38 #define ok_ole_success(hr, func) ok(hr == S_OK, func " failed with error 0x%08x\n", hr)
39
40 static CHAR filenameA[MAX_PATH];
41 static WCHAR filename[MAX_PATH];
42
43 static const char file1_nameA[] = {'c','o','p','y','t','e','s','t','A',0};
44 static const WCHAR file1_name[] = {'c','o','p','y','t','e','s','t','A',0};
45 static const char file2_nameA[] = {'c','o','p','y','t','e','s','t','B',0};
46 static const WCHAR file2_name[] = {'c','o','p','y','t','e','s','t','B',0};
47 static const WCHAR stgA_name[] = {'S','t','o','r','a','g','e','A',0};
48 static const WCHAR stgB_name[] = {'S','t','o','r','a','g','e','B',0};
49 static const WCHAR strmA_name[] = {'S','t','r','e','a','m','A',0};
50 static const WCHAR strmB_name[] = {'S','t','r','e','a','m','B',0};
51 static const WCHAR strmC_name[] = {'S','t','r','e','a','m','C',0};
52
53 /* Win9x and WinMe don't have lstrcmpW */
54 static int strcmp_ww(LPCWSTR strw1, LPCWSTR strw2)
55 {
56 CHAR stra1[512], stra2[512];
57 WideCharToMultiByte(CP_ACP, 0, strw1, -1, stra1, sizeof(stra1), NULL, NULL);
58 WideCharToMultiByte(CP_ACP, 0, strw2, -1, stra2, sizeof(stra2), NULL, NULL);
59 return lstrcmpA(stra1, stra2);
60 }
61
62 static void test_hglobal_storage_stat(void)
63 {
64 ILockBytes *ilb = NULL;
65 IStorage *stg = NULL;
66 HRESULT r;
67 STATSTG stat;
68 DWORD mode, refcount;
69
70 r = CreateILockBytesOnHGlobal( NULL, TRUE, &ilb );
71 ok( r == S_OK, "CreateILockBytesOnHGlobal failed\n");
72
73 r = StgIsStorageILockBytes( ilb );
74 ok( r == S_FALSE, "StgIsStorageILockBytes should have failed\n");
75
76 mode = STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE;/*0x1012*/
77 r = StgCreateDocfileOnILockBytes( ilb, mode, 0, &stg );
78 ok( r == S_OK, "StgCreateDocfileOnILockBytes failed\n");
79
80 r = WriteClassStg( stg, &test_stg_cls );
81 ok( r == S_OK, "WriteClassStg failed\n");
82
83 r = StgIsStorageILockBytes( ilb );
84 ok( r == S_OK, "StgIsStorageILockBytes failed\n");
85
86 memset( &stat, 0, sizeof stat );
87 r = IStorage_Stat( stg, &stat, 0 );
88
89 ok( stat.pwcsName == NULL, "storage name not null\n");
90 ok( stat.type == 1, "type is wrong\n");
91 ok( stat.grfMode == 0x12, "grf mode is incorrect\n");
92 ok( !memcmp(&stat.clsid, &test_stg_cls, sizeof test_stg_cls), "CLSID is wrong\n");
93
94 refcount = IStorage_Release( stg );
95 ok( refcount == 0, "IStorage refcount is wrong\n");
96 refcount = ILockBytes_Release( ilb );
97 ok( refcount == 0, "ILockBytes refcount is wrong\n");
98 }
99
100 static void test_create_storage_modes(void)
101 {
102 IStorage *stg = NULL;
103 HRESULT r;
104
105 DeleteFileA(filenameA);
106
107 /* test with some invalid parameters */
108 r = StgCreateDocfile( NULL, 0, 0, &stg);
109 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
110 r = StgCreateDocfile( filename, 0, 0, &stg);
111 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
112 r = StgCreateDocfile( filename, STGM_CREATE, 0, &stg);
113 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
114 r = StgCreateDocfile( filename, STGM_CREATE | STGM_READWRITE, 0, &stg);
115 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
116 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE, 0, &stg);
117 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
118 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, NULL);
119 ok(r==STG_E_INVALIDPOINTER, "StgCreateDocfile succeeded\n");
120 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 1, &stg);
121 ok(r==STG_E_INVALIDPARAMETER, "StgCreateDocfile succeeded\n");
122 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_DENY_WRITE | STGM_READWRITE, 0, &stg);
123 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
124 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READ, 0, &stg);
125 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
126 r = StgCreateDocfile( filename, STGM_PRIORITY, 0, &stg);
127 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
128
129 /* StgCreateDocfile seems to be very particular about the flags it accepts */
130 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED | STGM_WRITE, 0, &stg);
131 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
132 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED | 8, 0, &stg);
133 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
134 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED | 0x80, 0, &stg);
135 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
136 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED | 0x800, 0, &stg);
137 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
138 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED | 0x8000, 0, &stg);
139 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
140 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED | 0x80000, 0, &stg);
141 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
142 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED | 0x800000, 0, &stg);
143 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
144 ok(stg == NULL, "stg was set\n");
145
146 /* check what happens if the file already exists (which is how it's meant to be used) */
147 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &stg);
148 ok(r==S_OK, "StgCreateDocfile failed\n");
149 r = IStorage_Release(stg);
150 ok(r == 0, "storage not released\n");
151 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
152 ok(r==STG_E_FILEALREADYEXISTS, "StgCreateDocfile wrong error\n"); /* FAILIFTHERE is default */
153 r = StgCreateDocfile( filename, STGM_READ, 0, &stg);
154 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n"); /* need at least readmode and sharemode */
155 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE, 0, &stg);
156 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
157 r = StgCreateDocfile( filename, STGM_SHARE_DENY_WRITE, 0, &stg);
158 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
159 r = StgCreateDocfile( filename, STGM_SHARE_DENY_NONE, 0, &stg);
160 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile failed\n");
161 r = StgCreateDocfile( filename, STGM_SHARE_DENY_NONE | STGM_TRANSACTED, 0, &stg);
162 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile failed\n");
163 r = StgCreateDocfile( filename, STGM_SHARE_DENY_NONE | STGM_READWRITE, 0, &stg);
164 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile failed\n");
165 r = StgCreateDocfile( filename, STGM_SHARE_DENY_NONE | STGM_WRITE, 0, &stg);
166 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile failed\n");
167 r = StgCreateDocfile( filename, STGM_SHARE_DENY_WRITE | STGM_WRITE, 0, &stg);
168 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile failed\n");
169 r = StgCreateDocfile( filename, STGM_SHARE_DENY_WRITE | STGM_READ, 0, &stg);
170 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile wrong error\n");
171 r = StgCreateDocfile( filename, STGM_TRANSACTED | STGM_SHARE_DENY_WRITE | STGM_READ, 0, &stg);
172 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile wrong error\n");
173 ok(DeleteFileA(filenameA), "failed to delete file\n");
174
175 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
176 ok(r==S_OK, "StgCreateDocfile failed\n");
177 r = IStorage_Release(stg);
178 ok(r == 0, "storage not released\n");
179 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED |STGM_FAILIFTHERE, 0, &stg);
180 ok(r==STG_E_FILEALREADYEXISTS, "StgCreateDocfile wrong error\n");
181 r = StgCreateDocfile( filename, STGM_SHARE_EXCLUSIVE | STGM_WRITE, 0, &stg);
182 ok(r==STG_E_FILEALREADYEXISTS, "StgCreateDocfile wrong error\n");
183
184 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_DENY_WRITE | STGM_READWRITE, 0, &stg);
185 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
186 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
187 ok(r==S_OK, "StgCreateDocfile failed\n");
188 r = IStorage_Release(stg);
189 ok(r == 0, "storage not released\n");
190 ok(DeleteFileA(filenameA), "failed to delete file\n");
191
192 r = StgCreateDocfile( filename, STGM_CREATE | STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
193 ok(r==S_OK, "StgCreateDocfile failed\n");
194 r = IStorage_Release(stg);
195 ok(r == 0, "storage not released\n");
196 ok(DeleteFileA(filenameA), "failed to delete file\n");
197
198 /* test the way excel uses StgCreateDocFile */
199 r = StgCreateDocfile( filename, STGM_TRANSACTED|STGM_CREATE|STGM_SHARE_DENY_WRITE|STGM_READWRITE, 0, &stg);
200 ok(r==S_OK, "StgCreateDocfile the excel way failed\n");
201 if(r == S_OK)
202 {
203 r = IStorage_Release(stg);
204 ok(r == 0, "storage not released\n");
205 ok(DeleteFileA(filenameA), "failed to delete file\n");
206 }
207
208 /* and the way windows media uses it ... */
209 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_DENY_NONE | STGM_READWRITE | STGM_TRANSACTED, 0, &stg);
210 ok(r==S_OK, "StgCreateDocfile the windows media way failed\n");
211 if (r == S_OK)
212 {
213 r = IStorage_Release(stg);
214 ok(r == 0, "storage not released\n");
215 ok(DeleteFileA(filenameA), "failed to delete file\n");
216 }
217
218 /* looks like we need STGM_TRANSACTED or STGM_CREATE */
219 r = StgCreateDocfile( filename, STGM_TRANSACTED|STGM_SHARE_DENY_WRITE|STGM_READWRITE, 0, &stg);
220 ok(r==S_OK, "StgCreateDocfile the excel way failed\n");
221 if(r == S_OK)
222 {
223 r = IStorage_Release(stg);
224 ok(r == 0, "storage not released\n");
225 ok(DeleteFileA(filenameA), "failed to delete file\n");
226 }
227
228 r = StgCreateDocfile( filename, STGM_TRANSACTED|STGM_CREATE|STGM_SHARE_DENY_WRITE|STGM_WRITE, 0, &stg);
229 ok(r==S_OK, "StgCreateDocfile the excel way failed\n");
230 if(r == S_OK)
231 {
232 r = IStorage_Release(stg);
233 ok(r == 0, "storage not released\n");
234 ok(DeleteFileA(filenameA), "failed to delete file\n");
235 }
236
237 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &stg);
238 ok(r==S_OK, "StgCreateDocfile the powerpoint way failed\n");
239 if(r == S_OK)
240 {
241 r = IStorage_Release(stg);
242 ok(r == 0, "storage not released\n");
243 ok(DeleteFileA(filenameA), "failed to delete file\n");
244 }
245
246 /* test the way msi uses StgCreateDocfile */
247 r = StgCreateDocfile( filename, STGM_DIRECT | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &stg);
248 ok(r==S_OK, "StgCreateDocFile failed\n");
249 r = IStorage_Release(stg);
250 ok(r == 0, "storage not released\n");
251 ok(DeleteFileA(filenameA), "failed to delete file\n");
252 }
253
254 static void test_stgcreatestorageex(void)
255 {
256 HRESULT (WINAPI *pStgCreateStorageEx)(const WCHAR* pwcsName, DWORD grfMode, DWORD stgfmt, DWORD grfAttrs, STGOPTIONS* pStgOptions, void* reserved, REFIID riid, void** ppObjectOpen);
257 HMODULE hOle32 = GetModuleHandleA("ole32");
258 IStorage *stg = NULL;
259 STGOPTIONS stgoptions = {1, 0, 4096};
260 HRESULT r;
261
262 pStgCreateStorageEx = (void *) GetProcAddress(hOle32, "StgCreateStorageEx");
263 if (!pStgCreateStorageEx)
264 {
265 win_skip("skipping test on NT4\n");
266 return;
267 }
268
269 DeleteFileA(filenameA);
270
271 /* Verify that StgCreateStorageEx can accept an options param */
272 r = pStgCreateStorageEx( filename,
273 STGM_SHARE_EXCLUSIVE | STGM_READWRITE,
274 STGFMT_DOCFILE,
275 0,
276 &stgoptions,
277 NULL,
278 &IID_IStorage,
279 (void **) &stg);
280 ok(r==S_OK || r==STG_E_UNIMPLEMENTEDFUNCTION, "StgCreateStorageEx with options failed\n");
281 if (r==STG_E_UNIMPLEMENTEDFUNCTION)
282 {
283 /* We're on win98 which means all bets are off. Let's get out of here. */
284 win_skip("skipping test on win9x\n");
285 return;
286 }
287
288 r = IStorage_Release(stg);
289 ok(r == 0, "storage not released\n");
290 ok(DeleteFileA(filenameA), "failed to delete file\n");
291
292 /* Verify that StgCreateStorageEx can accept a NULL pStgOptions */
293 r = pStgCreateStorageEx( filename,
294 STGM_SHARE_EXCLUSIVE | STGM_READWRITE,
295 STGFMT_STORAGE,
296 0,
297 NULL,
298 NULL,
299 &IID_IStorage,
300 (void **) &stg);
301 ok(r==S_OK, "StgCreateStorageEx with NULL options failed\n");
302 r = IStorage_Release(stg);
303 ok(r == 0, "storage not released\n");
304 ok(DeleteFileA(filenameA), "failed to delete file\n");
305 }
306
307 static void test_storage_stream(void)
308 {
309 static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 };
310 static const WCHAR longname[] = {
311 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
312 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',0
313 };
314 IStorage *stg = NULL;
315 HRESULT r;
316 IStream *stm = NULL;
317 IStream *stm2 = NULL;
318 ULONG count = 0;
319 LARGE_INTEGER pos;
320 ULARGE_INTEGER p;
321 unsigned char buffer[0x100];
322 IUnknown *unk;
323
324 DeleteFileA(filenameA);
325
326 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
327 ok(r==S_OK, "StgCreateDocfile failed\n");
328
329 /* try create some invalid streams */
330 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 1, 0, &stm );
331 ok(r==STG_E_INVALIDPARAMETER, "IStorage->CreateStream wrong error\n");
332 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 1, &stm );
333 ok(r==STG_E_INVALIDPARAMETER, "IStorage->CreateStream wrong error\n");
334 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, NULL );
335 ok(r==STG_E_INVALIDPOINTER, "IStorage->CreateStream wrong error\n");
336 r = IStorage_CreateStream(stg, NULL, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
337 ok(r==STG_E_INVALIDNAME, "IStorage->CreateStream wrong error\n");
338 r = IStorage_CreateStream(stg, longname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
339 ok(r==STG_E_INVALIDNAME || broken(r==S_OK) /* nt4 */,
340 "IStorage->CreateStream wrong error, got %d GetLastError()=%d\n", r, GetLastError());
341 r = IStorage_CreateStream(stg, stmname, STGM_READWRITE, 0, 0, &stm );
342 ok(r==STG_E_INVALIDFLAG, "IStorage->CreateStream wrong error\n");
343 r = IStorage_CreateStream(stg, stmname, STGM_READ, 0, 0, &stm );
344 ok(r==STG_E_INVALIDFLAG, "IStorage->CreateStream wrong error\n");
345 r = IStorage_CreateStream(stg, stmname, STGM_WRITE, 0, 0, &stm );
346 ok(r==STG_E_INVALIDFLAG, "IStorage->CreateStream wrong error\n");
347 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_DENY_NONE | STGM_READWRITE, 0, 0, &stm );
348 ok(r==STG_E_INVALIDFLAG, "IStorage->CreateStream wrong error\n");
349 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_DENY_NONE | STGM_READ, 0, 0, &stm );
350 ok(r==STG_E_INVALIDFLAG, "IStorage->CreateStream wrong error\n");
351
352 /* now really create a stream and delete it */
353 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
354 ok(r==S_OK, "IStorage->CreateStream failed\n");
355
356 /* test for support interfaces */
357 r = IStream_QueryInterface(stm, &IID_IPersist, (void**)&unk);
358 ok(r==E_NOINTERFACE, "got 0x%08x\n", r);
359 r = IStream_QueryInterface(stm, &IID_IPersistStream, (void**)&unk);
360 ok(r==E_NOINTERFACE, "got 0x%08x\n", r);
361
362 r = IStream_Release(stm);
363 ok(r == 0, "wrong ref count\n");
364 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
365 ok(r==STG_E_FILEALREADYEXISTS, "IStorage->CreateStream failed\n");
366 r = IStorage_DestroyElement(stg,stmname);
367 ok(r==S_OK, "IStorage->DestroyElement failed\n");
368
369 /* create a stream and write to it */
370 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
371 ok(r==S_OK, "IStorage->CreateStream failed\n");
372
373 r = IStream_Clone(stm, &stm2);
374 ok(r==S_OK, "failed to clone stream\n");
375
376 r = IStream_Write(stm, NULL, 0, NULL );
377 ok(r==STG_E_INVALIDPOINTER, "IStream->Write wrong error\n");
378 r = IStream_Write(stm, "Hello\n", 0, NULL );
379 ok(r==S_OK, "failed to write stream\n");
380 r = IStream_Write(stm, "Hello\n", 0, &count );
381 ok(r==S_OK, "failed to write stream\n");
382 r = IStream_Write(stm, "Hello\n", 6, &count );
383 ok(r==S_OK, "failed to write stream\n");
384 r = IStream_Commit(stm, STGC_DEFAULT );
385 ok(r==S_OK, "failed to commit stream\n");
386 r = IStream_Commit(stm, STGC_DEFAULT );
387 ok(r==S_OK, "failed to commit stream\n");
388
389 /* Read past the end of the stream. */
390 pos.QuadPart = 3;
391 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p );
392 ok(r==S_OK, "failed to seek stream\n");
393 ok(p.QuadPart == 3, "at wrong place\n");
394 r = IStream_Read(stm, buffer, sizeof buffer, &count );
395 ok(r==S_OK, "failed to read\n");
396 ok(count == 3, "read bytes past end of stream\n");
397 pos.QuadPart = 10;
398 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p );
399 ok(r==S_OK, "failed to seek stream\n");
400 ok(p.QuadPart == 10, "at wrong place\n");
401 r = IStream_Read(stm, buffer, sizeof buffer, &count );
402 ok(r==S_OK, "failed to read\n");
403 ok(count == 0, "read bytes past end of stream\n");
404 pos.QuadPart = 10000;
405 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p );
406 ok(r==S_OK, "failed to seek stream\n");
407 ok(p.QuadPart == 10000, "at wrong place\n");
408 r = IStream_Read(stm, buffer, sizeof buffer, &count );
409 ok(r==S_OK, "failed to read\n");
410 ok(count == 0, "read bytes past end of stream\n");
411
412 /* Convert to a big block stream, and read past the end. */
413 p.QuadPart = 5000;
414 r = IStream_SetSize(stm,p);
415 ok(r==S_OK, "failed to set pos\n");
416 pos.QuadPart = 4997;
417 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p );
418 ok(r==S_OK, "failed to seek stream\n");
419 ok(p.QuadPart == 4997, "at wrong place\n");
420 r = IStream_Read(stm, buffer, sizeof buffer, &count );
421 ok(r==S_OK, "failed to read\n");
422 ok(count == 3, "read bytes past end of stream\n");
423 pos.QuadPart = 5001;
424 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p );
425 ok(r==S_OK, "failed to seek stream\n");
426 ok(p.QuadPart == 5001, "at wrong place\n");
427 r = IStream_Read(stm, buffer, sizeof buffer, &count );
428 ok(r==S_OK, "failed to read\n");
429 ok(count == 0, "read bytes past end of stream\n");
430 pos.QuadPart = 10000;
431 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p );
432 ok(r==S_OK, "failed to seek stream\n");
433 ok(p.QuadPart == 10000, "at wrong place\n");
434 r = IStream_Read(stm, buffer, sizeof buffer, &count );
435 ok(r==S_OK, "failed to read\n");
436 ok(count == 0, "read bytes past end of stream\n");
437
438 /* seek round a bit, reset the stream size */
439 pos.QuadPart = 0;
440 r = IStream_Seek(stm, pos, 3, &p );
441 ok(r==STG_E_INVALIDFUNCTION, "IStream->Seek returned wrong error\n");
442 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, NULL);
443 ok(r==S_OK, "failed to seek stream\n");
444 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p );
445 ok(r==S_OK, "failed to seek stream\n");
446 r = IStream_SetSize(stm,p);
447 ok(r==S_OK, "failed to set pos\n");
448 pos.QuadPart = 10;
449 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p );
450 ok(r==S_OK, "failed to seek stream\n");
451 ok(p.QuadPart == 10, "at wrong place\n");
452 r = IStream_Read(stm, buffer, sizeof buffer, &count );
453 ok(r==S_OK, "failed to set pos\n");
454 ok(count == 0, "read bytes from empty stream\n");
455 pos.QuadPart = 10000;
456 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p );
457 ok(r==S_OK, "failed to seek stream\n");
458 ok(p.QuadPart == 10000, "at wrong place\n");
459 r = IStream_Read(stm, buffer, sizeof buffer, &count );
460 ok(r==S_OK, "failed to set pos\n");
461 ok(count == 0, "read bytes from empty stream\n");
462 pos.QuadPart = 0;
463 r = IStream_Seek(stm, pos, STREAM_SEEK_END, &p );
464 ok(r==S_OK, "failed to seek stream\n");
465 ok(p.QuadPart == 0, "at wrong place\n");
466 r = IStream_Read(stm, buffer, sizeof buffer, &count );
467 ok(r==S_OK, "failed to set pos\n");
468 ok(count == 0, "read bytes from empty stream\n");
469
470 /* wrap up */
471 r = IStream_Release(stm2);
472 ok(r == 0, "wrong ref count\n");
473
474 /* create a stream and write to it */
475 r = IStorage_CreateStream(stg, stmname, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm2 );
476 ok(r==S_OK, "IStorage->CreateStream failed\n");
477
478 r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p);
479 ok(r==STG_E_REVERTED, "overwritten stream should return STG_E_REVERTED instead of 0x%08x\n", r);
480
481 r = IStream_Release(stm2);
482 ok(r == 0, "wrong ref count\n");
483 r = IStream_Release(stm);
484 ok(r == 0, "wrong ref count\n");
485
486 r = IStorage_Release(stg);
487 ok(r == 0, "wrong ref count\n");
488
489 /* try create some invalid streams */
490 stg = NULL;
491 stm = NULL;
492 r = StgOpenStorage(filename, NULL, STGM_READ | STGM_SHARE_DENY_WRITE, NULL, 0, &stg);
493 ok(r == S_OK, "should succeed\n");
494 if (stg)
495 {
496 r = IStorage_OpenStream(stg, stmname, NULL, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &stm);
497 ok(r == STG_E_INVALIDFLAG, "IStorage->OpenStream should return STG_E_INVALIDFLAG instead of 0x%08x\n", r);
498 IStorage_Release(stg);
499 }
500
501 r = DeleteFileA(filenameA);
502 ok(r, "file should exist\n");
503 }
504
505 static BOOL touch_file(LPCSTR filename)
506 {
507 HANDLE file;
508
509 file = CreateFileA(filename, GENERIC_READ|GENERIC_WRITE, 0, NULL,
510 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
511 if (file==INVALID_HANDLE_VALUE)
512 return FALSE;
513 CloseHandle(file);
514 return TRUE;
515 }
516
517 static BOOL is_zero_length(LPCSTR filename)
518 {
519 HANDLE file;
520 DWORD len;
521
522 file = CreateFileA(filename, GENERIC_READ, 0, NULL,
523 OPEN_EXISTING, 0, NULL);
524 if (file==INVALID_HANDLE_VALUE)
525 return FALSE;
526 len = GetFileSize(file, NULL);
527 CloseHandle(file);
528 return len == 0;
529 }
530
531 static BOOL is_existing_file(LPCSTR filename)
532 {
533 HANDLE file;
534
535 file = CreateFileA(filename, GENERIC_READ, 0, NULL,
536 OPEN_EXISTING, 0, NULL);
537 if (file==INVALID_HANDLE_VALUE)
538 return FALSE;
539 CloseHandle(file);
540 return TRUE;
541 }
542
543 static void test_open_storage(void)
544 {
545 static const WCHAR szNonExist[] = { 'n','o','n','e','x','i','s','t',0 };
546 IStorage *stg = NULL, *stg2 = NULL;
547 HRESULT r;
548 DWORD stgm;
549
550 /* try opening a zero length file - it should stay zero length */
551 DeleteFileA(filenameA);
552 touch_file(filenameA);
553 stgm = STGM_NOSCRATCH | STGM_TRANSACTED | STGM_SHARE_DENY_WRITE | STGM_READWRITE;
554 r = StgOpenStorage( filename, NULL, stgm, NULL, 0, &stg);
555 ok(r==STG_E_FILEALREADYEXISTS, "StgOpenStorage didn't fail\n");
556
557 stgm = STGM_SHARE_EXCLUSIVE | STGM_READWRITE;
558 r = StgOpenStorage( filename, NULL, stgm, NULL, 0, &stg);
559 ok(r==STG_E_FILEALREADYEXISTS, "StgOpenStorage didn't fail\n");
560 ok(is_zero_length(filenameA), "file length changed\n");
561
562 DeleteFileA(filenameA);
563
564 /* try opening a nonexistent file - it should not create it */
565 stgm = STGM_DIRECT | STGM_SHARE_EXCLUSIVE | STGM_READWRITE;
566 r = StgOpenStorage( filename, NULL, stgm, NULL, 0, &stg);
567 ok(r!=S_OK, "StgOpenStorage failed: 0x%08x\n", r);
568 if (r==S_OK) IStorage_Release(stg);
569 ok(!is_existing_file(filenameA), "StgOpenStorage should not create a file\n");
570 DeleteFileA(filenameA);
571
572 /* create the file */
573 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
574 ok(r==S_OK, "StgCreateDocfile failed\n");
575 IStorage_Release(stg);
576
577 r = StgOpenStorage( filename, NULL, 0, NULL, 0, &stg);
578 ok(r==STG_E_INVALIDFLAG, "StgOpenStorage wrong error\n");
579 r = StgOpenStorage( NULL, NULL, STGM_SHARE_EXCLUSIVE, NULL, 0, &stg);
580 ok(r==STG_E_INVALIDNAME, "StgOpenStorage wrong error\n");
581 r = StgOpenStorage( filename, NULL, STGM_SHARE_EXCLUSIVE | STGM_READ, NULL, 0, NULL);
582 ok(r==STG_E_INVALIDPOINTER, "StgOpenStorage wrong error\n");
583 r = StgOpenStorage( filename, NULL, STGM_SHARE_EXCLUSIVE | STGM_READ, NULL, 1, &stg);
584 ok(r==STG_E_INVALIDPARAMETER, "StgOpenStorage wrong error\n");
585 r = StgOpenStorage( szNonExist, NULL, STGM_SHARE_EXCLUSIVE | STGM_READ, NULL, 0, &stg);
586 ok(r==STG_E_FILENOTFOUND, "StgOpenStorage failed\n");
587 r = StgOpenStorage( filename, NULL, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READ, NULL, 0, &stg);
588 ok(r==STG_E_INVALIDFLAG, "StgOpenStorage failed\n");
589 r = StgOpenStorage( filename, NULL, STGM_SHARE_DENY_NONE | STGM_READ, NULL, 0, &stg);
590 ok(r==STG_E_INVALIDFLAG, "StgOpenStorage failed\n");
591 r = StgOpenStorage( filename, NULL, STGM_SHARE_DENY_READ | STGM_READ, NULL, 0, &stg);
592 ok(r==STG_E_INVALIDFLAG, "StgOpenStorage failed\n");
593 r = StgOpenStorage( filename, NULL, STGM_SHARE_DENY_WRITE | STGM_READWRITE, NULL, 0, &stg);
594 ok(r==STG_E_INVALIDFLAG, "StgOpenStorage failed\n");
595
596 /* open it for real */
597 r = StgOpenStorage( filename, NULL, STGM_SHARE_DENY_NONE | STGM_READ | STGM_TRANSACTED, NULL, 0, &stg); /* XLViewer 97/2000 */
598 ok(r==S_OK, "StgOpenStorage failed\n");
599 if(stg)
600 {
601 r = IStorage_Release(stg);
602 ok(r == 0, "wrong ref count\n");
603 }
604
605 r = StgOpenStorage( filename, NULL, STGM_SHARE_DENY_WRITE | STGM_READ, NULL, 0, &stg);
606 ok(r==S_OK, "StgOpenStorage failed\n");
607 if(stg)
608 {
609 r = IStorage_Release(stg);
610 ok(r == 0, "wrong ref count\n");
611 }
612
613 /* test the way word opens its custom dictionary */
614 r = StgOpenStorage( filename, NULL, STGM_NOSCRATCH | STGM_TRANSACTED |
615 STGM_SHARE_DENY_WRITE | STGM_READWRITE, NULL, 0, &stg);
616 ok(r==S_OK, "StgOpenStorage failed\n");
617 if(stg)
618 {
619 r = IStorage_Release(stg);
620 ok(r == 0, "wrong ref count\n");
621 }
622
623 r = StgOpenStorage( filename, NULL, STGM_SHARE_EXCLUSIVE | STGM_READ, NULL, 0, &stg);
624 ok(r==S_OK, "StgOpenStorage failed\n");
625 r = StgOpenStorage( filename, NULL, STGM_SHARE_EXCLUSIVE | STGM_READ, NULL, 0, &stg2);
626 ok(r==STG_E_SHAREVIOLATION, "StgOpenStorage failed\n");
627 if(stg)
628 {
629 r = IStorage_Release(stg);
630 ok(r == 0, "wrong ref count\n");
631 }
632
633 /* now try write to a storage file we opened read-only */
634 r = StgOpenStorage( filename, NULL, STGM_SHARE_EXCLUSIVE | STGM_READ, NULL, 0, &stg);
635 ok(r==S_OK, "StgOpenStorage failed\n");
636 if(stg)
637 {
638 static const WCHAR stmname[] = { 'w','i','n','e','t','e','s','t',0};
639 IStream *stm = NULL;
640 IStorage *stg2 = NULL;
641
642 r = IStorage_CreateStream( stg, stmname, STGM_WRITE | STGM_SHARE_EXCLUSIVE,
643 0, 0, &stm );
644 ok(r == STG_E_ACCESSDENIED, "CreateStream should fail\n");
645 r = IStorage_CreateStorage( stg, stmname, STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg2);
646 ok(r == STG_E_ACCESSDENIED, "CreateStream should fail\n");
647
648 r = IStorage_Release(stg);
649 ok(r == 0, "wrong ref count\n");
650 }
651
652 /* open like visio 2003 */
653 stg = NULL;
654 r = StgOpenStorage( filename, NULL, STGM_PRIORITY | STGM_SHARE_DENY_NONE, NULL, 0, &stg);
655 ok(r == S_OK, "should succeed\n");
656 if (stg)
657 IStorage_Release(stg);
658
659 /* test other sharing modes with STGM_PRIORITY */
660 stg = NULL;
661 r = StgOpenStorage( filename, NULL, STGM_PRIORITY | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg);
662 ok(r == S_OK, "should succeed\n");
663 if (stg)
664 IStorage_Release(stg);
665
666 stg = NULL;
667 r = StgOpenStorage( filename, NULL, STGM_PRIORITY | STGM_SHARE_DENY_WRITE, NULL, 0, &stg);
668 ok(r == S_OK, "should succeed\n");
669 if (stg)
670 IStorage_Release(stg);
671
672 stg = NULL;
673 r = StgOpenStorage( filename, NULL, STGM_PRIORITY | STGM_SHARE_DENY_READ, NULL, 0, &stg);
674 ok(r == S_OK, "should succeed\n");
675 if (stg)
676 IStorage_Release(stg);
677
678 /* open like Project 2003 */
679 stg = NULL;
680 r = StgOpenStorage( filename, NULL, STGM_PRIORITY, NULL, 0, &stg);
681 ok(r == S_OK, "should succeed\n");
682 r = StgOpenStorage( filename, NULL, STGM_PRIORITY, NULL, 0, &stg2);
683 ok(r == S_OK, "should succeed\n");
684 if (stg2)
685 IStorage_Release(stg2);
686 if (stg)
687 IStorage_Release(stg);
688
689 stg = NULL;
690 r = StgOpenStorage( filename, NULL, STGM_PRIORITY | STGM_READWRITE, NULL, 0, &stg);
691 ok(r == STG_E_INVALIDFLAG, "should fail\n");
692
693 r = StgOpenStorage( filename, NULL, STGM_TRANSACTED | STGM_PRIORITY, NULL, 0, &stg);
694 ok(r == STG_E_INVALIDFLAG, "should fail\n");
695
696 r = StgOpenStorage( filename, NULL, STGM_SIMPLE | STGM_PRIORITY, NULL, 0, &stg);
697 ok(r == STG_E_INVALIDFLAG, "should fail\n");
698
699 r = StgOpenStorage( filename, NULL, STGM_DELETEONRELEASE | STGM_PRIORITY, NULL, 0, &stg);
700 ok(r == STG_E_INVALIDFUNCTION, "should fail\n");
701
702 r = StgOpenStorage( filename, NULL, STGM_NOSCRATCH | STGM_PRIORITY, NULL, 0, &stg);
703 ok(r == STG_E_INVALIDFLAG, "should fail\n");
704
705 r = StgOpenStorage( filename, NULL, STGM_NOSNAPSHOT | STGM_PRIORITY, NULL, 0, &stg);
706 ok(r == STG_E_INVALIDFLAG, "should fail\n");
707
708 r = DeleteFileA(filenameA);
709 ok(r, "file didn't exist\n");
710 }
711
712 static void test_storage_suminfo(void)
713 {
714 IStorage *stg = NULL;
715 IPropertySetStorage *propset = NULL;
716 IPropertyStorage *ps = NULL;
717 HRESULT r;
718
719 DeleteFileA(filenameA);
720
721 /* create the file */
722 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
723 STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
724 ok(r==S_OK, "StgCreateDocfile failed\n");
725
726 r = IStorage_QueryInterface( stg, &IID_IPropertySetStorage, (LPVOID) &propset );
727 ok(r == S_OK, "query interface failed\n");
728
729 /* delete it */
730 r = IPropertySetStorage_Delete( propset, &FMTID_SummaryInformation );
731 ok(r == STG_E_FILENOTFOUND, "deleted property set storage\n");
732
733 r = IPropertySetStorage_Open( propset, &FMTID_SummaryInformation,
734 STGM_READ | STGM_SHARE_EXCLUSIVE, &ps );
735 ok(r == STG_E_FILENOTFOUND, "opened property set storage\n");
736
737 r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0,
738 STGM_READ | STGM_SHARE_EXCLUSIVE, &ps );
739 ok(r == STG_E_INVALIDFLAG, "created property set storage\n");
740
741 r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0,
742 STGM_READ, &ps );
743 ok(r == STG_E_INVALIDFLAG, "created property set storage\n");
744
745 r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0, 0, &ps );
746 ok(r == STG_E_INVALIDFLAG, "created property set storage\n");
747
748 r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0,
749 STGM_WRITE|STGM_SHARE_EXCLUSIVE, &ps );
750 ok(r == STG_E_INVALIDFLAG, "created property set storage\n");
751
752 r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0,
753 STGM_CREATE|STGM_WRITE|STGM_SHARE_EXCLUSIVE, &ps );
754 ok(r == STG_E_INVALIDFLAG, "created property set storage\n");
755
756 /* now try really creating a property set */
757 r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0,
758 STGM_CREATE|STGM_READWRITE|STGM_SHARE_EXCLUSIVE, &ps );
759 ok(r == S_OK, "failed to create property set storage\n");
760
761 if( ps )
762 IPropertyStorage_Release(ps);
763
764 /* now try creating the same thing again */
765 r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0,
766 STGM_CREATE|STGM_READWRITE|STGM_SHARE_EXCLUSIVE, &ps );
767 ok(r == S_OK, "failed to create property set storage\n");
768 if( ps )
769 IPropertyStorage_Release(ps);
770
771 /* should be able to open it */
772 r = IPropertySetStorage_Open( propset, &FMTID_SummaryInformation,
773 STGM_READWRITE|STGM_SHARE_EXCLUSIVE, &ps);
774 ok(r == S_OK, "open failed\n");
775 if(r == S_OK)
776 IPropertyStorage_Release(ps);
777
778 /* delete it */
779 r = IPropertySetStorage_Delete( propset, &FMTID_SummaryInformation );
780 ok(r == S_OK, "failed to delete property set storage\n");
781
782 /* try opening with an invalid FMTID */
783 r = IPropertySetStorage_Open( propset, NULL,
784 STGM_READWRITE|STGM_SHARE_EXCLUSIVE, &ps);
785 ok(r == E_INVALIDARG, "open succeeded\n");
786 if(r == S_OK)
787 IPropertyStorage_Release(ps);
788
789 /* try a bad guid */
790 r = IPropertySetStorage_Open( propset, &IID_IStorage,
791 STGM_READWRITE|STGM_SHARE_EXCLUSIVE, &ps);
792 ok(r == STG_E_FILENOTFOUND, "open succeeded\n");
793 if(r == S_OK)
794 IPropertyStorage_Release(ps);
795
796
797 /* try some invalid flags */
798 r = IPropertySetStorage_Open( propset, &FMTID_SummaryInformation,
799 STGM_CREATE | STGM_READWRITE|STGM_SHARE_EXCLUSIVE, &ps);
800 ok(r == STG_E_INVALIDFLAG, "open succeeded\n");
801 if(r == S_OK)
802 IPropertyStorage_Release(ps);
803
804 /* after deleting it, it should be gone */
805 r = IPropertySetStorage_Open( propset, &FMTID_SummaryInformation,
806 STGM_READWRITE|STGM_SHARE_EXCLUSIVE, &ps);
807 ok(r == STG_E_FILENOTFOUND, "open failed\n");
808 if(r == S_OK)
809 IPropertyStorage_Release(ps);
810
811 r = IPropertySetStorage_Release( propset );
812 ok(r == 1, "ref count wrong\n");
813
814 r = IStorage_Release(stg);
815 ok(r == 0, "ref count wrong\n");
816
817 DeleteFileA(filenameA);
818 }
819
820 static void test_storage_refcount(void)
821 {
822 IStorage *stg = NULL;
823 IStorage *stgprio = NULL;
824 HRESULT r;
825 IStream *stm = NULL;
826 static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 };
827 LARGE_INTEGER pos;
828 ULARGE_INTEGER upos;
829 STATSTG stat;
830 char buffer[10];
831
832 DeleteFileA(filenameA);
833
834 /* create the file */
835 r = StgCreateDocfile( filename, STGM_CREATE | STGM_SHARE_EXCLUSIVE |
836 STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
837 ok(r==S_OK, "StgCreateDocfile failed\n");
838
839 r = WriteClassStg( stg, &test_stg_cls );
840 ok( r == S_OK, "WriteClassStg failed\n");
841
842 r = IStorage_Commit( stg, STGC_DEFAULT );
843 ok( r == S_OK, "IStorage_Commit failed\n");
844
845 /* now create a stream */
846 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
847 ok(r==S_OK, "IStorage->CreateStream failed\n");
848
849 r = IStorage_Release( stg );
850 ok (r == 0, "storage not released\n");
851
852 pos.QuadPart = 0;
853 r = IStream_Seek( stm, pos, 0, &upos );
854 ok (r == STG_E_REVERTED, "seek should fail\n");
855
856 r = IStream_Stat( stm, &stat, STATFLAG_DEFAULT );
857 ok (r == STG_E_REVERTED, "stat should fail\n");
858
859 r = IStream_Write( stm, "Test string", strlen("Test string"), NULL);
860 ok (r == STG_E_REVERTED, "IStream_Write should return STG_E_REVERTED instead of 0x%08x\n", r);
861
862 r = IStream_Read( stm, buffer, sizeof(buffer), NULL);
863 ok (r == STG_E_REVERTED, "IStream_Read should return STG_E_REVERTED instead of 0x%08x\n", r);
864
865 r = IStream_Release(stm);
866 ok (r == 0, "stream not released\n");
867
868 /* tests that STGM_PRIORITY doesn't prevent readwrite access from other
869 * StgOpenStorage calls in transacted mode */
870 r = StgOpenStorage( filename, NULL, STGM_PRIORITY, NULL, 0, &stgprio);
871 ok(r==S_OK, "StgOpenStorage failed with error 0x%08x\n", r);
872
873 todo_wine {
874 /* non-transacted mode read/write fails */
875 r = StgOpenStorage( filename, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg);
876 ok(r==STG_E_LOCKVIOLATION, "StgOpenStorage should return STG_E_LOCKVIOLATION instead of 0x%08x\n", r);
877 }
878
879 /* non-transacted mode read-only succeeds */
880 r = StgOpenStorage( filename, NULL, STGM_SHARE_DENY_WRITE|STGM_READ, NULL, 0, &stg);
881 ok(r==S_OK, "StgOpenStorage failed with error 0x%08x\n", r);
882 IStorage_Release(stg);
883
884 r = StgOpenStorage( filename, NULL, STGM_TRANSACTED|STGM_SHARE_DENY_WRITE|STGM_READWRITE, NULL, 0, &stg);
885 ok(r==S_OK, "StgOpenStorage failed with error 0x%08x\n", r);
886 if(stg)
887 {
888 static const WCHAR stgname[] = { ' ',' ',' ','2','9',0 };
889 static const WCHAR stgname2[] = { 'C','V','_','i','e','w',0 };
890 static const WCHAR stmname2[] = { 'V','a','r','2','D','a','t','a',0 };
891 IStorage *stg2;
892 IStorage *stg3;
893 STATSTG statstg;
894
895 r = IStorage_Stat( stg, &statstg, STATFLAG_NONAME );
896 ok(r == S_OK, "Stat should have succeeded instead of returning 0x%08x\n", r);
897 ok(statstg.type == STGTY_STORAGE, "Statstg type should have been STGTY_STORAGE instead of %d\n", statstg.type);
898 ok(U(statstg.cbSize).LowPart == 0, "Statstg cbSize.LowPart should have been 0 instead of %d\n", U(statstg.cbSize).LowPart);
899 ok(U(statstg.cbSize).HighPart == 0, "Statstg cbSize.HighPart should have been 0 instead of %d\n", U(statstg.cbSize).HighPart);
900 ok(statstg.grfMode == (STGM_TRANSACTED|STGM_SHARE_DENY_WRITE|STGM_READWRITE),
901 "Statstg grfMode should have been 0x10022 instead of 0x%x\n", statstg.grfMode);
902 ok(statstg.grfLocksSupported == 0, "Statstg grfLocksSupported should have been 0 instead of %d\n", statstg.grfLocksSupported);
903 ok(IsEqualCLSID(&statstg.clsid, &test_stg_cls), "Statstg clsid is not test_stg_cls\n");
904 ok(statstg.grfStateBits == 0, "Statstg grfStateBits should have been 0 instead of %d\n", statstg.grfStateBits);
905 ok(statstg.reserved == 0, "Statstg reserved should have been 0 instead of %d\n", statstg.reserved);
906
907 r = IStorage_CreateStorage( stg, stgname, STGM_SHARE_EXCLUSIVE, 0, 0, &stg2 );
908 ok(r == S_OK, "CreateStorage should have succeeded instead of returning 0x%08x\n", r);
909
910 r = IStorage_Stat( stg2, &statstg, STATFLAG_DEFAULT );
911 ok(r == S_OK, "Stat should have succeeded instead of returning 0x%08x\n", r);
912 ok(!memcmp(statstg.pwcsName, stgname, sizeof(stgname)),
913 "Statstg pwcsName should have been the name the storage was created with\n");
914 ok(statstg.type == STGTY_STORAGE, "Statstg type should have been STGTY_STORAGE instead of %d\n", statstg.type);
915 ok(U(statstg.cbSize).LowPart == 0, "Statstg cbSize.LowPart should have been 0 instead of %d\n", U(statstg.cbSize).LowPart);
916 ok(U(statstg.cbSize).HighPart == 0, "Statstg cbSize.HighPart should have been 0 instead of %d\n", U(statstg.cbSize).HighPart);
917 ok(statstg.grfMode == STGM_SHARE_EXCLUSIVE,
918 "Statstg grfMode should have been STGM_SHARE_EXCLUSIVE instead of 0x%x\n", statstg.grfMode);
919 ok(statstg.grfLocksSupported == 0, "Statstg grfLocksSupported should have been 0 instead of %d\n", statstg.grfLocksSupported);
920 ok(IsEqualCLSID(&statstg.clsid, &CLSID_NULL), "Statstg clsid is not CLSID_NULL\n");
921 ok(statstg.grfStateBits == 0, "Statstg grfStateBits should have been 0 instead of %d\n", statstg.grfStateBits);
922 ok(statstg.reserved == 0, "Statstg reserved should have been 0 instead of %d\n", statstg.reserved);
923 CoTaskMemFree(statstg.pwcsName);
924
925 r = IStorage_CreateStorage( stg2, stgname2, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, 0, &stg3 );
926 ok(r == STG_E_ACCESSDENIED, "CreateStorage should have returned STG_E_ACCESSDENIED instead of 0x%08x\n", r);
927
928 r = IStorage_CreateStream( stg2, stmname2, STGM_CREATE|STGM_SHARE_EXCLUSIVE, 0, 0, &stm );
929 ok(r == STG_E_ACCESSDENIED, "CreateStream should have returned STG_E_ACCESSDENIED instead of 0x%08x\n", r);
930
931 IStorage_Release(stg2);
932
933 r = IStorage_Release(stg);
934 ok(r == 0, "wrong ref count\n");
935 }
936
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 START_TEST(storage32)
3150 {
3151 CHAR temp[MAX_PATH];
3152
3153 GetTempPathA(MAX_PATH, temp);
3154 if(!GetTempFileNameA(temp, "stg", 0, filenameA))
3155 {
3156 win_skip("Could not create temp file, %u\n", GetLastError());
3157 return;
3158 }
3159 MultiByteToWideChar(CP_ACP, 0, filenameA, -1, filename, MAX_PATH);
3160 DeleteFileA(filenameA);
3161
3162 test_hglobal_storage_stat();
3163 test_create_storage_modes();
3164 test_stgcreatestorageex();
3165 test_storage_stream();
3166 test_open_storage();
3167 test_storage_suminfo();
3168 test_storage_refcount();
3169 test_streamenum();
3170 test_transact();
3171 test_substorage_share();
3172 test_revert();
3173 test_parent_free();
3174 test_nonroot_transacted();
3175 test_ReadClassStm();
3176 test_access();
3177 test_writeclassstg();
3178 test_readonly();
3179 test_simple();
3180 test_fmtusertypestg();
3181 test_references();
3182 test_copyto();
3183 test_copyto_snbexclusions();
3184 test_copyto_iidexclusions_storage();
3185 test_copyto_iidexclusions_stream();
3186 test_rename();
3187 test_toplevel_stat();
3188 test_substorage_enum();
3189 test_copyto_locking();
3190 test_copyto_recursive();
3191 test_hglobal_storage_creation();
3192 test_convert();
3193 test_direct_swmr();
3194 }