ReactOS 0.4.16-dev-2-g02a6913
storage32.c
Go to the documentation of this file.
1/*
2 * Unit tests for OLE storage
3 *
4 * Copyright (c) 2004 Mike McCormack
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21#include <stdio.h>
22
23#define COBJMACROS
24#ifdef __REACTOS__
25#define CONST_VTABLE
26#else
27#define NONAMELESSUNION
28#define NONAMELESSSTRUCT
29#endif
30
31#include <windows.h>
32#include "wine/test.h"
33
34#include "ole2.h"
35#include "objidl.h"
36#include "initguid.h"
37
38DEFINE_GUID( test_stg_cls, 0x88888888, 0x0425, 0x0000, 0,0,0,0,0,0,0,0);
39
40#define ok_ole_success(hr, func) ok(hr == S_OK, func " failed with error 0x%08x\n", hr)
41
44
45static const char file1_nameA[] = {'c','o','p','y','t','e','s','t','A',0};
46static const WCHAR file1_name[] = {'c','o','p','y','t','e','s','t','A',0};
47static const char file2_nameA[] = {'c','o','p','y','t','e','s','t','B',0};
48static const WCHAR file2_name[] = {'c','o','p','y','t','e','s','t','B',0};
49static const WCHAR stgA_name[] = {'S','t','o','r','a','g','e','A',0};
50static const WCHAR stgB_name[] = {'S','t','o','r','a','g','e','B',0};
51static const WCHAR strmA_name[] = {'S','t','r','e','a','m','A',0};
52static const WCHAR strmB_name[] = {'S','t','r','e','a','m','B',0};
53static const WCHAR strmC_name[] = {'S','t','r','e','a','m','C',0};
54
55/* Win9x and WinMe don't have lstrcmpW */
56static int strcmp_ww(LPCWSTR strw1, LPCWSTR strw2)
57{
58 CHAR stra1[512], stra2[512];
59 WideCharToMultiByte(CP_ACP, 0, strw1, -1, stra1, sizeof(stra1), NULL, NULL);
60 WideCharToMultiByte(CP_ACP, 0, strw2, -1, stra2, sizeof(stra2), NULL, NULL);
61 return lstrcmpA(stra1, stra2);
62}
63
64typedef struct TestLockBytes {
74
76{
77 return CONTAINING_RECORD(iface, TestLockBytes, ILockBytes_iface);
78}
79
81 void **ppv)
82{
84
85 if (!ppv) return E_INVALIDARG;
86
87 if (IsEqualIID(&IID_IUnknown, iid) ||
88 IsEqualIID(&IID_ILockBytes, iid))
89 *ppv = &This->ILockBytes_iface;
90 else
91 return E_NOINTERFACE;
92
93 IUnknown_AddRef((IUnknown*)*ppv);
94 return S_OK;
95}
96
98{
101 return ref;
102}
103
105{
108 return ref;
109}
110
112 ULARGE_INTEGER ulOffset, void *pv, ULONG cb, ULONG *pcbRead)
113{
115 ULONG dummy;
116
117 if (!pv) return E_INVALIDARG;
118
119 if (!pcbRead) pcbRead = &dummy;
120
121 if (ulOffset.QuadPart >= This->size)
122 {
123 *pcbRead = 0;
124 return S_OK;
125 }
126
127 cb = min(cb, This->size - ulOffset.QuadPart);
128
129 *pcbRead = cb;
130 memcpy(pv, &This->contents[ulOffset.QuadPart], cb);
131
132 return S_OK;
133}
134
136 ULARGE_INTEGER ulOffset, const void *pv, ULONG cb, ULONG *pcbWritten)
137{
139 HRESULT hr;
140 ULONG dummy;
141
142 if (!pv) return E_INVALIDARG;
143
144 if (!pcbWritten) pcbWritten = &dummy;
145
146 if (ulOffset.QuadPart + cb > This->size)
147 {
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;
152 }
153
154 *pcbWritten = cb;
155 memcpy(&This->contents[ulOffset.QuadPart], pv, cb);
156
157 return S_OK;
158}
159
161{
162 return S_OK;
163}
164
167{
169
170 if (This->buffer_size < cb.QuadPart)
171 {
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;
178 }
179
180 if (cb.QuadPart > This->size)
181 memset(&This->contents[This->size], 0, cb.QuadPart - This->size);
182
183 This->size = cb.QuadPart;
184
185 return S_OK;
186}
187
189 ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
190{
192 This->lock_called++;
193 return This->lock_hr;
194}
195
197 ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
198{
200 return This->lock_hr;
201}
202
204 STATSTG *pstatstg, DWORD grfStatFlag)
205{
207 static const WCHAR dummy_name[] = {'d','u','m','m','y',0};
208
209 if (!pstatstg) return E_INVALIDARG;
210
211 memset(pstatstg, 0, sizeof(STATSTG));
212
213 if (!(grfStatFlag & STATFLAG_NONAME))
214 {
215 pstatstg->pwcsName = CoTaskMemAlloc(sizeof(dummy_name));
216 if (!pstatstg->pwcsName) return E_OUTOFMEMORY;
217 memcpy(pstatstg->pwcsName, dummy_name, sizeof(dummy_name));
218 }
219
220 pstatstg->type = STGTY_LOCKBYTES;
221 pstatstg->cbSize.QuadPart = This->size;
222 pstatstg->grfLocksSupported = This->locks_supported;
223
224 return S_OK;
225}
226
227static const ILockBytesVtbl TestLockBytes_Vtbl = {
238};
239
241{
243
244 if (*This)
245 {
246 (*This)->ILockBytes_iface.lpVtbl = &TestLockBytes_Vtbl;
247 (*This)->ref = 1;
248 }
249}
250
252{
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);
257}
258
260{
261 ILockBytes *ilb = NULL;
262 IStorage *stg = NULL;
263 HRESULT r;
264 STATSTG stat;
265 DWORD mode, refcount;
266
268 ok( r == S_OK, "CreateILockBytesOnHGlobal failed\n");
269
270 r = StgIsStorageILockBytes( ilb );
271 ok( r == S_FALSE, "StgIsStorageILockBytes should have failed\n");
272
274 r = StgCreateDocfileOnILockBytes( ilb, mode, 0, &stg );
275 ok( r == S_OK, "StgCreateDocfileOnILockBytes failed\n");
276
277 r = WriteClassStg( stg, &test_stg_cls );
278 ok( r == S_OK, "WriteClassStg failed\n");
279
280 r = StgIsStorageILockBytes( ilb );
281 ok( r == S_OK, "StgIsStorageILockBytes failed\n");
282
283 memset( &stat, 0, sizeof stat );
284 r = IStorage_Stat( stg, &stat, 0 );
285
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");
290
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");
295}
296
298{
299 IStorage *stg = NULL;
300 HRESULT r;
301
303
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");
310 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
312 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
314 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
316 ok(r==STG_E_INVALIDPOINTER, "StgCreateDocfile succeeded\n");
318 ok(r==STG_E_INVALIDPARAMETER, "StgCreateDocfile succeeded\n");
320 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
322 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
324 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
325
326 /* StgCreateDocfile seems to be very particular about the flags it accepts */
328 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
330 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
332 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
334 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
336 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
338 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
340 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
341 ok(stg == NULL, "stg was set\n");
342
343 /* check what happens if the file already exists (which is how it's meant to be used) */
345 ok(r==S_OK, "StgCreateDocfile failed\n");
346 r = IStorage_Release(stg);
347 ok(r == 0, "storage not released\n");
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 */
353 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
355 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
357 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile failed\n");
359 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile failed\n");
361 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile failed\n");
363 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile failed\n");
365 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile failed\n");
367 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile wrong error\n");
369 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile wrong error\n");
370 ok(DeleteFileA(filenameA), "failed to delete file\n");
371
373 ok(r==S_OK, "StgCreateDocfile failed\n");
374 r = IStorage_Release(stg);
375 ok(r == 0, "storage not released\n");
377 ok(r==STG_E_FILEALREADYEXISTS, "StgCreateDocfile wrong error\n");
379 ok(r==STG_E_FILEALREADYEXISTS, "StgCreateDocfile wrong error\n");
380
382 ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
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");
388
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");
394
395 /* test the way excel uses StgCreateDocFile */
397 ok(r==S_OK, "StgCreateDocfile the excel way failed\n");
398 if(r == S_OK)
399 {
400 r = IStorage_Release(stg);
401 ok(r == 0, "storage not released\n");
402 ok(DeleteFileA(filenameA), "failed to delete file\n");
403 }
404
405 /* and the way windows media uses it ... */
407 ok(r==S_OK, "StgCreateDocfile the windows media way failed\n");
408 if (r == S_OK)
409 {
410 r = IStorage_Release(stg);
411 ok(r == 0, "storage not released\n");
412 ok(DeleteFileA(filenameA), "failed to delete file\n");
413 }
414
415 /* looks like we need STGM_TRANSACTED or STGM_CREATE */
417 ok(r==S_OK, "StgCreateDocfile the excel way failed\n");
418 if(r == S_OK)
419 {
420 r = IStorage_Release(stg);
421 ok(r == 0, "storage not released\n");
422 ok(DeleteFileA(filenameA), "failed to delete file\n");
423 }
424
426 ok(r==S_OK, "StgCreateDocfile the excel way failed\n");
427 if(r == S_OK)
428 {
429 r = IStorage_Release(stg);
430 ok(r == 0, "storage not released\n");
431 ok(DeleteFileA(filenameA), "failed to delete file\n");
432 }
433
435 ok(r==S_OK, "StgCreateDocfile the powerpoint way failed\n");
436 if(r == S_OK)
437 {
438 r = IStorage_Release(stg);
439 ok(r == 0, "storage not released\n");
440 ok(DeleteFileA(filenameA), "failed to delete file\n");
441 }
442
443 /* test the way msi uses StgCreateDocfile */
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");
449}
450
451static void test_stgcreatestorageex(void)
452{
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};
457 HRESULT r;
458
459 pStgCreateStorageEx = (void *) GetProcAddress(hOle32, "StgCreateStorageEx");
460 if (!pStgCreateStorageEx)
461 {
462 win_skip("skipping test on NT4\n");
463 return;
464 }
465
467
468 /* Verify that StgCreateStorageEx can accept an options param */
469 r = pStgCreateStorageEx( filename,
472 0,
473 &stgoptions,
474 NULL,
475 &IID_IStorage,
476 (void **) &stg);
477 ok(r==S_OK || r==STG_E_UNIMPLEMENTEDFUNCTION, "StgCreateStorageEx with options failed\n");
479 {
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");
482 return;
483 }
484
485 r = IStorage_Release(stg);
486 ok(r == 0, "storage not released\n");
487 ok(DeleteFileA(filenameA), "failed to delete file\n");
488
489 /* Verify that StgCreateStorageEx can accept a NULL pStgOptions */
490 r = pStgCreateStorageEx( filename,
493 0,
494 NULL,
495 NULL,
496 &IID_IStorage,
497 (void **) &stg);
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");
502}
503
504static void test_storage_stream(void)
505{
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
510 };
511 IStorage *stg = NULL;
512 HRESULT r;
513 IStream *stm = NULL;
514 IStream *stm2 = NULL;
515 ULONG count = 0;
518 unsigned char buffer[0x100];
519 IUnknown *unk;
520 BOOL ret;
521
523
525 ok(r==S_OK, "StgCreateDocfile failed\n");
526
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");
549
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");
553
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);
559
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");
566
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");
570
571 r = IStream_Clone(stm, &stm2);
572 ok(r==S_OK, "failed to clone stream\n");
573
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");
586
587 /* Read past the end of the stream. */
588 pos.QuadPart = 3;
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");
595 pos.QuadPart = 10;
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");
609
610 /* Convert to a big block stream, and read past the end. */
611 p.QuadPart = 5000;
612 r = IStream_SetSize(stm,p);
613 ok(r==S_OK, "failed to set pos\n");
614 pos.QuadPart = 4997;
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");
621 pos.QuadPart = 5001;
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");
635
636 /* seek round a bit, reset the stream size */
637 pos.QuadPart = 0;
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");
646 pos.QuadPart = 10;
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");
660 pos.QuadPart = 0;
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");
667
668 /* wrap up */
669 r = IStream_Release(stm2);
670 ok(r == 0, "wrong ref count\n");
671
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");
675
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);
678
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");
683
684 r = IStorage_Release(stg);
685 ok(r == 0, "wrong ref count\n");
686
687 /* try create some invalid streams */
688 stg = NULL;
689 stm = NULL;
691 ok(r == S_OK, "should succeed\n");
692 if (stg)
693 {
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);
697 }
698
700 ok(ret, "file should exist\n");
701}
702
704{
705 HANDLE file;
706
710 return FALSE;
712 return TRUE;
713}
714
716{
717 HANDLE file;
718 DWORD len;
719
721 OPEN_EXISTING, 0, NULL);
723 return FALSE;
726 return len == 0;
727}
728
730{
731 HANDLE file;
732
734 OPEN_EXISTING, 0, NULL);
736 return FALSE;
738 return TRUE;
739}
740
741static void test_open_storage(void)
742{
743 static const WCHAR szNonExist[] = { 'n','o','n','e','x','i','s','t',0 };
744 IStorage *stg = NULL, *stg2 = NULL;
745 HRESULT r;
746 DWORD stgm;
747 BOOL ret;
748
749 /* try opening a zero length file - it should stay zero length */
753 r = StgOpenStorage( filename, NULL, stgm, NULL, 0, &stg);
754 ok(r==STG_E_FILEALREADYEXISTS, "StgOpenStorage didn't fail\n");
755
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");
760
762
763 /* try opening a nonexistent file - it should not create it */
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");
770
771 /* create the file */
773 ok(r==S_OK, "StgCreateDocfile failed\n");
774 IStorage_Release(stg);
775
776 r = StgOpenStorage( filename, NULL, 0, NULL, 0, &stg);
777 ok(r==STG_E_INVALIDFLAG, "StgOpenStorage wrong error\n");
779 ok(r==STG_E_INVALIDNAME, "StgOpenStorage wrong error\n");
781 ok(r==STG_E_INVALIDPOINTER, "StgOpenStorage wrong error\n");
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");
787 ok(r==STG_E_INVALIDFLAG, "StgOpenStorage failed\n");
789 ok(r==STG_E_INVALIDFLAG, "StgOpenStorage failed\n");
791 ok(r==STG_E_INVALIDFLAG, "StgOpenStorage failed\n");
793 ok(r==STG_E_INVALIDFLAG, "StgOpenStorage failed\n");
794
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");
798 if(stg)
799 {
800 r = IStorage_Release(stg);
801 ok(r == 0, "wrong ref count\n");
802 }
803
805 ok(r==S_OK, "StgOpenStorage failed\n");
806 if(stg)
807 {
808 r = IStorage_Release(stg);
809 ok(r == 0, "wrong ref count\n");
810 }
811
812 /* test the way word opens its custom dictionary */
815 ok(r==S_OK, "StgOpenStorage failed\n");
816 if(stg)
817 {
818 r = IStorage_Release(stg);
819 ok(r == 0, "wrong ref count\n");
820 }
821
823 ok(r==S_OK, "StgOpenStorage failed\n");
825 ok(r==STG_E_SHAREVIOLATION, "StgOpenStorage failed\n");
826 if(stg)
827 {
828 r = IStorage_Release(stg);
829 ok(r == 0, "wrong ref count\n");
830 }
831
832 /* now try write to a storage file we opened read-only */
834 ok(r==S_OK, "StgOpenStorage failed\n");
835 if(stg)
836 {
837 static const WCHAR stmname[] = { 'w','i','n','e','t','e','s','t',0};
838 IStream *stm = NULL;
839 IStorage *stg2 = NULL;
840
841 r = IStorage_CreateStream( stg, stmname, STGM_WRITE | STGM_SHARE_EXCLUSIVE,
842 0, 0, &stm );
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");
846
847 r = IStorage_Release(stg);
848 ok(r == 0, "wrong ref count\n");
849 }
850
851 /* open like visio 2003 */
852 stg = NULL;
854 ok(r == S_OK, "should succeed\n");
855 if (stg)
856 IStorage_Release(stg);
857
858 /* test other sharing modes with STGM_PRIORITY */
859 stg = NULL;
861 ok(r == S_OK, "should succeed\n");
862 if (stg)
863 IStorage_Release(stg);
864
865 stg = NULL;
867 ok(r == S_OK, "should succeed\n");
868 if (stg)
869 IStorage_Release(stg);
870
871 stg = NULL;
873 ok(r == S_OK, "should succeed\n");
874 if (stg)
875 IStorage_Release(stg);
876
877 /* open like Project 2003 */
878 stg = NULL;
880 ok(r == S_OK, "should succeed\n");
882 ok(r == S_OK, "should succeed\n");
883 if (stg2)
884 IStorage_Release(stg2);
885 if (stg)
886 IStorage_Release(stg);
887
888 stg = NULL;
890 ok(r == STG_E_INVALIDFLAG, "should fail\n");
891
893 ok(r == STG_E_INVALIDFLAG, "should fail\n");
894
896 ok(r == STG_E_INVALIDFLAG, "should fail\n");
897
899 ok(r == STG_E_INVALIDFUNCTION, "should fail\n");
900
902 ok(r == STG_E_INVALIDFLAG, "should fail\n");
903
905 ok(r == STG_E_INVALIDFLAG, "should fail\n");
906
908 ok(ret, "file didn't exist\n");
909}
910
911static void test_storage_suminfo(void)
912{
913 IStorage *stg = NULL;
914 IPropertySetStorage *propset = NULL;
916 HRESULT r;
917
919
920 /* create the file */
923 ok(r==S_OK, "StgCreateDocfile failed\n");
924
925 r = IStorage_QueryInterface( stg, &IID_IPropertySetStorage, (LPVOID) &propset );
926 ok(r == S_OK, "query interface failed\n");
927
928 /* delete it */
929 r = IPropertySetStorage_Delete( propset, &FMTID_SummaryInformation );
930 ok(r == STG_E_FILENOTFOUND, "deleted property set storage\n");
931
932 r = IPropertySetStorage_Open( propset, &FMTID_SummaryInformation,
934 ok(r == STG_E_FILENOTFOUND, "opened property set storage\n");
935
936 r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0,
938 ok(r == STG_E_INVALIDFLAG, "created property set storage\n");
939
940 r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0,
941 STGM_READ, &ps );
942 ok(r == STG_E_INVALIDFLAG, "created property set storage\n");
943
944 r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0, 0, &ps );
945 ok(r == STG_E_INVALIDFLAG, "created property set storage\n");
946
947 r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0,
949 ok(r == STG_E_INVALIDFLAG, "created property set storage\n");
950
951 r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0,
953 ok(r == STG_E_INVALIDFLAG, "created property set storage\n");
954
955 /* now try really creating a property set */
956 r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0,
958 ok(r == S_OK, "failed to create property set storage\n");
959
960 if( ps )
961 IPropertyStorage_Release(ps);
962
963 /* now try creating the same thing again */
964 r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0,
966 ok(r == S_OK, "failed to create property set storage\n");
967 if( ps )
968 IPropertyStorage_Release(ps);
969
970 /* should be able to open it */
971 r = IPropertySetStorage_Open( propset, &FMTID_SummaryInformation,
973 ok(r == S_OK, "open failed\n");
974 if(r == S_OK)
975 IPropertyStorage_Release(ps);
976
977 /* delete it */
978 r = IPropertySetStorage_Delete( propset, &FMTID_SummaryInformation );
979 ok(r == S_OK, "failed to delete property set storage\n");
980
981 /* try opening with an invalid FMTID */
982 r = IPropertySetStorage_Open( propset, NULL,
984 ok(r == E_INVALIDARG, "open succeeded\n");
985 if(r == S_OK)
986 IPropertyStorage_Release(ps);
987
988 /* try a bad guid */
989 r = IPropertySetStorage_Open( propset, &IID_IStorage,
991 ok(r == STG_E_FILENOTFOUND, "open succeeded\n");
992 if(r == S_OK)
993 IPropertyStorage_Release(ps);
994
995
996 /* try some invalid flags */
997 r = IPropertySetStorage_Open( propset, &FMTID_SummaryInformation,
999 ok(r == STG_E_INVALIDFLAG, "open succeeded\n");
1000 if(r == S_OK)
1001 IPropertyStorage_Release(ps);
1002
1003 /* after deleting it, it should be gone */
1004 r = IPropertySetStorage_Open( propset, &FMTID_SummaryInformation,
1006 ok(r == STG_E_FILENOTFOUND, "open failed\n");
1007 if(r == S_OK)
1008 IPropertyStorage_Release(ps);
1009
1010 r = IPropertySetStorage_Release( propset );
1011 ok(r == 1, "ref count wrong\n");
1012
1013 r = IStorage_Release(stg);
1014 ok(r == 0, "ref count wrong\n");
1015
1017}
1018
1019static void test_storage_refcount(void)
1020{
1021 IStorage *stg = NULL;
1022 IStorage *stgprio = NULL;
1023 HRESULT r;
1024 IStream *stm = NULL;
1025 static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 };
1027 ULARGE_INTEGER upos;
1028 STATSTG stat;
1029 char buffer[10];
1030
1032
1033 /* create the file */
1036 ok(r==S_OK, "StgCreateDocfile failed\n");
1037
1038 r = WriteClassStg( stg, &test_stg_cls );
1039 ok( r == S_OK, "WriteClassStg failed\n");
1040
1041 r = IStorage_Commit( stg, STGC_DEFAULT );
1042 ok( r == S_OK, "IStorage_Commit failed\n");
1043
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");
1047
1048 r = IStorage_Release( stg );
1049 ok (r == 0, "storage not released\n");
1050
1051 pos.QuadPart = 0;
1052 r = IStream_Seek( stm, pos, 0, &upos );
1053 ok (r == STG_E_REVERTED, "seek should fail\n");
1054
1055 r = IStream_Stat( stm, &stat, STATFLAG_DEFAULT );
1056 ok (r == STG_E_REVERTED, "stat should fail\n");
1057
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);
1060
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);
1063
1064 r = IStream_Release(stm);
1065 ok (r == 0, "stream not released\n");
1066
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);
1071
1072 /* non-transacted mode read/write fails */
1074 ok(r==STG_E_LOCKVIOLATION, "StgOpenStorage should return STG_E_LOCKVIOLATION instead of 0x%08x\n", r);
1075
1076 /* non-transacted mode read-only succeeds */
1078 ok(r==S_OK, "StgOpenStorage failed with error 0x%08x\n", r);
1079 IStorage_Release(stg);
1080
1082 ok(r==S_OK, "StgOpenStorage failed with error 0x%08x\n", r);
1083 if(stg)
1084 {
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 };
1088 IStorage *stg2;
1089 IStorage *stg3;
1090 STATSTG statstg;
1091
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);
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);
1103
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);
1106
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);
1121
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);
1124
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);
1127
1128 IStorage_Release(stg2);
1129
1130 r = IStorage_Release(stg);
1131 ok(r == 0, "wrong ref count\n");
1132 }
1133
1134 /* Multiple STGM_PRIORITY opens are possible. */
1136 ok(r==S_OK, "StgOpenStorage failed with error 0x%08x\n", r);
1137 if(stg)
1138 {
1139 r = IStorage_Release(stg);
1140 ok(r == 0, "wrong ref count\n");
1141 }
1142
1144 ok(r==S_OK, "StgOpenStorage failed with error 0x%08x\n", r);
1145 if(stg)
1146 {
1147 static const WCHAR stgname[] = { ' ',' ',' ','2','9',0 };
1148 IStorage *stg2;
1149 STATSTG statstg;
1150
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);
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);
1162
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);
1165
1166 IStorage_Release(stg2);
1167
1168 r = IStorage_Commit( stg, 0 );
1169 ok(r == S_OK, "Commit should have succeeded instead of returning 0x%08x\n", r);
1170
1171 r = IStorage_Release(stg);
1172 ok(r == 0, "wrong ref count\n");
1173 }
1174 /* IStorage_Release(stgprio) not necessary because StgOpenStorage released it. */
1175
1177}
1178
1179static void test_writeclassstg(void)
1180{
1181 IStorage *stg = NULL;
1182 HRESULT r;
1183 CLSID temp_cls, cls2;
1184
1186
1187 /* create the file */
1189 STGM_READWRITE, 0, &stg);
1190 ok(r==S_OK, "StgCreateDocfile failed\n");
1191
1192 r = ReadClassStg( NULL, NULL );
1193 ok(r == E_INVALIDARG, "ReadClassStg should return E_INVALIDARG instead of 0x%08X\n", r);
1194
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");
1200
1201 r = ReadClassStg( stg, NULL );
1202 ok(r == E_INVALIDARG, "ReadClassStg should return E_INVALIDARG instead of 0x%08X\n", r);
1203
1204 temp_cls.Data1 = 0xdeadbeef;
1205 r = ReadClassStg( stg, &temp_cls );
1206 ok(r == S_OK, "ReadClassStg failed with 0x%08X\n", r);
1207
1208 ok(IsEqualCLSID(&temp_cls, &CLSID_NULL), "ReadClassStg returned wrong clsid\n");
1209
1210 r = WriteClassStg( NULL, NULL );
1211 ok(r == E_INVALIDARG, "WriteClassStg should return E_INVALIDARG instead of 0x%08X\n", r);
1212
1213 r = WriteClassStg( stg, NULL );
1214 ok(r == STG_E_INVALIDPOINTER, "WriteClassStg should return STG_E_INVALIDPOINTER instead of 0x%08X\n", r);
1215
1216 r = WriteClassStg( stg, &test_stg_cls );
1217 ok( r == S_OK, "WriteClassStg failed with 0x%08X\n", r);
1218
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");
1222
1223 r = IStorage_Release( stg );
1224 ok (r == 0, "storage not released\n");
1225
1227}
1228
1229static void test_streamenum(void)
1230{
1231 IStorage *stg = NULL;
1232 HRESULT r;
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;
1238 STATSTG stat;
1239 IEnumSTATSTG *ee = NULL;
1240 ULONG count;
1241
1243
1244 /* create the file */
1247 ok(r==S_OK, "StgCreateDocfile failed\n");
1248
1249 r = WriteClassStg( stg, &test_stg_cls );
1250 ok( r == S_OK, "WriteClassStg failed\n");
1251
1252 r = IStorage_Commit( stg, STGC_DEFAULT );
1253 ok( r == S_OK, "IStorage_Commit failed\n");
1254
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");
1258
1259 IStream_Release(stm);
1260
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");
1264
1265 count = 0xf00;
1266 r = IEnumSTATSTG_Next(ee, 1, &stat, &count);
1267 ok(r==S_OK, "IEnumSTATSTG->Next failed\n");
1268 ok(count == 1, "count wrong\n");
1269
1270 if (r == S_OK)
1271 CoTaskMemFree(stat.pwcsName);
1272
1273 r = IEnumSTATSTG_Release(ee);
1274 ok(r==S_OK, "EnumSTATSTG_Release failed with error 0x%08x\n", r);
1275
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");
1279
1280 r = IStorage_DestroyElement(stg, stmname);
1281 ok(r==S_OK, "IStorage->DestroyElement failed\n");
1282
1283 memset(&stat, 0xad, sizeof(stat));
1284 count = 0xf00;
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");
1289
1290 /* reset and try again */
1291 r = IEnumSTATSTG_Reset(ee);
1292 ok(r==S_OK, "IEnumSTATSTG->Reset failed\n");
1293
1294 count = 0xf00;
1295 r = IEnumSTATSTG_Next(ee, 1, &stat, &count);
1296 ok(r==S_FALSE, "IEnumSTATSTG->Next failed\n");
1297 ok(count == 0, "count wrong\n");
1298
1299 /* add a stream before reading */
1300 r = IEnumSTATSTG_Reset(ee);
1301 ok(r==S_OK, "IEnumSTATSTG->Reset failed\n");
1302
1303 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1304 ok(r==S_OK, "IStorage->CreateStream failed\n");
1305
1306 r = IStream_Release(stm);
1307 ok(r==S_OK, "Stream_Release failed with error 0x%08x\n", r);
1308
1309 count = 0xf00;
1310 r = IEnumSTATSTG_Next(ee, 1, &stat, &count);
1311 ok(r==S_OK, "IEnumSTATSTG->Next failed\n");
1312 ok(count == 1, "count wrong\n");
1313
1314 if (r == S_OK)
1315 {
1316 ok(lstrcmpiW(stat.pwcsName, stmname) == 0, "expected CONTENTS, got %s\n", wine_dbgstr_w(stat.pwcsName));
1317 CoTaskMemFree(stat.pwcsName);
1318 }
1319
1320 r = IStorage_CreateStream(stg, stmname2, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1321 ok(r==S_OK, "IStorage->CreateStream failed\n");
1322
1323 r = IStream_Release(stm);
1324 ok(r==S_OK, "Stream_Release failed with error 0x%08x\n", r);
1325
1326 count = 0xf00;
1327 r = IEnumSTATSTG_Next(ee, 1, &stat, &count);
1328 ok(r==S_OK, "IEnumSTATSTG->Next failed\n");
1329 ok(count == 1, "count wrong\n");
1330
1331 if (r == S_OK)
1332 {
1333 ok(lstrcmpiW(stat.pwcsName, stmname2) == 0, "expected ABCDEFGHI, got %s\n", wine_dbgstr_w(stat.pwcsName));
1334 CoTaskMemFree(stat.pwcsName);
1335 }
1336
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");
1340
1341 r = IStream_Release(stm);
1342 ok(r==S_OK, "Stream_Release failed with error 0x%08x\n", r);
1343
1344 r = IEnumSTATSTG_Reset(ee);
1345 ok(r==S_OK, "IEnumSTATSTG->Reset failed\n");
1346
1347 count = 0xf00;
1348 r = IEnumSTATSTG_Next(ee, 1, &stat, &count);
1349 ok(r==S_OK, "IEnumSTATSTG->Next failed\n");
1350 ok(count == 1, "count wrong\n");
1351
1352 if (r == S_OK)
1353 {
1354 ok(lstrcmpiW(stat.pwcsName, stmname) == 0, "expected CONTENTS, got %s\n", wine_dbgstr_w(stat.pwcsName));
1355 CoTaskMemFree(stat.pwcsName);
1356 }
1357
1358 r = IStorage_DestroyElement(stg, stmname);
1359 ok(r==S_OK, "IStorage->DestroyElement failed\n");
1360
1361 r = IStorage_DestroyElement(stg, stmname2);
1362 ok(r==S_OK, "IStorage->DestroyElement failed\n");
1363
1364 count = 0xf00;
1365 r = IEnumSTATSTG_Next(ee, 1, &stat, &count);
1366 ok(r==S_OK, "IEnumSTATSTG->Next failed\n");
1367 ok(count == 1, "count wrong\n");
1368
1369 if (r == S_OK)
1370 {
1371 ok(lstrcmpiW(stat.pwcsName, stmname3) == 0, "expected ABCDEFGHIJ, got %s\n", wine_dbgstr_w(stat.pwcsName));
1372 CoTaskMemFree(stat.pwcsName);
1373 }
1374
1375 r = IStorage_Release( stg );
1376 todo_wine ok (r == 0, "storage not released\n");
1377
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");
1381
1382 count = 0xf00;
1383 r = IEnumSTATSTG_Next(ee, 1, &stat, &count);
1384 ok(r==S_OK, "IEnumSTATSTG->Next failed\n");
1385 ok(count == 1, "count wrong\n");
1386
1387 if (r == S_OK)
1388 {
1389 ok(lstrcmpiW(stat.pwcsName, stmname3) == 0, "expected ABCDEFGHIJ, got %s\n", wine_dbgstr_w(stat.pwcsName));
1390 CoTaskMemFree(stat.pwcsName);
1391 }
1392
1393 /* the storage is left open until the enumerator is freed */
1397 r==STG_E_LOCKVIOLATION, /* XP-SP2/W2K3-SP1 and below */
1398 "StgCreateDocfile failed, res=%x\n", r);
1399
1400 r = IEnumSTATSTG_Release(ee);
1401 ok (r == 0, "enum not released\n");
1402
1404}
1405
1406static void test_transact(void)
1407{
1408 IStorage *stg = NULL, *stg2 = NULL, *stg3 = NULL;
1409 HRESULT r;
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 };
1415 BOOL ret;
1416
1418
1419 /* create the file */
1422 ok(r==S_OK, "StgCreateDocfile failed\n");
1423
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");
1427
1428 r = IStream_Write(stm, "this is stream 1\n", 16, NULL);
1429 ok(r==S_OK, "IStream->Write failed\n");
1430
1431 IStream_Release(stm);
1432
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);
1435
1436 if (r == S_OK)
1437 {
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);
1441
1442 if (r == S_OK)
1443 IStorage_Release(stg3);
1444
1445 r = IStorage_Commit(stg, 0);
1446 ok(r==S_OK, "IStorage->Commit failed\n");
1447
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);
1450
1451 if (r == S_OK)
1452 IStorage_Release(stg3);
1453
1454 IStorage_Release(stg2);
1455 }
1456
1457 /* now create a stream and storage, but don't commit them */
1458 stm = NULL;
1459 r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1460 ok(r==S_OK, "IStorage->CreateStream failed\n");
1461
1462 r = IStream_Write(stm, "this is stream 2\n", 16, NULL);
1463 ok(r==S_OK, "IStream->Write failed\n");
1464
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");
1468
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);
1471
1472 if (r == S_OK)
1473 IStorage_Release(stg2);
1474
1475 IStream_Release(stm);
1476
1477 IStorage_Release(stg);
1478
1479 stm = NULL;
1480 stg = NULL;
1482 ok(r==S_OK, "StgOpenStorage failed\n");
1483
1484 if (!stg)
1485 return;
1486
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);
1489
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);
1492
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);
1495
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);
1498
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);
1501 if (r == S_OK)
1502 IStream_Release(stm);
1503
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);
1506 if (r == S_OK)
1507 IStorage_Release(stg2);
1508
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);
1511
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);
1514 if (r == S_OK)
1515 IStream_Release(stm);
1516
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);
1519 if (r == S_OK)
1520 {
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);
1523 if (r == S_OK)
1524 IStorage_Release(stg3);
1525
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);
1528 if (r == S_OK)
1529 IStorage_Release(stg3);
1530
1531 IStorage_Release(stg2);
1532 }
1533
1534 IStorage_Release(stg);
1535
1537 ok(ret, "deleted file\n");
1538}
1539
1540static void test_substorage_share(void)
1541{
1542 IStorage *stg, *stg2, *stg3;
1543 IStream *stm, *stm2;
1544 HRESULT r;
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 };
1548 BOOL ret;
1549
1551
1552 /* create the file */
1554 STGM_READWRITE, 0, &stg);
1555 ok(r==S_OK, "StgCreateDocfile failed\n");
1556
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);
1560
1561 if (r == S_OK)
1562 {
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);
1565
1566 if (r == S_OK)
1567 IStorage_Release(stg3);
1568
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);
1571
1572 if (r == S_OK)
1573 IStorage_Release(stg3);
1574
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);
1579
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);
1583
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);
1586
1587 if (r == S_OK)
1588 IStream_Release(stm);
1589
1590 IStorage_Release(stg2);
1591 }
1592
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);
1596
1597 if (r == S_OK)
1598 {
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);
1601
1602 if (r == S_OK)
1603 IStream_Release(stm2);
1604
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);
1607
1608 if (r == S_OK)
1609 IStream_Release(stm2);
1610
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);
1615
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);
1619
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);
1622
1623 IStream_Release(stm);
1624 }
1625
1626 IStorage_Release(stg);
1627
1629 ok(ret, "deleted file\n");
1630}
1631
1632static void test_revert(void)
1633{
1634 IStorage *stg = NULL, *stg2 = NULL, *stg3 = NULL;
1635 HRESULT r;
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 };
1641 STATSTG statstg;
1642 BOOL ret;
1643
1645
1646 /* create the file */
1649 ok(r==S_OK, "StgCreateDocfile failed\n");
1650
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");
1654
1655 r = IStream_Write(stm, "this is stream 1\n", 16, NULL);
1656 ok(r==S_OK, "IStream->Write failed\n");
1657
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);
1660
1661 if (r == S_OK)
1662 {
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);
1666
1667 if (r == S_OK)
1668 IStorage_Release(stg3);
1669
1670 r = IStorage_Commit(stg, 0);
1671 ok(r==S_OK, "IStorage->Commit failed\n");
1672
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);
1675
1676 if (r == S_OK)
1677 IStorage_Release(stg3);
1678 }
1679
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");
1683
1684 r = IStream_Write(stm2, "this is stream 2\n", 16, NULL);
1685 ok(r==S_OK, "IStream->Write failed\n");
1686
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);
1689
1690 r = IStorage_Revert(stg);
1691 ok(r==S_OK, "Storage_Revert failed with error 0x%08x\n", r);
1692
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);
1696
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);
1699
1700 r = IStorage_Stat(stg2, &statstg, STATFLAG_NONAME);
1701 ok(r==STG_E_REVERTED, "IStorage_Stat should fail %08x\n", r);
1702
1703 r = IStorage_Stat(stg3, &statstg, STATFLAG_NONAME);
1704 ok(r==STG_E_REVERTED, "IStorage_Stat should fail %08x\n", r);
1705
1706 IStream_Release(stm);
1707 IStream_Release(stm2);
1708 IStorage_Release(stg2);
1709 IStorage_Release(stg3);
1710
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);
1713
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);
1716
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);
1719
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);
1722
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);
1725 if (r == S_OK)
1726 IStream_Release(stm);
1727
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);
1730 if (r == S_OK)
1731 IStorage_Release(stg2);
1732
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);
1735
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);
1738 if (r == S_OK)
1739 IStream_Release(stm);
1740
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);
1743 if (r == S_OK)
1744 {
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);
1747 if (r == S_OK)
1748 IStorage_Release(stg3);
1749
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);
1752 if (r == S_OK)
1753 IStorage_Release(stg3);
1754
1755 IStorage_Release(stg2);
1756 }
1757
1758 IStorage_Release(stg);
1759
1761 ok(ret, "deleted file\n");
1762
1763 /* Revert only invalidates objects in transacted mode */
1765 STGM_READWRITE, 0, &stg);
1766 ok(r==S_OK, "StgCreateDocfile failed\n");
1767
1768 r = IStorage_CreateStream(stg, stmname2, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1769 ok(r==S_OK, "IStorage->CreateStream failed\n");
1770
1771 r = IStorage_Revert(stg);
1772 ok(r==S_OK, "IStorage->Revert failed %08x\n", r);
1773
1774 r = IStream_Write(stm, "this works\n", 11, NULL);
1775 ok(r==S_OK, "IStream_Write should succeed %08x\n", r);
1776
1777 IStream_Release(stm);
1778 IStorage_Release(stg);
1779
1781 ok(ret, "deleted file\n");
1782}
1783
1784static void test_parent_free(void)
1785{
1786 IStorage *stg = NULL, *stg2 = NULL, *stg3 = NULL;
1787 HRESULT r;
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 };
1791 ULONG ref;
1792 STATSTG statstg;
1793 BOOL ret;
1794
1796
1797 /* create the file */
1800 ok(r==S_OK, "StgCreateDocfile failed\n");
1801
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);
1805
1806 if (r == S_OK)
1807 {
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");
1811
1812 if (r == S_OK)
1813 {
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");
1817 }
1818
1819 /* free the parent */
1820 ref = IStorage_Release(stg2);
1821 ok(ref == 0, "IStorage still has %u references\n", ref);
1822
1823 /* child objects are invalid */
1824 if (r == S_OK)
1825 {
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);
1828
1829 IStream_Release(stm);
1830
1831 r = IStorage_Stat(stg3, &statstg, STATFLAG_NONAME);
1832 ok(r==STG_E_REVERTED, "IStorage_Stat should fail %08x\n", r);
1833
1834 r = IStorage_SetStateBits(stg3, 1, 1);
1835 ok(r==STG_E_REVERTED, "IStorage_Stat should fail %08x\n", r);
1836
1837 IStorage_Release(stg3);
1838 }
1839 }
1840
1841 IStorage_Release(stg);
1842
1844 ok(ret, "deleted file\n");
1845}
1846
1848{
1849 IStorage *stg = NULL, *stg2 = NULL, *stg3 = NULL;
1850 HRESULT r;
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 };
1855 BOOL ret;
1856
1858
1859 /* create a transacted file */
1862 ok(r==S_OK, "StgCreateDocfile failed\n");
1863
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);
1867
1868 if (r == S_OK)
1869 {
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");
1873 if (r == S_OK)
1874 IStream_Release(stm);
1875
1876 IStorage_Commit(stg2, 0);
1877
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");
1881 if (r == S_OK)
1882 IStream_Release(stm);
1883
1884 IStorage_Revert(stg2);
1885
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);
1889 if (r == S_OK)
1890 IStream_Release(stm);
1891
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);
1894 if (r == S_OK)
1895 IStream_Release(stm);
1896
1897 IStorage_Release(stg2);
1898 }
1899
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);
1903
1904 if (r == S_OK)
1905 {
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);
1909 if (r == S_OK)
1910 IStorage_Release(stg3);
1911
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);
1915
1916 IStorage_Release(stg2);
1917 }
1918
1919 IStorage_Release(stg);
1920
1921 /* create a non-transacted file */
1923 STGM_READWRITE, 0, &stg);
1924 ok(r==S_OK, "StgCreateDocfile failed\n");
1925
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);
1929
1930 if (r == S_OK)
1931 {
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");
1935 if (r == S_OK)
1936 IStream_Release(stm);
1937
1938 IStorage_Commit(stg2, 0);
1939
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");
1943 if (r == S_OK)
1944 IStream_Release(stm);
1945
1946 IStorage_Revert(stg2);
1947
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);
1951 if (r == S_OK)
1952 IStream_Release(stm);
1953
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);
1956 if (r == S_OK)
1957 IStream_Release(stm);
1958
1959 IStorage_Release(stg2);
1960 }
1961
1962 IStorage_Release(stg);
1963
1965 ok(ret, "deleted file\n");
1966}
1967
1968static void test_ReadClassStm(void)
1969{
1970 CLSID clsid, clsid2;
1971 HRESULT hr;
1972 IStream *pStream;
1973 static const LARGE_INTEGER llZero;
1974
1976 ok(hr == E_INVALIDARG, "ReadClassStm should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1977
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");
1982
1983 hr = ReadClassStm(pStream, NULL);
1984 ok(hr == E_INVALIDARG, "ReadClassStm should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1985
1986 memset(&clsid, 0xcc, sizeof(clsid));
1987 memset(&clsid2, 0xcc, sizeof(clsid2));
1989 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1990 ok(IsEqualCLSID(&clsid, &clsid2), "got wrong clsid\n");
1991
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");
1996
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");
2002
2003 IStream_Release(pStream);
2004}
2005
2006struct access_res
2007{
2009 DWORD lasterr;
2010 BOOL ignore;
2011};
2012
2013static const struct access_res create[16] =
2014{
2015 { TRUE, ERROR_SUCCESS, TRUE },
2016 { TRUE, ERROR_SUCCESS, TRUE },
2017 { TRUE, ERROR_SUCCESS, FALSE },
2018 { TRUE, ERROR_SUCCESS, FALSE },
2022 { TRUE, ERROR_SUCCESS, FALSE },
2026 { TRUE, ERROR_SUCCESS, TRUE },
2030 { TRUE, ERROR_SUCCESS, TRUE }
2031};
2032
2033static const struct access_res create_commit[16] =
2034{
2035 { TRUE, ERROR_SUCCESS, TRUE },
2036 { TRUE, ERROR_SUCCESS, TRUE },
2037 { TRUE, ERROR_SUCCESS, FALSE },
2038 { TRUE, ERROR_SUCCESS, FALSE },
2042 { TRUE, ERROR_SUCCESS, FALSE },
2046 { TRUE, ERROR_SUCCESS, TRUE },
2050 { TRUE, ERROR_SUCCESS, TRUE }
2051};
2052
2053static const struct access_res create_close[16] =
2054{
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 }
2071};
2072
2073static const DWORD access_modes[4] = {
2074 0,
2078};
2079
2080static const DWORD share_modes[4] = {
2081 0,
2085};
2086
2087static void _test_file_access(LPCSTR file, const struct access_res *ares, DWORD line)
2088{
2089 int i, j, idx = 0;
2090
2091 for (i = 0; i < ARRAY_SIZE(access_modes); i++)
2092 {
2093 for (j = 0; j < ARRAY_SIZE(share_modes); j++)
2094 {
2095 DWORD lasterr;
2096 HANDLE hfile;
2097
2098 if (ares[idx].ignore)
2099 continue;
2100
2101 SetLastError(0xdeadbeef);
2105
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));
2110
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);
2115
2116 CloseHandle(hfile);
2117 idx++;
2118 }
2119 }
2120}
2121
2122#define test_file_access(file, ares) _test_file_access(file, ares, __LINE__)
2123
2124static void test_access(void)
2125{
2126 static const WCHAR fileW[] = {'w','i','n','e','t','e','s','t',0};
2127 static const char fileA[] = "winetest";
2128 IStorage *stg;
2129 HRESULT hr;
2130
2131 /* STGM_TRANSACTED */
2134 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
2135
2136 test_file_access(fileA, create);
2137
2138 hr = IStorage_Commit(stg, STGC_DEFAULT);
2139 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
2140
2142
2143 IStorage_Release(stg);
2144
2146
2147 DeleteFileA(fileA);
2148
2149 /* STGM_DIRECT */
2152 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
2153
2154 test_file_access(fileA, create);
2155
2156 hr = IStorage_Commit(stg, STGC_DEFAULT);
2157 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
2158
2160
2161 IStorage_Release(stg);
2162
2164
2165 DeleteFileA(fileA);
2166
2167 /* STGM_SHARE_DENY_NONE */
2170 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
2171
2172 test_file_access(fileA, create);
2173
2174 hr = IStorage_Commit(stg, STGC_DEFAULT);
2175 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
2176
2178
2179 IStorage_Release(stg);
2180
2182
2183 DeleteFileA(fileA);
2184
2185 /* STGM_SHARE_DENY_READ */
2188 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
2189
2190 test_file_access(fileA, create);
2191
2192 hr = IStorage_Commit(stg, STGC_DEFAULT);
2193 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
2194
2196
2197 IStorage_Release(stg);
2198
2200
2201 DeleteFileA(fileA);
2202
2203 /* STGM_SHARE_DENY_WRITE */
2206 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
2207
2208 test_file_access(fileA, create);
2209
2210 hr = IStorage_Commit(stg, STGC_DEFAULT);
2211 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
2212
2214
2215 IStorage_Release(stg);
2216
2218
2219 DeleteFileA(fileA);
2220
2221 /* STGM_DIRECT_SWMR | STGM_READ | STGM_SHARE_DENY_NONE - reader mode for direct SWMR mode */
2223 ok(hr == S_OK, "got %08x\n", hr);
2224 IStorage_Release(stg);
2225
2227 ok(hr == S_OK || broken(hr == STG_E_INVALIDFLAG), "got %08x\n", hr);
2228 if(hr != S_OK)
2229 return;
2230
2231 test_file_access(fileA, create);
2232
2233 IStorage_Release(stg);
2235
2236 DeleteFileA(fileA);
2237}
2238
2239static void test_readonly(void)
2240{
2241 IStorage *stg, *stg2, *stg3;
2242 IStream *stream;
2243 HRESULT hr;
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};
2247
2249 ok(hr == S_OK, "should succeed, res=%x\n", hr);
2250 if (SUCCEEDED(hr))
2251 {
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);
2254 if (SUCCEEDED(hr))
2255 {
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);
2258 if (SUCCEEDED(hr))
2259 IStream_Release(stream);
2260 IStorage_Release(stg2);
2261 }
2262 IStorage_Release(stg);
2263 }
2264
2265 /* re-open read only */
2267 ok(hr == S_OK, "should succeed, res=%x\n", hr);
2268 if (SUCCEEDED(hr))
2269 {
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);
2272 if (SUCCEEDED(hr))
2273 {
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);
2277 if (SUCCEEDED(hr))
2278 IStream_Release(stream);
2279
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);
2283 if (SUCCEEDED(hr))
2284 IStream_Release(stream);
2285
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);
2289 if (SUCCEEDED(hr))
2290 IStorage_Release(stg3);
2291
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);
2295 if (SUCCEEDED(hr))
2296 IStorage_Release(stg3);
2297
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);
2301
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);
2305
2306 IStorage_Release(stg2);
2307 }
2308
2309 IStorage_Release(stg);
2310 }
2311
2312 DeleteFileA("winetest");
2313}
2314
2315static void test_simple(void)
2316{
2317 /* Tests for STGM_SIMPLE mode */
2318
2319 IStorage *stg, *stg2;
2320 HRESULT r;
2321 IStream *stm;
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;
2327 DWORD count;
2328 STATSTG stat;
2329
2331
2333 ok(r == S_OK, "got %08x\n", r);
2334
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);
2338
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);
2343
2344 upos.QuadPart = 6000;
2345 r = IStream_SetSize(stm, upos);
2346 ok(r == S_OK, "got %08x\n", r);
2347
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);
2351
2352 pos.QuadPart = 0;
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);
2356
2357 r = IStream_Stat(stm, &stat, STATFLAG_NONAME);
2358 ok(r == S_OK ||
2359 broken(r == STG_E_INVALIDFUNCTION), /* NT4 and below */
2360 "got %08x\n", r);
2361 if (r == S_OK)
2362 ok(stat.cbSize.QuadPart == 3, "got %d\n", stat.cbSize.u.LowPart);
2363
2364 pos.QuadPart = 1;
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);
2368
2369 r = IStream_Stat(stm, &stat, STATFLAG_NONAME);
2370 ok(r == S_OK ||
2371 broken(r == STG_E_INVALIDFUNCTION), /* NT4 and below */
2372 "got %08x\n", r);
2373 if (r == S_OK)
2374 ok(stat.cbSize.QuadPart == 1, "got %d\n", stat.cbSize.u.LowPart);
2375
2376 IStream_Release(stm);
2377
2378 r = IStorage_CreateStream(stg, stmname2, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm);
2379 ok(r == S_OK, "got %08x\n", r);
2380
2381 upos.QuadPart = 100;
2382 r = IStream_SetSize(stm, upos);
2383 ok(r == S_OK, "got %08x\n", r);
2384
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);
2388
2389 IStream_Release(stm);
2390
2391 IStorage_Commit(stg, STGC_DEFAULT);
2392 IStorage_Release(stg);
2393
2395 if (r == STG_E_INVALIDFLAG)
2396 {
2397 win_skip("Flag combination is not supported on NT4 and below\n");
2399 return;
2400 }
2401 ok(r == S_OK, "got %08x\n", r);
2402
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);
2406
2407 r = IStorage_OpenStream(stg, stmname, NULL, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &stm);
2408 ok(r == S_OK, "got %08x\n", r);
2409
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);
2413
2414 IStream_Release(stm);
2415
2416 r = IStorage_OpenStream(stg, stmname2, NULL, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &stm);
2417 ok(r == S_OK, "got %08x\n", r);
2418
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);
2422
2423 IStream_Release(stm);
2424
2425
2426 IStorage_Release(stg);
2427
2429}
2430
2431static void test_fmtusertypestg(void)
2432{
2433 IStorage *stg;
2435 HRESULT hr;
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;
2441
2443 ok(hr == S_OK, "should succeed, res=%x\n", hr);
2444
2445 if (SUCCEEDED(hr))
2446 {
2447 /* try to write the stream */
2448 hr = WriteFmtUserTypeStg(stg, 0, userTypeW);
2449 ok(hr == S_OK, "should succeed, res=%x\n", hr);
2450
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);
2454 if (SUCCEEDED(hr))
2455 {
2456 BOOL found = FALSE;
2457 STATSTG statstg;
2458 DWORD got;
2459 memset(&statstg, 0xad, sizeof(statstg));
2460 while ((hr = IEnumSTATSTG_Next(stat, 1, &statstg, &got)) == S_OK && got == 1)
2461 {
2462 if (strcmp_ww(statstg.pwcsName, strmNameW) == 0)
2463 found = TRUE;
2464 else
2465 ok(0, "found unexpected stream or storage\n");
2466 CoTaskMemFree(statstg.pwcsName);
2467 }
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);
2471 }
2472
2473 /* re-write the stream */
2474 hr = WriteFmtUserTypeStg(stg, 0, userTypeW);
2475 ok(hr == S_OK, "should succeed, res=%x\n", hr);
2476
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);
2480 if (SUCCEEDED(hr))
2481 {
2482 BOOL found = FALSE;
2483 STATSTG statstg;
2484 DWORD got;
2485 memset(&statstg, 0xad, sizeof(statstg));
2486 while ((hr = IEnumSTATSTG_Next(stat, 1, &statstg, &got)) == S_OK && got == 1)
2487 {
2488 if (strcmp_ww(statstg.pwcsName, strmNameW) == 0)
2489 found = TRUE;
2490 else
2491 ok(0, "found unexpected stream or storage\n");
2492 CoTaskMemFree(statstg.pwcsName);
2493 }
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);
2497 }
2498
2499 IStorage_Release(stg);
2500 DeleteFileA( fileA );
2501 }
2502}
2503
2504static void test_references(void)
2505{
2506 IStorage *stg,*stg2;
2507 HRESULT hr;
2508 unsigned c1,c2;
2509 static const WCHAR StorName[] = { 'D','a','t','a','S','p','a','c','e','I','n','f','o',0 };
2510
2512
2514 ok(hr==S_OK, "StgCreateDocfile failed\n");
2515
2516 if (SUCCEEDED(hr))
2517 {
2518 IStorage_Release(stg);
2519
2521 ok(hr==S_OK, "StgOpenStorage failed (result=%x)\n",hr);
2522
2523 if (SUCCEEDED(hr))
2524 {
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);
2527
2528 if (SUCCEEDED(hr))
2529 {
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");
2536 }
2537 c1 = IStorage_Release(stg);
2538 while ( c1 ) c1 = IStorage_Release(stg);
2539 }
2540 }
2541
2543}
2544
2545/* dest
2546 * |-StorageA
2547 * | `StreamA: "StreamA"
2548 * |-StorageB
2549 * | `StreamB: "StreamB"
2550 * `StreamC: "StreamC"
2551 */
2553{
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);
2559 ULONG bytes;
2560 HRESULT hr;
2561
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);
2564 if(FAILED(hr))
2565 goto cleanup;
2566
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);
2569 if(FAILED(hr))
2570 goto cleanup;
2571
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);
2574
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);
2577 if(FAILED(hr))
2578 goto cleanup;
2579
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);
2582 if(FAILED(hr))
2583 goto cleanup;
2584
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);
2587
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);
2590 if(FAILED(hr))
2591 goto cleanup;
2592
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);
2595
2596cleanup:
2597 if(strmC)
2598 IStream_Release(strmC);
2599 if(strmB)
2600 IStream_Release(strmB);
2601 if(stgB)
2602 IStorage_Release(stgB);
2603 if(strmA)
2604 IStream_Release(strmA);
2605 if(stgA)
2606 IStorage_Release(stgA);
2607
2608 return hr;
2609}
2610
2611static void test_copyto(void)
2612{
2613 IStorage *file1 = NULL, *file2 = NULL, *stg_tmp;
2614 IStream *strm_tmp;
2615 WCHAR buf[64];
2616 HRESULT hr;
2617
2618 /* create & populate file1 */
2620 ok(hr == S_OK, "StgCreateDocfile failed: 0x%08x\n", hr);
2621 if(FAILED(hr))
2622 goto cleanup;
2623
2624 hr = create_test_file(file1);
2625 if(FAILED(hr))
2626 goto cleanup;
2627
2628 /* create file2 */
2630 ok(hr == S_OK, "StgCreateDocfile failed: 0x%08x\n", hr);
2631 if(FAILED(hr))
2632 goto cleanup;
2633
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);
2637
2638 hr = IStorage_CopyTo(file1, 0, NULL, NULL, file2);
2639 ok(hr == S_OK, "CopyTo failed: 0x%08x\n", hr);
2640 if(FAILED(hr))
2641 goto cleanup;
2642
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);
2647
2648 if(SUCCEEDED(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);
2652
2653 if(SUCCEEDED(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);
2657 if(SUCCEEDED(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));
2660
2661 IStream_Release(strm_tmp);
2662 }
2663
2664 IStorage_Release(stg_tmp);
2665 }
2666
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);
2670
2671 if(SUCCEEDED(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);
2675
2676 if(SUCCEEDED(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);
2680 if(SUCCEEDED(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));
2683
2684 IStream_Release(strm_tmp);
2685 }
2686
2687 IStorage_Release(stg_tmp);
2688 }
2689
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);
2693
2694 if(SUCCEEDED(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);
2698 if(SUCCEEDED(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));
2701
2702 IStream_Release(strm_tmp);
2703 }
2704
2705cleanup:
2706 if(file1)
2707 IStorage_Release(file1);
2708 if(file2)
2709 IStorage_Release(file2);
2710
2713}
2714
2716{
2717 static const WCHAR *snb_exclude[] = {stgA_name, strmB_name, strmC_name, 0};
2718
2719 IStorage *file1 = NULL, *file2 = NULL, *stg_tmp;
2720 IStream *strm_tmp;
2721 WCHAR buf[64];
2722 HRESULT hr;
2723
2724 /* create & populate file1 */
2726 ok(hr == S_OK, "StgCreateDocfile failed: 0x%08x\n", hr);
2727 if(FAILED(hr))
2728 goto cleanup;
2729
2730 hr = create_test_file(file1);
2731 if(FAILED(hr))
2732 goto cleanup;
2733
2734 /* create file2 */
2736 ok(hr == S_OK, "StgCreateDocfile failed: 0x%08x\n", hr);
2737 if(FAILED(hr))
2738 goto cleanup;
2739
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);
2743 if(FAILED(hr))
2744 goto cleanup;
2745
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);
2750 if(SUCCEEDED(hr))
2751 IStorage_Release(stg_tmp);
2752
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);
2756 if(SUCCEEDED(hr))
2757 IStream_Release(strm_tmp);
2758
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);
2762
2763 if(SUCCEEDED(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);
2767
2768 if(SUCCEEDED(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);
2772 if(SUCCEEDED(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));
2775
2776 IStream_Release(strm_tmp);
2777 }
2778
2779 IStorage_Release(stg_tmp);
2780 }
2781
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);
2785 if(SUCCEEDED(hr))
2786 IStream_Release(strm_tmp);
2787
2788cleanup:
2789 if(file1)
2790 IStorage_Release(file1);
2791 if(file2)
2792 IStorage_Release(file2);
2793
2796}
2797
2799{
2800 IStorage *file1 = NULL, *file2 = NULL, *stg_tmp;
2801 IStream *strm_tmp;
2802 WCHAR buf[64];
2803 HRESULT hr;
2804
2805 /* create & populate file1 */
2807 ok(hr == S_OK, "StgCreateDocfile failed: 0x%08x\n", hr);
2808 if(FAILED(hr))
2809 goto cleanup;
2810
2811 hr = create_test_file(file1);
2812 if(FAILED(hr))
2813 goto cleanup;
2814
2815 /* create file2 */
2817 ok(hr == S_OK, "StgCreateDocfile failed: 0x%08x\n", hr);
2818 if(FAILED(hr))
2819 goto cleanup;
2820
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);
2824 if(FAILED(hr))
2825 goto cleanup;
2826
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);
2831 if(SUCCEEDED(hr))
2832 IStorage_Release(stg_tmp);
2833
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);
2837 if(SUCCEEDED(hr))
2838 IStream_Release(strm_tmp);
2839
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);
2843 if(SUCCEEDED(hr))
2844 IStorage_Release(stg_tmp);
2845
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);
2849 if(SUCCEEDED(hr))
2850 IStream_Release(strm_tmp);
2851
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);
2855
2856 if(SUCCEEDED(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);
2860 if(SUCCEEDED(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));
2863
2864 IStream_Release(strm_tmp);
2865 }
2866
2867cleanup:
2868 if(file1)
2869 IStorage_Release(file1);
2870 if(file2)
2871 IStorage_Release(file2);
2872
2875}
2876
2878{
2879 IStorage *file1 = NULL, *file2 = NULL, *stg_tmp;
2880 IStream *strm_tmp;
2881 HRESULT hr;
2882
2883 /* create & populate file1 */
2885 ok(hr == S_OK, "StgCreateDocfile failed: 0x%08x\n", hr);
2886 if(FAILED(hr))
2887 goto cleanup;
2888
2889 hr = create_test_file(file1);
2890 if(FAILED(hr))
2891 goto cleanup;
2892
2893 /* create file2 */
2895 ok(hr == S_OK, "StgCreateDocfile failed: 0x%08x\n", hr);
2896 if(FAILED(hr))
2897 goto cleanup;
2898
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);
2902 if(FAILED(hr))
2903 goto cleanup;
2904
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);
2909
2910 if(SUCCEEDED(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);
2914 if(SUCCEEDED(hr))
2915 IStream_Release(strm_tmp);
2916
2917 IStorage_Release(stg_tmp);
2918 }
2919
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);
2923
2924 if(SUCCEEDED(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);
2928 if(SUCCEEDED(hr))
2929 IStream_Release(strm_tmp);
2930
2931 IStorage_Release(stg_tmp);
2932 }
2933
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);
2937 if(SUCCEEDED(hr))
2938 IStream_Release(strm_tmp);
2939
2940cleanup:
2941 if(file1)
2942 IStorage_Release(file1);
2943 if(file2)
2944 IStorage_Release(file2);
2945
2948}
2949
2950static void test_rename(void)
2951{
2952 IStorage *stg, *stg2;
2953 IStream *stm;
2954 HRESULT r;
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 };
2959 BOOL ret;
2960
2962
2963 /* create the file */
2965 STGM_READWRITE, 0, &stg);
2966 ok(r==S_OK, "StgCreateDocfile failed\n");
2967
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);
2971
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);
2976
2977 /* rename the stream */
2978 r = IStorage_RenameElement(stg2, stmname, stmname2);
2979 ok(r==S_OK, "IStorage->RenameElement failed, hr=%08x\n", r);
2980
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);
2985
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);
2990
2991 IStorage_Release(stg2);
2992
2993 /* rename the storage */
2994 IStorage_RenameElement(stg, stgname, stgname2);
2995
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);
3000
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);
3004 if (SUCCEEDED(r))
3005 {
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);
3010
3011 IStorage_Release(stg2);
3012 }
3013
3014 IStorage_Release(stg);
3015
3017 ok(ret, "deleted file\n");
3018}
3019
3020static void test_toplevel_stat(void)
3021{
3022 IStorage *stg = NULL;
3023 HRESULT r;
3024 STATSTG stat;
3025 char prev_dir[MAX_PATH];
3026 char temp[MAX_PATH];
3027 char full_path[MAX_PATH];
3028 LPSTR rel_pathA;
3029 WCHAR rel_path[MAX_PATH];
3030
3032
3035 ok(r==S_OK, "StgCreateDocfile failed\n");
3036
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",
3041 CoTaskMemFree(stat.pwcsName);
3042
3043 IStorage_Release( stg );
3044
3046 ok(r==S_OK, "StgOpenStorage failed with error 0x%08x\n", r);
3047
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",
3052 CoTaskMemFree(stat.pwcsName);
3053
3054 IStorage_Release( stg );
3055
3057
3058 /* Stat always returns the full path, even for files opened with a relative path. */
3059 GetCurrentDirectoryA(MAX_PATH, prev_dir);
3060
3062
3064
3065 GetFullPathNameA(filenameA, MAX_PATH, full_path, &rel_pathA);
3066 MultiByteToWideChar(CP_ACP, 0, rel_pathA, -1, rel_path, MAX_PATH);
3067
3070 ok(r==S_OK, "StgCreateDocfile failed\n");
3071
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",
3076 CoTaskMemFree(stat.pwcsName);
3077
3078 IStorage_Release( stg );
3079
3081 ok(r==S_OK, "StgOpenStorage failed with error 0x%08x\n", r);
3082
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",
3087 CoTaskMemFree(stat.pwcsName);
3088
3089 IStorage_Release( stg );
3090
3091 SetCurrentDirectoryA(prev_dir);
3092
3094}
3095
3096static void test_substorage_enum(void)
3097{
3098 IStorage *stg, *stg2;
3099 IEnumSTATSTG *ee;
3100 HRESULT r;
3101 ULONG ref;
3102 static const WCHAR stgname[] = { 'P','E','R','M','S','T','G',0 };
3103 BOOL ret;
3104
3106
3107 /* create the file */
3109 STGM_READWRITE, 0, &stg);
3110 ok(r==S_OK, "StgCreateDocfile failed\n");
3111
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);
3115
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);
3119
3120 /* release the substorage */
3121 ref = IStorage_Release(stg2);
3122 todo_wine ok(ref==0, "storage not released\n");
3123
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);
3127
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);
3131
3132 r = IEnumSTATSTG_Reset(ee);
3133 ok(r==STG_E_REVERTED, "IEnumSTATSTG->Reset failed, hr=%08x\n", r);
3134
3135 IEnumSTATSTG_Release(ee);
3136
3137 IStorage_Release(stg);
3138
3140 ok(ret, "deleted file\n");
3141}
3142
3143static void test_copyto_locking(void)
3144{
3145 IStorage *stg, *stg2, *stg3, *stg4;
3146 IStream *stm;
3147 HRESULT r;
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 };
3151 BOOL ret;
3152
3154
3155 /* create the file */
3157 STGM_READWRITE, 0, &stg);
3158 ok(r==S_OK, "StgCreateDocfile failed\n");
3159
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);
3163
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);
3167
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);
3171
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);
3175
3176 IStream_Release(stm);
3177
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);
3181
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);
3185
3186 IStorage_Release(stg4);
3187 IStorage_Release(stg3);
3188 IStorage_Release(stg2);
3189 IStorage_Release(stg);
3190
3192 ok(ret, "deleted file\n");
3193}
3194
3195static void test_copyto_recursive(void)
3196{
3197 IStorage *stg, *stg2, *stg3, *stg4;
3198 HRESULT r;
3199 static const WCHAR stgname[] = { 'S','T','G','1',0 };
3200 static const WCHAR stgname2[] = { 'S','T','G','2',0 };
3201 BOOL ret;
3202
3204
3205 /* create the file */