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