2 * Unit tests for OLE storage
4 * Copyright (c) 2004 Mike McCormack
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
27 #define NONAMELESSUNION
28 #define NONAMELESSSTRUCT
32 #include "wine/test.h"
38 DEFINE_GUID( test_stg_cls
, 0x88888888, 0x0425, 0x0000, 0,0,0,0,0,0,0,0);
40 #define ok_ole_success(hr, func) ok(hr == S_OK, func " failed with error 0x%08x\n", hr)
42 static CHAR filenameA
[MAX_PATH
];
43 static WCHAR filename
[MAX_PATH
];
45 static const char file1_nameA
[] = {'c','o','p','y','t','e','s','t','A',0};
46 static const WCHAR file1_name
[] = {'c','o','p','y','t','e','s','t','A',0};
47 static const char file2_nameA
[] = {'c','o','p','y','t','e','s','t','B',0};
48 static const WCHAR file2_name
[] = {'c','o','p','y','t','e','s','t','B',0};
49 static const WCHAR stgA_name
[] = {'S','t','o','r','a','g','e','A',0};
50 static const WCHAR stgB_name
[] = {'S','t','o','r','a','g','e','B',0};
51 static const WCHAR strmA_name
[] = {'S','t','r','e','a','m','A',0};
52 static const WCHAR strmB_name
[] = {'S','t','r','e','a','m','B',0};
53 static const WCHAR strmC_name
[] = {'S','t','r','e','a','m','C',0};
55 /* Win9x and WinMe don't have lstrcmpW */
56 static int strcmp_ww(LPCWSTR strw1
, LPCWSTR strw2
)
58 CHAR stra1
[512], stra2
[512];
59 WideCharToMultiByte(CP_ACP
, 0, strw1
, -1, stra1
, sizeof(stra1
), NULL
, NULL
);
60 WideCharToMultiByte(CP_ACP
, 0, strw2
, -1, stra2
, sizeof(stra2
), NULL
, NULL
);
61 return lstrcmpA(stra1
, stra2
);
64 typedef struct TestLockBytes
{
65 ILockBytes ILockBytes_iface
;
71 ULONG locks_supported
;
75 static inline TestLockBytes
*impl_from_ILockBytes(ILockBytes
*iface
)
77 return CONTAINING_RECORD(iface
, TestLockBytes
, ILockBytes_iface
);
80 static HRESULT WINAPI
TestLockBytes_QueryInterface(ILockBytes
*iface
, REFIID iid
,
83 TestLockBytes
*This
= impl_from_ILockBytes(iface
);
85 if (!ppv
) return E_INVALIDARG
;
87 if (IsEqualIID(&IID_IUnknown
, iid
) ||
88 IsEqualIID(&IID_ILockBytes
, iid
))
89 *ppv
= &This
->ILockBytes_iface
;
93 IUnknown_AddRef((IUnknown
*)*ppv
);
97 static ULONG WINAPI
TestLockBytes_AddRef(ILockBytes
*iface
)
99 TestLockBytes
*This
= impl_from_ILockBytes(iface
);
100 ULONG ref
= InterlockedIncrement(&This
->ref
);
104 static ULONG WINAPI
TestLockBytes_Release(ILockBytes
*iface
)
106 TestLockBytes
*This
= impl_from_ILockBytes(iface
);
107 ULONG ref
= InterlockedDecrement(&This
->ref
);
111 static HRESULT WINAPI
TestLockBytes_ReadAt(ILockBytes
*iface
,
112 ULARGE_INTEGER ulOffset
, void *pv
, ULONG cb
, ULONG
*pcbRead
)
114 TestLockBytes
*This
= impl_from_ILockBytes(iface
);
117 if (!pv
) return E_INVALIDARG
;
119 if (!pcbRead
) pcbRead
= &dummy
;
121 if (ulOffset
.QuadPart
>= This
->size
)
127 cb
= min(cb
, This
->size
- ulOffset
.QuadPart
);
130 memcpy(pv
, &This
->contents
[ulOffset
.QuadPart
], cb
);
135 static HRESULT WINAPI
TestLockBytes_WriteAt(ILockBytes
*iface
,
136 ULARGE_INTEGER ulOffset
, const void *pv
, ULONG cb
, ULONG
*pcbWritten
)
138 TestLockBytes
*This
= impl_from_ILockBytes(iface
);
142 if (!pv
) return E_INVALIDARG
;
144 if (!pcbWritten
) pcbWritten
= &dummy
;
146 if (ulOffset
.QuadPart
+ cb
> This
->size
)
148 ULARGE_INTEGER new_size
;
149 new_size
.QuadPart
= ulOffset
.QuadPart
+ cb
;
150 hr
= ILockBytes_SetSize(iface
, new_size
);
151 if (FAILED(hr
)) return hr
;
155 memcpy(&This
->contents
[ulOffset
.QuadPart
], pv
, cb
);
160 static HRESULT WINAPI
TestLockBytes_Flush(ILockBytes
*iface
)
165 static HRESULT WINAPI
TestLockBytes_SetSize(ILockBytes
*iface
,
168 TestLockBytes
*This
= impl_from_ILockBytes(iface
);
170 if (This
->buffer_size
< cb
.QuadPart
)
172 ULONG new_buffer_size
= max(This
->buffer_size
* 2, cb
.QuadPart
);
173 BYTE
* new_buffer
= HeapAlloc(GetProcessHeap(), 0, new_buffer_size
);
174 if (!new_buffer
) return E_OUTOFMEMORY
;
175 memcpy(new_buffer
, This
->contents
, This
->size
);
176 HeapFree(GetProcessHeap(), 0, This
->contents
);
177 This
->contents
= new_buffer
;
180 if (cb
.QuadPart
> This
->size
)
181 memset(&This
->contents
[This
->size
], 0, cb
.QuadPart
- This
->size
);
183 This
->size
= cb
.QuadPart
;
188 static HRESULT WINAPI
TestLockBytes_LockRegion(ILockBytes
*iface
,
189 ULARGE_INTEGER libOffset
, ULARGE_INTEGER cb
, DWORD dwLockType
)
191 TestLockBytes
*This
= impl_from_ILockBytes(iface
);
193 return This
->lock_hr
;
196 static HRESULT WINAPI
TestLockBytes_UnlockRegion(ILockBytes
*iface
,
197 ULARGE_INTEGER libOffset
, ULARGE_INTEGER cb
, DWORD dwLockType
)
199 TestLockBytes
*This
= impl_from_ILockBytes(iface
);
200 return This
->lock_hr
;
203 static HRESULT WINAPI
TestLockBytes_Stat(ILockBytes
*iface
,
204 STATSTG
*pstatstg
, DWORD grfStatFlag
)
206 TestLockBytes
*This
= impl_from_ILockBytes(iface
);
207 static const WCHAR dummy_name
[] = {'d','u','m','m','y',0};
209 if (!pstatstg
) return E_INVALIDARG
;
211 memset(pstatstg
, 0, sizeof(STATSTG
));
213 if (!(grfStatFlag
& STATFLAG_NONAME
))
215 pstatstg
->pwcsName
= CoTaskMemAlloc(sizeof(dummy_name
));
216 if (!pstatstg
->pwcsName
) return E_OUTOFMEMORY
;
217 memcpy(pstatstg
->pwcsName
, dummy_name
, sizeof(dummy_name
));
220 pstatstg
->type
= STGTY_LOCKBYTES
;
221 pstatstg
->cbSize
.QuadPart
= This
->size
;
222 pstatstg
->grfLocksSupported
= This
->locks_supported
;
227 static const ILockBytesVtbl TestLockBytes_Vtbl
= {
228 TestLockBytes_QueryInterface
,
229 TestLockBytes_AddRef
,
230 TestLockBytes_Release
,
231 TestLockBytes_ReadAt
,
232 TestLockBytes_WriteAt
,
234 TestLockBytes_SetSize
,
235 TestLockBytes_LockRegion
,
236 TestLockBytes_UnlockRegion
,
240 static void CreateTestLockBytes(TestLockBytes
**This
)
242 *This
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(**This
));
246 (*This
)->ILockBytes_iface
.lpVtbl
= &TestLockBytes_Vtbl
;
251 static void DeleteTestLockBytes(TestLockBytes
*This
)
253 ok(This
->ILockBytes_iface
.lpVtbl
== &TestLockBytes_Vtbl
, "test lock bytes %p deleted with incorrect vtable\n", This
);
254 ok(This
->ref
== 1, "test lock bytes %p deleted with %i references instead of 1\n", This
, This
->ref
);
255 HeapFree(GetProcessHeap(), 0, This
->contents
);
256 HeapFree(GetProcessHeap(), 0, This
);
259 static void test_hglobal_storage_stat(void)
261 ILockBytes
*ilb
= NULL
;
262 IStorage
*stg
= NULL
;
265 DWORD mode
, refcount
;
267 r
= CreateILockBytesOnHGlobal( NULL
, TRUE
, &ilb
);
268 ok( r
== S_OK
, "CreateILockBytesOnHGlobal failed\n");
270 r
= StgIsStorageILockBytes( ilb
);
271 ok( r
== S_FALSE
, "StgIsStorageILockBytes should have failed\n");
273 mode
= STGM_CREATE
|STGM_SHARE_EXCLUSIVE
|STGM_READWRITE
;/*0x1012*/
274 r
= StgCreateDocfileOnILockBytes( ilb
, mode
, 0, &stg
);
275 ok( r
== S_OK
, "StgCreateDocfileOnILockBytes failed\n");
277 r
= WriteClassStg( stg
, &test_stg_cls
);
278 ok( r
== S_OK
, "WriteClassStg failed\n");
280 r
= StgIsStorageILockBytes( ilb
);
281 ok( r
== S_OK
, "StgIsStorageILockBytes failed\n");
283 memset( &stat
, 0, sizeof stat
);
284 r
= IStorage_Stat( stg
, &stat
, 0 );
286 ok( stat
.pwcsName
== NULL
, "storage name not null\n");
287 ok( stat
.type
== 1, "type is wrong\n");
288 ok( stat
.grfMode
== 0x12, "grf mode is incorrect\n");
289 ok( !memcmp(&stat
.clsid
, &test_stg_cls
, sizeof test_stg_cls
), "CLSID is wrong\n");
291 refcount
= IStorage_Release( stg
);
292 ok( refcount
== 0, "IStorage refcount is wrong\n");
293 refcount
= ILockBytes_Release( ilb
);
294 ok( refcount
== 0, "ILockBytes refcount is wrong\n");
297 static void test_create_storage_modes(void)
299 IStorage
*stg
= NULL
;
302 DeleteFileA(filenameA
);
304 /* test with some invalid parameters */
305 r
= StgCreateDocfile( NULL
, 0, 0, &stg
);
306 ok(r
==STG_E_INVALIDFLAG
, "StgCreateDocfile succeeded\n");
307 r
= StgCreateDocfile( filename
, 0, 0, &stg
);
308 ok(r
==STG_E_INVALIDFLAG
, "StgCreateDocfile succeeded\n");
309 r
= StgCreateDocfile( filename
, STGM_CREATE
, 0, &stg
);
310 ok(r
==STG_E_INVALIDFLAG
, "StgCreateDocfile succeeded\n");
311 r
= StgCreateDocfile( filename
, STGM_CREATE
| STGM_READWRITE
, 0, &stg
);
312 ok(r
==STG_E_INVALIDFLAG
, "StgCreateDocfile succeeded\n");
313 r
= StgCreateDocfile( filename
, STGM_CREATE
| STGM_SHARE_EXCLUSIVE
, 0, &stg
);
314 ok(r
==STG_E_INVALIDFLAG
, "StgCreateDocfile succeeded\n");
315 r
= StgCreateDocfile( filename
, STGM_CREATE
| STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
, 0, NULL
);
316 ok(r
==STG_E_INVALIDPOINTER
, "StgCreateDocfile succeeded\n");
317 r
= StgCreateDocfile( filename
, STGM_CREATE
| STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
, 1, &stg
);
318 ok(r
==STG_E_INVALIDPARAMETER
, "StgCreateDocfile succeeded\n");
319 r
= StgCreateDocfile( filename
, STGM_CREATE
| STGM_SHARE_DENY_WRITE
| STGM_READWRITE
, 0, &stg
);
320 ok(r
==STG_E_INVALIDFLAG
, "StgCreateDocfile succeeded\n");
321 r
= StgCreateDocfile( filename
, STGM_SHARE_EXCLUSIVE
| STGM_READ
, 0, &stg
);
322 ok(r
==STG_E_INVALIDFLAG
, "StgCreateDocfile succeeded\n");
323 r
= StgCreateDocfile( filename
, STGM_PRIORITY
, 0, &stg
);
324 ok(r
==STG_E_INVALIDFLAG
, "StgCreateDocfile succeeded\n");
326 /* StgCreateDocfile seems to be very particular about the flags it accepts */
327 r
= StgCreateDocfile( filename
, STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
|STGM_TRANSACTED
| STGM_WRITE
, 0, &stg
);
328 ok(r
==STG_E_INVALIDFLAG
, "StgCreateDocfile succeeded\n");
329 r
= StgCreateDocfile( filename
, STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
|STGM_TRANSACTED
| 8, 0, &stg
);
330 ok(r
==STG_E_INVALIDFLAG
, "StgCreateDocfile succeeded\n");
331 r
= StgCreateDocfile( filename
, STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
|STGM_TRANSACTED
| 0x80, 0, &stg
);
332 ok(r
==STG_E_INVALIDFLAG
, "StgCreateDocfile succeeded\n");
333 r
= StgCreateDocfile( filename
, STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
|STGM_TRANSACTED
| 0x800, 0, &stg
);
334 ok(r
==STG_E_INVALIDFLAG
, "StgCreateDocfile succeeded\n");
335 r
= StgCreateDocfile( filename
, STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
|STGM_TRANSACTED
| 0x8000, 0, &stg
);
336 ok(r
==STG_E_INVALIDFLAG
, "StgCreateDocfile succeeded\n");
337 r
= StgCreateDocfile( filename
, STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
|STGM_TRANSACTED
| 0x80000, 0, &stg
);
338 ok(r
==STG_E_INVALIDFLAG
, "StgCreateDocfile succeeded\n");
339 r
= StgCreateDocfile( filename
, STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
|STGM_TRANSACTED
| 0x800000, 0, &stg
);
340 ok(r
==STG_E_INVALIDFLAG
, "StgCreateDocfile succeeded\n");
341 ok(stg
== NULL
, "stg was set\n");
343 /* check what happens if the file already exists (which is how it's meant to be used) */
344 r
= StgCreateDocfile( filename
, STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
, 0, &stg
);
345 ok(r
==S_OK
, "StgCreateDocfile failed\n");
346 r
= IStorage_Release(stg
);
347 ok(r
== 0, "storage not released\n");
348 r
= StgCreateDocfile( filename
, STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
|STGM_TRANSACTED
, 0, &stg
);
349 ok(r
==STG_E_FILEALREADYEXISTS
, "StgCreateDocfile wrong error\n"); /* FAILIFTHERE is default */
350 r
= StgCreateDocfile( filename
, STGM_READ
, 0, &stg
);
351 ok(r
==STG_E_INVALIDFLAG
, "StgCreateDocfile succeeded\n"); /* need at least readmode and sharemode */
352 r
= StgCreateDocfile( filename
, STGM_SHARE_EXCLUSIVE
, 0, &stg
);
353 ok(r
==STG_E_INVALIDFLAG
, "StgCreateDocfile succeeded\n");
354 r
= StgCreateDocfile( filename
, STGM_SHARE_DENY_WRITE
, 0, &stg
);
355 ok(r
==STG_E_INVALIDFLAG
, "StgCreateDocfile succeeded\n");
356 r
= StgCreateDocfile( filename
, STGM_SHARE_DENY_NONE
, 0, &stg
);
357 ok(r
==STG_E_INVALIDFLAG
, "StgCreateDocfile failed\n");
358 r
= StgCreateDocfile( filename
, STGM_SHARE_DENY_NONE
| STGM_TRANSACTED
, 0, &stg
);
359 ok(r
==STG_E_INVALIDFLAG
, "StgCreateDocfile failed\n");
360 r
= StgCreateDocfile( filename
, STGM_SHARE_DENY_NONE
| STGM_READWRITE
, 0, &stg
);
361 ok(r
==STG_E_INVALIDFLAG
, "StgCreateDocfile failed\n");
362 r
= StgCreateDocfile( filename
, STGM_SHARE_DENY_NONE
| STGM_WRITE
, 0, &stg
);
363 ok(r
==STG_E_INVALIDFLAG
, "StgCreateDocfile failed\n");
364 r
= StgCreateDocfile( filename
, STGM_SHARE_DENY_WRITE
| STGM_WRITE
, 0, &stg
);
365 ok(r
==STG_E_INVALIDFLAG
, "StgCreateDocfile failed\n");
366 r
= StgCreateDocfile( filename
, STGM_SHARE_DENY_WRITE
| STGM_READ
, 0, &stg
);
367 ok(r
==STG_E_INVALIDFLAG
, "StgCreateDocfile wrong error\n");
368 r
= StgCreateDocfile( filename
, STGM_TRANSACTED
| STGM_SHARE_DENY_WRITE
| STGM_READ
, 0, &stg
);
369 ok(r
==STG_E_INVALIDFLAG
, "StgCreateDocfile wrong error\n");
370 ok(DeleteFileA(filenameA
), "failed to delete file\n");
372 r
= StgCreateDocfile( filename
, STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
|STGM_TRANSACTED
, 0, &stg
);
373 ok(r
==S_OK
, "StgCreateDocfile failed\n");
374 r
= IStorage_Release(stg
);
375 ok(r
== 0, "storage not released\n");
376 r
= StgCreateDocfile( filename
, STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
|STGM_TRANSACTED
|STGM_FAILIFTHERE
, 0, &stg
);
377 ok(r
==STG_E_FILEALREADYEXISTS
, "StgCreateDocfile wrong error\n");
378 r
= StgCreateDocfile( filename
, STGM_SHARE_EXCLUSIVE
| STGM_WRITE
, 0, &stg
);
379 ok(r
==STG_E_FILEALREADYEXISTS
, "StgCreateDocfile wrong error\n");
381 r
= StgCreateDocfile( filename
, STGM_CREATE
| STGM_SHARE_DENY_WRITE
| STGM_READWRITE
, 0, &stg
);
382 ok(r
==STG_E_INVALIDFLAG
, "StgCreateDocfile succeeded\n");
383 r
= StgCreateDocfile( filename
, STGM_CREATE
| STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
|STGM_TRANSACTED
, 0, &stg
);
384 ok(r
==S_OK
, "StgCreateDocfile failed\n");
385 r
= IStorage_Release(stg
);
386 ok(r
== 0, "storage not released\n");
387 ok(DeleteFileA(filenameA
), "failed to delete file\n");
389 r
= StgCreateDocfile( filename
, STGM_CREATE
| STGM_READWRITE
|STGM_TRANSACTED
, 0, &stg
);
390 ok(r
==S_OK
, "StgCreateDocfile failed\n");
391 r
= IStorage_Release(stg
);
392 ok(r
== 0, "storage not released\n");
393 ok(DeleteFileA(filenameA
), "failed to delete file\n");
395 /* test the way excel uses StgCreateDocFile */
396 r
= StgCreateDocfile( filename
, STGM_TRANSACTED
|STGM_CREATE
|STGM_SHARE_DENY_WRITE
|STGM_READWRITE
, 0, &stg
);
397 ok(r
==S_OK
, "StgCreateDocfile the excel way failed\n");
400 r
= IStorage_Release(stg
);
401 ok(r
== 0, "storage not released\n");
402 ok(DeleteFileA(filenameA
), "failed to delete file\n");
405 /* and the way windows media uses it ... */
406 r
= StgCreateDocfile( filename
, STGM_CREATE
| STGM_SHARE_DENY_NONE
| STGM_READWRITE
| STGM_TRANSACTED
, 0, &stg
);
407 ok(r
==S_OK
, "StgCreateDocfile the windows media way failed\n");
410 r
= IStorage_Release(stg
);
411 ok(r
== 0, "storage not released\n");
412 ok(DeleteFileA(filenameA
), "failed to delete file\n");
415 /* looks like we need STGM_TRANSACTED or STGM_CREATE */
416 r
= StgCreateDocfile( filename
, STGM_TRANSACTED
|STGM_SHARE_DENY_WRITE
|STGM_READWRITE
, 0, &stg
);
417 ok(r
==S_OK
, "StgCreateDocfile the excel way failed\n");
420 r
= IStorage_Release(stg
);
421 ok(r
== 0, "storage not released\n");
422 ok(DeleteFileA(filenameA
), "failed to delete file\n");
425 r
= StgCreateDocfile( filename
, STGM_TRANSACTED
|STGM_CREATE
|STGM_SHARE_DENY_WRITE
|STGM_WRITE
, 0, &stg
);
426 ok(r
==S_OK
, "StgCreateDocfile the excel way failed\n");
429 r
= IStorage_Release(stg
);
430 ok(r
== 0, "storage not released\n");
431 ok(DeleteFileA(filenameA
), "failed to delete file\n");
434 r
= StgCreateDocfile( filename
, STGM_CREATE
| STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
, 0, &stg
);
435 ok(r
==S_OK
, "StgCreateDocfile the powerpoint way failed\n");
438 r
= IStorage_Release(stg
);
439 ok(r
== 0, "storage not released\n");
440 ok(DeleteFileA(filenameA
), "failed to delete file\n");
443 /* test the way msi uses StgCreateDocfile */
444 r
= StgCreateDocfile( filename
, STGM_DIRECT
| STGM_READWRITE
| STGM_SHARE_EXCLUSIVE
, 0, &stg
);
445 ok(r
==S_OK
, "StgCreateDocFile failed\n");
446 r
= IStorage_Release(stg
);
447 ok(r
== 0, "storage not released\n");
448 ok(DeleteFileA(filenameA
), "failed to delete file\n");
451 static void test_stgcreatestorageex(void)
453 HRESULT (WINAPI
*pStgCreateStorageEx
)(const WCHAR
* pwcsName
, DWORD grfMode
, DWORD stgfmt
, DWORD grfAttrs
, STGOPTIONS
* pStgOptions
, void* reserved
, REFIID riid
, void** ppObjectOpen
);
454 HMODULE hOle32
= GetModuleHandleA("ole32");
455 IStorage
*stg
= NULL
;
456 STGOPTIONS stgoptions
= {1, 0, 4096};
459 pStgCreateStorageEx
= (void *) GetProcAddress(hOle32
, "StgCreateStorageEx");
460 if (!pStgCreateStorageEx
)
462 win_skip("skipping test on NT4\n");
466 DeleteFileA(filenameA
);
468 /* Verify that StgCreateStorageEx can accept an options param */
469 r
= pStgCreateStorageEx( filename
,
470 STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
,
477 ok(r
==S_OK
|| r
==STG_E_UNIMPLEMENTEDFUNCTION
, "StgCreateStorageEx with options failed\n");
478 if (r
==STG_E_UNIMPLEMENTEDFUNCTION
)
480 /* We're on win98 which means all bets are off. Let's get out of here. */
481 win_skip("skipping test on win9x\n");
485 r
= IStorage_Release(stg
);
486 ok(r
== 0, "storage not released\n");
487 ok(DeleteFileA(filenameA
), "failed to delete file\n");
489 /* Verify that StgCreateStorageEx can accept a NULL pStgOptions */
490 r
= pStgCreateStorageEx( filename
,
491 STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
,
498 ok(r
==S_OK
, "StgCreateStorageEx with NULL options failed\n");
499 r
= IStorage_Release(stg
);
500 ok(r
== 0, "storage not released\n");
501 ok(DeleteFileA(filenameA
), "failed to delete file\n");
504 static void test_storage_stream(void)
506 static const WCHAR stmname
[] = { 'C','O','N','T','E','N','T','S',0 };
507 static const WCHAR longname
[] = {
508 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
509 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',0
511 IStorage
*stg
= NULL
;
514 IStream
*stm2
= NULL
;
518 unsigned char buffer
[0x100];
522 DeleteFileA(filenameA
);
524 r
= StgCreateDocfile( filename
, STGM_CREATE
| STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
|STGM_TRANSACTED
, 0, &stg
);
525 ok(r
==S_OK
, "StgCreateDocfile failed\n");
527 /* try create some invalid streams */
528 r
= IStorage_CreateStream(stg
, stmname
, STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
, 1, 0, &stm
);
529 ok(r
==STG_E_INVALIDPARAMETER
, "IStorage->CreateStream wrong error\n");
530 r
= IStorage_CreateStream(stg
, stmname
, STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
, 0, 1, &stm
);
531 ok(r
==STG_E_INVALIDPARAMETER
, "IStorage->CreateStream wrong error\n");
532 r
= IStorage_CreateStream(stg
, stmname
, STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
, 0, 0, NULL
);
533 ok(r
==STG_E_INVALIDPOINTER
, "IStorage->CreateStream wrong error\n");
534 r
= IStorage_CreateStream(stg
, NULL
, STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
, 0, 0, &stm
);
535 ok(r
==STG_E_INVALIDNAME
, "IStorage->CreateStream wrong error\n");
536 r
= IStorage_CreateStream(stg
, longname
, STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
, 0, 0, &stm
);
537 ok(r
==STG_E_INVALIDNAME
|| broken(r
==S_OK
) /* nt4 */,
538 "IStorage->CreateStream wrong error, got %d GetLastError()=%d\n", r
, GetLastError());
539 r
= IStorage_CreateStream(stg
, stmname
, STGM_READWRITE
, 0, 0, &stm
);
540 ok(r
==STG_E_INVALIDFLAG
, "IStorage->CreateStream wrong error\n");
541 r
= IStorage_CreateStream(stg
, stmname
, STGM_READ
, 0, 0, &stm
);
542 ok(r
==STG_E_INVALIDFLAG
, "IStorage->CreateStream wrong error\n");
543 r
= IStorage_CreateStream(stg
, stmname
, STGM_WRITE
, 0, 0, &stm
);
544 ok(r
==STG_E_INVALIDFLAG
, "IStorage->CreateStream wrong error\n");
545 r
= IStorage_CreateStream(stg
, stmname
, STGM_SHARE_DENY_NONE
| STGM_READWRITE
, 0, 0, &stm
);
546 ok(r
==STG_E_INVALIDFLAG
, "IStorage->CreateStream wrong error\n");
547 r
= IStorage_CreateStream(stg
, stmname
, STGM_SHARE_DENY_NONE
| STGM_READ
, 0, 0, &stm
);
548 ok(r
==STG_E_INVALIDFLAG
, "IStorage->CreateStream wrong error\n");
550 /* now really create a stream and delete it */
551 r
= IStorage_CreateStream(stg
, stmname
, STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
, 0, 0, &stm
);
552 ok(r
==S_OK
, "IStorage->CreateStream failed\n");
554 /* test for support interfaces */
555 r
= IStream_QueryInterface(stm
, &IID_IPersist
, (void**)&unk
);
556 ok(r
==E_NOINTERFACE
, "got 0x%08x\n", r
);
557 r
= IStream_QueryInterface(stm
, &IID_IPersistStream
, (void**)&unk
);
558 ok(r
==E_NOINTERFACE
, "got 0x%08x\n", r
);
560 r
= IStream_Release(stm
);
561 ok(r
== 0, "wrong ref count\n");
562 r
= IStorage_CreateStream(stg
, stmname
, STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
, 0, 0, &stm
);
563 ok(r
==STG_E_FILEALREADYEXISTS
, "IStorage->CreateStream failed\n");
564 r
= IStorage_DestroyElement(stg
,stmname
);
565 ok(r
==S_OK
, "IStorage->DestroyElement failed\n");
567 /* create a stream and write to it */
568 r
= IStorage_CreateStream(stg
, stmname
, STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
, 0, 0, &stm
);
569 ok(r
==S_OK
, "IStorage->CreateStream failed\n");
571 r
= IStream_Clone(stm
, &stm2
);
572 ok(r
==S_OK
, "failed to clone stream\n");
574 r
= IStream_Write(stm
, NULL
, 0, NULL
);
575 ok(r
==STG_E_INVALIDPOINTER
, "IStream->Write wrong error\n");
576 r
= IStream_Write(stm
, "Hello\n", 0, NULL
);
577 ok(r
==S_OK
, "failed to write stream\n");
578 r
= IStream_Write(stm
, "Hello\n", 0, &count
);
579 ok(r
==S_OK
, "failed to write stream\n");
580 r
= IStream_Write(stm
, "Hello\n", 6, &count
);
581 ok(r
==S_OK
, "failed to write stream\n");
582 r
= IStream_Commit(stm
, STGC_DEFAULT
);
583 ok(r
==S_OK
, "failed to commit stream\n");
584 r
= IStream_Commit(stm
, STGC_DEFAULT
);
585 ok(r
==S_OK
, "failed to commit stream\n");
587 /* Read past the end of the stream. */
589 r
= IStream_Seek(stm
, pos
, STREAM_SEEK_SET
, &p
);
590 ok(r
==S_OK
, "failed to seek stream\n");
591 ok(p
.QuadPart
== 3, "at wrong place\n");
592 r
= IStream_Read(stm
, buffer
, sizeof buffer
, &count
);
593 ok(r
==S_OK
, "failed to read\n");
594 ok(count
== 3, "read bytes past end of stream\n");
596 r
= IStream_Seek(stm
, pos
, STREAM_SEEK_SET
, &p
);
597 ok(r
==S_OK
, "failed to seek stream\n");
598 ok(p
.QuadPart
== 10, "at wrong place\n");
599 r
= IStream_Read(stm
, buffer
, sizeof buffer
, &count
);
600 ok(r
==S_OK
, "failed to read\n");
601 ok(count
== 0, "read bytes past end of stream\n");
602 pos
.QuadPart
= 10000;
603 r
= IStream_Seek(stm
, pos
, STREAM_SEEK_SET
, &p
);
604 ok(r
==S_OK
, "failed to seek stream\n");
605 ok(p
.QuadPart
== 10000, "at wrong place\n");
606 r
= IStream_Read(stm
, buffer
, sizeof buffer
, &count
);
607 ok(r
==S_OK
, "failed to read\n");
608 ok(count
== 0, "read bytes past end of stream\n");
610 /* Convert to a big block stream, and read past the end. */
612 r
= IStream_SetSize(stm
,p
);
613 ok(r
==S_OK
, "failed to set pos\n");
615 r
= IStream_Seek(stm
, pos
, STREAM_SEEK_SET
, &p
);
616 ok(r
==S_OK
, "failed to seek stream\n");
617 ok(p
.QuadPart
== 4997, "at wrong place\n");
618 r
= IStream_Read(stm
, buffer
, sizeof buffer
, &count
);
619 ok(r
==S_OK
, "failed to read\n");
620 ok(count
== 3, "read bytes past end of stream\n");
622 r
= IStream_Seek(stm
, pos
, STREAM_SEEK_SET
, &p
);
623 ok(r
==S_OK
, "failed to seek stream\n");
624 ok(p
.QuadPart
== 5001, "at wrong place\n");
625 r
= IStream_Read(stm
, buffer
, sizeof buffer
, &count
);
626 ok(r
==S_OK
, "failed to read\n");
627 ok(count
== 0, "read bytes past end of stream\n");
628 pos
.QuadPart
= 10000;
629 r
= IStream_Seek(stm
, pos
, STREAM_SEEK_SET
, &p
);
630 ok(r
==S_OK
, "failed to seek stream\n");
631 ok(p
.QuadPart
== 10000, "at wrong place\n");
632 r
= IStream_Read(stm
, buffer
, sizeof buffer
, &count
);
633 ok(r
==S_OK
, "failed to read\n");
634 ok(count
== 0, "read bytes past end of stream\n");
636 /* seek round a bit, reset the stream size */
638 r
= IStream_Seek(stm
, pos
, 3, &p
);
639 ok(r
==STG_E_INVALIDFUNCTION
, "IStream->Seek returned wrong error\n");
640 r
= IStream_Seek(stm
, pos
, STREAM_SEEK_SET
, NULL
);
641 ok(r
==S_OK
, "failed to seek stream\n");
642 r
= IStream_Seek(stm
, pos
, STREAM_SEEK_SET
, &p
);
643 ok(r
==S_OK
, "failed to seek stream\n");
644 r
= IStream_SetSize(stm
,p
);
645 ok(r
==S_OK
, "failed to set pos\n");
647 r
= IStream_Seek(stm
, pos
, STREAM_SEEK_SET
, &p
);
648 ok(r
==S_OK
, "failed to seek stream\n");
649 ok(p
.QuadPart
== 10, "at wrong place\n");
650 r
= IStream_Read(stm
, buffer
, sizeof buffer
, &count
);
651 ok(r
==S_OK
, "failed to set pos\n");
652 ok(count
== 0, "read bytes from empty stream\n");
653 pos
.QuadPart
= 10000;
654 r
= IStream_Seek(stm
, pos
, STREAM_SEEK_SET
, &p
);
655 ok(r
==S_OK
, "failed to seek stream\n");
656 ok(p
.QuadPart
== 10000, "at wrong place\n");
657 r
= IStream_Read(stm
, buffer
, sizeof buffer
, &count
);
658 ok(r
==S_OK
, "failed to set pos\n");
659 ok(count
== 0, "read bytes from empty stream\n");
661 r
= IStream_Seek(stm
, pos
, STREAM_SEEK_END
, &p
);
662 ok(r
==S_OK
, "failed to seek stream\n");
663 ok(p
.QuadPart
== 0, "at wrong place\n");
664 r
= IStream_Read(stm
, buffer
, sizeof buffer
, &count
);
665 ok(r
==S_OK
, "failed to set pos\n");
666 ok(count
== 0, "read bytes from empty stream\n");
669 r
= IStream_Release(stm2
);
670 ok(r
== 0, "wrong ref count\n");
672 /* create a stream and write to it */
673 r
= IStorage_CreateStream(stg
, stmname
, STGM_CREATE
| STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
, 0, 0, &stm2
);
674 ok(r
==S_OK
, "IStorage->CreateStream failed\n");
676 r
= IStream_Seek(stm
, pos
, STREAM_SEEK_SET
, &p
);
677 ok(r
==STG_E_REVERTED
, "overwritten stream should return STG_E_REVERTED instead of 0x%08x\n", r
);
679 r
= IStream_Release(stm2
);
680 ok(r
== 0, "wrong ref count\n");
681 r
= IStream_Release(stm
);
682 ok(r
== 0, "wrong ref count\n");
684 r
= IStorage_Release(stg
);
685 ok(r
== 0, "wrong ref count\n");
687 /* try create some invalid streams */
690 r
= StgOpenStorage(filename
, NULL
, STGM_READ
| STGM_SHARE_DENY_WRITE
, NULL
, 0, &stg
);
691 ok(r
== S_OK
, "should succeed\n");
694 r
= IStorage_OpenStream(stg
, stmname
, NULL
, STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
, 0, &stm
);
695 ok(r
== STG_E_INVALIDFLAG
, "IStorage->OpenStream should return STG_E_INVALIDFLAG instead of 0x%08x\n", r
);
696 IStorage_Release(stg
);
699 ret
= DeleteFileA(filenameA
);
700 ok(ret
, "file should exist\n");
703 static BOOL
touch_file(LPCSTR filename
)
707 file
= CreateFileA(filename
, GENERIC_READ
|GENERIC_WRITE
, 0, NULL
,
708 CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
709 if (file
==INVALID_HANDLE_VALUE
)
715 static BOOL
is_zero_length(LPCSTR filename
)
720 file
= CreateFileA(filename
, GENERIC_READ
, 0, NULL
,
721 OPEN_EXISTING
, 0, NULL
);
722 if (file
==INVALID_HANDLE_VALUE
)
724 len
= GetFileSize(file
, NULL
);
729 static BOOL
is_existing_file(LPCSTR filename
)
733 file
= CreateFileA(filename
, GENERIC_READ
, 0, NULL
,
734 OPEN_EXISTING
, 0, NULL
);
735 if (file
==INVALID_HANDLE_VALUE
)
741 static void test_open_storage(void)
743 static const WCHAR szNonExist
[] = { 'n','o','n','e','x','i','s','t',0 };
744 IStorage
*stg
= NULL
, *stg2
= NULL
;
749 /* try opening a zero length file - it should stay zero length */
750 DeleteFileA(filenameA
);
751 touch_file(filenameA
);
752 stgm
= STGM_NOSCRATCH
| STGM_TRANSACTED
| STGM_SHARE_DENY_WRITE
| STGM_READWRITE
;
753 r
= StgOpenStorage( filename
, NULL
, stgm
, NULL
, 0, &stg
);
754 ok(r
==STG_E_FILEALREADYEXISTS
, "StgOpenStorage didn't fail\n");
756 stgm
= STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
;
757 r
= StgOpenStorage( filename
, NULL
, stgm
, NULL
, 0, &stg
);
758 ok(r
==STG_E_FILEALREADYEXISTS
, "StgOpenStorage didn't fail\n");
759 ok(is_zero_length(filenameA
), "file length changed\n");
761 DeleteFileA(filenameA
);
763 /* try opening a nonexistent file - it should not create it */
764 stgm
= STGM_DIRECT
| STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
;
765 r
= StgOpenStorage( filename
, NULL
, stgm
, NULL
, 0, &stg
);
766 ok(r
!=S_OK
, "StgOpenStorage failed: 0x%08x\n", r
);
767 if (r
==S_OK
) IStorage_Release(stg
);
768 ok(!is_existing_file(filenameA
), "StgOpenStorage should not create a file\n");
769 DeleteFileA(filenameA
);
771 /* create the file */
772 r
= StgCreateDocfile( filename
, STGM_CREATE
| STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
|STGM_TRANSACTED
, 0, &stg
);
773 ok(r
==S_OK
, "StgCreateDocfile failed\n");
774 IStorage_Release(stg
);
776 r
= StgOpenStorage( filename
, NULL
, 0, NULL
, 0, &stg
);
777 ok(r
==STG_E_INVALIDFLAG
, "StgOpenStorage wrong error\n");
778 r
= StgOpenStorage( NULL
, NULL
, STGM_SHARE_EXCLUSIVE
, NULL
, 0, &stg
);
779 ok(r
==STG_E_INVALIDNAME
, "StgOpenStorage wrong error\n");
780 r
= StgOpenStorage( filename
, NULL
, STGM_SHARE_EXCLUSIVE
| STGM_READ
, NULL
, 0, NULL
);
781 ok(r
==STG_E_INVALIDPOINTER
, "StgOpenStorage wrong error\n");
782 r
= StgOpenStorage( filename
, NULL
, STGM_SHARE_EXCLUSIVE
| STGM_READ
, NULL
, 1, &stg
);
783 ok(r
==STG_E_INVALIDPARAMETER
, "StgOpenStorage wrong error\n");
784 r
= StgOpenStorage( szNonExist
, NULL
, STGM_SHARE_EXCLUSIVE
| STGM_READ
, NULL
, 0, &stg
);
785 ok(r
==STG_E_FILENOTFOUND
, "StgOpenStorage failed\n");
786 r
= StgOpenStorage( filename
, NULL
, STGM_CREATE
| STGM_SHARE_EXCLUSIVE
| STGM_READ
, NULL
, 0, &stg
);
787 ok(r
==STG_E_INVALIDFLAG
, "StgOpenStorage failed\n");
788 r
= StgOpenStorage( filename
, NULL
, STGM_SHARE_DENY_NONE
| STGM_READ
, NULL
, 0, &stg
);
789 ok(r
==STG_E_INVALIDFLAG
, "StgOpenStorage failed\n");
790 r
= StgOpenStorage( filename
, NULL
, STGM_SHARE_DENY_READ
| STGM_READ
, NULL
, 0, &stg
);
791 ok(r
==STG_E_INVALIDFLAG
, "StgOpenStorage failed\n");
792 r
= StgOpenStorage( filename
, NULL
, STGM_SHARE_DENY_WRITE
| STGM_READWRITE
, NULL
, 0, &stg
);
793 ok(r
==STG_E_INVALIDFLAG
, "StgOpenStorage failed\n");
795 /* open it for real */
796 r
= StgOpenStorage( filename
, NULL
, STGM_SHARE_DENY_NONE
| STGM_READ
| STGM_TRANSACTED
, NULL
, 0, &stg
); /* XLViewer 97/2000 */
797 ok(r
==S_OK
, "StgOpenStorage failed\n");
800 r
= IStorage_Release(stg
);
801 ok(r
== 0, "wrong ref count\n");
804 r
= StgOpenStorage( filename
, NULL
, STGM_SHARE_DENY_WRITE
| STGM_READ
, NULL
, 0, &stg
);
805 ok(r
==S_OK
, "StgOpenStorage failed\n");
808 r
= IStorage_Release(stg
);
809 ok(r
== 0, "wrong ref count\n");
812 /* test the way word opens its custom dictionary */
813 r
= StgOpenStorage( filename
, NULL
, STGM_NOSCRATCH
| STGM_TRANSACTED
|
814 STGM_SHARE_DENY_WRITE
| STGM_READWRITE
, NULL
, 0, &stg
);
815 ok(r
==S_OK
, "StgOpenStorage failed\n");
818 r
= IStorage_Release(stg
);
819 ok(r
== 0, "wrong ref count\n");
822 r
= StgOpenStorage( filename
, NULL
, STGM_SHARE_EXCLUSIVE
| STGM_READ
, NULL
, 0, &stg
);
823 ok(r
==S_OK
, "StgOpenStorage failed\n");
824 r
= StgOpenStorage( filename
, NULL
, STGM_SHARE_EXCLUSIVE
| STGM_READ
, NULL
, 0, &stg2
);
825 ok(r
==STG_E_SHAREVIOLATION
, "StgOpenStorage failed\n");
828 r
= IStorage_Release(stg
);
829 ok(r
== 0, "wrong ref count\n");
832 /* now try write to a storage file we opened read-only */
833 r
= StgOpenStorage( filename
, NULL
, STGM_SHARE_EXCLUSIVE
| STGM_READ
, NULL
, 0, &stg
);
834 ok(r
==S_OK
, "StgOpenStorage failed\n");
837 static const WCHAR stmname
[] = { 'w','i','n','e','t','e','s','t',0};
839 IStorage
*stg2
= NULL
;
841 r
= IStorage_CreateStream( stg
, stmname
, STGM_WRITE
| STGM_SHARE_EXCLUSIVE
,
843 ok(r
== STG_E_ACCESSDENIED
, "CreateStream should fail\n");
844 r
= IStorage_CreateStorage( stg
, stmname
, STGM_WRITE
| STGM_SHARE_EXCLUSIVE
, 0, 0, &stg2
);
845 ok(r
== STG_E_ACCESSDENIED
, "CreateStream should fail\n");
847 r
= IStorage_Release(stg
);
848 ok(r
== 0, "wrong ref count\n");
851 /* open like visio 2003 */
853 r
= StgOpenStorage( filename
, NULL
, STGM_PRIORITY
| STGM_SHARE_DENY_NONE
, NULL
, 0, &stg
);
854 ok(r
== S_OK
, "should succeed\n");
856 IStorage_Release(stg
);
858 /* test other sharing modes with STGM_PRIORITY */
860 r
= StgOpenStorage( filename
, NULL
, STGM_PRIORITY
| STGM_SHARE_EXCLUSIVE
, NULL
, 0, &stg
);
861 ok(r
== S_OK
, "should succeed\n");
863 IStorage_Release(stg
);
866 r
= StgOpenStorage( filename
, NULL
, STGM_PRIORITY
| STGM_SHARE_DENY_WRITE
, NULL
, 0, &stg
);
867 ok(r
== S_OK
, "should succeed\n");
869 IStorage_Release(stg
);
872 r
= StgOpenStorage( filename
, NULL
, STGM_PRIORITY
| STGM_SHARE_DENY_READ
, NULL
, 0, &stg
);
873 ok(r
== S_OK
, "should succeed\n");
875 IStorage_Release(stg
);
877 /* open like Project 2003 */
879 r
= StgOpenStorage( filename
, NULL
, STGM_PRIORITY
, NULL
, 0, &stg
);
880 ok(r
== S_OK
, "should succeed\n");
881 r
= StgOpenStorage( filename
, NULL
, STGM_PRIORITY
, NULL
, 0, &stg2
);
882 ok(r
== S_OK
, "should succeed\n");
884 IStorage_Release(stg2
);
886 IStorage_Release(stg
);
889 r
= StgOpenStorage( filename
, NULL
, STGM_PRIORITY
| STGM_READWRITE
, NULL
, 0, &stg
);
890 ok(r
== STG_E_INVALIDFLAG
, "should fail\n");
892 r
= StgOpenStorage( filename
, NULL
, STGM_TRANSACTED
| STGM_PRIORITY
, NULL
, 0, &stg
);
893 ok(r
== STG_E_INVALIDFLAG
, "should fail\n");
895 r
= StgOpenStorage( filename
, NULL
, STGM_SIMPLE
| STGM_PRIORITY
, NULL
, 0, &stg
);
896 ok(r
== STG_E_INVALIDFLAG
, "should fail\n");
898 r
= StgOpenStorage( filename
, NULL
, STGM_DELETEONRELEASE
| STGM_PRIORITY
, NULL
, 0, &stg
);
899 ok(r
== STG_E_INVALIDFUNCTION
, "should fail\n");
901 r
= StgOpenStorage( filename
, NULL
, STGM_NOSCRATCH
| STGM_PRIORITY
, NULL
, 0, &stg
);
902 ok(r
== STG_E_INVALIDFLAG
, "should fail\n");
904 r
= StgOpenStorage( filename
, NULL
, STGM_NOSNAPSHOT
| STGM_PRIORITY
, NULL
, 0, &stg
);
905 ok(r
== STG_E_INVALIDFLAG
, "should fail\n");
907 ret
= DeleteFileA(filenameA
);
908 ok(ret
, "file didn't exist\n");
911 static void test_storage_suminfo(void)
913 IStorage
*stg
= NULL
;
914 IPropertySetStorage
*propset
= NULL
;
915 IPropertyStorage
*ps
= NULL
;
918 DeleteFileA(filenameA
);
920 /* create the file */
921 r
= StgCreateDocfile( filename
, STGM_CREATE
| STGM_SHARE_EXCLUSIVE
|
922 STGM_READWRITE
|STGM_TRANSACTED
, 0, &stg
);
923 ok(r
==S_OK
, "StgCreateDocfile failed\n");
925 r
= IStorage_QueryInterface( stg
, &IID_IPropertySetStorage
, (LPVOID
) &propset
);
926 ok(r
== S_OK
, "query interface failed\n");
929 r
= IPropertySetStorage_Delete( propset
, &FMTID_SummaryInformation
);
930 ok(r
== STG_E_FILENOTFOUND
, "deleted property set storage\n");
932 r
= IPropertySetStorage_Open( propset
, &FMTID_SummaryInformation
,
933 STGM_READ
| STGM_SHARE_EXCLUSIVE
, &ps
);
934 ok(r
== STG_E_FILENOTFOUND
, "opened property set storage\n");
936 r
= IPropertySetStorage_Create( propset
, &FMTID_SummaryInformation
, NULL
, 0,
937 STGM_READ
| STGM_SHARE_EXCLUSIVE
, &ps
);
938 ok(r
== STG_E_INVALIDFLAG
, "created property set storage\n");
940 r
= IPropertySetStorage_Create( propset
, &FMTID_SummaryInformation
, NULL
, 0,
942 ok(r
== STG_E_INVALIDFLAG
, "created property set storage\n");
944 r
= IPropertySetStorage_Create( propset
, &FMTID_SummaryInformation
, NULL
, 0, 0, &ps
);
945 ok(r
== STG_E_INVALIDFLAG
, "created property set storage\n");
947 r
= IPropertySetStorage_Create( propset
, &FMTID_SummaryInformation
, NULL
, 0,
948 STGM_WRITE
|STGM_SHARE_EXCLUSIVE
, &ps
);
949 ok(r
== STG_E_INVALIDFLAG
, "created property set storage\n");
951 r
= IPropertySetStorage_Create( propset
, &FMTID_SummaryInformation
, NULL
, 0,
952 STGM_CREATE
|STGM_WRITE
|STGM_SHARE_EXCLUSIVE
, &ps
);
953 ok(r
== STG_E_INVALIDFLAG
, "created property set storage\n");
955 /* now try really creating a property set */
956 r
= IPropertySetStorage_Create( propset
, &FMTID_SummaryInformation
, NULL
, 0,
957 STGM_CREATE
|STGM_READWRITE
|STGM_SHARE_EXCLUSIVE
, &ps
);
958 ok(r
== S_OK
, "failed to create property set storage\n");
961 IPropertyStorage_Release(ps
);
963 /* now try creating the same thing again */
964 r
= IPropertySetStorage_Create( propset
, &FMTID_SummaryInformation
, NULL
, 0,
965 STGM_CREATE
|STGM_READWRITE
|STGM_SHARE_EXCLUSIVE
, &ps
);
966 ok(r
== S_OK
, "failed to create property set storage\n");
968 IPropertyStorage_Release(ps
);
970 /* should be able to open it */
971 r
= IPropertySetStorage_Open( propset
, &FMTID_SummaryInformation
,
972 STGM_READWRITE
|STGM_SHARE_EXCLUSIVE
, &ps
);
973 ok(r
== S_OK
, "open failed\n");
975 IPropertyStorage_Release(ps
);
978 r
= IPropertySetStorage_Delete( propset
, &FMTID_SummaryInformation
);
979 ok(r
== S_OK
, "failed to delete property set storage\n");
981 /* try opening with an invalid FMTID */
982 r
= IPropertySetStorage_Open( propset
, NULL
,
983 STGM_READWRITE
|STGM_SHARE_EXCLUSIVE
, &ps
);
984 ok(r
== E_INVALIDARG
, "open succeeded\n");
986 IPropertyStorage_Release(ps
);
989 r
= IPropertySetStorage_Open( propset
, &IID_IStorage
,
990 STGM_READWRITE
|STGM_SHARE_EXCLUSIVE
, &ps
);
991 ok(r
== STG_E_FILENOTFOUND
, "open succeeded\n");
993 IPropertyStorage_Release(ps
);
996 /* try some invalid flags */
997 r
= IPropertySetStorage_Open( propset
, &FMTID_SummaryInformation
,
998 STGM_CREATE
| STGM_READWRITE
|STGM_SHARE_EXCLUSIVE
, &ps
);
999 ok(r
== STG_E_INVALIDFLAG
, "open succeeded\n");
1001 IPropertyStorage_Release(ps
);
1003 /* after deleting it, it should be gone */
1004 r
= IPropertySetStorage_Open( propset
, &FMTID_SummaryInformation
,
1005 STGM_READWRITE
|STGM_SHARE_EXCLUSIVE
, &ps
);
1006 ok(r
== STG_E_FILENOTFOUND
, "open failed\n");
1008 IPropertyStorage_Release(ps
);
1010 r
= IPropertySetStorage_Release( propset
);
1011 ok(r
== 1, "ref count wrong\n");
1013 r
= IStorage_Release(stg
);
1014 ok(r
== 0, "ref count wrong\n");
1016 DeleteFileA(filenameA
);
1019 static void test_storage_refcount(void)
1021 IStorage
*stg
= NULL
;
1022 IStorage
*stgprio
= NULL
;
1024 IStream
*stm
= NULL
;
1025 static const WCHAR stmname
[] = { 'C','O','N','T','E','N','T','S',0 };
1027 ULARGE_INTEGER upos
;
1031 DeleteFileA(filenameA
);
1033 /* create the file */
1034 r
= StgCreateDocfile( filename
, STGM_CREATE
| STGM_SHARE_EXCLUSIVE
|
1035 STGM_READWRITE
|STGM_TRANSACTED
, 0, &stg
);
1036 ok(r
==S_OK
, "StgCreateDocfile failed\n");
1038 r
= WriteClassStg( stg
, &test_stg_cls
);
1039 ok( r
== S_OK
, "WriteClassStg failed\n");
1041 r
= IStorage_Commit( stg
, STGC_DEFAULT
);
1042 ok( r
== S_OK
, "IStorage_Commit failed\n");
1044 /* now create a stream */
1045 r
= IStorage_CreateStream(stg
, stmname
, STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
, 0, 0, &stm
);
1046 ok(r
==S_OK
, "IStorage->CreateStream failed\n");
1048 r
= IStorage_Release( stg
);
1049 ok (r
== 0, "storage not released\n");
1052 r
= IStream_Seek( stm
, pos
, 0, &upos
);
1053 ok (r
== STG_E_REVERTED
, "seek should fail\n");
1055 r
= IStream_Stat( stm
, &stat
, STATFLAG_DEFAULT
);
1056 ok (r
== STG_E_REVERTED
, "stat should fail\n");
1058 r
= IStream_Write( stm
, "Test string", strlen("Test string"), NULL
);
1059 ok (r
== STG_E_REVERTED
, "IStream_Write should return STG_E_REVERTED instead of 0x%08x\n", r
);
1061 r
= IStream_Read( stm
, buffer
, sizeof(buffer
), NULL
);
1062 ok (r
== STG_E_REVERTED
, "IStream_Read should return STG_E_REVERTED instead of 0x%08x\n", r
);
1064 r
= IStream_Release(stm
);
1065 ok (r
== 0, "stream not released\n");
1067 /* tests that STGM_PRIORITY doesn't prevent readwrite access from other
1068 * StgOpenStorage calls in transacted mode */
1069 r
= StgOpenStorage( filename
, NULL
, STGM_PRIORITY
, NULL
, 0, &stgprio
);
1070 ok(r
==S_OK
, "StgOpenStorage failed with error 0x%08x\n", r
);
1072 /* non-transacted mode read/write fails */
1073 r
= StgOpenStorage( filename
, NULL
, STGM_SHARE_EXCLUSIVE
|STGM_READWRITE
, NULL
, 0, &stg
);
1074 ok(r
==STG_E_LOCKVIOLATION
, "StgOpenStorage should return STG_E_LOCKVIOLATION instead of 0x%08x\n", r
);
1076 /* non-transacted mode read-only succeeds */
1077 r
= StgOpenStorage( filename
, NULL
, STGM_SHARE_DENY_WRITE
|STGM_READ
, NULL
, 0, &stg
);
1078 ok(r
==S_OK
, "StgOpenStorage failed with error 0x%08x\n", r
);
1079 IStorage_Release(stg
);
1081 r
= StgOpenStorage( filename
, NULL
, STGM_TRANSACTED
|STGM_SHARE_DENY_WRITE
|STGM_READWRITE
, NULL
, 0, &stg
);
1082 ok(r
==S_OK
, "StgOpenStorage failed with error 0x%08x\n", r
);
1085 static const WCHAR stgname
[] = { ' ',' ',' ','2','9',0 };
1086 static const WCHAR stgname2
[] = { 'C','V','_','i','e','w',0 };
1087 static const WCHAR stmname2
[] = { 'V','a','r','2','D','a','t','a',0 };
1092 r
= IStorage_Stat( stg
, &statstg
, STATFLAG_NONAME
);
1093 ok(r
== S_OK
, "Stat should have succeeded instead of returning 0x%08x\n", r
);
1094 ok(statstg
.type
== STGTY_STORAGE
, "Statstg type should have been STGTY_STORAGE instead of %d\n", statstg
.type
);
1095 ok(U(statstg
.cbSize
).LowPart
== 0, "Statstg cbSize.LowPart should have been 0 instead of %d\n", U(statstg
.cbSize
).LowPart
);
1096 ok(U(statstg
.cbSize
).HighPart
== 0, "Statstg cbSize.HighPart should have been 0 instead of %d\n", U(statstg
.cbSize
).HighPart
);
1097 ok(statstg
.grfMode
== (STGM_TRANSACTED
|STGM_SHARE_DENY_WRITE
|STGM_READWRITE
),
1098 "Statstg grfMode should have been 0x10022 instead of 0x%x\n", statstg
.grfMode
);
1099 ok(statstg
.grfLocksSupported
== 0, "Statstg grfLocksSupported should have been 0 instead of %d\n", statstg
.grfLocksSupported
);
1100 ok(IsEqualCLSID(&statstg
.clsid
, &test_stg_cls
), "Statstg clsid is not test_stg_cls\n");
1101 ok(statstg
.grfStateBits
== 0, "Statstg grfStateBits should have been 0 instead of %d\n", statstg
.grfStateBits
);
1102 ok(statstg
.reserved
== 0, "Statstg reserved should have been 0 instead of %d\n", statstg
.reserved
);
1104 r
= IStorage_CreateStorage( stg
, stgname
, STGM_SHARE_EXCLUSIVE
, 0, 0, &stg2
);
1105 ok(r
== S_OK
, "CreateStorage should have succeeded instead of returning 0x%08x\n", r
);
1107 r
= IStorage_Stat( stg2
, &statstg
, STATFLAG_DEFAULT
);
1108 ok(r
== S_OK
, "Stat should have succeeded instead of returning 0x%08x\n", r
);
1109 ok(!memcmp(statstg
.pwcsName
, stgname
, sizeof(stgname
)),
1110 "Statstg pwcsName should have been the name the storage was created with\n");
1111 ok(statstg
.type
== STGTY_STORAGE
, "Statstg type should have been STGTY_STORAGE instead of %d\n", statstg
.type
);
1112 ok(U(statstg
.cbSize
).LowPart
== 0, "Statstg cbSize.LowPart should have been 0 instead of %d\n", U(statstg
.cbSize
).LowPart
);
1113 ok(U(statstg
.cbSize
).HighPart
== 0, "Statstg cbSize.HighPart should have been 0 instead of %d\n", U(statstg
.cbSize
).HighPart
);
1114 ok(statstg
.grfMode
== STGM_SHARE_EXCLUSIVE
,
1115 "Statstg grfMode should have been STGM_SHARE_EXCLUSIVE instead of 0x%x\n", statstg
.grfMode
);
1116 ok(statstg
.grfLocksSupported
== 0, "Statstg grfLocksSupported should have been 0 instead of %d\n", statstg
.grfLocksSupported
);
1117 ok(IsEqualCLSID(&statstg
.clsid
, &CLSID_NULL
), "Statstg clsid is not CLSID_NULL\n");
1118 ok(statstg
.grfStateBits
== 0, "Statstg grfStateBits should have been 0 instead of %d\n", statstg
.grfStateBits
);
1119 ok(statstg
.reserved
== 0, "Statstg reserved should have been 0 instead of %d\n", statstg
.reserved
);
1120 CoTaskMemFree(statstg
.pwcsName
);
1122 r
= IStorage_CreateStorage( stg2
, stgname2
, STGM_SHARE_EXCLUSIVE
|STGM_READWRITE
, 0, 0, &stg3
);
1123 ok(r
== STG_E_ACCESSDENIED
, "CreateStorage should have returned STG_E_ACCESSDENIED instead of 0x%08x\n", r
);
1125 r
= IStorage_CreateStream( stg2
, stmname2
, STGM_CREATE
|STGM_SHARE_EXCLUSIVE
, 0, 0, &stm
);
1126 ok(r
== STG_E_ACCESSDENIED
, "CreateStream should have returned STG_E_ACCESSDENIED instead of 0x%08x\n", r
);
1128 IStorage_Release(stg2
);
1130 r
= IStorage_Release(stg
);
1131 ok(r
== 0, "wrong ref count\n");
1134 /* Multiple STGM_PRIORITY opens are possible. */
1135 r
= StgOpenStorage( filename
, NULL
, STGM_PRIORITY
, NULL
, 0, &stg
);
1136 ok(r
==S_OK
, "StgOpenStorage failed with error 0x%08x\n", r
);
1139 r
= IStorage_Release(stg
);
1140 ok(r
== 0, "wrong ref count\n");
1143 r
= StgOpenStorage( NULL
, stgprio
, STGM_TRANSACTED
|STGM_SHARE_DENY_WRITE
|STGM_READWRITE
, NULL
, 0, &stg
);
1144 ok(r
==S_OK
, "StgOpenStorage failed with error 0x%08x\n", r
);
1147 static const WCHAR stgname
[] = { ' ',' ',' ','2','9',0 };
1151 r
= IStorage_Stat( stg
, &statstg
, STATFLAG_NONAME
);
1152 ok(r
== S_OK
, "Stat should have succeeded instead of returning 0x%08x\n", r
);
1153 ok(statstg
.type
== STGTY_STORAGE
, "Statstg type should have been STGTY_STORAGE instead of %d\n", statstg
.type
);
1154 ok(U(statstg
.cbSize
).LowPart
== 0, "Statstg cbSize.LowPart should have been 0 instead of %d\n", U(statstg
.cbSize
).LowPart
);
1155 ok(U(statstg
.cbSize
).HighPart
== 0, "Statstg cbSize.HighPart should have been 0 instead of %d\n", U(statstg
.cbSize
).HighPart
);
1156 ok(statstg
.grfMode
== (STGM_TRANSACTED
|STGM_SHARE_DENY_WRITE
|STGM_READWRITE
),
1157 "Statstg grfMode should have been 0x10022 instead of 0x%x\n", statstg
.grfMode
);
1158 ok(statstg
.grfLocksSupported
== 0, "Statstg grfLocksSupported should have been 0 instead of %d\n", statstg
.grfLocksSupported
);
1159 ok(IsEqualCLSID(&statstg
.clsid
, &test_stg_cls
), "Statstg clsid is not test_stg_cls\n");
1160 ok(statstg
.grfStateBits
== 0, "Statstg grfStateBits should have been 0 instead of %d\n", statstg
.grfStateBits
);
1161 ok(statstg
.reserved
== 0, "Statstg reserved should have been 0 instead of %d\n", statstg
.reserved
);
1163 r
= IStorage_CreateStorage( stg
, stgname
, STGM_SHARE_EXCLUSIVE
, 0, 0, &stg2
);
1164 ok(r
== S_OK
, "CreateStorage should have succeeded instead of returning 0x%08x\n", r
);
1166 IStorage_Release(stg2
);
1168 r
= IStorage_Commit( stg
, 0 );
1169 ok(r
== S_OK
, "Commit should have succeeded instead of returning 0x%08x\n", r
);
1171 r
= IStorage_Release(stg
);
1172 ok(r
== 0, "wrong ref count\n");
1174 /* IStorage_Release(stgprio) not necessary because StgOpenStorage released it. */
1176 DeleteFileA(filenameA
);
1179 static void test_writeclassstg(void)
1181 IStorage
*stg
= NULL
;
1183 CLSID temp_cls
, cls2
;
1185 DeleteFileA(filenameA
);
1187 /* create the file */
1188 r
= StgCreateDocfile( filename
, STGM_CREATE
| STGM_SHARE_EXCLUSIVE
|
1189 STGM_READWRITE
, 0, &stg
);
1190 ok(r
==S_OK
, "StgCreateDocfile failed\n");
1192 r
= ReadClassStg( NULL
, NULL
);
1193 ok(r
== E_INVALIDARG
, "ReadClassStg should return E_INVALIDARG instead of 0x%08X\n", r
);
1195 memset(&temp_cls
, 0xcc, sizeof(temp_cls
));
1196 memset(&cls2
, 0xcc, sizeof(cls2
));
1197 r
= ReadClassStg( NULL
, &temp_cls
);
1198 ok(r
== E_INVALIDARG
, "got 0x%08x\n", r
);
1199 ok(IsEqualCLSID(&temp_cls
, &cls2
), "got wrong clsid\n");
1201 r
= ReadClassStg( stg
, NULL
);
1202 ok(r
== E_INVALIDARG
, "ReadClassStg should return E_INVALIDARG instead of 0x%08X\n", r
);
1204 temp_cls
.Data1
= 0xdeadbeef;
1205 r
= ReadClassStg( stg
, &temp_cls
);
1206 ok(r
== S_OK
, "ReadClassStg failed with 0x%08X\n", r
);
1208 ok(IsEqualCLSID(&temp_cls
, &CLSID_NULL
), "ReadClassStg returned wrong clsid\n");
1210 r
= WriteClassStg( NULL
, NULL
);
1211 ok(r
== E_INVALIDARG
, "WriteClassStg should return E_INVALIDARG instead of 0x%08X\n", r
);
1213 r
= WriteClassStg( stg
, NULL
);
1214 ok(r
== STG_E_INVALIDPOINTER
, "WriteClassStg should return STG_E_INVALIDPOINTER instead of 0x%08X\n", r
);
1216 r
= WriteClassStg( stg
, &test_stg_cls
);
1217 ok( r
== S_OK
, "WriteClassStg failed with 0x%08X\n", r
);
1219 r
= ReadClassStg( stg
, &temp_cls
);
1220 ok( r
== S_OK
, "ReadClassStg failed with 0x%08X\n", r
);
1221 ok(IsEqualCLSID(&temp_cls
, &test_stg_cls
), "ReadClassStg returned wrong clsid\n");
1223 r
= IStorage_Release( stg
);
1224 ok (r
== 0, "storage not released\n");
1226 DeleteFileA(filenameA
);
1229 static void test_streamenum(void)
1231 IStorage
*stg
= NULL
;
1233 IStream
*stm
= NULL
;
1234 static const WCHAR stmname
[] = { 'C','O','N','T','E','N','T','S',0 };
1235 static const WCHAR stmname2
[] = { 'A','B','C','D','E','F','G','H','I',0 };
1236 static const WCHAR stmname3
[] = { 'A','B','C','D','E','F','G','H','I','J',0 };
1237 static const STATSTG stat_null
;
1239 IEnumSTATSTG
*ee
= NULL
;
1242 DeleteFileA(filenameA
);
1244 /* create the file */
1245 r
= StgCreateDocfile( filename
, STGM_CREATE
| STGM_SHARE_EXCLUSIVE
|
1246 STGM_READWRITE
|STGM_TRANSACTED
, 0, &stg
);
1247 ok(r
==S_OK
, "StgCreateDocfile failed\n");
1249 r
= WriteClassStg( stg
, &test_stg_cls
);
1250 ok( r
== S_OK
, "WriteClassStg failed\n");
1252 r
= IStorage_Commit( stg
, STGC_DEFAULT
);
1253 ok( r
== S_OK
, "IStorage_Commit failed\n");
1255 /* now create a stream */
1256 r
= IStorage_CreateStream(stg
, stmname
, STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
, 0, 0, &stm
);
1257 ok(r
==S_OK
, "IStorage->CreateStream failed\n");
1259 IStream_Release(stm
);
1261 /* first enum ... should be 1 stream */
1262 r
= IStorage_EnumElements(stg
, 0, NULL
, 0, &ee
);
1263 ok(r
==S_OK
, "IStorage->EnumElements failed\n");
1266 r
= IEnumSTATSTG_Next(ee
, 1, &stat
, &count
);
1267 ok(r
==S_OK
, "IEnumSTATSTG->Next failed\n");
1268 ok(count
== 1, "count wrong\n");
1271 CoTaskMemFree(stat
.pwcsName
);
1273 r
= IEnumSTATSTG_Release(ee
);
1274 ok(r
==S_OK
, "EnumSTATSTG_Release failed with error 0x%08x\n", r
);
1276 /* second enum... destroy the stream before reading */
1277 r
= IStorage_EnumElements(stg
, 0, NULL
, 0, &ee
);
1278 ok(r
==S_OK
, "IStorage->EnumElements failed\n");
1280 r
= IStorage_DestroyElement(stg
, stmname
);
1281 ok(r
==S_OK
, "IStorage->DestroyElement failed\n");
1283 memset(&stat
, 0xad, sizeof(stat
));
1285 r
= IEnumSTATSTG_Next(ee
, 1, &stat
, &count
);
1286 ok(r
==S_FALSE
, "IEnumSTATSTG->Next failed\n");
1287 ok(count
== 0, "count wrong\n");
1288 ok(memcmp(&stat
, &stat_null
, sizeof(stat
)) == 0, "stat is not zeroed\n");
1290 /* reset and try again */
1291 r
= IEnumSTATSTG_Reset(ee
);
1292 ok(r
==S_OK
, "IEnumSTATSTG->Reset failed\n");
1295 r
= IEnumSTATSTG_Next(ee
, 1, &stat
, &count
);
1296 ok(r
==S_FALSE
, "IEnumSTATSTG->Next failed\n");
1297 ok(count
== 0, "count wrong\n");
1299 /* add a stream before reading */
1300 r
= IEnumSTATSTG_Reset(ee
);
1301 ok(r
==S_OK
, "IEnumSTATSTG->Reset failed\n");
1303 r
= IStorage_CreateStream(stg
, stmname
, STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
, 0, 0, &stm
);
1304 ok(r
==S_OK
, "IStorage->CreateStream failed\n");
1306 r
= IStream_Release(stm
);
1307 ok(r
==S_OK
, "Stream_Release failed with error 0x%08x\n", r
);
1310 r
= IEnumSTATSTG_Next(ee
, 1, &stat
, &count
);
1311 ok(r
==S_OK
, "IEnumSTATSTG->Next failed\n");
1312 ok(count
== 1, "count wrong\n");
1316 ok(lstrcmpiW(stat
.pwcsName
, stmname
) == 0, "expected CONTENTS, got %s\n", wine_dbgstr_w(stat
.pwcsName
));
1317 CoTaskMemFree(stat
.pwcsName
);
1320 r
= IStorage_CreateStream(stg
, stmname2
, STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
, 0, 0, &stm
);
1321 ok(r
==S_OK
, "IStorage->CreateStream failed\n");
1323 r
= IStream_Release(stm
);
1324 ok(r
==S_OK
, "Stream_Release failed with error 0x%08x\n", r
);
1327 r
= IEnumSTATSTG_Next(ee
, 1, &stat
, &count
);
1328 ok(r
==S_OK
, "IEnumSTATSTG->Next failed\n");
1329 ok(count
== 1, "count wrong\n");
1333 ok(lstrcmpiW(stat
.pwcsName
, stmname2
) == 0, "expected ABCDEFGHI, got %s\n", wine_dbgstr_w(stat
.pwcsName
));
1334 CoTaskMemFree(stat
.pwcsName
);
1337 /* delete previous and next stream after reading */
1338 r
= IStorage_CreateStream(stg
, stmname3
, STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
, 0, 0, &stm
);
1339 ok(r
==S_OK
, "IStorage->CreateStream failed\n");
1341 r
= IStream_Release(stm
);
1342 ok(r
==S_OK
, "Stream_Release failed with error 0x%08x\n", r
);
1344 r
= IEnumSTATSTG_Reset(ee
);
1345 ok(r
==S_OK
, "IEnumSTATSTG->Reset failed\n");
1348 r
= IEnumSTATSTG_Next(ee
, 1, &stat
, &count
);
1349 ok(r
==S_OK
, "IEnumSTATSTG->Next failed\n");
1350 ok(count
== 1, "count wrong\n");
1354 ok(lstrcmpiW(stat
.pwcsName
, stmname
) == 0, "expected CONTENTS, got %s\n", wine_dbgstr_w(stat
.pwcsName
));
1355 CoTaskMemFree(stat
.pwcsName
);
1358 r
= IStorage_DestroyElement(stg
, stmname
);
1359 ok(r
==S_OK
, "IStorage->DestroyElement failed\n");
1361 r
= IStorage_DestroyElement(stg
, stmname2
);
1362 ok(r
==S_OK
, "IStorage->DestroyElement failed\n");
1365 r
= IEnumSTATSTG_Next(ee
, 1, &stat
, &count
);
1366 ok(r
==S_OK
, "IEnumSTATSTG->Next failed\n");
1367 ok(count
== 1, "count wrong\n");
1371 ok(lstrcmpiW(stat
.pwcsName
, stmname3
) == 0, "expected ABCDEFGHIJ, got %s\n", wine_dbgstr_w(stat
.pwcsName
));
1372 CoTaskMemFree(stat
.pwcsName
);
1375 r
= IStorage_Release( stg
);
1376 todo_wine
ok (r
== 0, "storage not released\n");
1378 /* enumerator is still valid and working after the storage is released */
1379 r
= IEnumSTATSTG_Reset(ee
);
1380 ok(r
==S_OK
, "IEnumSTATSTG->Reset failed\n");
1383 r
= IEnumSTATSTG_Next(ee
, 1, &stat
, &count
);
1384 ok(r
==S_OK
, "IEnumSTATSTG->Next failed\n");
1385 ok(count
== 1, "count wrong\n");
1389 ok(lstrcmpiW(stat
.pwcsName
, stmname3
) == 0, "expected ABCDEFGHIJ, got %s\n", wine_dbgstr_w(stat
.pwcsName
));
1390 CoTaskMemFree(stat
.pwcsName
);
1393 /* the storage is left open until the enumerator is freed */
1394 r
= StgOpenStorage( filename
, NULL
, STGM_SHARE_EXCLUSIVE
|
1395 STGM_READWRITE
|STGM_TRANSACTED
, NULL
, 0, &stg
);
1396 ok(r
==STG_E_SHAREVIOLATION
||
1397 r
==STG_E_LOCKVIOLATION
, /* XP-SP2/W2K3-SP1 and below */
1398 "StgCreateDocfile failed, res=%x\n", r
);
1400 r
= IEnumSTATSTG_Release(ee
);
1401 ok (r
== 0, "enum not released\n");
1403 DeleteFileA(filenameA
);
1406 static void test_transact(void)
1408 IStorage
*stg
= NULL
, *stg2
= NULL
, *stg3
= NULL
;
1410 IStream
*stm
= NULL
;
1411 static const WCHAR stmname
[] = { 'C','O','N','T','E','N','T','S',0 };
1412 static const WCHAR stmname2
[] = { 'F','O','O',0 };
1413 static const WCHAR stgname
[] = { 'P','E','R','M','S','T','G',0 };
1414 static const WCHAR stgname2
[] = { 'T','E','M','P','S','T','G',0 };
1417 DeleteFileA(filenameA
);
1419 /* create the file */
1420 r
= StgCreateDocfile( filename
, STGM_CREATE
| STGM_SHARE_EXCLUSIVE
|
1421 STGM_READWRITE
|STGM_TRANSACTED
, 0, &stg
);
1422 ok(r
==S_OK
, "StgCreateDocfile failed\n");
1424 /* commit a new stream and storage */
1425 r
= IStorage_CreateStream(stg
, stmname2
, STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
, 0, 0, &stm
);
1426 ok(r
==S_OK
, "IStorage->CreateStream failed\n");
1428 r
= IStream_Write(stm
, "this is stream 1\n", 16, NULL
);
1429 ok(r
==S_OK
, "IStream->Write failed\n");
1431 IStream_Release(stm
);
1433 r
= IStorage_CreateStorage(stg
, stgname
, STGM_READWRITE
| STGM_SHARE_EXCLUSIVE
, 0, 0, &stg2
);
1434 ok(r
==S_OK
, "IStorage->CreateStorage failed, hr=%08x\n", r
);
1438 /* Create two substorages but only commit one */
1439 r
= IStorage_CreateStorage(stg2
, stgname
, STGM_READWRITE
| STGM_SHARE_EXCLUSIVE
, 0, 0, &stg3
);
1440 ok(r
==S_OK
, "IStorage->CreateStorage failed, hr=%08x\n", r
);
1443 IStorage_Release(stg3
);
1445 r
= IStorage_Commit(stg
, 0);
1446 ok(r
==S_OK
, "IStorage->Commit failed\n");
1448 r
= IStorage_CreateStorage(stg2
, stgname2
, STGM_READWRITE
| STGM_SHARE_EXCLUSIVE
, 0, 0, &stg3
);
1449 ok(r
==S_OK
, "IStorage->CreateStorage failed, hr=%08x\n", r
);
1452 IStorage_Release(stg3
);
1454 IStorage_Release(stg2
);
1457 /* now create a stream and storage, but don't commit them */
1459 r
= IStorage_CreateStream(stg
, stmname
, STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
, 0, 0, &stm
);
1460 ok(r
==S_OK
, "IStorage->CreateStream failed\n");
1462 r
= IStream_Write(stm
, "this is stream 2\n", 16, NULL
);
1463 ok(r
==S_OK
, "IStream->Write failed\n");
1465 /* IStream::Commit does nothing for OLE storage streams */
1466 r
= IStream_Commit(stm
, STGC_ONLYIFCURRENT
| STGC_DANGEROUSLYCOMMITMERELYTODISKCACHE
);
1467 ok(r
==S_OK
, "IStream->Commit failed\n");
1469 r
= IStorage_CreateStorage(stg
, stgname2
, STGM_READWRITE
| STGM_SHARE_EXCLUSIVE
, 0, 0, &stg2
);
1470 ok(r
==S_OK
, "IStorage->CreateStorage failed, hr=%08x\n", r
);
1473 IStorage_Release(stg2
);
1475 IStream_Release(stm
);
1477 IStorage_Release(stg
);
1481 r
= StgOpenStorage( filename
, NULL
, STGM_SHARE_DENY_NONE
| STGM_READ
| STGM_TRANSACTED
, NULL
, 0, &stg
);
1482 ok(r
==S_OK
, "StgOpenStorage failed\n");
1487 r
= IStorage_OpenStream(stg
, stmname
, NULL
, STGM_SHARE_DENY_NONE
|STGM_READ
, 0, &stm
);
1488 ok(r
==STG_E_INVALIDFLAG
, "IStorage->OpenStream failed %08x\n", r
);
1490 r
= IStorage_OpenStream(stg
, stmname
, NULL
, STGM_DELETEONRELEASE
|STGM_SHARE_EXCLUSIVE
|STGM_READWRITE
, 0, &stm
);
1491 ok(r
==STG_E_INVALIDFUNCTION
, "IStorage->OpenStream failed %08x\n", r
);
1493 r
= IStorage_OpenStream(stg
, stmname
, NULL
, STGM_TRANSACTED
|STGM_SHARE_EXCLUSIVE
|STGM_READWRITE
, 0, &stm
);
1494 ok(r
==STG_E_INVALIDFUNCTION
, "IStorage->OpenStream failed %08x\n", r
);
1496 r
= IStorage_OpenStorage(stg
, stmname
, NULL
, STGM_TRANSACTED
|STGM_SHARE_EXCLUSIVE
|STGM_READWRITE
, NULL
, 0, &stg2
);
1497 ok(r
==STG_E_FILENOTFOUND
, "IStorage->OpenStream failed %08x\n", r
);
1499 r
= IStorage_OpenStream(stg
, stmname
, NULL
, STGM_SHARE_EXCLUSIVE
|STGM_READWRITE
, 0, &stm
);
1500 ok(r
==STG_E_FILENOTFOUND
, "IStorage->OpenStream should fail %08x\n", r
);
1502 IStream_Release(stm
);
1504 r
= IStorage_OpenStorage(stg
, stgname2
, NULL
, STGM_SHARE_EXCLUSIVE
|STGM_READWRITE
, NULL
, 0, &stg2
);
1505 ok(r
==STG_E_FILENOTFOUND
, "IStorage->OpenStorage should fail %08x\n", r
);
1507 IStorage_Release(stg2
);
1509 r
= IStorage_OpenStorage(stg
, stmname2
, NULL
, STGM_TRANSACTED
|STGM_SHARE_EXCLUSIVE
|STGM_READWRITE
, NULL
, 0, &stg2
);
1510 ok(r
==STG_E_FILENOTFOUND
, "IStorage->OpenStream failed %08x\n", r
);
1512 r
= IStorage_OpenStream(stg
, stmname2
, NULL
, STGM_SHARE_EXCLUSIVE
|STGM_READWRITE
, 0, &stm
);
1513 ok(r
==S_OK
, "IStorage->OpenStream should succeed %08x\n", r
);
1515 IStream_Release(stm
);
1517 r
= IStorage_OpenStorage(stg
, stgname
, NULL
, STGM_SHARE_EXCLUSIVE
|STGM_READWRITE
, NULL
, 0, &stg2
);
1518 ok(r
==S_OK
, "IStorage->OpenStorage should succeed %08x\n", r
);
1521 r
= IStorage_OpenStorage(stg2
, stgname
, NULL
, STGM_SHARE_EXCLUSIVE
|STGM_READWRITE
, NULL
, 0, &stg3
);
1522 ok(r
==S_OK
, "IStorage->OpenStorage should succeed %08x\n", r
);
1524 IStorage_Release(stg3
);
1526 r
= IStorage_OpenStorage(stg2
, stgname2
, NULL
, STGM_SHARE_EXCLUSIVE
|STGM_READWRITE
, NULL
, 0, &stg3
);
1527 ok(r
==STG_E_FILENOTFOUND
, "IStorage->OpenStorage should fail %08x\n", r
);
1529 IStorage_Release(stg3
);
1531 IStorage_Release(stg2
);
1534 IStorage_Release(stg
);
1536 ret
= DeleteFileA(filenameA
);
1537 ok(ret
, "deleted file\n");
1540 static void test_substorage_share(void)
1542 IStorage
*stg
, *stg2
, *stg3
;
1543 IStream
*stm
, *stm2
;
1545 static const WCHAR stgname
[] = { 'P','E','R','M','S','T','G',0 };
1546 static const WCHAR stmname
[] = { 'C','O','N','T','E','N','T','S',0 };
1547 static const WCHAR othername
[] = { 'N','E','W','N','A','M','E',0 };
1550 DeleteFileA(filenameA
);
1552 /* create the file */
1553 r
= StgCreateDocfile( filename
, STGM_CREATE
| STGM_SHARE_EXCLUSIVE
|
1554 STGM_READWRITE
, 0, &stg
);
1555 ok(r
==S_OK
, "StgCreateDocfile failed\n");
1557 /* create a read/write storage and try to open it again */
1558 r
= IStorage_CreateStorage(stg
, stgname
, STGM_READWRITE
| STGM_SHARE_EXCLUSIVE
, 0, 0, &stg2
);
1559 ok(r
==S_OK
, "IStorage->CreateStorage failed, hr=%08x\n", r
);
1563 r
= IStorage_OpenStorage(stg
, stgname
, NULL
, STGM_READWRITE
| STGM_SHARE_EXCLUSIVE
, 0, 0, &stg3
);
1564 ok(r
==STG_E_ACCESSDENIED
, "IStorage->OpenStorage should fail %08x\n", r
);
1567 IStorage_Release(stg3
);
1569 r
= IStorage_OpenStorage(stg
, stgname
, NULL
, STGM_READ
| STGM_SHARE_EXCLUSIVE
, 0, 0, &stg3
);
1570 ok(r
==STG_E_ACCESSDENIED
, "IStorage->OpenStorage should fail %08x\n", r
);
1573 IStorage_Release(stg3
);
1575 /* cannot rename the storage while it's open */
1576 r
= IStorage_RenameElement(stg
, stgname
, othername
);
1577 ok(r
==STG_E_ACCESSDENIED
, "IStorage->RenameElement should fail %08x\n", r
);
1578 if (SUCCEEDED(r
)) IStorage_RenameElement(stg
, othername
, stgname
);
1580 /* destroying an object while it's open invalidates it */
1581 r
= IStorage_DestroyElement(stg
, stgname
);
1582 ok(r
==S_OK
, "IStorage->DestroyElement failed, hr=%08x\n", r
);
1584 r
= IStorage_CreateStream(stg2
, stmname
, STGM_READWRITE
| STGM_SHARE_EXCLUSIVE
, 0, 0, &stm
);
1585 ok(r
==STG_E_REVERTED
, "IStorage->CreateStream failed, hr=%08x\n", r
);
1588 IStream_Release(stm
);
1590 IStorage_Release(stg2
);
1593 /* create a read/write stream and try to open it again */
1594 r
= IStorage_CreateStream(stg
, stmname
, STGM_READWRITE
| STGM_SHARE_EXCLUSIVE
, 0, 0, &stm
);
1595 ok(r
==S_OK
, "IStorage->CreateStream failed, hr=%08x\n", r
);
1599 r
= IStorage_OpenStream(stg
, stmname
, NULL
, STGM_READWRITE
| STGM_SHARE_EXCLUSIVE
, 0, &stm2
);
1600 ok(r
==STG_E_ACCESSDENIED
, "IStorage->OpenStream should fail %08x\n", r
);
1603 IStream_Release(stm2
);
1605 r
= IStorage_OpenStream(stg
, stmname
, NULL
, STGM_READ
| STGM_SHARE_EXCLUSIVE
, 0, &stm2
);
1606 ok(r
==STG_E_ACCESSDENIED
, "IStorage->OpenStream should fail %08x\n", r
);
1609 IStream_Release(stm2
);
1611 /* cannot rename the stream while it's open */
1612 r
= IStorage_RenameElement(stg
, stmname
, othername
);
1613 ok(r
==STG_E_ACCESSDENIED
, "IStorage->RenameElement should fail %08x\n", r
);
1614 if (SUCCEEDED(r
)) IStorage_RenameElement(stg
, othername
, stmname
);
1616 /* destroying an object while it's open invalidates it */
1617 r
= IStorage_DestroyElement(stg
, stmname
);
1618 ok(r
==S_OK
, "IStorage->DestroyElement failed, hr=%08x\n", r
);
1620 r
= IStream_Write(stm
, "this shouldn't work\n", 20, NULL
);
1621 ok(r
==STG_E_REVERTED
, "IStream_Write should fail %08x\n", r
);
1623 IStream_Release(stm
);
1626 IStorage_Release(stg
);
1628 ret
= DeleteFileA(filenameA
);
1629 ok(ret
, "deleted file\n");
1632 static void test_revert(void)
1634 IStorage
*stg
= NULL
, *stg2
= NULL
, *stg3
= NULL
;
1636 IStream
*stm
= NULL
, *stm2
= NULL
;
1637 static const WCHAR stmname
[] = { 'C','O','N','T','E','N','T','S',0 };
1638 static const WCHAR stmname2
[] = { 'F','O','O',0 };
1639 static const WCHAR stgname
[] = { 'P','E','R','M','S','T','G',0 };
1640 static const WCHAR stgname2
[] = { 'T','E','M','P','S','T','G',0 };
1644 DeleteFileA(filenameA
);
1646 /* create the file */
1647 r
= StgCreateDocfile( filename
, STGM_CREATE
| STGM_SHARE_EXCLUSIVE
|
1648 STGM_READWRITE
|STGM_TRANSACTED
, 0, &stg
);
1649 ok(r
==S_OK
, "StgCreateDocfile failed\n");
1651 /* commit a new stream and storage */
1652 r
= IStorage_CreateStream(stg
, stmname2
, STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
, 0, 0, &stm
);
1653 ok(r
==S_OK
, "IStorage->CreateStream failed\n");
1655 r
= IStream_Write(stm
, "this is stream 1\n", 16, NULL
);
1656 ok(r
==S_OK
, "IStream->Write failed\n");
1658 r
= IStorage_CreateStorage(stg
, stgname
, STGM_READWRITE
| STGM_SHARE_EXCLUSIVE
, 0, 0, &stg2
);
1659 ok(r
==S_OK
, "IStorage->CreateStorage failed, hr=%08x\n", r
);
1663 /* Create two substorages but only commit one */
1664 r
= IStorage_CreateStorage(stg2
, stgname
, STGM_READWRITE
| STGM_SHARE_EXCLUSIVE
, 0, 0, &stg3
);
1665 ok(r
==S_OK
, "IStorage->CreateStorage failed, hr=%08x\n", r
);
1668 IStorage_Release(stg3
);
1670 r
= IStorage_Commit(stg
, 0);
1671 ok(r
==S_OK
, "IStorage->Commit failed\n");
1673 r
= IStorage_CreateStorage(stg2
, stgname2
, STGM_READWRITE
| STGM_SHARE_EXCLUSIVE
, 0, 0, &stg3
);
1674 ok(r
==S_OK
, "IStorage->CreateStorage failed, hr=%08x\n", r
);
1677 IStorage_Release(stg3
);
1680 /* now create a stream and storage, then revert */
1681 r
= IStorage_CreateStream(stg
, stmname
, STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
, 0, 0, &stm2
);
1682 ok(r
==S_OK
, "IStorage->CreateStream failed\n");
1684 r
= IStream_Write(stm2
, "this is stream 2\n", 16, NULL
);
1685 ok(r
==S_OK
, "IStream->Write failed\n");
1687 r
= IStorage_CreateStorage(stg
, stgname2
, STGM_READWRITE
| STGM_SHARE_EXCLUSIVE
, 0, 0, &stg3
);
1688 ok(r
==S_OK
, "IStorage->CreateStorage failed, hr=%08x\n", r
);
1690 r
= IStorage_Revert(stg
);
1691 ok(r
==S_OK
, "Storage_Revert failed with error 0x%08x\n", r
);
1693 /* all open objects become invalid */
1694 r
= IStream_Write(stm
, "this shouldn't work\n", 20, NULL
);
1695 ok(r
==STG_E_REVERTED
, "IStream_Write should fail %08x\n", r
);
1697 r
= IStream_Write(stm2
, "this shouldn't work\n", 20, NULL
);
1698 ok(r
==STG_E_REVERTED
, "IStream_Write should fail %08x\n", r
);
1700 r
= IStorage_Stat(stg2
, &statstg
, STATFLAG_NONAME
);
1701 ok(r
==STG_E_REVERTED
, "IStorage_Stat should fail %08x\n", r
);
1703 r
= IStorage_Stat(stg3
, &statstg
, STATFLAG_NONAME
);
1704 ok(r
==STG_E_REVERTED
, "IStorage_Stat should fail %08x\n", r
);
1706 IStream_Release(stm
);
1707 IStream_Release(stm2
);
1708 IStorage_Release(stg2
);
1709 IStorage_Release(stg3
);
1711 r
= IStorage_OpenStream(stg
, stmname
, NULL
, STGM_SHARE_DENY_NONE
|STGM_READ
, 0, &stm
);
1712 ok(r
==STG_E_INVALIDFLAG
, "IStorage->OpenStream failed %08x\n", r
);
1714 r
= IStorage_OpenStream(stg
, stmname
, NULL
, STGM_DELETEONRELEASE
|STGM_SHARE_EXCLUSIVE
|STGM_READWRITE
, 0, &stm
);
1715 ok(r
==STG_E_INVALIDFUNCTION
, "IStorage->OpenStream failed %08x\n", r
);
1717 r
= IStorage_OpenStream(stg
, stmname
, NULL
, STGM_TRANSACTED
|STGM_SHARE_EXCLUSIVE
|STGM_READWRITE
, 0, &stm
);
1718 ok(r
==STG_E_INVALIDFUNCTION
, "IStorage->OpenStream failed %08x\n", r
);
1720 r
= IStorage_OpenStorage(stg
, stmname
, NULL
, STGM_TRANSACTED
|STGM_SHARE_EXCLUSIVE
|STGM_READWRITE
, NULL
, 0, &stg2
);
1721 ok(r
==STG_E_FILENOTFOUND
, "IStorage->OpenStream failed %08x\n", r
);
1723 r
= IStorage_OpenStream(stg
, stmname
, NULL
, STGM_SHARE_EXCLUSIVE
|STGM_READWRITE
, 0, &stm
);
1724 ok(r
==STG_E_FILENOTFOUND
, "IStorage->OpenStream should fail %08x\n", r
);
1726 IStream_Release(stm
);
1728 r
= IStorage_OpenStorage(stg
, stgname2
, NULL
, STGM_SHARE_EXCLUSIVE
|STGM_READWRITE
, NULL
, 0, &stg2
);
1729 ok(r
==STG_E_FILENOTFOUND
, "IStorage->OpenStorage should fail %08x\n", r
);
1731 IStorage_Release(stg2
);
1733 r
= IStorage_OpenStorage(stg
, stmname2
, NULL
, STGM_TRANSACTED
|STGM_SHARE_EXCLUSIVE
|STGM_READWRITE
, NULL
, 0, &stg2
);
1734 ok(r
==STG_E_FILENOTFOUND
, "IStorage->OpenStream failed %08x\n", r
);
1736 r
= IStorage_OpenStream(stg
, stmname2
, NULL
, STGM_SHARE_EXCLUSIVE
|STGM_READWRITE
, 0, &stm
);
1737 ok(r
==S_OK
, "IStorage->OpenStream should succeed %08x\n", r
);
1739 IStream_Release(stm
);
1741 r
= IStorage_OpenStorage(stg
, stgname
, NULL
, STGM_SHARE_EXCLUSIVE
|STGM_READWRITE
, NULL
, 0, &stg2
);
1742 ok(r
==S_OK
, "IStorage->OpenStorage should succeed %08x\n", r
);
1745 r
= IStorage_OpenStorage(stg2
, stgname
, NULL
, STGM_SHARE_EXCLUSIVE
|STGM_READWRITE
, NULL
, 0, &stg3
);
1746 ok(r
==S_OK
, "IStorage->OpenStorage should succeed %08x\n", r
);
1748 IStorage_Release(stg3
);
1750 r
= IStorage_OpenStorage(stg2
, stgname2
, NULL
, STGM_SHARE_EXCLUSIVE
|STGM_READWRITE
, NULL
, 0, &stg3
);
1751 ok(r
==STG_E_FILENOTFOUND
, "IStorage->OpenStorage should fail %08x\n", r
);
1753 IStorage_Release(stg3
);
1755 IStorage_Release(stg2
);
1758 IStorage_Release(stg
);
1760 ret
= DeleteFileA(filenameA
);
1761 ok(ret
, "deleted file\n");
1763 /* Revert only invalidates objects in transacted mode */
1764 r
= StgCreateDocfile( filename
, STGM_CREATE
| STGM_SHARE_EXCLUSIVE
|
1765 STGM_READWRITE
, 0, &stg
);
1766 ok(r
==S_OK
, "StgCreateDocfile failed\n");
1768 r
= IStorage_CreateStream(stg
, stmname2
, STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
, 0, 0, &stm
);
1769 ok(r
==S_OK
, "IStorage->CreateStream failed\n");
1771 r
= IStorage_Revert(stg
);
1772 ok(r
==S_OK
, "IStorage->Revert failed %08x\n", r
);
1774 r
= IStream_Write(stm
, "this works\n", 11, NULL
);
1775 ok(r
==S_OK
, "IStream_Write should succeed %08x\n", r
);
1777 IStream_Release(stm
);
1778 IStorage_Release(stg
);
1780 ret
= DeleteFileA(filenameA
);
1781 ok(ret
, "deleted file\n");
1784 static void test_parent_free(void)
1786 IStorage
*stg
= NULL
, *stg2
= NULL
, *stg3
= NULL
;
1788 IStream
*stm
= NULL
;
1789 static const WCHAR stmname
[] = { 'C','O','N','T','E','N','T','S',0 };
1790 static const WCHAR stgname
[] = { 'P','E','R','M','S','T','G',0 };
1795 DeleteFileA(filenameA
);
1797 /* create the file */
1798 r
= StgCreateDocfile( filename
, STGM_CREATE
| STGM_SHARE_EXCLUSIVE
|
1799 STGM_READWRITE
|STGM_TRANSACTED
, 0, &stg
);
1800 ok(r
==S_OK
, "StgCreateDocfile failed\n");
1802 /* create a new storage */
1803 r
= IStorage_CreateStorage(stg
, stgname
, STGM_READWRITE
| STGM_SHARE_EXCLUSIVE
, 0, 0, &stg2
);
1804 ok(r
==S_OK
, "IStorage->CreateStorage failed, hr=%08x\n", r
);
1808 /* now create a stream inside the new storage */
1809 r
= IStorage_CreateStream(stg2
, stmname
, STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
, 0, 0, &stm
);
1810 ok(r
==S_OK
, "IStorage->CreateStream failed\n");
1814 /* create a storage inside the new storage */
1815 r
= IStorage_CreateStorage(stg2
, stgname
, STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
, 0, 0, &stg3
);
1816 ok(r
==S_OK
, "IStorage->CreateStorage failed\n");
1819 /* free the parent */
1820 ref
= IStorage_Release(stg2
);
1821 ok(ref
== 0, "IStorage still has %u references\n", ref
);
1823 /* child objects are invalid */
1826 r
= IStream_Write(stm
, "this should fail\n", 17, NULL
);
1827 ok(r
==STG_E_REVERTED
, "IStream->Write should fail, hr=%x\n", r
);
1829 IStream_Release(stm
);
1831 r
= IStorage_Stat(stg3
, &statstg
, STATFLAG_NONAME
);
1832 ok(r
==STG_E_REVERTED
, "IStorage_Stat should fail %08x\n", r
);
1834 r
= IStorage_SetStateBits(stg3
, 1, 1);
1835 ok(r
==STG_E_REVERTED
, "IStorage_Stat should fail %08x\n", r
);
1837 IStorage_Release(stg3
);
1841 IStorage_Release(stg
);
1843 ret
= DeleteFileA(filenameA
);
1844 ok(ret
, "deleted file\n");
1847 static void test_nonroot_transacted(void)
1849 IStorage
*stg
= NULL
, *stg2
= NULL
, *stg3
= NULL
;
1851 IStream
*stm
= NULL
;
1852 static const WCHAR stgname
[] = { 'P','E','R','M','S','T','G',0 };
1853 static const WCHAR stmname
[] = { 'C','O','N','T','E','N','T','S',0 };
1854 static const WCHAR stmname2
[] = { 'F','O','O',0 };
1857 DeleteFileA(filenameA
);
1859 /* create a transacted file */
1860 r
= StgCreateDocfile( filename
, STGM_CREATE
| STGM_SHARE_EXCLUSIVE
|
1861 STGM_READWRITE
|STGM_TRANSACTED
, 0, &stg
);
1862 ok(r
==S_OK
, "StgCreateDocfile failed\n");
1864 /* create a transacted substorage */
1865 r
= IStorage_CreateStorage(stg
, stgname
, STGM_READWRITE
| STGM_SHARE_EXCLUSIVE
| STGM_TRANSACTED
, 0, 0, &stg2
);
1866 ok(r
==S_OK
, "IStorage->CreateStorage failed, hr=%08x\n", r
);
1870 /* create and commit stmname */
1871 r
= IStorage_CreateStream(stg2
, stmname
, STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
, 0, 0, &stm
);
1872 ok(r
==S_OK
, "IStorage->CreateStream failed\n");
1874 IStream_Release(stm
);
1876 IStorage_Commit(stg2
, 0);
1878 /* create and revert stmname2 */
1879 r
= IStorage_CreateStream(stg2
, stmname2
, STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
, 0, 0, &stm
);
1880 ok(r
==S_OK
, "IStorage->CreateStream failed\n");
1882 IStream_Release(stm
);
1884 IStorage_Revert(stg2
);
1886 /* check that Commit and Revert really worked */
1887 r
= IStorage_OpenStream(stg2
, stmname
, NULL
, STGM_SHARE_EXCLUSIVE
|STGM_READWRITE
, 0, &stm
);
1888 ok(r
==S_OK
, "IStorage->OpenStream should succeed %08x\n", r
);
1890 IStream_Release(stm
);
1892 r
= IStorage_OpenStream(stg2
, stmname2
, NULL
, STGM_SHARE_EXCLUSIVE
|STGM_READWRITE
, 0, &stm
);
1893 ok(r
==STG_E_FILENOTFOUND
, "IStorage->OpenStream should fail %08x\n", r
);
1895 IStream_Release(stm
);
1897 IStorage_Release(stg2
);
1900 /* create a read-only transacted substorage */
1901 r
= IStorage_OpenStorage(stg
, stgname
, NULL
, STGM_READ
| STGM_SHARE_EXCLUSIVE
| STGM_TRANSACTED
, NULL
, 0, &stg2
);
1902 ok(r
==S_OK
, "IStorage->OpenStorage failed, hr=%08x\n", r
);
1906 /* The storage can be modified. */
1907 r
= IStorage_CreateStorage(stg2
, stgname
, STGM_READWRITE
| STGM_SHARE_EXCLUSIVE
, 0, 0, &stg3
);
1908 ok(r
==S_OK
, "IStorage->CreateStorage failed, hr=%08x\n", r
);
1910 IStorage_Release(stg3
);
1912 /* But changes cannot be committed. */
1913 r
= IStorage_Commit(stg2
, 0);
1914 ok(r
==STG_E_ACCESSDENIED
, "IStorage->Commit should fail, hr=%08x\n", r
);
1916 IStorage_Release(stg2
);
1919 IStorage_Release(stg
);
1921 /* create a non-transacted file */
1922 r
= StgCreateDocfile( filename
, STGM_CREATE
| STGM_SHARE_EXCLUSIVE
|
1923 STGM_READWRITE
, 0, &stg
);
1924 ok(r
==S_OK
, "StgCreateDocfile failed\n");
1926 /* create a transacted substorage */
1927 r
= IStorage_CreateStorage(stg
, stgname
, STGM_READWRITE
| STGM_SHARE_EXCLUSIVE
| STGM_TRANSACTED
, 0, 0, &stg2
);
1928 ok(r
==S_OK
, "IStorage->CreateStorage failed, hr=%08x\n", r
);
1932 /* create and commit stmname */
1933 r
= IStorage_CreateStream(stg2
, stmname
, STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
, 0, 0, &stm
);
1934 ok(r
==S_OK
, "IStorage->CreateStream failed\n");
1936 IStream_Release(stm
);
1938 IStorage_Commit(stg2
, 0);
1940 /* create and revert stmname2 */
1941 r
= IStorage_CreateStream(stg2
, stmname2
, STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
, 0, 0, &stm
);
1942 ok(r
==S_OK
, "IStorage->CreateStream failed\n");
1944 IStream_Release(stm
);
1946 IStorage_Revert(stg2
);
1948 /* check that Commit and Revert really worked */
1949 r
= IStorage_OpenStream(stg2
, stmname
, NULL
, STGM_SHARE_EXCLUSIVE
|STGM_READWRITE
, 0, &stm
);
1950 ok(r
==S_OK
, "IStorage->OpenStream should succeed %08x\n", r
);
1952 IStream_Release(stm
);
1954 r
= IStorage_OpenStream(stg2
, stmname2
, NULL
, STGM_SHARE_EXCLUSIVE
|STGM_READWRITE
, 0, &stm
);
1955 ok(r
==STG_E_FILENOTFOUND
, "IStorage->OpenStream should fail %08x\n", r
);
1957 IStream_Release(stm
);
1959 IStorage_Release(stg2
);
1962 IStorage_Release(stg
);
1964 ret
= DeleteFileA(filenameA
);
1965 ok(ret
, "deleted file\n");
1968 static void test_ReadClassStm(void)
1970 CLSID clsid
, clsid2
;
1973 static const LARGE_INTEGER llZero
;
1975 hr
= ReadClassStm(NULL
, &clsid
);
1976 ok(hr
== E_INVALIDARG
, "ReadClassStm should have returned E_INVALIDARG instead of 0x%08x\n", hr
);
1978 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1979 ok_ole_success(hr
, "CreateStreamOnHGlobal");
1980 hr
= WriteClassStm(pStream
, &test_stg_cls
);
1981 ok_ole_success(hr
, "WriteClassStm");
1983 hr
= ReadClassStm(pStream
, NULL
);
1984 ok(hr
== E_INVALIDARG
, "ReadClassStm should have returned E_INVALIDARG instead of 0x%08x\n", hr
);
1986 memset(&clsid
, 0xcc, sizeof(clsid
));
1987 memset(&clsid2
, 0xcc, sizeof(clsid2
));
1988 hr
= ReadClassStm(NULL
, &clsid
);
1989 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
1990 ok(IsEqualCLSID(&clsid
, &clsid2
), "got wrong clsid\n");
1992 /* test not rewound stream */
1993 hr
= ReadClassStm(pStream
, &clsid
);
1994 ok(hr
== STG_E_READFAULT
, "ReadClassStm should have returned STG_E_READFAULT instead of 0x%08x\n", hr
);
1995 ok(IsEqualCLSID(&clsid
, &CLSID_NULL
), "clsid should have been zeroed\n");
1997 hr
= IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
1998 ok_ole_success(hr
, "IStream_Seek");
1999 hr
= ReadClassStm(pStream
, &clsid
);
2000 ok_ole_success(hr
, "ReadClassStm");
2001 ok(IsEqualCLSID(&clsid
, &test_stg_cls
), "clsid should have been set to CLSID_WineTest\n");
2003 IStream_Release(pStream
);
2013 static const struct access_res create
[16] =
2015 { TRUE
, ERROR_SUCCESS
, TRUE
},
2016 { TRUE
, ERROR_SUCCESS
, TRUE
},
2017 { TRUE
, ERROR_SUCCESS
, FALSE
},
2018 { TRUE
, ERROR_SUCCESS
, FALSE
},
2019 { FALSE
, ERROR_SHARING_VIOLATION
, FALSE
},
2020 { FALSE
, ERROR_SHARING_VIOLATION
, FALSE
},
2021 { FALSE
, ERROR_SHARING_VIOLATION
, FALSE
},
2022 { TRUE
, ERROR_SUCCESS
, FALSE
},
2023 { FALSE
, ERROR_SHARING_VIOLATION
, FALSE
},
2024 { FALSE
, ERROR_SHARING_VIOLATION
, FALSE
},
2025 { FALSE
, ERROR_SHARING_VIOLATION
, FALSE
},
2026 { TRUE
, ERROR_SUCCESS
, TRUE
},
2027 { FALSE
, ERROR_SHARING_VIOLATION
, FALSE
},
2028 { FALSE
, ERROR_SHARING_VIOLATION
, FALSE
},
2029 { FALSE
, ERROR_SHARING_VIOLATION
, FALSE
},
2030 { TRUE
, ERROR_SUCCESS
, TRUE
}
2033 static const struct access_res create_commit
[16] =
2035 { TRUE
, ERROR_SUCCESS
, TRUE
},
2036 { TRUE
, ERROR_SUCCESS
, TRUE
},
2037 { TRUE
, ERROR_SUCCESS
, FALSE
},
2038 { TRUE
, ERROR_SUCCESS
, FALSE
},
2039 { FALSE
, ERROR_SHARING_VIOLATION
, FALSE
},
2040 { FALSE
, ERROR_SHARING_VIOLATION
, FALSE
},
2041 { FALSE
, ERROR_SHARING_VIOLATION
, FALSE
},
2042 { TRUE
, ERROR_SUCCESS
, FALSE
},
2043 { FALSE
, ERROR_SHARING_VIOLATION
, FALSE
},
2044 { FALSE
, ERROR_SHARING_VIOLATION
, FALSE
},
2045 { FALSE
, ERROR_SHARING_VIOLATION
, FALSE
},
2046 { TRUE
, ERROR_SUCCESS
, TRUE
},
2047 { FALSE
, ERROR_SHARING_VIOLATION
, FALSE
},
2048 { FALSE
, ERROR_SHARING_VIOLATION
, FALSE
},
2049 { FALSE
, ERROR_SHARING_VIOLATION
, FALSE
},
2050 { TRUE
, ERROR_SUCCESS
, TRUE
}
2053 static const struct access_res create_close
[16] =
2055 { TRUE
, ERROR_SUCCESS
, FALSE
},
2056 { TRUE
, ERROR_SUCCESS
, FALSE
},
2057 { TRUE
, ERROR_SUCCESS
, FALSE
},
2058 { TRUE
, ERROR_SUCCESS
, FALSE
},
2059 { TRUE
, ERROR_SUCCESS
, FALSE
},
2060 { TRUE
, ERROR_SUCCESS
, FALSE
},
2061 { TRUE
, ERROR_SUCCESS
, FALSE
},
2062 { TRUE
, ERROR_SUCCESS
, FALSE
},
2063 { TRUE
, ERROR_SUCCESS
, FALSE
},
2064 { TRUE
, ERROR_SUCCESS
, FALSE
},
2065 { TRUE
, ERROR_SUCCESS
, FALSE
},
2066 { TRUE
, ERROR_SUCCESS
, FALSE
},
2067 { TRUE
, ERROR_SUCCESS
, FALSE
},
2068 { TRUE
, ERROR_SUCCESS
, FALSE
},
2069 { TRUE
, ERROR_SUCCESS
, FALSE
},
2070 { TRUE
, ERROR_SUCCESS
}
2073 static const DWORD access_modes
[4] = {
2077 GENERIC_READ
| GENERIC_WRITE
2080 static const DWORD share_modes
[4] = {
2084 FILE_SHARE_READ
| FILE_SHARE_WRITE
2087 static void _test_file_access(LPCSTR file
, const struct access_res
*ares
, DWORD line
)
2091 for (i
= 0; i
< ARRAY_SIZE(access_modes
); i
++)
2093 for (j
= 0; j
< ARRAY_SIZE(share_modes
); j
++)
2098 if (ares
[idx
].ignore
)
2101 SetLastError(0xdeadbeef);
2102 hfile
= CreateFileA(file
, access_modes
[i
], share_modes
[j
], NULL
, OPEN_EXISTING
,
2103 FILE_ATTRIBUTE_NORMAL
, 0);
2104 lasterr
= GetLastError();
2106 ok((hfile
!= INVALID_HANDLE_VALUE
) == ares
[idx
].gothandle
,
2107 "(%d, handle, %d): Expected %d, got %d\n",
2108 line
, idx
, ares
[idx
].gothandle
,
2109 (hfile
!= INVALID_HANDLE_VALUE
));
2111 ok(lasterr
== ares
[idx
].lasterr
||
2112 broken(lasterr
== 0xdeadbeef) /* win9x */,
2113 "(%d, lasterr, %d): Expected %d, got %d\n",
2114 line
, idx
, ares
[idx
].lasterr
, lasterr
);
2122 #define test_file_access(file, ares) _test_file_access(file, ares, __LINE__)
2124 static void test_access(void)
2126 static const WCHAR fileW
[] = {'w','i','n','e','t','e','s','t',0};
2127 static const char fileA
[] = "winetest";
2131 /* STGM_TRANSACTED */
2132 hr
= StgCreateDocfile(fileW
, STGM_CREATE
| STGM_READWRITE
|
2133 STGM_SHARE_EXCLUSIVE
| STGM_TRANSACTED
, 0, &stg
);
2134 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2136 test_file_access(fileA
, create
);
2138 hr
= IStorage_Commit(stg
, STGC_DEFAULT
);
2139 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2141 test_file_access(fileA
, create_commit
);
2143 IStorage_Release(stg
);
2145 test_file_access(fileA
, create_close
);
2150 hr
= StgCreateDocfile(fileW
, STGM_CREATE
| STGM_READWRITE
|
2151 STGM_SHARE_EXCLUSIVE
| STGM_DIRECT
, 0, &stg
);
2152 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2154 test_file_access(fileA
, create
);
2156 hr
= IStorage_Commit(stg
, STGC_DEFAULT
);
2157 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2159 test_file_access(fileA
, create_commit
);
2161 IStorage_Release(stg
);
2163 test_file_access(fileA
, create_close
);
2167 /* STGM_SHARE_DENY_NONE */
2168 hr
= StgCreateDocfile(fileW
, STGM_CREATE
| STGM_READWRITE
|
2169 STGM_SHARE_DENY_NONE
| STGM_TRANSACTED
, 0, &stg
);
2170 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2172 test_file_access(fileA
, create
);
2174 hr
= IStorage_Commit(stg
, STGC_DEFAULT
);
2175 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2177 test_file_access(fileA
, create_commit
);
2179 IStorage_Release(stg
);
2181 test_file_access(fileA
, create_close
);
2185 /* STGM_SHARE_DENY_READ */
2186 hr
= StgCreateDocfile(fileW
, STGM_CREATE
| STGM_READWRITE
|
2187 STGM_SHARE_DENY_READ
| STGM_TRANSACTED
, 0, &stg
);
2188 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2190 test_file_access(fileA
, create
);
2192 hr
= IStorage_Commit(stg
, STGC_DEFAULT
);
2193 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2195 test_file_access(fileA
, create_commit
);
2197 IStorage_Release(stg
);
2199 test_file_access(fileA
, create_close
);
2203 /* STGM_SHARE_DENY_WRITE */
2204 hr
= StgCreateDocfile(fileW
, STGM_CREATE
| STGM_READWRITE
|
2205 STGM_SHARE_DENY_WRITE
| STGM_TRANSACTED
, 0, &stg
);
2206 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2208 test_file_access(fileA
, create
);
2210 hr
= IStorage_Commit(stg
, STGC_DEFAULT
);
2211 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
2213 test_file_access(fileA
, create_commit
);
2215 IStorage_Release(stg
);
2217 test_file_access(fileA
, create_close
);
2221 /* STGM_DIRECT_SWMR | STGM_READ | STGM_SHARE_DENY_NONE - reader mode for direct SWMR mode */
2222 hr
= StgCreateDocfile(fileW
, STGM_CREATE
| STGM_READWRITE
| STGM_SHARE_DENY_WRITE
| STGM_TRANSACTED
, 0, &stg
);
2223 ok(hr
== S_OK
, "got %08x\n", hr
);
2224 IStorage_Release(stg
);
2226 hr
= StgOpenStorage(fileW
, NULL
, STGM_DIRECT_SWMR
| STGM_READ
| STGM_SHARE_DENY_NONE
, NULL
, 0, &stg
);
2227 ok(hr
== S_OK
|| broken(hr
== STG_E_INVALIDFLAG
), "got %08x\n", hr
);
2231 test_file_access(fileA
, create
);
2233 IStorage_Release(stg
);
2234 test_file_access(fileA
, create_close
);
2239 static void test_readonly(void)
2241 IStorage
*stg
, *stg2
, *stg3
;
2244 static const WCHAR fileW
[] = {'w','i','n','e','t','e','s','t',0};
2245 static const WCHAR storageW
[] = {'s','t','o','r','a','g','e',0};
2246 static const WCHAR streamW
[] = {'s','t','r','e','a','m',0};
2248 hr
= StgCreateDocfile( fileW
, STGM_CREATE
| STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
, 0, &stg
);
2249 ok(hr
== S_OK
, "should succeed, res=%x\n", hr
);
2252 hr
= IStorage_CreateStorage( stg
, storageW
, STGM_CREATE
| STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
, 0, 0, &stg2
);
2253 ok(hr
== S_OK
, "should succeed, res=%x\n", hr
);
2256 hr
= IStorage_CreateStream( stg2
, streamW
, STGM_CREATE
| STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
, 0, 0, &stream
);
2257 ok(hr
== S_OK
, "should succeed, res=%x\n", hr
);
2259 IStream_Release(stream
);
2260 IStorage_Release(stg2
);
2262 IStorage_Release(stg
);
2265 /* re-open read only */
2266 hr
= StgOpenStorage( fileW
, NULL
, STGM_TRANSACTED
| STGM_SHARE_DENY_NONE
| STGM_READ
, NULL
, 0, &stg
);
2267 ok(hr
== S_OK
, "should succeed, res=%x\n", hr
);
2270 hr
= IStorage_OpenStorage( stg
, storageW
, NULL
, STGM_SHARE_EXCLUSIVE
| STGM_READ
, NULL
, 0, &stg2
);
2271 ok(hr
== S_OK
, "should succeed, res=%x\n", hr
);
2274 /* CreateStream on read-only storage, name exists */
2275 hr
= IStorage_CreateStream( stg2
, streamW
, STGM_CREATE
| STGM_SHARE_EXCLUSIVE
| STGM_READ
, 0, 0, &stream
);
2276 ok(hr
== STG_E_ACCESSDENIED
, "should fail, res=%x\n", hr
);
2278 IStream_Release(stream
);
2280 /* CreateStream on read-only storage, name does not exist */
2281 hr
= IStorage_CreateStream( stg2
, storageW
, STGM_CREATE
| STGM_SHARE_EXCLUSIVE
| STGM_READ
, 0, 0, &stream
);
2282 ok(hr
== STG_E_ACCESSDENIED
, "should fail, res=%x\n", hr
);
2284 IStream_Release(stream
);
2286 /* CreateStorage on read-only storage, name exists */
2287 hr
= IStorage_CreateStorage( stg2
, streamW
, STGM_CREATE
| STGM_SHARE_EXCLUSIVE
| STGM_READ
, 0, 0, &stg3
);
2288 ok(hr
== STG_E_FILEALREADYEXISTS
, "should fail, res=%x\n", hr
);
2290 IStorage_Release(stg3
);
2292 /* CreateStorage on read-only storage, name does not exist */
2293 hr
= IStorage_CreateStorage( stg2
, storageW
, STGM_CREATE
| STGM_SHARE_EXCLUSIVE
| STGM_READ
, 0, 0, &stg3
);
2294 ok(hr
== STG_E_ACCESSDENIED
, "should fail, res=%x\n", hr
);
2296 IStorage_Release(stg3
);
2298 /* DestroyElement on read-only storage, name exists */
2299 hr
= IStorage_DestroyElement( stg2
, streamW
);
2300 ok(hr
== STG_E_ACCESSDENIED
, "should fail, res=%x\n", hr
);
2302 /* DestroyElement on read-only storage, name does not exist */
2303 hr
= IStorage_DestroyElement( stg2
, storageW
);
2304 ok(hr
== STG_E_ACCESSDENIED
, "should fail, res=%x\n", hr
);
2306 IStorage_Release(stg2
);
2309 IStorage_Release(stg
);
2312 DeleteFileA("winetest");
2315 static void test_simple(void)
2317 /* Tests for STGM_SIMPLE mode */
2319 IStorage
*stg
, *stg2
;
2322 static const WCHAR stgname
[] = { 'S','t','g',0 };
2323 static const WCHAR stmname
[] = { 'C','O','N','T','E','N','T','S',0 };
2324 static const WCHAR stmname2
[] = { 'S','m','a','l','l',0 };
2326 ULARGE_INTEGER upos
;
2330 DeleteFileA(filenameA
);
2332 r
= StgCreateDocfile( filename
, STGM_SIMPLE
| STGM_CREATE
| STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
, 0, &stg
);
2333 ok(r
== S_OK
, "got %08x\n", r
);
2335 r
= IStorage_CreateStorage(stg
, stgname
, STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
, 0, 0, &stg2
);
2336 ok(r
== STG_E_INVALIDFUNCTION
, "got %08x\n", r
);
2337 if (SUCCEEDED(r
)) IStorage_Release(stg2
);
2339 r
= IStorage_CreateStream(stg
, stmname
, STGM_CREATE
| STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
, 0, 0, &stm
);
2340 ok(r
== STG_E_INVALIDFLAG
, "got %08x\n", r
);
2341 r
= IStorage_CreateStream(stg
, stmname
, STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
, 0, 0, &stm
);
2342 ok(r
== S_OK
, "got %08x\n", r
);
2344 upos
.QuadPart
= 6000;
2345 r
= IStream_SetSize(stm
, upos
);
2346 ok(r
== S_OK
, "got %08x\n", r
);
2348 r
= IStream_Write(stm
, "foo", 3, &count
);
2349 ok(r
== S_OK
, "got %08x\n", r
);
2350 ok(count
== 3, "got %d\n", count
);
2353 r
= IStream_Seek(stm
, pos
, STREAM_SEEK_CUR
, &upos
);
2354 ok(r
== S_OK
, "got %08x\n", r
);
2355 ok(upos
.QuadPart
== 3, "got %d\n", upos
.u
.LowPart
);
2357 r
= IStream_Stat(stm
, &stat
, STATFLAG_NONAME
);
2359 broken(r
== STG_E_INVALIDFUNCTION
), /* NT4 and below */
2362 ok(stat
.cbSize
.QuadPart
== 3, "got %d\n", stat
.cbSize
.u
.LowPart
);
2365 r
= IStream_Seek(stm
, pos
, STREAM_SEEK_SET
, &upos
);
2366 ok(r
== S_OK
, "got %08x\n", r
);
2367 ok(upos
.QuadPart
== 1, "got %d\n", upos
.u
.LowPart
);
2369 r
= IStream_Stat(stm
, &stat
, STATFLAG_NONAME
);
2371 broken(r
== STG_E_INVALIDFUNCTION
), /* NT4 and below */
2374 ok(stat
.cbSize
.QuadPart
== 1, "got %d\n", stat
.cbSize
.u
.LowPart
);
2376 IStream_Release(stm
);
2378 r
= IStorage_CreateStream(stg
, stmname2
, STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
, 0, 0, &stm
);
2379 ok(r
== S_OK
, "got %08x\n", r
);
2381 upos
.QuadPart
= 100;
2382 r
= IStream_SetSize(stm
, upos
);
2383 ok(r
== S_OK
, "got %08x\n", r
);
2385 r
= IStream_Write(stm
, "foo", 3, &count
);
2386 ok(r
== S_OK
, "got %08x\n", r
);
2387 ok(count
== 3, "got %d\n", count
);
2389 IStream_Release(stm
);
2391 IStorage_Commit(stg
, STGC_DEFAULT
);
2392 IStorage_Release(stg
);
2394 r
= StgOpenStorage( filename
, NULL
, STGM_SIMPLE
| STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
, NULL
, 0, &stg
);
2395 if (r
== STG_E_INVALIDFLAG
)
2397 win_skip("Flag combination is not supported on NT4 and below\n");
2398 DeleteFileA(filenameA
);
2401 ok(r
== S_OK
, "got %08x\n", r
);
2403 r
= IStorage_OpenStorage(stg
, stgname
, NULL
, STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
, NULL
, 0, &stg2
);
2404 ok(r
== STG_E_INVALIDFUNCTION
, "got %08x\n", r
);
2405 if (SUCCEEDED(r
)) IStorage_Release(stg2
);
2407 r
= IStorage_OpenStream(stg
, stmname
, NULL
, STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
, 0, &stm
);
2408 ok(r
== S_OK
, "got %08x\n", r
);
2410 r
= IStream_Stat(stm
, &stat
, STATFLAG_NONAME
);
2411 ok(r
== S_OK
, "got %08x\n", r
);
2412 ok(stat
.cbSize
.QuadPart
== 6000, "got %d\n", stat
.cbSize
.u
.LowPart
);
2414 IStream_Release(stm
);
2416 r
= IStorage_OpenStream(stg
, stmname2
, NULL
, STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
, 0, &stm
);
2417 ok(r
== S_OK
, "got %08x\n", r
);
2419 r
= IStream_Stat(stm
, &stat
, STATFLAG_NONAME
);
2420 ok(r
== S_OK
, "got %08x\n", r
);
2421 ok(stat
.cbSize
.QuadPart
== 4096, "got %d\n", stat
.cbSize
.u
.LowPart
);
2423 IStream_Release(stm
);
2426 IStorage_Release(stg
);
2428 DeleteFileA(filenameA
);
2431 static void test_fmtusertypestg(void)
2436 static const char fileA
[] = {'f','m','t','t','e','s','t',0};
2437 static const WCHAR fileW
[] = {'f','m','t','t','e','s','t',0};
2438 static WCHAR userTypeW
[] = {'S','t','g','U','s','r','T','y','p','e',0};
2439 static const WCHAR strmNameW
[] = {1,'C','o','m','p','O','b','j',0};
2440 static const STATSTG statstg_null
;
2442 hr
= StgCreateDocfile( fileW
, STGM_CREATE
| STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
, 0, &stg
);
2443 ok(hr
== S_OK
, "should succeed, res=%x\n", hr
);
2447 /* try to write the stream */
2448 hr
= WriteFmtUserTypeStg(stg
, 0, userTypeW
);
2449 ok(hr
== S_OK
, "should succeed, res=%x\n", hr
);
2451 /* check that the stream was created */
2452 hr
= IStorage_EnumElements(stg
, 0, NULL
, 0, &stat
);
2453 ok(hr
== S_OK
, "should succeed, res=%x\n", hr
);
2459 memset(&statstg
, 0xad, sizeof(statstg
));
2460 while ((hr
= IEnumSTATSTG_Next(stat
, 1, &statstg
, &got
)) == S_OK
&& got
== 1)
2462 if (strcmp_ww(statstg
.pwcsName
, strmNameW
) == 0)
2465 ok(0, "found unexpected stream or storage\n");
2466 CoTaskMemFree(statstg
.pwcsName
);
2468 ok(memcmp(&statstg
, &statstg_null
, sizeof(statstg
)) == 0, "statstg is not zeroed\n");
2469 ok(found
== TRUE
, "expected storage to contain stream \\0001CompObj\n");
2470 IEnumSTATSTG_Release(stat
);
2473 /* re-write the stream */
2474 hr
= WriteFmtUserTypeStg(stg
, 0, userTypeW
);
2475 ok(hr
== S_OK
, "should succeed, res=%x\n", hr
);
2477 /* check that the stream is still there */
2478 hr
= IStorage_EnumElements(stg
, 0, NULL
, 0, &stat
);
2479 ok(hr
== S_OK
, "should succeed, res=%x\n", hr
);
2485 memset(&statstg
, 0xad, sizeof(statstg
));
2486 while ((hr
= IEnumSTATSTG_Next(stat
, 1, &statstg
, &got
)) == S_OK
&& got
== 1)
2488 if (strcmp_ww(statstg
.pwcsName
, strmNameW
) == 0)
2491 ok(0, "found unexpected stream or storage\n");
2492 CoTaskMemFree(statstg
.pwcsName
);
2494 ok(memcmp(&statstg
, &statstg_null
, sizeof(statstg
)) == 0, "statstg is not zeroed\n");
2495 ok(found
== TRUE
, "expected storage to contain stream \\0001CompObj\n");
2496 IEnumSTATSTG_Release(stat
);
2499 IStorage_Release(stg
);
2500 DeleteFileA( fileA
);
2504 static void test_references(void)
2506 IStorage
*stg
,*stg2
;
2509 static const WCHAR StorName
[] = { 'D','a','t','a','S','p','a','c','e','I','n','f','o',0 };
2511 DeleteFileA(filenameA
);
2513 hr
= StgCreateDocfile( filename
, STGM_CREATE
| STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
|STGM_TRANSACTED
, 0, &stg
);
2514 ok(hr
==S_OK
, "StgCreateDocfile failed\n");
2518 IStorage_Release(stg
);
2520 hr
= StgOpenStorage( filename
, NULL
, STGM_TRANSACTED
| STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
, NULL
, 0, &stg
);
2521 ok(hr
==S_OK
, "StgOpenStorage failed (result=%x)\n",hr
);
2525 hr
= IStorage_CreateStorage(stg
,StorName
,STGM_READWRITE
| STGM_SHARE_EXCLUSIVE
,0,0,&stg2
);
2526 ok(hr
== S_OK
, "IStorage_CreateStorage failed (result=%x)\n",hr
);
2530 c1
= IStorage_AddRef(stg
);
2531 ok(c1
== 2, "creating internal storage added references to ancestor\n");
2532 c1
= IStorage_AddRef(stg
);
2533 IStorage_Release(stg2
);
2534 c2
= IStorage_AddRef(stg
) - 1;
2535 ok(c1
== c2
, "releasing internal storage removed references to ancestor\n");
2537 c1
= IStorage_Release(stg
);
2538 while ( c1
) c1
= IStorage_Release(stg
);
2542 DeleteFileA(filenameA
);
2547 * | `StreamA: "StreamA"
2549 * | `StreamB: "StreamB"
2550 * `StreamC: "StreamC"
2552 static HRESULT
create_test_file(IStorage
*dest
)
2554 IStorage
*stgA
= NULL
, *stgB
= NULL
;
2555 IStream
*strmA
= NULL
, *strmB
= NULL
, *strmC
= NULL
;
2556 const ULONG strmA_name_size
= lstrlenW(strmA_name
) * sizeof(WCHAR
);
2557 const ULONG strmB_name_size
= lstrlenW(strmB_name
) * sizeof(WCHAR
);
2558 const ULONG strmC_name_size
= lstrlenW(strmC_name
) * sizeof(WCHAR
);
2562 hr
= IStorage_CreateStorage(dest
, stgA_name
, STGM_READWRITE
| STGM_SHARE_EXCLUSIVE
, 0, 0, &stgA
);
2563 ok(hr
== S_OK
, "IStorage_CreateStorage failed: 0x%08x\n", hr
);
2567 hr
= IStorage_CreateStream(stgA
, strmA_name
, STGM_READWRITE
| STGM_SHARE_EXCLUSIVE
, 0, 0, &strmA
);
2568 ok(hr
== S_OK
, "IStorage_CreateStream failed: 0x%08x\n", hr
);
2572 hr
= IStream_Write(strmA
, strmA_name
, strmA_name_size
, &bytes
);
2573 ok(hr
== S_OK
&& bytes
== strmA_name_size
, "IStream_Write failed: 0x%08x, %d of %d bytes written\n", hr
, bytes
, strmA_name_size
);
2575 hr
= IStorage_CreateStorage(dest
, stgB_name
, STGM_READWRITE
| STGM_SHARE_EXCLUSIVE
, 0, 0, &stgB
);
2576 ok(hr
== S_OK
, "IStorage_CreateStorage failed: 0x%08x\n", hr
);
2580 hr
= IStorage_CreateStream(stgB
, strmB_name
, STGM_READWRITE
| STGM_SHARE_EXCLUSIVE
, 0, 0, &strmB
);
2581 ok(hr
== S_OK
, "IStorage_CreateStream failed: 0x%08x\n", hr
);
2585 hr
= IStream_Write(strmB
, strmB_name
, strmB_name_size
, &bytes
);
2586 ok(hr
== S_OK
&& bytes
== strmB_name_size
, "IStream_Write failed: 0x%08x, %d of %d bytes written\n", hr
, bytes
, strmB_name_size
);
2588 hr
= IStorage_CreateStream(dest
, strmC_name
, STGM_READWRITE
| STGM_SHARE_EXCLUSIVE
, 0, 0, &strmC
);
2589 ok(hr
== S_OK
, "IStorage_CreateStream failed: 0x%08x\n", hr
);
2593 hr
= IStream_Write(strmC
, strmC_name
, strmC_name_size
, &bytes
);
2594 ok(hr
== S_OK
&& bytes
== strmC_name_size
, "IStream_Write failed: 0x%08x, %d of %d bytes written\n", hr
, bytes
, strmC_name_size
);
2598 IStream_Release(strmC
);
2600 IStream_Release(strmB
);
2602 IStorage_Release(stgB
);
2604 IStream_Release(strmA
);
2606 IStorage_Release(stgA
);
2611 static void test_copyto(void)
2613 IStorage
*file1
= NULL
, *file2
= NULL
, *stg_tmp
;
2618 /* create & populate file1 */
2619 hr
= StgCreateDocfile(file1_name
, STGM_CREATE
| STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
, 0, &file1
);
2620 ok(hr
== S_OK
, "StgCreateDocfile failed: 0x%08x\n", hr
);
2624 hr
= create_test_file(file1
);
2629 hr
= StgCreateDocfile(file2_name
, STGM_CREATE
| STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
, 0, &file2
);
2630 ok(hr
== S_OK
, "StgCreateDocfile failed: 0x%08x\n", hr
);
2634 /* copy file1 into file2 */
2635 hr
= IStorage_CopyTo(file1
, 0, NULL
, NULL
, NULL
);
2636 ok(hr
== STG_E_INVALIDPOINTER
, "CopyTo should give STG_E_INVALIDPONITER, gave: 0x%08x\n", hr
);
2638 hr
= IStorage_CopyTo(file1
, 0, NULL
, NULL
, file2
);
2639 ok(hr
== S_OK
, "CopyTo failed: 0x%08x\n", hr
);
2643 /* verify that all of file1 was copied */
2644 hr
= IStorage_OpenStorage(file2
, stgA_name
, NULL
,
2645 STGM_READWRITE
| STGM_SHARE_EXCLUSIVE
, NULL
, 0, &stg_tmp
);
2646 ok(hr
== S_OK
, "OpenStorage failed: 0x%08x\n", hr
);
2649 hr
= IStorage_OpenStream(stg_tmp
, strmA_name
, NULL
,
2650 STGM_READWRITE
| STGM_SHARE_EXCLUSIVE
, 0, &strm_tmp
);
2651 ok(hr
== S_OK
, "OpenStream failed: 0x%08x\n", hr
);
2654 memset(buf
, 0, sizeof(buf
));
2655 hr
= IStream_Read(strm_tmp
, buf
, sizeof(buf
), NULL
);
2656 ok(hr
== S_OK
, "Read failed: 0x%08x\n", hr
);
2658 ok(strcmp_ww(buf
, strmA_name
) == 0,
2659 "Expected %s to be read, got %s\n", wine_dbgstr_w(strmA_name
), wine_dbgstr_w(buf
));
2661 IStream_Release(strm_tmp
);
2664 IStorage_Release(stg_tmp
);
2667 hr
= IStorage_OpenStorage(file2
, stgB_name
, NULL
,
2668 STGM_READWRITE
| STGM_SHARE_EXCLUSIVE
, NULL
, 0, &stg_tmp
);
2669 ok(hr
== S_OK
, "OpenStorage failed: 0x%08x\n", hr
);
2672 hr
= IStorage_OpenStream(stg_tmp
, strmB_name
, NULL
,
2673 STGM_READWRITE
| STGM_SHARE_EXCLUSIVE
, 0, &strm_tmp
);
2674 ok(hr
== S_OK
, "OpenStream failed: 0x%08x\n", hr
);
2677 memset(buf
, 0, sizeof(buf
));
2678 hr
= IStream_Read(strm_tmp
, buf
, sizeof(buf
), NULL
);
2679 ok(hr
== S_OK
, "Read failed: 0x%08x\n", hr
);
2681 ok(strcmp_ww(buf
, strmB_name
) == 0,
2682 "Expected %s to be read, got %s\n", wine_dbgstr_w(strmB_name
), wine_dbgstr_w(buf
));
2684 IStream_Release(strm_tmp
);
2687 IStorage_Release(stg_tmp
);
2690 hr
= IStorage_OpenStream(file2
, strmC_name
, NULL
,
2691 STGM_READWRITE
| STGM_SHARE_EXCLUSIVE
, 0, &strm_tmp
);
2692 ok(hr
== S_OK
, "OpenStream failed: 0x%08x\n", hr
);
2695 memset(buf
, 0, sizeof(buf
));
2696 hr
= IStream_Read(strm_tmp
, buf
, sizeof(buf
), NULL
);
2697 ok(hr
== S_OK
, "Read failed: 0x%08x\n", hr
);
2699 ok(strcmp_ww(buf
, strmC_name
) == 0,
2700 "Expected %s to be read, got %s\n", wine_dbgstr_w(strmC_name
), wine_dbgstr_w(buf
));
2702 IStream_Release(strm_tmp
);
2707 IStorage_Release(file1
);
2709 IStorage_Release(file2
);
2711 DeleteFileA(file1_nameA
);
2712 DeleteFileA(file2_nameA
);
2715 static void test_copyto_snbexclusions(void)
2717 static const WCHAR
*snb_exclude
[] = {stgA_name
, strmB_name
, strmC_name
, 0};
2719 IStorage
*file1
= NULL
, *file2
= NULL
, *stg_tmp
;
2724 /* create & populate file1 */
2725 hr
= StgCreateDocfile(file1_name
, STGM_CREATE
| STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
, 0, &file1
);
2726 ok(hr
== S_OK
, "StgCreateDocfile failed: 0x%08x\n", hr
);
2730 hr
= create_test_file(file1
);
2735 hr
= StgCreateDocfile(file2_name
, STGM_CREATE
| STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
, 0, &file2
);
2736 ok(hr
== S_OK
, "StgCreateDocfile failed: 0x%08x\n", hr
);
2740 /* copy file1 to file2 with name exclusions */
2741 hr
= IStorage_CopyTo(file1
, 0, NULL
, (SNB
)snb_exclude
, file2
);
2742 ok(hr
== S_OK
, "CopyTo failed: 0x%08x\n", hr
);
2746 /* verify that file1 copied over, respecting exclusions */
2747 hr
= IStorage_OpenStorage(file2
, stgA_name
, NULL
,
2748 STGM_READWRITE
| STGM_SHARE_EXCLUSIVE
, NULL
, 0, &stg_tmp
);
2749 ok(hr
== STG_E_FILENOTFOUND
, "OpenStorage should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr
);
2751 IStorage_Release(stg_tmp
);
2753 hr
= IStorage_OpenStream(file2
, strmA_name
, NULL
,
2754 STGM_READWRITE
| STGM_SHARE_EXCLUSIVE
, 0, &strm_tmp
);
2755 ok(hr
== STG_E_FILENOTFOUND
, "OpenStream should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr
);
2757 IStream_Release(strm_tmp
);
2759 hr
= IStorage_OpenStorage(file2
, stgB_name
, NULL
,
2760 STGM_READWRITE
| STGM_SHARE_EXCLUSIVE
, NULL
, 0, &stg_tmp
);
2761 ok(hr
== S_OK
, "OpenStorage failed: 0x%08x\n", hr
);
2764 hr
= IStorage_OpenStream(stg_tmp
, strmB_name
, NULL
,
2765 STGM_READWRITE
| STGM_SHARE_EXCLUSIVE
, 0, &strm_tmp
);
2766 ok(hr
== S_OK
, "OpenStream failed: 0x%08x\n", hr
);
2769 memset(buf
, 0, sizeof(buf
));
2770 hr
= IStream_Read(strm_tmp
, buf
, sizeof(buf
), NULL
);
2771 ok(hr
== S_OK
, "Read failed: 0x%08x\n", hr
);
2773 ok(strcmp_ww(buf
, strmB_name
) == 0,
2774 "Expected %s to be read, got %s\n", wine_dbgstr_w(strmB_name
), wine_dbgstr_w(buf
));
2776 IStream_Release(strm_tmp
);
2779 IStorage_Release(stg_tmp
);
2782 hr
= IStorage_OpenStream(file2
, strmC_name
, NULL
,
2783 STGM_READWRITE
| STGM_SHARE_EXCLUSIVE
, 0, &strm_tmp
);
2784 ok(hr
== STG_E_FILENOTFOUND
, "OpenStream should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr
);
2786 IStream_Release(strm_tmp
);
2790 IStorage_Release(file1
);
2792 IStorage_Release(file2
);
2794 DeleteFileA(file1_nameA
);
2795 DeleteFileA(file2_nameA
);
2798 static void test_copyto_iidexclusions_storage(void)
2800 IStorage
*file1
= NULL
, *file2
= NULL
, *stg_tmp
;
2805 /* create & populate file1 */
2806 hr
= StgCreateDocfile(file1_name
, STGM_CREATE
| STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
, 0, &file1
);
2807 ok(hr
== S_OK
, "StgCreateDocfile failed: 0x%08x\n", hr
);
2811 hr
= create_test_file(file1
);
2816 hr
= StgCreateDocfile(file2_name
, STGM_CREATE
| STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
, 0, &file2
);
2817 ok(hr
== S_OK
, "StgCreateDocfile failed: 0x%08x\n", hr
);
2821 /* copy file1 to file2 with iid exclusions */
2822 hr
= IStorage_CopyTo(file1
, 1, &IID_IStorage
, NULL
, file2
);
2823 ok(hr
== S_OK
, "CopyTo failed: 0x%08x\n", hr
);
2827 /* verify that file1 copied over, respecting exclusions */
2828 hr
= IStorage_OpenStorage(file2
, stgA_name
, NULL
,
2829 STGM_READWRITE
| STGM_SHARE_EXCLUSIVE
, NULL
, 0, &stg_tmp
);
2830 ok(hr
== STG_E_FILENOTFOUND
, "OpenStorage should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr
);
2832 IStorage_Release(stg_tmp
);
2834 hr
= IStorage_OpenStream(file2
, strmA_name
, NULL
,
2835 STGM_READWRITE
| STGM_SHARE_EXCLUSIVE
, 0, &strm_tmp
);
2836 ok(hr
== STG_E_FILENOTFOUND
, "OpenStream should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr
);
2838 IStream_Release(strm_tmp
);
2840 hr
= IStorage_OpenStorage(file2
, stgB_name
, NULL
,
2841 STGM_READWRITE
| STGM_SHARE_EXCLUSIVE
, NULL
, 0, &stg_tmp
);
2842 ok(hr
== STG_E_FILENOTFOUND
, "OpenStorage should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr
);
2844 IStorage_Release(stg_tmp
);
2846 hr
= IStorage_OpenStream(file2
, strmB_name
, NULL
,
2847 STGM_READWRITE
| STGM_SHARE_EXCLUSIVE
, 0, &strm_tmp
);
2848 ok(hr
== STG_E_FILENOTFOUND
, "OpenStream should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr
);
2850 IStream_Release(strm_tmp
);
2852 hr
= IStorage_OpenStream(file2
, strmC_name
, NULL
,
2853 STGM_READWRITE
| STGM_SHARE_EXCLUSIVE
, 0, &strm_tmp
);
2854 ok(hr
== S_OK
, "OpenStream failed: 0x%08x\n", hr
);
2857 memset(buf
, 0, sizeof(buf
));
2858 hr
= IStream_Read(strm_tmp
, buf
, sizeof(buf
), NULL
);
2859 ok(hr
== S_OK
, "Read failed: 0x%08x\n", hr
);
2861 ok(strcmp_ww(buf
, strmC_name
) == 0,
2862 "Expected %s to be read, got %s\n", wine_dbgstr_w(strmC_name
), wine_dbgstr_w(buf
));
2864 IStream_Release(strm_tmp
);
2869 IStorage_Release(file1
);
2871 IStorage_Release(file2
);
2873 DeleteFileA(file1_nameA
);
2874 DeleteFileA(file2_nameA
);
2877 static void test_copyto_iidexclusions_stream(void)
2879 IStorage
*file1
= NULL
, *file2
= NULL
, *stg_tmp
;
2883 /* create & populate file1 */
2884 hr
= StgCreateDocfile(file1_name
, STGM_CREATE
| STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
, 0, &file1
);
2885 ok(hr
== S_OK
, "StgCreateDocfile failed: 0x%08x\n", hr
);
2889 hr
= create_test_file(file1
);
2894 hr
= StgCreateDocfile(file2_name
, STGM_CREATE
| STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
, 0, &file2
);
2895 ok(hr
== S_OK
, "StgCreateDocfile failed: 0x%08x\n", hr
);
2899 /* copy file1 to file2 with iid exclusions */
2900 hr
= IStorage_CopyTo(file1
, 1, &IID_IStream
, NULL
, file2
);
2901 ok(hr
== S_OK
, "CopyTo failed: 0x%08x\n", hr
);
2905 /* verify that file1 copied over, respecting exclusions */
2906 hr
= IStorage_OpenStorage(file2
, stgA_name
, NULL
,
2907 STGM_READWRITE
| STGM_SHARE_EXCLUSIVE
, NULL
, 0, &stg_tmp
);
2908 ok(hr
== S_OK
, "OpenStorage failed: 0x%08x\n", hr
);
2911 hr
= IStorage_OpenStream(stg_tmp
, strmA_name
, NULL
,
2912 STGM_READWRITE
| STGM_SHARE_EXCLUSIVE
, 0, &strm_tmp
);
2913 ok(hr
== STG_E_FILENOTFOUND
, "OpenStream should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr
);
2915 IStream_Release(strm_tmp
);
2917 IStorage_Release(stg_tmp
);
2920 hr
= IStorage_OpenStorage(file2
, stgB_name
, NULL
,
2921 STGM_READWRITE
| STGM_SHARE_EXCLUSIVE
, NULL
, 0, &stg_tmp
);
2922 ok(hr
== S_OK
, "OpenStorage failed: 0x%08x\n", hr
);
2925 hr
= IStorage_OpenStream(stg_tmp
, strmB_name
, NULL
,
2926 STGM_READWRITE
| STGM_SHARE_EXCLUSIVE
, 0, &strm_tmp
);
2927 ok(hr
== STG_E_FILENOTFOUND
, "OpenStream should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr
);
2929 IStream_Release(strm_tmp
);
2931 IStorage_Release(stg_tmp
);
2934 hr
= IStorage_OpenStream(file2
, strmC_name
, NULL
,
2935 STGM_READWRITE
| STGM_SHARE_EXCLUSIVE
, 0, &strm_tmp
);
2936 ok(hr
== STG_E_FILENOTFOUND
, "OpenStream should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr
);
2938 IStream_Release(strm_tmp
);
2942 IStorage_Release(file1
);
2944 IStorage_Release(file2
);
2946 DeleteFileA(file1_nameA
);
2947 DeleteFileA(file2_nameA
);
2950 static void test_rename(void)
2952 IStorage
*stg
, *stg2
;
2955 static const WCHAR stgname
[] = { 'P','E','R','M','S','T','G',0 };
2956 static const WCHAR stgname2
[] = { 'S','T','G',0 };
2957 static const WCHAR stmname
[] = { 'C','O','N','T','E','N','T','S',0 };
2958 static const WCHAR stmname2
[] = { 'E','N','T','S',0 };
2961 DeleteFileA(filenameA
);
2963 /* create the file */
2964 r
= StgCreateDocfile( filename
, STGM_CREATE
| STGM_SHARE_EXCLUSIVE
|
2965 STGM_READWRITE
, 0, &stg
);
2966 ok(r
==S_OK
, "StgCreateDocfile failed\n");
2968 /* create a substorage */
2969 r
= IStorage_CreateStorage(stg
, stgname
, STGM_READWRITE
| STGM_SHARE_EXCLUSIVE
, 0, 0, &stg2
);
2970 ok(r
==S_OK
, "IStorage->CreateStorage failed, hr=%08x\n", r
);
2972 /* create a stream in the substorage */
2973 r
= IStorage_CreateStream(stg2
, stmname
, STGM_READWRITE
| STGM_SHARE_EXCLUSIVE
, 0, 0, &stm
);
2974 ok(r
==S_OK
, "IStorage->CreateStream failed, hr=%08x\n", r
);
2975 IStream_Release(stm
);
2977 /* rename the stream */
2978 r
= IStorage_RenameElement(stg2
, stmname
, stmname2
);
2979 ok(r
==S_OK
, "IStorage->RenameElement failed, hr=%08x\n", r
);
2981 /* cannot open stream with old name */
2982 r
= IStorage_OpenStream(stg2
, stmname
, NULL
, STGM_READWRITE
| STGM_SHARE_EXCLUSIVE
, 0, &stm
);
2983 ok(r
==STG_E_FILENOTFOUND
, "IStorage_OpenStream should fail, hr=%08x\n", r
);
2984 if (SUCCEEDED(r
)) IStream_Release(stm
);
2986 /* can open stream with new name */
2987 r
= IStorage_OpenStream(stg2
, stmname2
, NULL
, STGM_READWRITE
| STGM_SHARE_EXCLUSIVE
, 0, &stm
);
2988 ok(r
==S_OK
, "IStorage_OpenStream failed, hr=%08x\n", r
);
2989 if (SUCCEEDED(r
)) IStream_Release(stm
);
2991 IStorage_Release(stg2
);
2993 /* rename the storage */
2994 IStorage_RenameElement(stg
, stgname
, stgname2
);
2996 /* cannot open storage with old name */
2997 r
= IStorage_OpenStorage(stg
, stgname
, NULL
, STGM_READWRITE
| STGM_SHARE_EXCLUSIVE
, NULL
, 0, &stg2
);
2998 ok(r
==STG_E_FILENOTFOUND
, "IStorage_OpenStream should fail, hr=%08x\n", r
);
2999 if (SUCCEEDED(r
)) IStorage_Release(stg2
);
3001 /* can open storage with new name */
3002 r
= IStorage_OpenStorage(stg
, stgname2
, NULL
, STGM_READWRITE
| STGM_SHARE_EXCLUSIVE
, NULL
, 0, &stg2
);
3003 ok(r
==S_OK
, "IStorage_OpenStream should fail, hr=%08x\n", r
);
3006 /* opened storage still has the stream */
3007 r
= IStorage_OpenStream(stg2
, stmname2
, NULL
, STGM_READWRITE
| STGM_SHARE_EXCLUSIVE
, 0, &stm
);
3008 ok(r
==S_OK
, "IStorage_OpenStream failed, hr=%08x\n", r
);
3009 if (SUCCEEDED(r
)) IStream_Release(stm
);
3011 IStorage_Release(stg2
);
3014 IStorage_Release(stg
);
3016 ret
= DeleteFileA(filenameA
);
3017 ok(ret
, "deleted file\n");
3020 static void test_toplevel_stat(void)
3022 IStorage
*stg
= NULL
;
3025 char prev_dir
[MAX_PATH
];
3026 char temp
[MAX_PATH
];
3027 char full_path
[MAX_PATH
];
3029 WCHAR rel_path
[MAX_PATH
];
3031 DeleteFileA(filenameA
);
3033 r
= StgCreateDocfile( filename
, STGM_CREATE
| STGM_SHARE_EXCLUSIVE
|
3034 STGM_READWRITE
|STGM_TRANSACTED
, 0, &stg
);
3035 ok(r
==S_OK
, "StgCreateDocfile failed\n");
3037 r
= IStorage_Stat( stg
, &stat
, STATFLAG_DEFAULT
);
3038 ok(r
==S_OK
, "Storage_Stat failed with error 0x%08x\n", r
);
3039 ok(!strcmp_ww(stat
.pwcsName
, filename
), "expected %s, got %s\n",
3040 wine_dbgstr_w(filename
), wine_dbgstr_w(stat
.pwcsName
));
3041 CoTaskMemFree(stat
.pwcsName
);
3043 IStorage_Release( stg
);
3045 r
= StgOpenStorage( filename
, NULL
, STGM_SHARE_EXCLUSIVE
|STGM_READWRITE
, NULL
, 0, &stg
);
3046 ok(r
==S_OK
, "StgOpenStorage failed with error 0x%08x\n", r
);
3048 r
= IStorage_Stat( stg
, &stat
, STATFLAG_DEFAULT
);
3049 ok(r
==S_OK
, "Storage_Stat failed with error 0x%08x\n", r
);
3050 ok(!strcmp_ww(stat
.pwcsName
, filename
), "expected %s, got %s\n",
3051 wine_dbgstr_w(filename
), wine_dbgstr_w(stat
.pwcsName
));
3052 CoTaskMemFree(stat
.pwcsName
);
3054 IStorage_Release( stg
);
3056 DeleteFileA(filenameA
);
3058 /* Stat always returns the full path, even for files opened with a relative path. */
3059 GetCurrentDirectoryA(MAX_PATH
, prev_dir
);
3061 GetTempPathA(MAX_PATH
, temp
);
3063 SetCurrentDirectoryA(temp
);
3065 GetFullPathNameA(filenameA
, MAX_PATH
, full_path
, &rel_pathA
);
3066 MultiByteToWideChar(CP_ACP
, 0, rel_pathA
, -1, rel_path
, MAX_PATH
);
3068 r
= StgCreateDocfile( rel_path
, STGM_CREATE
| STGM_SHARE_EXCLUSIVE
|
3069 STGM_READWRITE
|STGM_TRANSACTED
, 0, &stg
);
3070 ok(r
==S_OK
, "StgCreateDocfile failed\n");
3072 r
= IStorage_Stat( stg
, &stat
, STATFLAG_DEFAULT
);
3073 ok(r
==S_OK
, "Storage_Stat failed with error 0x%08x\n", r
);
3074 ok(!strcmp_ww(stat
.pwcsName
, filename
), "expected %s, got %s\n",
3075 wine_dbgstr_w(filename
), wine_dbgstr_w(stat
.pwcsName
));
3076 CoTaskMemFree(stat
.pwcsName
);
3078 IStorage_Release( stg
);
3080 r
= StgOpenStorage( rel_path
, NULL
, STGM_SHARE_EXCLUSIVE
|STGM_READWRITE
, NULL
, 0, &stg
);
3081 ok(r
==S_OK
, "StgOpenStorage failed with error 0x%08x\n", r
);
3083 r
= IStorage_Stat( stg
, &stat
, STATFLAG_DEFAULT
);
3084 ok(r
==S_OK
, "Storage_Stat failed with error 0x%08x\n", r
);
3085 ok(!strcmp_ww(stat
.pwcsName
, filename
), "expected %s, got %s\n",
3086 wine_dbgstr_w(filename
), wine_dbgstr_w(stat
.pwcsName
));
3087 CoTaskMemFree(stat
.pwcsName
);
3089 IStorage_Release( stg
);
3091 SetCurrentDirectoryA(prev_dir
);
3093 DeleteFileA(filenameA
);
3096 static void test_substorage_enum(void)
3098 IStorage
*stg
, *stg2
;
3102 static const WCHAR stgname
[] = { 'P','E','R','M','S','T','G',0 };
3105 DeleteFileA(filenameA
);
3107 /* create the file */
3108 r
= StgCreateDocfile( filename
, STGM_CREATE
| STGM_SHARE_EXCLUSIVE
|
3109 STGM_READWRITE
, 0, &stg
);
3110 ok(r
==S_OK
, "StgCreateDocfile failed\n");
3112 /* create a substorage */
3113 r
= IStorage_CreateStorage(stg
, stgname
, STGM_READWRITE
| STGM_SHARE_EXCLUSIVE
, 0, 0, &stg2
);
3114 ok(r
==S_OK
, "IStorage->CreateStorage failed, hr=%08x\n", r
);
3116 /* create an enumelements */
3117 r
= IStorage_EnumElements(stg2
, 0, NULL
, 0, &ee
);
3118 ok(r
==S_OK
, "IStorage->EnumElements failed, hr=%08x\n", r
);
3120 /* release the substorage */
3121 ref
= IStorage_Release(stg2
);
3122 todo_wine
ok(ref
==0, "storage not released\n");
3124 /* reopening fails, because the substorage is really still open */
3125 r
= IStorage_OpenStorage(stg
, stgname
, NULL
, STGM_READWRITE
| STGM_SHARE_EXCLUSIVE
, 0, 0, &stg2
);
3126 ok(r
==STG_E_ACCESSDENIED
, "IStorage->OpenStorage failed, hr=%08x\n", r
);
3128 /* destroying the storage invalidates the enumerator */
3129 r
= IStorage_DestroyElement(stg
, stgname
);
3130 ok(r
==S_OK
, "IStorage->CreateStorage failed, hr=%08x\n", r
);
3132 r
= IEnumSTATSTG_Reset(ee
);
3133 ok(r
==STG_E_REVERTED
, "IEnumSTATSTG->Reset failed, hr=%08x\n", r
);
3135 IEnumSTATSTG_Release(ee
);
3137 IStorage_Release(stg
);
3139 ret
= DeleteFileA(filenameA
);
3140 ok(ret
, "deleted file\n");
3143 static void test_copyto_locking(void)
3145 IStorage
*stg
, *stg2
, *stg3
, *stg4
;
3148 static const WCHAR stgname
[] = { 'S','T','G','1',0 };
3149 static const WCHAR stgname2
[] = { 'S','T','G','2',0 };
3150 static const WCHAR stmname
[] = { 'C','O','N','T','E','N','T','S',0 };
3153 DeleteFileA(filenameA
);
3155 /* create the file */
3156 r
= StgCreateDocfile( filename
, STGM_CREATE
| STGM_SHARE_EXCLUSIVE
|
3157 STGM_READWRITE
, 0, &stg
);
3158 ok(r
==S_OK
, "StgCreateDocfile failed\n");
3160 /* create a substorage */
3161 r
= IStorage_CreateStorage(stg
, stgname
, STGM_READWRITE
| STGM_SHARE_EXCLUSIVE
, 0, 0, &stg2
);
3162 ok(r
==S_OK
, "IStorage->CreateStorage failed, hr=%08x\n", r
);
3164 /* create another substorage */
3165 r
= IStorage_CreateStorage(stg
, stgname2
, STGM_READWRITE
| STGM_SHARE_EXCLUSIVE
, 0, 0, &stg3
);
3166 ok(r
==S_OK
, "IStorage->CreateStorage failed, hr=%08x\n", r
);
3168 /* add a stream, and leave it open */
3169 r
= IStorage_CreateStream(stg2
, stmname
, STGM_READWRITE
| STGM_SHARE_EXCLUSIVE
, 0, 0, &stm
);
3170 ok(r
==S_OK
, "IStorage->CreateStream failed, hr=%08x\n", r
);
3172 /* Try to copy the storage while the stream is open */
3173 r
= IStorage_CopyTo(stg2
, 0, NULL
, NULL
, stg3
);
3174 ok(r
==S_OK
, "IStorage->CopyTo failed, hr=%08x\n", r
);
3176 IStream_Release(stm
);
3178 /* create a substorage */
3179 r
= IStorage_CreateStorage(stg2
, stgname
, STGM_READWRITE
| STGM_SHARE_EXCLUSIVE
, 0, 0, &stg4
);
3180 ok(r
==S_OK
, "IStorage->CreateStorage failed, hr=%08x\n", r
);
3182 /* Try to copy the storage while the substorage is open */
3183 r
= IStorage_CopyTo(stg2
, 0, NULL
, NULL
, stg3
);
3184 ok(r
==S_OK
, "IStorage->CopyTo failed, hr=%08x\n", r
);
3186 IStorage_Release(stg4
);
3187 IStorage_Release(stg3
);
3188 IStorage_Release(stg2
);
3189 IStorage_Release(stg
);
3191 ret
= DeleteFileA(filenameA
);
3192 ok(ret
, "deleted file\n");
3195 static void test_copyto_recursive(void)
3197 IStorage
*stg
, *stg2
, *stg3
, *stg4
;
3199 static const WCHAR stgname
[] = { 'S','T','G','1',0 };
3200 static const WCHAR stgname2
[] = { 'S','T','G','2',0 };
3203 DeleteFileA(filenameA
);
3205 /* create the file */
3206 r
= StgCreateDocfile( filename
, STGM_CREATE
| STGM_SHARE_EXCLUSIVE
|
3207 STGM_READWRITE
, 0, &stg
);
3208 ok(r
==S_OK
, "StgCreateDocfile failed\n");
3210 /* create a substorage */
3211 r
= IStorage_CreateStorage(stg
, stgname
, STGM_READWRITE
| STGM_SHARE_EXCLUSIVE
, 0, 0, &stg2
);
3212 ok(r
==S_OK
, "IStorage->CreateStorage failed, hr=%08x\n", r
);
3214 /* copy the parent to the child */
3215 r
= IStorage_CopyTo(stg
, 0, NULL
, NULL
, stg2
);
3216 ok(r
==STG_E_ACCESSDENIED
, "IStorage->CopyTo failed, hr=%08x\n", r
);
3218 /* create a transacted substorage */
3219 r
= IStorage_CreateStorage(stg
, stgname2
, STGM_READWRITE
| STGM_SHARE_EXCLUSIVE
| STGM_TRANSACTED
, 0, 0, &stg3
);
3220 ok(r
==S_OK
, "IStorage->CreateStorage failed, hr=%08x\n", r
);
3222 /* copy the parent to the transacted child */
3223 r
= IStorage_CopyTo(stg
, 0, NULL
, NULL
, stg2
);
3224 ok(r
==STG_E_ACCESSDENIED
, "IStorage->CopyTo failed, hr=%08x\n", r
);
3226 /* create a transacted subsubstorage */
3227 r
= IStorage_CreateStorage(stg3
, stgname2
, STGM_READWRITE
| STGM_SHARE_EXCLUSIVE
| STGM_TRANSACTED
, 0, 0, &stg4
);
3228 ok(r
==S_OK
, "IStorage->CreateStorage failed, hr=%08x\n", r
);
3230 /* copy the parent to the transacted child of the transacted child */
3231 r
= IStorage_CopyTo(stg
, 0, NULL
, NULL
, stg4
);
3232 ok(r
==STG_E_ACCESSDENIED
, "IStorage->CopyTo failed, hr=%08x\n", r
);
3234 /* copy the parent but exclude storage objects */
3235 r
= IStorage_CopyTo(stg
, 1, &IID_IStorage
, NULL
, stg4
);
3236 ok(r
==S_OK
, "IStorage->CopyTo failed, hr=%08x\n", r
);
3238 IStorage_Release(stg4
);
3239 IStorage_Release(stg3
);
3240 IStorage_Release(stg2
);
3241 IStorage_Release(stg
);
3243 ret
= DeleteFileA(filenameA
);
3244 ok(ret
, "deleted file\n");
3247 static void test_hglobal_storage_creation(void)
3249 ILockBytes
*ilb
= NULL
;
3250 IStorage
*stg
= NULL
;
3254 ULARGE_INTEGER offset
;
3256 r
= CreateILockBytesOnHGlobal(NULL
, TRUE
, &ilb
);
3257 ok(r
== S_OK
, "CreateILockBytesOnHGlobal failed, hr=%x\n", r
);
3259 offset
.QuadPart
= 0;
3260 memset(junk
, 0xaa, 512);
3261 r
= ILockBytes_WriteAt(ilb
, offset
, junk
, 512, NULL
);
3262 ok(r
== S_OK
, "ILockBytes_WriteAt failed, hr=%x\n", r
);
3264 offset
.QuadPart
= 2000;
3265 r
= ILockBytes_WriteAt(ilb
, offset
, junk
, 512, NULL
);
3266 ok(r
== S_OK
, "ILockBytes_WriteAt failed, hr=%x\n", r
);
3268 r
= StgCreateDocfileOnILockBytes(ilb
, STGM_CREATE
|STGM_SHARE_EXCLUSIVE
|STGM_READWRITE
, 0, &stg
);
3269 ok(r
== S_OK
, "StgCreateDocfileOnILockBytes failed, hr=%x\n", r
);
3271 IStorage_Release(stg
);
3273 r
= StgOpenStorageOnILockBytes(ilb
, NULL
, STGM_READ
|STGM_SHARE_EXCLUSIVE
,
3275 ok(r
== S_OK
, "StgOpenStorageOnILockBytes failed, hr=%x\n", r
);
3279 r
= IStorage_Stat(stg
, &stat
, STATFLAG_NONAME
);
3280 ok(r
== S_OK
, "StgOpenStorageOnILockBytes failed, hr=%x\n", r
);
3281 ok(IsEqualCLSID(&stat
.clsid
, &GUID_NULL
), "unexpected CLSID value\n");
3283 IStorage_Release(stg
);
3286 r
= ILockBytes_Stat(ilb
, &stat
, STATFLAG_NONAME
);
3287 ok(r
== S_OK
, "ILockBytes_Stat failed, hr=%x\n", r
);
3288 ok(stat
.cbSize
.u
.LowPart
< 2512, "expected truncated size, got %d\n", stat
.cbSize
.u
.LowPart
);
3290 ILockBytes_Release(ilb
);
3293 static void test_convert(void)
3295 static const WCHAR filename
[] = {'s','t','o','r','a','g','e','.','s','t','g',0};
3299 hr
= GetConvertStg(NULL
);
3300 ok(hr
== E_INVALIDARG
, "got 0x%08x\n", hr
);
3302 hr
= StgCreateDocfile( filename
, STGM_CREATE
| STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
, 0, &stg
);
3303 ok(hr
== S_OK
, "StgCreateDocfile failed\n");
3304 hr
= GetConvertStg(stg
);
3305 ok(hr
== STG_E_FILENOTFOUND
, "got 0x%08x\n", hr
);
3306 hr
= SetConvertStg(stg
, TRUE
);
3307 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3308 hr
= SetConvertStg(stg
, TRUE
);
3309 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3310 hr
= GetConvertStg(stg
);
3311 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3312 hr
= SetConvertStg(stg
, FALSE
);
3313 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3314 hr
= GetConvertStg(stg
);
3315 ok(hr
== S_FALSE
, "got 0x%08x\n", hr
);
3317 IStorage_Release(stg
);
3319 DeleteFileW(filename
);
3322 static void test_direct_swmr(void)
3324 static const WCHAR fileW
[] = {'w','i','n','e','t','e','s','t',0};
3325 IDirectWriterLock
*dwlock
;
3330 /* it's possible to create in writer mode */
3331 hr
= StgCreateDocfile(fileW
, STGM_CREATE
| STGM_READWRITE
| STGM_SHARE_DENY_WRITE
| STGM_DIRECT_SWMR
, 0, &stg
);
3333 ok(hr
== S_OK
, "got %08x\n", hr
);
3335 IStorage_Release(stg
);
3339 hr
= StgCreateDocfile(fileW
, STGM_CREATE
| STGM_READWRITE
| STGM_SHARE_DENY_WRITE
| STGM_TRANSACTED
, 0, &stg
);
3340 ok(hr
== S_OK
, "got %08x\n", hr
);
3341 IStorage_Release(stg
);
3344 hr
= StgOpenStorage(fileW
, NULL
, STGM_DIRECT_SWMR
| STGM_READ
| STGM_SHARE_DENY_NONE
, NULL
, 0, &stg
);
3345 ok(hr
== S_OK
|| broken(hr
== STG_E_INVALIDFLAG
), "got %08x\n", hr
);
3348 hr
= IStorage_QueryInterface(stg
, &IID_IDirectWriterLock
, (void**)&dwlock
);
3349 ok(hr
== E_NOINTERFACE
, "got %08x\n", hr
);
3350 IStorage_Release(stg
);
3354 hr
= StgOpenStorage(fileW
, NULL
, STGM_DIRECT_SWMR
| STGM_READWRITE
| STGM_SHARE_DENY_WRITE
, NULL
, 0, &stg
);
3355 ok(hr
== S_OK
, "got %08x\n", hr
);
3358 ref
= IStorage_AddRef(stg
);
3359 IStorage_Release(stg
);
3361 hr
= IStorage_QueryInterface(stg
, &IID_IDirectWriterLock
, (void**)&dwlock
);
3362 ok(hr
== S_OK
, "got %08x\n", hr
);
3364 ref2
= IStorage_AddRef(stg
);
3365 IStorage_Release(stg
);
3366 ok(ref2
== ref
+ 1, "got %u\n", ref2
);
3368 IDirectWriterLock_Release(dwlock
);
3369 IStorage_Release(stg
);
3381 const int *locked_bytes
;
3382 const int *fail_ranges
;
3386 static const int priority_locked_bytes
[] = { 0x158, 0x181, 0x193, -1 };
3387 static const int rwex_locked_bytes
[] = { 0x193, 0x1a7, 0x1bb, 0x1cf, -1 };
3388 static const int rw_locked_bytes
[] = { 0x193, 0x1a7, -1 };
3389 static const int nosn_locked_bytes
[] = { 0x16c, 0x193, 0x1a7, 0x1cf, -1 };
3390 static const int rwdw_locked_bytes
[] = { 0x193, 0x1a7, 0x1cf, -1 };
3391 static const int wodw_locked_bytes
[] = { 0x1a7, 0x1cf, -1 };
3392 static const int tr_locked_bytes
[] = { 0x193, -1 };
3393 static const int no_locked_bytes
[] = { -1 };
3394 static const int roex_locked_bytes
[] = { 0x193, 0x1bb, 0x1cf, -1 };
3396 static const int rwex_fail_ranges
[] = { 0x193,0x1e3, -1 };
3397 static const int rw_fail_ranges
[] = { 0x1bb,0x1e3, -1 };
3398 static const int rwdw_fail_ranges
[] = { 0x1a7,0x1e3, -1 };
3399 static const int dw_fail_ranges
[] = { 0x1a7,0x1cf, -1 };
3400 static const int tr_fail_ranges
[] = { 0x1bb,0x1cf, -1 };
3401 static const int pr_fail_ranges
[] = { 0x180,0x181, 0x1bb,0x1cf, -1 };
3402 static const int roex_fail_ranges
[] = { 0x0,-1 };
3404 static const struct lock_test lock_tests
[] = {
3405 { STGM_PRIORITY
, FALSE
, GENERIC_READ
, FILE_SHARE_READ
|FILE_SHARE_WRITE
, priority_locked_bytes
, pr_fail_ranges
, FALSE
},
3406 { STGM_CREATE
|STGM_SHARE_EXCLUSIVE
|STGM_READWRITE
, TRUE
, GENERIC_READ
|GENERIC_WRITE
, FILE_SHARE_READ
, rwex_locked_bytes
, 0, FALSE
},
3407 { STGM_CREATE
|STGM_SHARE_EXCLUSIVE
|STGM_READWRITE
|STGM_TRANSACTED
, TRUE
, GENERIC_READ
|GENERIC_WRITE
, FILE_SHARE_READ
, rwex_locked_bytes
, 0, FALSE
},
3408 { STGM_CREATE
|STGM_READWRITE
|STGM_TRANSACTED
, TRUE
, GENERIC_READ
|GENERIC_WRITE
, FILE_SHARE_READ
|FILE_SHARE_WRITE
, rw_locked_bytes
, 0, FALSE
},
3409 { STGM_CREATE
|STGM_READWRITE
|STGM_SHARE_DENY_WRITE
|STGM_TRANSACTED
, TRUE
, GENERIC_READ
|GENERIC_WRITE
, FILE_SHARE_READ
, rwdw_locked_bytes
, 0, FALSE
},
3410 { STGM_CREATE
|STGM_WRITE
|STGM_SHARE_DENY_WRITE
|STGM_TRANSACTED
, TRUE
, GENERIC_READ
|GENERIC_WRITE
, FILE_SHARE_READ
, wodw_locked_bytes
, 0, FALSE
},
3411 { STGM_SHARE_EXCLUSIVE
|STGM_READWRITE
, FALSE
, GENERIC_READ
|GENERIC_WRITE
, FILE_SHARE_READ
, rwex_locked_bytes
, rwex_fail_ranges
, FALSE
},
3412 { STGM_SHARE_EXCLUSIVE
|STGM_READWRITE
|STGM_TRANSACTED
, FALSE
, GENERIC_READ
|GENERIC_WRITE
, FILE_SHARE_READ
, rwex_locked_bytes
, rwex_fail_ranges
, FALSE
},
3413 { STGM_READWRITE
|STGM_TRANSACTED
, FALSE
, GENERIC_READ
|GENERIC_WRITE
, FILE_SHARE_READ
|FILE_SHARE_WRITE
, rw_locked_bytes
, rw_fail_ranges
, FALSE
},
3414 { STGM_READWRITE
|STGM_TRANSACTED
|STGM_NOSNAPSHOT
, FALSE
, GENERIC_READ
|GENERIC_WRITE
, FILE_SHARE_READ
|FILE_SHARE_WRITE
, nosn_locked_bytes
, rwdw_fail_ranges
, FALSE
},
3415 { STGM_READWRITE
|STGM_TRANSACTED
|STGM_SHARE_DENY_WRITE
, FALSE
, GENERIC_READ
|GENERIC_WRITE
, FILE_SHARE_READ
, rwdw_locked_bytes
, rwdw_fail_ranges
, FALSE
},
3416 { STGM_READ
|STGM_SHARE_DENY_WRITE
, FALSE
, GENERIC_READ
, FILE_SHARE_READ
, no_locked_bytes
, dw_fail_ranges
, TRUE
},
3417 { STGM_READ
|STGM_TRANSACTED
, FALSE
, GENERIC_READ
, FILE_SHARE_READ
|FILE_SHARE_WRITE
, tr_locked_bytes
, tr_fail_ranges
, FALSE
},
3418 { STGM_READ
|STGM_SHARE_EXCLUSIVE
, FALSE
, GENERIC_READ
, FILE_SHARE_READ
, roex_locked_bytes
, roex_fail_ranges
, FALSE
},
3419 { STGM_READ
|STGM_SHARE_EXCLUSIVE
|STGM_TRANSACTED
, FALSE
, GENERIC_READ
, FILE_SHARE_READ
, roex_locked_bytes
, roex_fail_ranges
, FALSE
},
3422 static BOOL
can_open(LPCWSTR filename
, DWORD access
, DWORD sharing
)
3426 hfile
= CreateFileW(filename
, access
, sharing
, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
3428 if (hfile
== INVALID_HANDLE_VALUE
)
3435 static void check_sharing(LPCWSTR filename
, const struct lock_test
*current
,
3436 DWORD access
, DWORD sharing
, const char *desc
, DWORD
*open_mode
, BOOL
*any_failure
)
3438 if (can_open(filename
, access
, FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
))
3440 *open_mode
= access
;
3441 if (!current
->todo
|| (current
->sharing
& sharing
))
3442 ok(current
->sharing
& sharing
||
3443 broken(!(current
->sharing
& sharing
) && access
== GENERIC_WRITE
&& (current
->stg_mode
& 0xf) != STGM_READ
) /* win2k */,
3444 "file with mode %x should not be openable with %s permission\n", current
->stg_mode
, desc
);
3447 todo_wine
ok(current
->sharing
& sharing
||
3448 broken(!(current
->sharing
& sharing
) && access
== GENERIC_WRITE
&& (current
->stg_mode
& 0xf) != STGM_READ
) /* win2k */,
3449 "file with mode %x should not be openable with %s permission\n", current
->stg_mode
, desc
);
3450 *any_failure
= TRUE
;
3455 if (!current
->todo
|| !(current
->sharing
& sharing
))
3456 ok(!(current
->sharing
& sharing
), "file with mode %x should be openable with %s permission\n", current
->stg_mode
, desc
);
3459 todo_wine
ok(!(current
->sharing
& sharing
), "file with mode %x should be openable with %s permission\n", current
->stg_mode
, desc
);
3460 *any_failure
= TRUE
;
3465 static void check_access(LPCWSTR filename
, const struct lock_test
*current
,
3466 DWORD access
, DWORD sharing
, const char *desc
, DWORD open_mode
, BOOL
*any_failure
)
3468 if (can_open(filename
, open_mode
, (FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
) & ~sharing
))
3470 if (!current
->todo
|| !(current
->access
& access
))
3471 ok(!(current
->access
& access
), "file with mode %x should not be openable without %s sharing\n", current
->stg_mode
, desc
);
3474 todo_wine
ok(!(current
->access
& access
), "file with mode %x should not be openable without %s sharing\n", current
->stg_mode
, desc
);
3475 *any_failure
= TRUE
;
3480 if (!current
->todo
|| (current
->access
& access
))
3481 ok(current
->access
& access
, "file with mode %x should be openable without %s sharing\n", current
->stg_mode
, desc
);
3484 todo_wine
ok(current
->access
& access
, "file with mode %x should be openable without %s sharing\n", current
->stg_mode
, desc
);
3485 *any_failure
= TRUE
;
3490 static void test_locking(void)
3492 static const WCHAR filename
[] = {'w','i','n','e','t','e','s','t',0};
3497 for (i
= 0; i
< ARRAY_SIZE(lock_tests
); i
++)
3499 const struct lock_test
*current
= &lock_tests
[i
];
3500 BOOL any_failure
= FALSE
;
3501 DWORD open_mode
= 0;
3503 if (current
->create
)
3505 hr
= StgCreateDocfile(filename
, current
->stg_mode
, 0, &stg
);
3506 ok(SUCCEEDED(hr
), "StgCreateDocfile with mode %x failed with hr %x\n", current
->stg_mode
, hr
);
3507 if (FAILED(hr
)) continue;
3511 hr
= StgCreateDocfile(filename
, STGM_CREATE
| STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
, 0, &stg
);
3512 ok(SUCCEEDED(hr
), "StgCreateDocfile failed with hr %x\n", hr
);
3513 if (FAILED(hr
)) continue;
3514 IStorage_Release(stg
);
3516 hr
= StgOpenStorage(filename
, NULL
, current
->stg_mode
, NULL
, 0, &stg
);
3517 ok(SUCCEEDED(hr
), "StgOpenStorage with mode %x failed with hr %x\n", current
->stg_mode
, hr
);
3520 DeleteFileW(filename
);
3525 check_sharing(filename
, current
, GENERIC_READ
, FILE_SHARE_READ
, "READ", &open_mode
, &any_failure
);
3526 check_sharing(filename
, current
, GENERIC_WRITE
, FILE_SHARE_WRITE
, "WRITE", &open_mode
, &any_failure
);
3527 check_sharing(filename
, current
, DELETE
, FILE_SHARE_DELETE
, "DELETE", &open_mode
, &any_failure
);
3532 BOOL locked
, expect_locked
;
3534 const int* next_lock
= current
->locked_bytes
;
3536 check_access(filename
, current
, GENERIC_READ
, FILE_SHARE_READ
, "READ", open_mode
, &any_failure
);
3537 check_access(filename
, current
, GENERIC_WRITE
, FILE_SHARE_WRITE
, "WRITE", open_mode
, &any_failure
);
3538 check_access(filename
, current
, DELETE
, FILE_SHARE_DELETE
, "DELETE", open_mode
, &any_failure
);
3540 hfile
= CreateFileW(filename
, open_mode
, FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
3541 ok(hfile
!= INVALID_HANDLE_VALUE
, "couldn't open file with mode %x\n", current
->stg_mode
);
3546 for (ol
.Offset
= 0x7ffffe00; ol
.Offset
!= 0x80000000; ol
.Offset
++)
3548 if (LockFileEx(hfile
, LOCKFILE_EXCLUSIVE_LOCK
|LOCKFILE_FAIL_IMMEDIATELY
, 0, 1, 0, &ol
))
3552 ok(!LockFileEx(hfile
, LOCKFILE_FAIL_IMMEDIATELY
, 0, 1, 0, &ol
), "shared locks should not be used\n");
3556 UnlockFileEx(hfile
, 0, 1, 0, &ol
);
3558 if ((ol
.Offset
&0x1ff) == *next_lock
)
3560 expect_locked
= TRUE
;
3564 expect_locked
= FALSE
;
3566 if (!current
->todo
|| locked
== expect_locked
)
3567 ok(locked
== expect_locked
, "byte %x of file with mode %x is %slocked but should %sbe\n",
3568 ol
.Offset
, current
->stg_mode
, locked
?"":"not ", expect_locked
?"":"not ");
3572 todo_wine
ok(locked
== expect_locked
, "byte %x of file with mode %x is %slocked but should %sbe\n",
3573 ol
.Offset
, current
->stg_mode
, locked
?"":"not ", expect_locked
?"":"not ");
3580 IStorage_Release( stg
);
3582 if (!current
->create
)
3585 BOOL failed
, expect_failed
=FALSE
;
3587 const int* next_range
= current
->fail_ranges
;
3589 hfile
= CreateFileW(filename
, open_mode
, FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
3590 ok(hfile
!= INVALID_HANDLE_VALUE
, "couldn't open file with mode %x\n", current
->stg_mode
);
3595 for (ol
.Offset
= 0x7ffffe00; ol
.Offset
!= 0x80000000; ol
.Offset
++)
3597 if (ol
.Offset
== 0x7fffff92 ||
3598 (ol
.Offset
== 0x7fffff80 && current
->stg_mode
== (STGM_TRANSACTED
|STGM_READWRITE
)) ||
3599 (ol
.Offset
== 0x7fffff80 && current
->stg_mode
== (STGM_TRANSACTED
|STGM_READ
)))
3600 continue; /* This makes opens hang */
3602 if (ol
.Offset
< 0x7fffff00)
3603 LockFileEx(hfile
, 0, 0, 1, 0, &ol
);
3605 LockFileEx(hfile
, LOCKFILE_EXCLUSIVE_LOCK
, 0, 1, 0, &ol
);
3607 hr
= StgOpenStorage(filename
, NULL
, current
->stg_mode
, NULL
, 0, &stg
);
3608 ok(hr
== S_OK
|| hr
== STG_E_LOCKVIOLATION
|| hr
== STG_E_SHAREVIOLATION
, "failed with unexpected hr %x\n", hr
);
3609 if (SUCCEEDED(hr
)) IStorage_Release(stg
);
3611 UnlockFileEx(hfile
, 0, 1, 0, &ol
);
3613 failed
= FAILED(hr
);
3615 if (!expect_failed
&& (ol
.Offset
&0x1ff) == next_range
[0])
3617 expect_failed
= TRUE
;
3619 else if (expect_failed
&& (ol
.Offset
&0x1ff) == next_range
[1])
3621 expect_failed
= FALSE
;
3625 if (!current
->todo
|| failed
== expect_failed
)
3626 ok(failed
== expect_failed
, "open with byte %x locked, mode %x %s but should %s\n",
3627 ol
.Offset
, current
->stg_mode
, failed
?"failed":"succeeded", expect_failed
?"fail":"succeed");
3631 todo_wine
ok(failed
== expect_failed
, "open with byte %x locked, mode %x %s but should %s\n",
3632 ol
.Offset
, current
->stg_mode
, failed
?"failed":"succeeded", expect_failed
?"fail":"succeed");
3639 DeleteFileW(filename
);
3641 if (current
->todo
&& !any_failure
)
3642 todo_wine
ok(1, "tests succeeded for mode %x\n", current
->stg_mode
);
3646 static void test_transacted_shared(void)
3648 IStorage
*stg
= NULL
;
3649 IStorage
*stgrw
= NULL
;
3651 IStream
*stm
= NULL
;
3652 static const WCHAR stmname
[] = { 'C','O','N','T','E','N','T','S',0 };
3654 ULARGE_INTEGER upos
;
3658 DeleteFileA(filenameA
);
3660 /* create a new transacted storage with a stream */
3661 r
= StgCreateDocfile(filename
, STGM_CREATE
|
3662 STGM_READWRITE
|STGM_TRANSACTED
, 0, &stg
);
3663 ok(r
==S_OK
, "StgCreateDocfile failed %x\n", r
);
3665 r
= WriteClassStg(stg
, &test_stg_cls
);
3666 ok(r
== S_OK
, "WriteClassStg failed %x\n", r
);
3668 r
= IStorage_CreateStream(stg
, stmname
, STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
, 0, 0, &stm
);
3669 ok(r
==S_OK
, "IStorage->CreateStream failed %x\n", r
);
3672 r
= IStream_Seek(stm
, pos
, 0, &upos
);
3673 ok(r
==S_OK
, "IStream->Seek failed %x\n", r
);
3675 r
= IStream_Write(stm
, "aaa", 3, NULL
);
3676 ok(r
==S_OK
, "IStream->Write failed %x\n", r
);
3678 r
= IStorage_Commit(stg
, STGC_ONLYIFCURRENT
);
3679 ok(r
==S_OK
, "IStorage->Commit failed %x\n", r
);
3681 /* open a second transacted read/write storage */
3682 r
= StgOpenStorage(filename
, NULL
, STGM_READWRITE
| STGM_TRANSACTED
| STGM_SHARE_DENY_NONE
, NULL
, 0, &stgrw
);
3683 ok(r
==S_OK
, "StgOpenStorage failed %x\n", r
);
3685 /* update stream on the first storage and commit */
3687 r
= IStream_Seek(stm
, pos
, 0, &upos
);
3688 ok(r
==S_OK
, "IStream->Seek failed %x\n", r
);
3690 r
= IStream_Write(stm
, "ccc", 3, NULL
);
3691 ok(r
==S_OK
, "IStream->Write failed %x\n", r
);
3693 r
= IStorage_Commit(stg
, STGC_ONLYIFCURRENT
);
3694 ok(r
==S_OK
, "IStorage->Commit failed %x\n", r
);
3696 /* update again without committing */
3698 r
= IStream_Seek(stm
, pos
, 0, &upos
);
3699 ok(r
==S_OK
, "IStream->Seek failed %x\n", r
);
3701 r
= IStream_Write(stm
, "ddd", 3, NULL
);
3702 ok(r
==S_OK
, "IStream->Write failed %x\n", r
);
3704 IStream_Release(stm
);
3706 /* we can still read the old content from the second storage */
3707 r
= IStorage_OpenStream(stgrw
, stmname
, NULL
, STGM_READWRITE
| STGM_SHARE_EXCLUSIVE
, 0, &stm
);
3708 ok(r
==S_OK
, "IStorage->OpenStream failed %x\n", r
);
3711 r
= IStream_Seek(stm
, pos
, 0, &upos
);
3712 ok(r
==S_OK
, "IStream->Seek failed %x\n", r
);
3714 r
= IStream_Read(stm
, buffer
, sizeof(buffer
), &bytesread
);
3715 ok(r
==S_OK
, "IStream->Read failed %x\n", r
);
3716 ok(bytesread
== 3, "read wrong number of bytes %i\n", bytesread
);
3717 ok(memcmp(buffer
, "aaa", 3) == 0, "wrong data\n");
3719 /* and overwrite the data */
3721 r
= IStream_Seek(stm
, pos
, 0, &upos
);
3722 ok(r
==S_OK
, "IStream->Seek failed %x\n", r
);
3724 r
= IStream_Write(stm
, "bbb", 3, NULL
);
3725 ok(r
==S_OK
, "IStream->Write failed %x\n", r
);
3727 IStream_Release(stm
);
3729 /* commit fails because we're out of date */
3730 r
= IStorage_Commit(stgrw
, STGC_ONLYIFCURRENT
);
3731 ok(r
==STG_E_NOTCURRENT
, "IStorage->Commit failed %x\n", r
);
3733 /* unless we force it */
3734 r
= IStorage_Commit(stgrw
, STGC_DEFAULT
);
3735 ok(r
==S_OK
, "IStorage->Commit failed %x\n", r
);
3737 /* reverting gets us back to the last commit from the same storage */
3738 r
= IStorage_Revert(stg
);
3739 ok(r
==S_OK
, "IStorage->Revert failed %x\n", r
);
3741 r
= IStorage_OpenStream(stg
, stmname
, NULL
, STGM_READWRITE
| STGM_SHARE_EXCLUSIVE
, 0, &stm
);
3742 ok(r
==S_OK
, "IStorage->CreateStream failed %x\n", r
);
3745 r
= IStream_Seek(stm
, pos
, 0, &upos
);
3746 ok(r
==S_OK
, "IStream->Seek failed %x\n", r
);
3748 r
= IStream_Read(stm
, buffer
, sizeof(buffer
), &bytesread
);
3749 ok(r
==S_OK
, "IStream->Read failed %x\n", r
);
3750 ok(bytesread
== 3, "read wrong number of bytes %i\n", bytesread
);
3751 ok(memcmp(buffer
, "ccc", 3) == 0, "wrong data\n");
3753 /* and committing fails forever */
3754 r
= IStorage_Commit(stg
, STGC_ONLYIFCURRENT
);
3755 ok(r
==STG_E_NOTCURRENT
, "IStorage->Commit failed %x\n", r
);
3757 IStream_Release(stm
);
3759 IStorage_Release(stg
);
3760 IStorage_Release(stgrw
);
3762 DeleteFileA(filenameA
);
3765 static void test_overwrite(void)
3767 IStorage
*stg
= NULL
;
3769 IStream
*stm
= NULL
;
3770 static const WCHAR stmname
[] = { 'C','O','N','T','E','N','T','S',0 };
3771 static const WCHAR stmname2
[] = { 'C','O','N','T','E','N','T','2',0 };
3773 ULARGE_INTEGER upos
;
3775 DWORD orig_size
, new_size
;
3780 DeleteFileA(filenameA
);
3782 r
= StgCreateDocfile(filename
, STGM_CREATE
| STGM_READWRITE
| STGM_TRANSACTED
, 0, &stg
);
3783 ok(r
==S_OK
, "StgCreateDocfile failed %x\n", r
);
3785 r
= WriteClassStg(stg
, &test_stg_cls
);
3786 ok(r
== S_OK
, "WriteClassStg failed %x\n", r
);
3788 r
= IStorage_CreateStream(stg
, stmname
, STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
, 0, 0, &stm
);
3789 ok(r
==S_OK
, "IStorage->CreateStream failed %x\n", r
);
3792 r
= IStream_Seek(stm
, pos
, STREAM_SEEK_SET
, &upos
);
3793 ok(r
==S_OK
, "IStream->Seek failed %x\n", r
);
3795 memset(buffer
, 'a', sizeof(buffer
));
3798 /* Write enough bytes to pass the minimum storage file size */
3799 r
= IStream_Write(stm
, buffer
, sizeof(buffer
), NULL
);
3800 ok(r
==S_OK
, "IStream->Write failed %x\n", r
);
3803 r
= IStorage_Commit(stg
, STGC_DEFAULT
);
3804 ok(r
==S_OK
, "IStorage->Commit failed %x\n", r
);
3806 hfile
= CreateFileA(filenameA
, GENERIC_READ
, FILE_SHARE_READ
|FILE_SHARE_WRITE
|FILE_SHARE_DELETE
,
3807 NULL
, OPEN_EXISTING
, 0, NULL
);
3808 ok(hfile
!= NULL
, "couldn't open file %d\n", GetLastError());
3810 orig_size
= GetFileSize(hfile
, NULL
);
3813 r
= IStream_Seek(stm
, pos
, STREAM_SEEK_SET
, &upos
);
3814 ok(r
==S_OK
, "IStream->Seek failed %x\n", r
);
3816 r
= IStream_Write(stm
, "b", 1, NULL
);
3817 ok(r
==S_OK
, "IStream->Write failed %x\n", r
);
3819 r
= IStorage_Commit(stg
, STGC_OVERWRITE
);
3820 ok(r
==S_OK
, "IStorage->Commit failed %x\n", r
);
3822 new_size
= GetFileSize(hfile
, NULL
);
3824 todo_wine
ok(new_size
== orig_size
, "file grew from %d bytes to %d\n", orig_size
, new_size
);
3826 IStream_Release(stm
);
3828 IStorage_RenameElement(stg
, stmname
, stmname2
);
3830 r
= IStorage_Commit(stg
, STGC_OVERWRITE
);
3831 ok(r
==S_OK
, "IStorage->Commit failed %x\n", r
);
3833 new_size
= GetFileSize(hfile
, NULL
);
3835 todo_wine
ok(new_size
== orig_size
, "file grew from %d bytes to %d\n", orig_size
, new_size
);
3837 IStorage_Release(stg
);
3839 r
= StgOpenStorage(filename
, NULL
, STGM_READWRITE
| STGM_TRANSACTED
| STGM_SHARE_EXCLUSIVE
, NULL
, 0, &stg
);
3840 ok(r
==S_OK
, "StgOpenStorage failed %x\n", r
);
3842 r
= IStorage_OpenStream(stg
, stmname2
, NULL
, STGM_SHARE_EXCLUSIVE
| STGM_READWRITE
, 0, &stm
);
3843 ok(r
==S_OK
, "IStorage->CreateStream failed %x\n", r
);
3845 r
= IStream_Read(stm
, buffer
, sizeof(buffer
), &bytesread
);
3846 ok(r
==S_OK
, "IStream->Write failed %x\n", r
);
3847 ok(bytesread
== sizeof(buffer
), "only read %d bytes\n", bytesread
);
3848 ok(buffer
[0] == 'b', "unexpected data at byte 0\n");
3850 for (i
=1; i
<sizeof(buffer
); i
++)
3851 if (buffer
[i
] != 'a')
3853 ok(i
== sizeof(buffer
), "unexpected data at byte %i\n", i
);
3856 r
= IStream_Seek(stm
, pos
, STREAM_SEEK_SET
, &upos
);
3857 ok(r
==S_OK
, "IStream->Seek failed %x\n", r
);
3859 r
= IStream_Write(stm
, "c", 1, NULL
);
3860 ok(r
==S_OK
, "IStream->Write failed %x\n", r
);
3862 r
= IStorage_Commit(stg
, STGC_OVERWRITE
);
3863 ok(r
==S_OK
, "IStorage->Commit failed %x\n", r
);
3865 new_size
= GetFileSize(hfile
, NULL
);
3867 todo_wine
ok(new_size
== orig_size
, "file grew from %d bytes to %d\n", orig_size
, new_size
);
3869 IStream_Release(stm
);
3871 IStorage_Release(stg
);
3875 DeleteFileA(filenameA
);
3878 static void test_custom_lockbytes(void)
3880 static const WCHAR stmname
[] = { 'C','O','N','T','E','N','T','S',0 };
3881 TestLockBytes
* lockbytes
;
3886 CreateTestLockBytes(&lockbytes
);
3888 hr
= StgCreateDocfileOnILockBytes(&lockbytes
->ILockBytes_iface
, STGM_CREATE
|STGM_READWRITE
|STGM_TRANSACTED
, 0, &stg
);
3889 ok(hr
==S_OK
, "StgCreateDocfileOnILockBytes failed %x\n", hr
);
3891 hr
= IStorage_CreateStream(stg
, stmname
, STGM_SHARE_EXCLUSIVE
|STGM_READWRITE
, 0, 0, &stm
);
3892 ok(hr
==S_OK
, "IStorage_CreateStream failed %x\n", hr
);
3894 IStream_Release(stm
);
3896 hr
= IStorage_Commit(stg
, 0);
3898 IStorage_Release(stg
);
3900 ok(!lockbytes
->lock_called
, "unexpected call to LockRegion\n");
3902 lockbytes
->locks_supported
= LOCK_WRITE
|LOCK_EXCLUSIVE
|LOCK_ONLYONCE
;
3904 hr
= StgCreateDocfileOnILockBytes(&lockbytes
->ILockBytes_iface
, STGM_CREATE
|STGM_READWRITE
|STGM_TRANSACTED
, 0, &stg
);
3905 ok(hr
==S_OK
, "StgCreateDocfileOnILockBytes failed %x\n", hr
);
3907 hr
= IStorage_CreateStream(stg
, stmname
, STGM_SHARE_EXCLUSIVE
|STGM_READWRITE
, 0, 0, &stm
);
3908 ok(hr
==S_OK
, "IStorage_CreateStream failed %x\n", hr
);
3910 IStream_Release(stm
);
3912 hr
= IStorage_Commit(stg
, 0);
3914 IStorage_Release(stg
);
3916 ok(lockbytes
->lock_called
, "expected LockRegion to be called\n");
3918 lockbytes
->lock_hr
= STG_E_INVALIDFUNCTION
;
3920 hr
= StgCreateDocfileOnILockBytes(&lockbytes
->ILockBytes_iface
, STGM_CREATE
|STGM_READWRITE
|STGM_TRANSACTED
, 0, &stg
);
3921 ok(hr
==STG_E_INVALIDFUNCTION
, "StgCreateDocfileOnILockBytes failed %x\n", hr
);
3923 DeleteTestLockBytes(lockbytes
);
3926 START_TEST(storage32
)
3928 CHAR temp
[MAX_PATH
];
3930 GetTempPathA(MAX_PATH
, temp
);
3931 if(!GetTempFileNameA(temp
, "stg", 0, filenameA
))
3933 win_skip("Could not create temp file, %u\n", GetLastError());
3936 MultiByteToWideChar(CP_ACP
, 0, filenameA
, -1, filename
, MAX_PATH
);
3937 DeleteFileA(filenameA
);
3939 test_hglobal_storage_stat();
3940 test_create_storage_modes();
3941 test_stgcreatestorageex();
3942 test_storage_stream();
3943 test_open_storage();
3944 test_storage_suminfo();
3945 test_storage_refcount();
3948 test_substorage_share();
3951 test_nonroot_transacted();
3952 test_ReadClassStm();
3954 test_writeclassstg();
3957 test_fmtusertypestg();
3960 test_copyto_snbexclusions();
3961 test_copyto_iidexclusions_storage();
3962 test_copyto_iidexclusions_stream();
3964 test_toplevel_stat();
3965 test_substorage_enum();
3966 test_copyto_locking();
3967 test_copyto_recursive();
3968 test_hglobal_storage_creation();
3972 test_transacted_shared();
3974 test_custom_lockbytes();