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