ReactOS  0.4.13-dev-242-g611e6d7
storage32.c
Go to the documentation of this file.
1 /*
2  * Unit tests for OLE storage
3  *
4  * Copyright (c) 2004 Mike McCormack
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20 
21 #include <stdio.h>
22 
23 #define COBJMACROS
24 #ifdef __REACTOS__
25 #define CONST_VTABLE
26 #else
27 #define NONAMELESSUNION
28 #define NONAMELESSSTRUCT
29 #endif
30 
31 #include <windows.h>
32 #include "wine/test.h"
33 
34 #include "ole2.h"
35 #include "objidl.h"
36 #include "initguid.h"
37 
38 DEFINE_GUID( test_stg_cls, 0x88888888, 0x0425, 0x0000, 0,0,0,0,0,0,0,0);
39 
40 #define ok_ole_success(hr, func) ok(hr == S_OK, func " failed with error 0x%08x\n", hr)
41 
44 
45 static const char file1_nameA[] = {'c','o','p','y','t','e','s','t','A',0};
46 static const WCHAR file1_name[] = {'c','o','p','y','t','e','s','t','A',0};
47 static const char file2_nameA[] = {'c','o','p','y','t','e','s','t','B',0};
48 static const WCHAR file2_name[] = {'c','o','p','y','t','e','s','t','B',0};
49 static const WCHAR stgA_name[] = {'S','t','o','r','a','g','e','A',0};
50 static const WCHAR stgB_name[] = {'S','t','o','r','a','g','e','B',0};
51 static const WCHAR strmA_name[] = {'S','t','r','e','a','m','A',0};
52 static const WCHAR strmB_name[] = {'S','t','r','e','a','m','B',0};
53 static const WCHAR strmC_name[] = {'S','t','r','e','a','m','C',0};
54 
55 /* Win9x and WinMe don't have lstrcmpW */
56 static int strcmp_ww(LPCWSTR strw1, LPCWSTR strw2)
57 {
58  CHAR stra1[512], stra2[512];
59  WideCharToMultiByte(CP_ACP, 0, strw1, -1, stra1, sizeof(stra1), NULL, NULL);
60  WideCharToMultiByte(CP_ACP, 0, strw2, -1, stra2, sizeof(stra2), NULL, NULL);
61  return lstrcmpA(stra1, stra2);
62 }
63 
64 typedef struct TestLockBytes {
74 
76 {
77  return CONTAINING_RECORD(iface, TestLockBytes, ILockBytes_iface);
78 }
79 
81  void **ppv)
82 {
84 
85  if (!ppv) return E_INVALIDARG;
86 
87  if (IsEqualIID(&IID_IUnknown, iid) ||
88  IsEqualIID(&IID_ILockBytes, iid))
89  *ppv = &This->ILockBytes_iface;
90  else
91  return E_NOINTERFACE;
92 
93  IUnknown_AddRef((IUnknown*)*ppv);
94  return S_OK;
95 }
96 
98 {
101  return ref;
102 }
103 
105 {
108  return ref;
109 }
110 
112  ULARGE_INTEGER ulOffset, void *pv, ULONG cb, ULONG *pcbRead)
113 {
115  ULONG dummy;
116 
117  if (!pv) return E_INVALIDARG;
118 
119  if (!pcbRead) pcbRead = &dummy;
120 
121  if (ulOffset.QuadPart >= This->size)
122  {
123  *pcbRead = 0;
124  return S_OK;
125  }
126 
127  cb = min(cb, This->size - ulOffset.QuadPart);
128 
129  *pcbRead = cb;
130  memcpy(pv, &This->contents[ulOffset.QuadPart], cb);
131 
132  return S_OK;
133 }
134 
136  ULARGE_INTEGER ulOffset, const void *pv, ULONG cb, ULONG *pcbWritten)
137 {
139  HRESULT hr;
140  ULONG dummy;
141 
142  if (!pv) return E_INVALIDARG;
143 
144  if (!pcbWritten) pcbWritten = &dummy;
145 
146  if (ulOffset.QuadPart + cb > This->size)
147  {
148  ULARGE_INTEGER new_size;
149  new_size.QuadPart = ulOffset.QuadPart + cb;
150  hr = ILockBytes_SetSize(iface, new_size);
151  if (FAILED(hr)) return hr;
152  }
153 
154  *pcbWritten = cb;
155  memcpy(&This->contents[ulOffset.QuadPart], pv, cb);
156 
157  return S_OK;
158 }
159 
161 {
162  return S_OK;
163 }
164 
167 {
169 
170  if (This->buffer_size < cb.QuadPart)
171  {
172  ULONG new_buffer_size = max(This->buffer_size * 2, cb.QuadPart);
173  BYTE* new_buffer = HeapAlloc(GetProcessHeap(), 0, new_buffer_size);
174  if (!new_buffer) return E_OUTOFMEMORY;
175  memcpy(new_buffer, This->contents, This->size);
176  HeapFree(GetProcessHeap(), 0, This->contents);
177  This->contents = new_buffer;
178  }
179 
180  if (cb.QuadPart > This->size)
181  memset(&This->contents[This->size], 0, cb.QuadPart - This->size);
182 
183  This->size = cb.QuadPart;
184 
185  return S_OK;
186 }
187 
189  ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
190 {
192  This->lock_called++;
193  return This->lock_hr;
194 }
195 
197  ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
198 {
200  return This->lock_hr;
201 }
202 
204  STATSTG *pstatstg, DWORD grfStatFlag)
205 {
207  static const WCHAR dummy_name[] = {'d','u','m','m','y',0};
208 
209  if (!pstatstg) return E_INVALIDARG;
210 
211  memset(pstatstg, 0, sizeof(STATSTG));
212 
213  if (!(grfStatFlag & STATFLAG_NONAME))
214  {
215  pstatstg->pwcsName = CoTaskMemAlloc(sizeof(dummy_name));
216  if (!pstatstg->pwcsName) return E_OUTOFMEMORY;
217  memcpy(pstatstg->pwcsName, dummy_name, sizeof(dummy_name));
218  }
219 
220  pstatstg->type = STGTY_LOCKBYTES;
221  pstatstg->cbSize.QuadPart = This->size;
222  pstatstg->grfLocksSupported = This->locks_supported;
223 
224  return S_OK;
225 }
226 
227 static const ILockBytesVtbl TestLockBytes_Vtbl = {
238 };
239 
241 {
243 
244  if (*This)
245  {
246  (*This)->ILockBytes_iface.lpVtbl = &TestLockBytes_Vtbl;
247  (*This)->ref = 1;
248  }
249 }
250 
252 {
253  ok(This->ILockBytes_iface.lpVtbl == &TestLockBytes_Vtbl, "test lock bytes %p deleted with incorrect vtable\n", This);
254  ok(This->ref == 1, "test lock bytes %p deleted with %i references instead of 1\n", This, This->ref);
255  HeapFree(GetProcessHeap(), 0, This->contents);
257 }
258 
259 static void test_hglobal_storage_stat(void)
260 {
261  ILockBytes *ilb = NULL;
262  IStorage *stg = NULL;
263  HRESULT r;
264  STATSTG stat;
265  DWORD mode, refcount;
266 
267  r = CreateILockBytesOnHGlobal( NULL, TRUE, &ilb );
268  ok( r == S_OK, "CreateILockBytesOnHGlobal failed\n");
269 
270  r = StgIsStorageILockBytes( ilb );
271  ok( r == S_FALSE, "StgIsStorageILockBytes should have failed\n");
272 
274  r = StgCreateDocfileOnILockBytes( ilb, mode, 0, &stg );
275  ok( r == S_OK, "StgCreateDocfileOnILockBytes failed\n");
276 
277  r = WriteClassStg( stg, &test_stg_cls );
278  ok( r == S_OK, "WriteClassStg failed\n");
279 
280  r = StgIsStorageILockBytes( ilb );
281  ok( r == S_OK, "StgIsStorageILockBytes failed\n");
282 
283  memset( &stat, 0, sizeof stat );
284  r = IStorage_Stat( stg, &stat, 0 );
285 
286  ok( stat.pwcsName == NULL, "storage name not null\n");
287  ok( stat.type == 1, "type is wrong\n");
288  ok( stat.grfMode == 0x12, "grf mode is incorrect\n");
289  ok( !memcmp(&stat.clsid, &test_stg_cls, sizeof test_stg_cls), "CLSID is wrong\n");
290 
291  refcount = IStorage_Release( stg );
292  ok( refcount == 0, "IStorage refcount is wrong\n");
293  refcount = ILockBytes_Release( ilb );
294  ok( refcount == 0, "ILockBytes refcount is wrong\n");
295 }
296 
297 static void test_create_storage_modes(void)
298 {
299  IStorage *stg = NULL;
300  HRESULT r;
301 
303 
304  /* test with some invalid parameters */
305  r = StgCreateDocfile( NULL, 0, 0, &stg);
306  ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
307  r = StgCreateDocfile( filename, 0, 0, &stg);
308  ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
309  r = StgCreateDocfile( filename, STGM_CREATE, 0, &stg);
310  ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
312  ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
314  ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
316  ok(r==STG_E_INVALIDPOINTER, "StgCreateDocfile succeeded\n");
318  ok(r==STG_E_INVALIDPARAMETER, "StgCreateDocfile succeeded\n");
320  ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
322  ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
324  ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
325 
326  /* StgCreateDocfile seems to be very particular about the flags it accepts */
328  ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
330  ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
332  ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
334  ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
336  ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
338  ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
340  ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
341  ok(stg == NULL, "stg was set\n");
342 
343  /* check what happens if the file already exists (which is how it's meant to be used) */
345  ok(r==S_OK, "StgCreateDocfile failed\n");
346  r = IStorage_Release(stg);
347  ok(r == 0, "storage not released\n");
349  ok(r==STG_E_FILEALREADYEXISTS, "StgCreateDocfile wrong error\n"); /* FAILIFTHERE is default */
350  r = StgCreateDocfile( filename, STGM_READ, 0, &stg);
351  ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n"); /* need at least readmode and sharemode */
353  ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
355  ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
357  ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile failed\n");
359  ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile failed\n");
361  ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile failed\n");
363  ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile failed\n");
365  ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile failed\n");
367  ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile wrong error\n");
369  ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile wrong error\n");
370  ok(DeleteFileA(filenameA), "failed to delete file\n");
371 
373  ok(r==S_OK, "StgCreateDocfile failed\n");
374  r = IStorage_Release(stg);
375  ok(r == 0, "storage not released\n");
377  ok(r==STG_E_FILEALREADYEXISTS, "StgCreateDocfile wrong error\n");
379  ok(r==STG_E_FILEALREADYEXISTS, "StgCreateDocfile wrong error\n");
380 
382  ok(r==STG_E_INVALIDFLAG, "StgCreateDocfile succeeded\n");
384  ok(r==S_OK, "StgCreateDocfile failed\n");
385  r = IStorage_Release(stg);
386  ok(r == 0, "storage not released\n");
387  ok(DeleteFileA(filenameA), "failed to delete file\n");
388 
390  ok(r==S_OK, "StgCreateDocfile failed\n");
391  r = IStorage_Release(stg);
392  ok(r == 0, "storage not released\n");
393  ok(DeleteFileA(filenameA), "failed to delete file\n");
394 
395  /* test the way excel uses StgCreateDocFile */
397  ok(r==S_OK, "StgCreateDocfile the excel way failed\n");
398  if(r == S_OK)
399  {
400  r = IStorage_Release(stg);
401  ok(r == 0, "storage not released\n");
402  ok(DeleteFileA(filenameA), "failed to delete file\n");
403  }
404 
405  /* and the way windows media uses it ... */
407  ok(r==S_OK, "StgCreateDocfile the windows media way failed\n");
408  if (r == S_OK)
409  {
410  r = IStorage_Release(stg);
411  ok(r == 0, "storage not released\n");
412  ok(DeleteFileA(filenameA), "failed to delete file\n");
413  }
414 
415  /* looks like we need STGM_TRANSACTED or STGM_CREATE */
417  ok(r==S_OK, "StgCreateDocfile the excel way failed\n");
418  if(r == S_OK)
419  {
420  r = IStorage_Release(stg);
421  ok(r == 0, "storage not released\n");
422  ok(DeleteFileA(filenameA), "failed to delete file\n");
423  }
424 
426  ok(r==S_OK, "StgCreateDocfile the excel way failed\n");
427  if(r == S_OK)
428  {
429  r = IStorage_Release(stg);
430  ok(r == 0, "storage not released\n");
431  ok(DeleteFileA(filenameA), "failed to delete file\n");
432  }
433 
435  ok(r==S_OK, "StgCreateDocfile the powerpoint way failed\n");
436  if(r == S_OK)
437  {
438  r = IStorage_Release(stg);
439  ok(r == 0, "storage not released\n");
440  ok(DeleteFileA(filenameA), "failed to delete file\n");
441  }
442 
443  /* test the way msi uses StgCreateDocfile */
445  ok(r==S_OK, "StgCreateDocFile failed\n");
446  r = IStorage_Release(stg);
447  ok(r == 0, "storage not released\n");
448  ok(DeleteFileA(filenameA), "failed to delete file\n");
449 }
450 
451 static void test_stgcreatestorageex(void)
452 {
453  HRESULT (WINAPI *pStgCreateStorageEx)(const WCHAR* pwcsName, DWORD grfMode, DWORD stgfmt, DWORD grfAttrs, STGOPTIONS* pStgOptions, void* reserved, REFIID riid, void** ppObjectOpen);
454  HMODULE hOle32 = GetModuleHandleA("ole32");
455  IStorage *stg = NULL;
456  STGOPTIONS stgoptions = {1, 0, 4096};
457  HRESULT r;
458 
459  pStgCreateStorageEx = (void *) GetProcAddress(hOle32, "StgCreateStorageEx");
460  if (!pStgCreateStorageEx)
461  {
462  win_skip("skipping test on NT4\n");
463  return;
464  }
465 
467 
468  /* Verify that StgCreateStorageEx can accept an options param */
469  r = pStgCreateStorageEx( filename,
472  0,
473  &stgoptions,
474  NULL,
475  &IID_IStorage,
476  (void **) &stg);
477  ok(r==S_OK || r==STG_E_UNIMPLEMENTEDFUNCTION, "StgCreateStorageEx with options failed\n");
479  {
480  /* We're on win98 which means all bets are off. Let's get out of here. */
481  win_skip("skipping test on win9x\n");
482  return;
483  }
484 
485  r = IStorage_Release(stg);
486  ok(r == 0, "storage not released\n");
487  ok(DeleteFileA(filenameA), "failed to delete file\n");
488 
489  /* Verify that StgCreateStorageEx can accept a NULL pStgOptions */
490  r = pStgCreateStorageEx( filename,
493  0,
494  NULL,
495  NULL,
496  &IID_IStorage,
497  (void **) &stg);
498  ok(r==S_OK, "StgCreateStorageEx with NULL options failed\n");
499  r = IStorage_Release(stg);
500  ok(r == 0, "storage not released\n");
501  ok(DeleteFileA(filenameA), "failed to delete file\n");
502 }
503 
504 static void test_storage_stream(void)
505 {
506  static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 };
507  static const WCHAR longname[] = {
508  'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',
509  'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a',0
510  };
511  IStorage *stg = NULL;
512  HRESULT r;
513  IStream *stm = NULL;
514  IStream *stm2 = NULL;
515  ULONG count = 0;
518  unsigned char buffer[0x100];
519  IUnknown *unk;
520  BOOL ret;
521 
523 
525  ok(r==S_OK, "StgCreateDocfile failed\n");
526 
527  /* try create some invalid streams */
528  r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 1, 0, &stm );
529  ok(r==STG_E_INVALIDPARAMETER, "IStorage->CreateStream wrong error\n");
530  r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 1, &stm );
531  ok(r==STG_E_INVALIDPARAMETER, "IStorage->CreateStream wrong error\n");
532  r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, NULL );
533  ok(r==STG_E_INVALIDPOINTER, "IStorage->CreateStream wrong error\n");
534  r = IStorage_CreateStream(stg, NULL, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
535  ok(r==STG_E_INVALIDNAME, "IStorage->CreateStream wrong error\n");
536  r = IStorage_CreateStream(stg, longname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
537  ok(r==STG_E_INVALIDNAME || broken(r==S_OK) /* nt4 */,
538  "IStorage->CreateStream wrong error, got %d GetLastError()=%d\n", r, GetLastError());
539  r = IStorage_CreateStream(stg, stmname, STGM_READWRITE, 0, 0, &stm );
540  ok(r==STG_E_INVALIDFLAG, "IStorage->CreateStream wrong error\n");
541  r = IStorage_CreateStream(stg, stmname, STGM_READ, 0, 0, &stm );
542  ok(r==STG_E_INVALIDFLAG, "IStorage->CreateStream wrong error\n");
543  r = IStorage_CreateStream(stg, stmname, STGM_WRITE, 0, 0, &stm );
544  ok(r==STG_E_INVALIDFLAG, "IStorage->CreateStream wrong error\n");
545  r = IStorage_CreateStream(stg, stmname, STGM_SHARE_DENY_NONE | STGM_READWRITE, 0, 0, &stm );
546  ok(r==STG_E_INVALIDFLAG, "IStorage->CreateStream wrong error\n");
547  r = IStorage_CreateStream(stg, stmname, STGM_SHARE_DENY_NONE | STGM_READ, 0, 0, &stm );
548  ok(r==STG_E_INVALIDFLAG, "IStorage->CreateStream wrong error\n");
549 
550  /* now really create a stream and delete it */
551  r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
552  ok(r==S_OK, "IStorage->CreateStream failed\n");
553 
554  /* test for support interfaces */
555  r = IStream_QueryInterface(stm, &IID_IPersist, (void**)&unk);
556  ok(r==E_NOINTERFACE, "got 0x%08x\n", r);
557  r = IStream_QueryInterface(stm, &IID_IPersistStream, (void**)&unk);
558  ok(r==E_NOINTERFACE, "got 0x%08x\n", r);
559 
560  r = IStream_Release(stm);
561  ok(r == 0, "wrong ref count\n");
562  r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
563  ok(r==STG_E_FILEALREADYEXISTS, "IStorage->CreateStream failed\n");
564  r = IStorage_DestroyElement(stg,stmname);
565  ok(r==S_OK, "IStorage->DestroyElement failed\n");
566 
567  /* create a stream and write to it */
568  r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
569  ok(r==S_OK, "IStorage->CreateStream failed\n");
570 
571  r = IStream_Clone(stm, &stm2);
572  ok(r==S_OK, "failed to clone stream\n");
573 
574  r = IStream_Write(stm, NULL, 0, NULL );
575  ok(r==STG_E_INVALIDPOINTER, "IStream->Write wrong error\n");
576  r = IStream_Write(stm, "Hello\n", 0, NULL );
577  ok(r==S_OK, "failed to write stream\n");
578  r = IStream_Write(stm, "Hello\n", 0, &count );
579  ok(r==S_OK, "failed to write stream\n");
580  r = IStream_Write(stm, "Hello\n", 6, &count );
581  ok(r==S_OK, "failed to write stream\n");
582  r = IStream_Commit(stm, STGC_DEFAULT );
583  ok(r==S_OK, "failed to commit stream\n");
584  r = IStream_Commit(stm, STGC_DEFAULT );
585  ok(r==S_OK, "failed to commit stream\n");
586 
587  /* Read past the end of the stream. */
588  pos.QuadPart = 3;
589  r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p );
590  ok(r==S_OK, "failed to seek stream\n");
591  ok(p.QuadPart == 3, "at wrong place\n");
592  r = IStream_Read(stm, buffer, sizeof buffer, &count );
593  ok(r==S_OK, "failed to read\n");
594  ok(count == 3, "read bytes past end of stream\n");
595  pos.QuadPart = 10;
596  r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p );
597  ok(r==S_OK, "failed to seek stream\n");
598  ok(p.QuadPart == 10, "at wrong place\n");
599  r = IStream_Read(stm, buffer, sizeof buffer, &count );
600  ok(r==S_OK, "failed to read\n");
601  ok(count == 0, "read bytes past end of stream\n");
602  pos.QuadPart = 10000;
603  r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p );
604  ok(r==S_OK, "failed to seek stream\n");
605  ok(p.QuadPart == 10000, "at wrong place\n");
606  r = IStream_Read(stm, buffer, sizeof buffer, &count );
607  ok(r==S_OK, "failed to read\n");
608  ok(count == 0, "read bytes past end of stream\n");
609 
610  /* Convert to a big block stream, and read past the end. */
611  p.QuadPart = 5000;
612  r = IStream_SetSize(stm,p);
613  ok(r==S_OK, "failed to set pos\n");
614  pos.QuadPart = 4997;
615  r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p );
616  ok(r==S_OK, "failed to seek stream\n");
617  ok(p.QuadPart == 4997, "at wrong place\n");
618  r = IStream_Read(stm, buffer, sizeof buffer, &count );
619  ok(r==S_OK, "failed to read\n");
620  ok(count == 3, "read bytes past end of stream\n");
621  pos.QuadPart = 5001;
622  r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p );
623  ok(r==S_OK, "failed to seek stream\n");
624  ok(p.QuadPart == 5001, "at wrong place\n");
625  r = IStream_Read(stm, buffer, sizeof buffer, &count );
626  ok(r==S_OK, "failed to read\n");
627  ok(count == 0, "read bytes past end of stream\n");
628  pos.QuadPart = 10000;
629  r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p );
630  ok(r==S_OK, "failed to seek stream\n");
631  ok(p.QuadPart == 10000, "at wrong place\n");
632  r = IStream_Read(stm, buffer, sizeof buffer, &count );
633  ok(r==S_OK, "failed to read\n");
634  ok(count == 0, "read bytes past end of stream\n");
635 
636  /* seek round a bit, reset the stream size */
637  pos.QuadPart = 0;
638  r = IStream_Seek(stm, pos, 3, &p );
639  ok(r==STG_E_INVALIDFUNCTION, "IStream->Seek returned wrong error\n");
640  r = IStream_Seek(stm, pos, STREAM_SEEK_SET, NULL);
641  ok(r==S_OK, "failed to seek stream\n");
642  r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p );
643  ok(r==S_OK, "failed to seek stream\n");
644  r = IStream_SetSize(stm,p);
645  ok(r==S_OK, "failed to set pos\n");
646  pos.QuadPart = 10;
647  r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p );
648  ok(r==S_OK, "failed to seek stream\n");
649  ok(p.QuadPart == 10, "at wrong place\n");
650  r = IStream_Read(stm, buffer, sizeof buffer, &count );
651  ok(r==S_OK, "failed to set pos\n");
652  ok(count == 0, "read bytes from empty stream\n");
653  pos.QuadPart = 10000;
654  r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p );
655  ok(r==S_OK, "failed to seek stream\n");
656  ok(p.QuadPart == 10000, "at wrong place\n");
657  r = IStream_Read(stm, buffer, sizeof buffer, &count );
658  ok(r==S_OK, "failed to set pos\n");
659  ok(count == 0, "read bytes from empty stream\n");
660  pos.QuadPart = 0;
661  r = IStream_Seek(stm, pos, STREAM_SEEK_END, &p );
662  ok(r==S_OK, "failed to seek stream\n");
663  ok(p.QuadPart == 0, "at wrong place\n");
664  r = IStream_Read(stm, buffer, sizeof buffer, &count );
665  ok(r==S_OK, "failed to set pos\n");
666  ok(count == 0, "read bytes from empty stream\n");
667 
668  /* wrap up */
669  r = IStream_Release(stm2);
670  ok(r == 0, "wrong ref count\n");
671 
672  /* create a stream and write to it */
673  r = IStorage_CreateStream(stg, stmname, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm2 );
674  ok(r==S_OK, "IStorage->CreateStream failed\n");
675 
676  r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p);
677  ok(r==STG_E_REVERTED, "overwritten stream should return STG_E_REVERTED instead of 0x%08x\n", r);
678 
679  r = IStream_Release(stm2);
680  ok(r == 0, "wrong ref count\n");
681  r = IStream_Release(stm);
682  ok(r == 0, "wrong ref count\n");
683 
684  r = IStorage_Release(stg);
685  ok(r == 0, "wrong ref count\n");
686 
687  /* try create some invalid streams */
688  stg = NULL;
689  stm = NULL;
691  ok(r == S_OK, "should succeed\n");
692  if (stg)
693  {
694  r = IStorage_OpenStream(stg, stmname, NULL, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &stm);
695  ok(r == STG_E_INVALIDFLAG, "IStorage->OpenStream should return STG_E_INVALIDFLAG instead of 0x%08x\n", r);
696  IStorage_Release(stg);
697  }
698 
700  ok(ret, "file should exist\n");
701 }
702 
704 {
705  HANDLE file;
706 
710  return FALSE;
711  CloseHandle(file);
712  return TRUE;
713 }
714 
716 {
717  HANDLE file;
718  DWORD len;
719 
721  OPEN_EXISTING, 0, NULL);
723  return FALSE;
724  len = GetFileSize(file, NULL);
725  CloseHandle(file);
726  return len == 0;
727 }
728 
730 {
731  HANDLE file;
732 
734  OPEN_EXISTING, 0, NULL);
736  return FALSE;
737  CloseHandle(file);
738  return TRUE;
739 }
740 
741 static void test_open_storage(void)
742 {
743  static const WCHAR szNonExist[] = { 'n','o','n','e','x','i','s','t',0 };
744  IStorage *stg = NULL, *stg2 = NULL;
745  HRESULT r;
746  DWORD stgm;
747  BOOL ret;
748 
749  /* try opening a zero length file - it should stay zero length */
753  r = StgOpenStorage( filename, NULL, stgm, NULL, 0, &stg);
754  ok(r==STG_E_FILEALREADYEXISTS, "StgOpenStorage didn't fail\n");
755 
757  r = StgOpenStorage( filename, NULL, stgm, NULL, 0, &stg);
758  ok(r==STG_E_FILEALREADYEXISTS, "StgOpenStorage didn't fail\n");
759  ok(is_zero_length(filenameA), "file length changed\n");
760 
762 
763  /* try opening a nonexistent file - it should not create it */
765  r = StgOpenStorage( filename, NULL, stgm, NULL, 0, &stg);
766  ok(r!=S_OK, "StgOpenStorage failed: 0x%08x\n", r);
767  if (r==S_OK) IStorage_Release(stg);
768  ok(!is_existing_file(filenameA), "StgOpenStorage should not create a file\n");
770 
771  /* create the file */
773  ok(r==S_OK, "StgCreateDocfile failed\n");
774  IStorage_Release(stg);
775 
776  r = StgOpenStorage( filename, NULL, 0, NULL, 0, &stg);
777  ok(r==STG_E_INVALIDFLAG, "StgOpenStorage wrong error\n");
779  ok(r==STG_E_INVALIDNAME, "StgOpenStorage wrong error\n");
781  ok(r==STG_E_INVALIDPOINTER, "StgOpenStorage wrong error\n");
783  ok(r==STG_E_INVALIDPARAMETER, "StgOpenStorage wrong error\n");
784  r = StgOpenStorage( szNonExist, NULL, STGM_SHARE_EXCLUSIVE | STGM_READ, NULL, 0, &stg);
785  ok(r==STG_E_FILENOTFOUND, "StgOpenStorage failed\n");
787  ok(r==STG_E_INVALIDFLAG, "StgOpenStorage failed\n");
789  ok(r==STG_E_INVALIDFLAG, "StgOpenStorage failed\n");
791  ok(r==STG_E_INVALIDFLAG, "StgOpenStorage failed\n");
793  ok(r==STG_E_INVALIDFLAG, "StgOpenStorage failed\n");
794 
795  /* open it for real */
796  r = StgOpenStorage( filename, NULL, STGM_SHARE_DENY_NONE | STGM_READ | STGM_TRANSACTED, NULL, 0, &stg); /* XLViewer 97/2000 */
797  ok(r==S_OK, "StgOpenStorage failed\n");
798  if(stg)
799  {
800  r = IStorage_Release(stg);
801  ok(r == 0, "wrong ref count\n");
802  }
803 
805  ok(r==S_OK, "StgOpenStorage failed\n");
806  if(stg)
807  {
808  r = IStorage_Release(stg);
809  ok(r == 0, "wrong ref count\n");
810  }
811 
812  /* test the way word opens its custom dictionary */
815  ok(r==S_OK, "StgOpenStorage failed\n");
816  if(stg)
817  {
818  r = IStorage_Release(stg);
819  ok(r == 0, "wrong ref count\n");
820  }
821 
823  ok(r==S_OK, "StgOpenStorage failed\n");
825  ok(r==STG_E_SHAREVIOLATION, "StgOpenStorage failed\n");
826  if(stg)
827  {
828  r = IStorage_Release(stg);
829  ok(r == 0, "wrong ref count\n");
830  }
831 
832  /* now try write to a storage file we opened read-only */
834  ok(r==S_OK, "StgOpenStorage failed\n");
835  if(stg)
836  {
837  static const WCHAR stmname[] = { 'w','i','n','e','t','e','s','t',0};
838  IStream *stm = NULL;
839  IStorage *stg2 = NULL;
840 
841  r = IStorage_CreateStream( stg, stmname, STGM_WRITE | STGM_SHARE_EXCLUSIVE,
842  0, 0, &stm );
843  ok(r == STG_E_ACCESSDENIED, "CreateStream should fail\n");
844  r = IStorage_CreateStorage( stg, stmname, STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg2);
845  ok(r == STG_E_ACCESSDENIED, "CreateStream should fail\n");
846 
847  r = IStorage_Release(stg);
848  ok(r == 0, "wrong ref count\n");
849  }
850 
851  /* open like visio 2003 */
852  stg = NULL;
854  ok(r == S_OK, "should succeed\n");
855  if (stg)
856  IStorage_Release(stg);
857 
858  /* test other sharing modes with STGM_PRIORITY */
859  stg = NULL;
861  ok(r == S_OK, "should succeed\n");
862  if (stg)
863  IStorage_Release(stg);
864 
865  stg = NULL;
867  ok(r == S_OK, "should succeed\n");
868  if (stg)
869  IStorage_Release(stg);
870 
871  stg = NULL;
873  ok(r == S_OK, "should succeed\n");
874  if (stg)
875  IStorage_Release(stg);
876 
877  /* open like Project 2003 */
878  stg = NULL;
880  ok(r == S_OK, "should succeed\n");
881  r = StgOpenStorage( filename, NULL, STGM_PRIORITY, NULL, 0, &stg2);
882  ok(r == S_OK, "should succeed\n");
883  if (stg2)
884  IStorage_Release(stg2);
885  if (stg)
886  IStorage_Release(stg);
887 
888  stg = NULL;
890  ok(r == STG_E_INVALIDFLAG, "should fail\n");
891 
893  ok(r == STG_E_INVALIDFLAG, "should fail\n");
894 
896  ok(r == STG_E_INVALIDFLAG, "should fail\n");
897 
899  ok(r == STG_E_INVALIDFUNCTION, "should fail\n");
900 
902  ok(r == STG_E_INVALIDFLAG, "should fail\n");
903 
905  ok(r == STG_E_INVALIDFLAG, "should fail\n");
906 
908  ok(ret, "file didn't exist\n");
909 }
910 
911 static void test_storage_suminfo(void)
912 {
913  IStorage *stg = NULL;
914  IPropertySetStorage *propset = NULL;
915  IPropertyStorage *ps = NULL;
916  HRESULT r;
917 
919 
920  /* create the file */
922  STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
923  ok(r==S_OK, "StgCreateDocfile failed\n");
924 
925  r = IStorage_QueryInterface( stg, &IID_IPropertySetStorage, (LPVOID) &propset );
926  ok(r == S_OK, "query interface failed\n");
927 
928  /* delete it */
929  r = IPropertySetStorage_Delete( propset, &FMTID_SummaryInformation );
930  ok(r == STG_E_FILENOTFOUND, "deleted property set storage\n");
931 
932  r = IPropertySetStorage_Open( propset, &FMTID_SummaryInformation,
934  ok(r == STG_E_FILENOTFOUND, "opened property set storage\n");
935 
936  r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0,
938  ok(r == STG_E_INVALIDFLAG, "created property set storage\n");
939 
940  r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0,
941  STGM_READ, &ps );
942  ok(r == STG_E_INVALIDFLAG, "created property set storage\n");
943 
944  r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0, 0, &ps );
945  ok(r == STG_E_INVALIDFLAG, "created property set storage\n");
946 
947  r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0,
949  ok(r == STG_E_INVALIDFLAG, "created property set storage\n");
950 
951  r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0,
953  ok(r == STG_E_INVALIDFLAG, "created property set storage\n");
954 
955  /* now try really creating a property set */
956  r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0,
958  ok(r == S_OK, "failed to create property set storage\n");
959 
960  if( ps )
961  IPropertyStorage_Release(ps);
962 
963  /* now try creating the same thing again */
964  r = IPropertySetStorage_Create( propset, &FMTID_SummaryInformation, NULL, 0,
966  ok(r == S_OK, "failed to create property set storage\n");
967  if( ps )
968  IPropertyStorage_Release(ps);
969 
970  /* should be able to open it */
971  r = IPropertySetStorage_Open( propset, &FMTID_SummaryInformation,
973  ok(r == S_OK, "open failed\n");
974  if(r == S_OK)
975  IPropertyStorage_Release(ps);
976 
977  /* delete it */
978  r = IPropertySetStorage_Delete( propset, &FMTID_SummaryInformation );
979  ok(r == S_OK, "failed to delete property set storage\n");
980 
981  /* try opening with an invalid FMTID */
982  r = IPropertySetStorage_Open( propset, NULL,
984  ok(r == E_INVALIDARG, "open succeeded\n");
985  if(r == S_OK)
986  IPropertyStorage_Release(ps);
987 
988  /* try a bad guid */
989  r = IPropertySetStorage_Open( propset, &IID_IStorage,
991  ok(r == STG_E_FILENOTFOUND, "open succeeded\n");
992  if(r == S_OK)
993  IPropertyStorage_Release(ps);
994 
995 
996  /* try some invalid flags */
997  r = IPropertySetStorage_Open( propset, &FMTID_SummaryInformation,
999  ok(r == STG_E_INVALIDFLAG, "open succeeded\n");
1000  if(r == S_OK)
1001  IPropertyStorage_Release(ps);
1002 
1003  /* after deleting it, it should be gone */
1004  r = IPropertySetStorage_Open( propset, &FMTID_SummaryInformation,
1006  ok(r == STG_E_FILENOTFOUND, "open failed\n");
1007  if(r == S_OK)
1008  IPropertyStorage_Release(ps);
1009 
1010  r = IPropertySetStorage_Release( propset );
1011  ok(r == 1, "ref count wrong\n");
1012 
1013  r = IStorage_Release(stg);
1014  ok(r == 0, "ref count wrong\n");
1015 
1017 }
1018 
1019 static void test_storage_refcount(void)
1020 {
1021  IStorage *stg = NULL;
1022  IStorage *stgprio = NULL;
1023  HRESULT r;
1024  IStream *stm = NULL;
1025  static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 };
1027  ULARGE_INTEGER upos;
1028  STATSTG stat;
1029  char buffer[10];
1030 
1032 
1033  /* create the file */
1035  STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
1036  ok(r==S_OK, "StgCreateDocfile failed\n");
1037 
1038  r = WriteClassStg( stg, &test_stg_cls );
1039  ok( r == S_OK, "WriteClassStg failed\n");
1040 
1041  r = IStorage_Commit( stg, STGC_DEFAULT );
1042  ok( r == S_OK, "IStorage_Commit failed\n");
1043 
1044  /* now create a stream */
1045  r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1046  ok(r==S_OK, "IStorage->CreateStream failed\n");
1047 
1048  r = IStorage_Release( stg );
1049  ok (r == 0, "storage not released\n");
1050 
1051  pos.QuadPart = 0;
1052  r = IStream_Seek( stm, pos, 0, &upos );
1053  ok (r == STG_E_REVERTED, "seek should fail\n");
1054 
1055  r = IStream_Stat( stm, &stat, STATFLAG_DEFAULT );
1056  ok (r == STG_E_REVERTED, "stat should fail\n");
1057 
1058  r = IStream_Write( stm, "Test string", strlen("Test string"), NULL);
1059  ok (r == STG_E_REVERTED, "IStream_Write should return STG_E_REVERTED instead of 0x%08x\n", r);
1060 
1061  r = IStream_Read( stm, buffer, sizeof(buffer), NULL);
1062  ok (r == STG_E_REVERTED, "IStream_Read should return STG_E_REVERTED instead of 0x%08x\n", r);
1063 
1064  r = IStream_Release(stm);
1065  ok (r == 0, "stream not released\n");
1066 
1067  /* tests that STGM_PRIORITY doesn't prevent readwrite access from other
1068  * StgOpenStorage calls in transacted mode */
1069  r = StgOpenStorage( filename, NULL, STGM_PRIORITY, NULL, 0, &stgprio);
1070  ok(r==S_OK, "StgOpenStorage failed with error 0x%08x\n", r);
1071 
1072  /* non-transacted mode read/write fails */
1074  ok(r==STG_E_LOCKVIOLATION, "StgOpenStorage should return STG_E_LOCKVIOLATION instead of 0x%08x\n", r);
1075 
1076  /* non-transacted mode read-only succeeds */
1078  ok(r==S_OK, "StgOpenStorage failed with error 0x%08x\n", r);
1079  IStorage_Release(stg);
1080 
1082  ok(r==S_OK, "StgOpenStorage failed with error 0x%08x\n", r);
1083  if(stg)
1084  {
1085  static const WCHAR stgname[] = { ' ',' ',' ','2','9',0 };
1086  static const WCHAR stgname2[] = { 'C','V','_','i','e','w',0 };
1087  static const WCHAR stmname2[] = { 'V','a','r','2','D','a','t','a',0 };
1088  IStorage *stg2;
1089  IStorage *stg3;
1090  STATSTG statstg;
1091 
1092  r = IStorage_Stat( stg, &statstg, STATFLAG_NONAME );
1093  ok(r == S_OK, "Stat should have succeeded instead of returning 0x%08x\n", r);
1094  ok(statstg.type == STGTY_STORAGE, "Statstg type should have been STGTY_STORAGE instead of %d\n", statstg.type);
1095  ok(U(statstg.cbSize).LowPart == 0, "Statstg cbSize.LowPart should have been 0 instead of %d\n", U(statstg.cbSize).LowPart);
1096  ok(U(statstg.cbSize).HighPart == 0, "Statstg cbSize.HighPart should have been 0 instead of %d\n", U(statstg.cbSize).HighPart);
1098  "Statstg grfMode should have been 0x10022 instead of 0x%x\n", statstg.grfMode);
1099  ok(statstg.grfLocksSupported == 0, "Statstg grfLocksSupported should have been 0 instead of %d\n", statstg.grfLocksSupported);
1100  ok(IsEqualCLSID(&statstg.clsid, &test_stg_cls), "Statstg clsid is not test_stg_cls\n");
1101  ok(statstg.grfStateBits == 0, "Statstg grfStateBits should have been 0 instead of %d\n", statstg.grfStateBits);
1102  ok(statstg.reserved == 0, "Statstg reserved should have been 0 instead of %d\n", statstg.reserved);
1103 
1104  r = IStorage_CreateStorage( stg, stgname, STGM_SHARE_EXCLUSIVE, 0, 0, &stg2 );
1105  ok(r == S_OK, "CreateStorage should have succeeded instead of returning 0x%08x\n", r);
1106 
1107  r = IStorage_Stat( stg2, &statstg, STATFLAG_DEFAULT );
1108  ok(r == S_OK, "Stat should have succeeded instead of returning 0x%08x\n", r);
1109  ok(!memcmp(statstg.pwcsName, stgname, sizeof(stgname)),
1110  "Statstg pwcsName should have been the name the storage was created with\n");
1111  ok(statstg.type == STGTY_STORAGE, "Statstg type should have been STGTY_STORAGE instead of %d\n", statstg.type);
1112  ok(U(statstg.cbSize).LowPart == 0, "Statstg cbSize.LowPart should have been 0 instead of %d\n", U(statstg.cbSize).LowPart);
1113  ok(U(statstg.cbSize).HighPart == 0, "Statstg cbSize.HighPart should have been 0 instead of %d\n", U(statstg.cbSize).HighPart);
1114  ok(statstg.grfMode == STGM_SHARE_EXCLUSIVE,
1115  "Statstg grfMode should have been STGM_SHARE_EXCLUSIVE instead of 0x%x\n", statstg.grfMode);
1116  ok(statstg.grfLocksSupported == 0, "Statstg grfLocksSupported should have been 0 instead of %d\n", statstg.grfLocksSupported);
1117  ok(IsEqualCLSID(&statstg.clsid, &CLSID_NULL), "Statstg clsid is not CLSID_NULL\n");
1118  ok(statstg.grfStateBits == 0, "Statstg grfStateBits should have been 0 instead of %d\n", statstg.grfStateBits);
1119  ok(statstg.reserved == 0, "Statstg reserved should have been 0 instead of %d\n", statstg.reserved);
1120  CoTaskMemFree(statstg.pwcsName);
1121 
1122  r = IStorage_CreateStorage( stg2, stgname2, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, 0, &stg3 );
1123  ok(r == STG_E_ACCESSDENIED, "CreateStorage should have returned STG_E_ACCESSDENIED instead of 0x%08x\n", r);
1124 
1125  r = IStorage_CreateStream( stg2, stmname2, STGM_CREATE|STGM_SHARE_EXCLUSIVE, 0, 0, &stm );
1126  ok(r == STG_E_ACCESSDENIED, "CreateStream should have returned STG_E_ACCESSDENIED instead of 0x%08x\n", r);
1127 
1128  IStorage_Release(stg2);
1129 
1130  r = IStorage_Release(stg);
1131  ok(r == 0, "wrong ref count\n");
1132  }
1133 
1134  /* Multiple STGM_PRIORITY opens are possible. */
1135  r = StgOpenStorage( filename, NULL, STGM_PRIORITY, NULL, 0, &stg);
1136  ok(r==S_OK, "StgOpenStorage failed with error 0x%08x\n", r);
1137  if(stg)
1138  {
1139  r = IStorage_Release(stg);
1140  ok(r == 0, "wrong ref count\n");
1141  }
1142 
1144  ok(r==S_OK, "StgOpenStorage failed with error 0x%08x\n", r);
1145  if(stg)
1146  {
1147  static const WCHAR stgname[] = { ' ',' ',' ','2','9',0 };
1148  IStorage *stg2;
1149  STATSTG statstg;
1150 
1151  r = IStorage_Stat( stg, &statstg, STATFLAG_NONAME );
1152  ok(r == S_OK, "Stat should have succeeded instead of returning 0x%08x\n", r);
1153  ok(statstg.type == STGTY_STORAGE, "Statstg type should have been STGTY_STORAGE instead of %d\n", statstg.type);
1154  ok(U(statstg.cbSize).LowPart == 0, "Statstg cbSize.LowPart should have been 0 instead of %d\n", U(statstg.cbSize).LowPart);
1155  ok(U(statstg.cbSize).HighPart == 0, "Statstg cbSize.HighPart should have been 0 instead of %d\n", U(statstg.cbSize).HighPart);
1157  "Statstg grfMode should have been 0x10022 instead of 0x%x\n", statstg.grfMode);
1158  ok(statstg.grfLocksSupported == 0, "Statstg grfLocksSupported should have been 0 instead of %d\n", statstg.grfLocksSupported);
1159  ok(IsEqualCLSID(&statstg.clsid, &test_stg_cls), "Statstg clsid is not test_stg_cls\n");
1160  ok(statstg.grfStateBits == 0, "Statstg grfStateBits should have been 0 instead of %d\n", statstg.grfStateBits);
1161  ok(statstg.reserved == 0, "Statstg reserved should have been 0 instead of %d\n", statstg.reserved);
1162 
1163  r = IStorage_CreateStorage( stg, stgname, STGM_SHARE_EXCLUSIVE, 0, 0, &stg2 );
1164  ok(r == S_OK, "CreateStorage should have succeeded instead of returning 0x%08x\n", r);
1165 
1166  IStorage_Release(stg2);
1167 
1168  r = IStorage_Commit( stg, 0 );
1169  ok(r == S_OK, "Commit should have succeeded instead of returning 0x%08x\n", r);
1170 
1171  r = IStorage_Release(stg);
1172  ok(r == 0, "wrong ref count\n");
1173  }
1174  /* IStorage_Release(stgprio) not necessary because StgOpenStorage released it. */
1175 
1177 }
1178 
1179 static void test_writeclassstg(void)
1180 {
1181  IStorage *stg = NULL;
1182  HRESULT r;
1183  CLSID temp_cls, cls2;
1184 
1186 
1187  /* create the file */
1189  STGM_READWRITE, 0, &stg);
1190  ok(r==S_OK, "StgCreateDocfile failed\n");
1191 
1192  r = ReadClassStg( NULL, NULL );
1193  ok(r == E_INVALIDARG, "ReadClassStg should return E_INVALIDARG instead of 0x%08X\n", r);
1194 
1195  memset(&temp_cls, 0xcc, sizeof(temp_cls));
1196  memset(&cls2, 0xcc, sizeof(cls2));
1197  r = ReadClassStg( NULL, &temp_cls );
1198  ok(r == E_INVALIDARG, "got 0x%08x\n", r);
1199  ok(IsEqualCLSID(&temp_cls, &cls2), "got wrong clsid\n");
1200 
1201  r = ReadClassStg( stg, NULL );
1202  ok(r == E_INVALIDARG, "ReadClassStg should return E_INVALIDARG instead of 0x%08X\n", r);
1203 
1204  temp_cls.Data1 = 0xdeadbeef;
1205  r = ReadClassStg( stg, &temp_cls );
1206  ok(r == S_OK, "ReadClassStg failed with 0x%08X\n", r);
1207 
1208  ok(IsEqualCLSID(&temp_cls, &CLSID_NULL), "ReadClassStg returned wrong clsid\n");
1209 
1210  r = WriteClassStg( NULL, NULL );
1211  ok(r == E_INVALIDARG, "WriteClassStg should return E_INVALIDARG instead of 0x%08X\n", r);
1212 
1213  r = WriteClassStg( stg, NULL );
1214  ok(r == STG_E_INVALIDPOINTER, "WriteClassStg should return STG_E_INVALIDPOINTER instead of 0x%08X\n", r);
1215 
1216  r = WriteClassStg( stg, &test_stg_cls );
1217  ok( r == S_OK, "WriteClassStg failed with 0x%08X\n", r);
1218 
1219  r = ReadClassStg( stg, &temp_cls );
1220  ok( r == S_OK, "ReadClassStg failed with 0x%08X\n", r);
1221  ok(IsEqualCLSID(&temp_cls, &test_stg_cls), "ReadClassStg returned wrong clsid\n");
1222 
1223  r = IStorage_Release( stg );
1224  ok (r == 0, "storage not released\n");
1225 
1227 }
1228 
1229 static void test_streamenum(void)
1230 {
1231  IStorage *stg = NULL;
1232  HRESULT r;
1233  IStream *stm = NULL;
1234  static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 };
1235  static const WCHAR stmname2[] = { 'A','B','C','D','E','F','G','H','I',0 };
1236  static const WCHAR stmname3[] = { 'A','B','C','D','E','F','G','H','I','J',0 };
1237  static const STATSTG stat_null;
1238  STATSTG stat;
1239  IEnumSTATSTG *ee = NULL;
1240  ULONG count;
1241 
1243 
1244  /* create the file */
1246  STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
1247  ok(r==S_OK, "StgCreateDocfile failed\n");
1248 
1249  r = WriteClassStg( stg, &test_stg_cls );
1250  ok( r == S_OK, "WriteClassStg failed\n");
1251 
1252  r = IStorage_Commit( stg, STGC_DEFAULT );
1253  ok( r == S_OK, "IStorage_Commit failed\n");
1254 
1255  /* now create a stream */
1256  r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1257  ok(r==S_OK, "IStorage->CreateStream failed\n");
1258 
1259  IStream_Release(stm);
1260 
1261  /* first enum ... should be 1 stream */
1262  r = IStorage_EnumElements(stg, 0, NULL, 0, &ee);
1263  ok(r==S_OK, "IStorage->EnumElements failed\n");
1264 
1265  count = 0xf00;
1266  r = IEnumSTATSTG_Next(ee, 1, &stat, &count);
1267  ok(r==S_OK, "IEnumSTATSTG->Next failed\n");
1268  ok(count == 1, "count wrong\n");
1269 
1270  if (r == S_OK)
1271  CoTaskMemFree(stat.pwcsName);
1272 
1273  r = IEnumSTATSTG_Release(ee);
1274  ok(r==S_OK, "EnumSTATSTG_Release failed with error 0x%08x\n", r);
1275 
1276  /* second enum... destroy the stream before reading */
1277  r = IStorage_EnumElements(stg, 0, NULL, 0, &ee);
1278  ok(r==S_OK, "IStorage->EnumElements failed\n");
1279 
1280  r = IStorage_DestroyElement(stg, stmname);
1281  ok(r==S_OK, "IStorage->DestroyElement failed\n");
1282 
1283  memset(&stat, 0xad, sizeof(stat));
1284  count = 0xf00;
1285  r = IEnumSTATSTG_Next(ee, 1, &stat, &count);
1286  ok(r==S_FALSE, "IEnumSTATSTG->Next failed\n");
1287  ok(count == 0, "count wrong\n");
1288  ok(memcmp(&stat, &stat_null, sizeof(stat)) == 0, "stat is not zeroed\n");
1289 
1290  /* reset and try again */
1291  r = IEnumSTATSTG_Reset(ee);
1292  ok(r==S_OK, "IEnumSTATSTG->Reset failed\n");
1293 
1294  count = 0xf00;
1295  r = IEnumSTATSTG_Next(ee, 1, &stat, &count);
1296  ok(r==S_FALSE, "IEnumSTATSTG->Next failed\n");
1297  ok(count == 0, "count wrong\n");
1298 
1299  /* add a stream before reading */
1300  r = IEnumSTATSTG_Reset(ee);
1301  ok(r==S_OK, "IEnumSTATSTG->Reset failed\n");
1302 
1303  r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1304  ok(r==S_OK, "IStorage->CreateStream failed\n");
1305 
1306  r = IStream_Release(stm);
1307  ok(r==S_OK, "Stream_Release failed with error 0x%08x\n", r);
1308 
1309  count = 0xf00;
1310  r = IEnumSTATSTG_Next(ee, 1, &stat, &count);
1311  ok(r==S_OK, "IEnumSTATSTG->Next failed\n");
1312  ok(count == 1, "count wrong\n");
1313 
1314  if (r == S_OK)
1315  {
1316  ok(lstrcmpiW(stat.pwcsName, stmname) == 0, "expected CONTENTS, got %s\n", wine_dbgstr_w(stat.pwcsName));
1317  CoTaskMemFree(stat.pwcsName);
1318  }
1319 
1320  r = IStorage_CreateStream(stg, stmname2, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1321  ok(r==S_OK, "IStorage->CreateStream failed\n");
1322 
1323  r = IStream_Release(stm);
1324  ok(r==S_OK, "Stream_Release failed with error 0x%08x\n", r);
1325 
1326  count = 0xf00;
1327  r = IEnumSTATSTG_Next(ee, 1, &stat, &count);
1328  ok(r==S_OK, "IEnumSTATSTG->Next failed\n");
1329  ok(count == 1, "count wrong\n");
1330 
1331  if (r == S_OK)
1332  {
1333  ok(lstrcmpiW(stat.pwcsName, stmname2) == 0, "expected ABCDEFGHI, got %s\n", wine_dbgstr_w(stat.pwcsName));
1334  CoTaskMemFree(stat.pwcsName);
1335  }
1336 
1337  /* delete previous and next stream after reading */
1338  r = IStorage_CreateStream(stg, stmname3, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1339  ok(r==S_OK, "IStorage->CreateStream failed\n");
1340 
1341  r = IStream_Release(stm);
1342  ok(r==S_OK, "Stream_Release failed with error 0x%08x\n", r);
1343 
1344  r = IEnumSTATSTG_Reset(ee);
1345  ok(r==S_OK, "IEnumSTATSTG->Reset failed\n");
1346 
1347  count = 0xf00;
1348  r = IEnumSTATSTG_Next(ee, 1, &stat, &count);
1349  ok(r==S_OK, "IEnumSTATSTG->Next failed\n");
1350  ok(count == 1, "count wrong\n");
1351 
1352  if (r == S_OK)
1353  {
1354  ok(lstrcmpiW(stat.pwcsName, stmname) == 0, "expected CONTENTS, got %s\n", wine_dbgstr_w(stat.pwcsName));
1355  CoTaskMemFree(stat.pwcsName);
1356  }
1357 
1358  r = IStorage_DestroyElement(stg, stmname);
1359  ok(r==S_OK, "IStorage->DestroyElement failed\n");
1360 
1361  r = IStorage_DestroyElement(stg, stmname2);
1362  ok(r==S_OK, "IStorage->DestroyElement failed\n");
1363 
1364  count = 0xf00;
1365  r = IEnumSTATSTG_Next(ee, 1, &stat, &count);
1366  ok(r==S_OK, "IEnumSTATSTG->Next failed\n");
1367  ok(count == 1, "count wrong\n");
1368 
1369  if (r == S_OK)
1370  {
1371  ok(lstrcmpiW(stat.pwcsName, stmname3) == 0, "expected ABCDEFGHIJ, got %s\n", wine_dbgstr_w(stat.pwcsName));
1372  CoTaskMemFree(stat.pwcsName);
1373  }
1374 
1375  r = IStorage_Release( stg );
1376  todo_wine ok (r == 0, "storage not released\n");
1377 
1378  /* enumerator is still valid and working after the storage is released */
1379  r = IEnumSTATSTG_Reset(ee);
1380  ok(r==S_OK, "IEnumSTATSTG->Reset failed\n");
1381 
1382  count = 0xf00;
1383  r = IEnumSTATSTG_Next(ee, 1, &stat, &count);
1384  ok(r==S_OK, "IEnumSTATSTG->Next failed\n");
1385  ok(count == 1, "count wrong\n");
1386 
1387  if (r == S_OK)
1388  {
1389  ok(lstrcmpiW(stat.pwcsName, stmname3) == 0, "expected ABCDEFGHIJ, got %s\n", wine_dbgstr_w(stat.pwcsName));
1390  CoTaskMemFree(stat.pwcsName);
1391  }
1392 
1393  /* the storage is left open until the enumerator is freed */
1395  STGM_READWRITE |STGM_TRANSACTED, NULL, 0, &stg);
1397  r==STG_E_LOCKVIOLATION, /* XP-SP2/W2K3-SP1 and below */
1398  "StgCreateDocfile failed, res=%x\n", r);
1399 
1400  r = IEnumSTATSTG_Release(ee);
1401  ok (r == 0, "enum not released\n");
1402 
1404 }
1405 
1406 static void test_transact(void)
1407 {
1408  IStorage *stg = NULL, *stg2 = NULL, *stg3 = NULL;
1409  HRESULT r;
1410  IStream *stm = NULL;
1411  static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 };
1412  static const WCHAR stmname2[] = { 'F','O','O',0 };
1413  static const WCHAR stgname[] = { 'P','E','R','M','S','T','G',0 };
1414  static const WCHAR stgname2[] = { 'T','E','M','P','S','T','G',0 };
1415  BOOL ret;
1416 
1418 
1419  /* create the file */
1421  STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
1422  ok(r==S_OK, "StgCreateDocfile failed\n");
1423 
1424  /* commit a new stream and storage */
1425  r = IStorage_CreateStream(stg, stmname2, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1426  ok(r==S_OK, "IStorage->CreateStream failed\n");
1427 
1428  r = IStream_Write(stm, "this is stream 1\n", 16, NULL);
1429  ok(r==S_OK, "IStream->Write failed\n");
1430 
1431  IStream_Release(stm);
1432 
1433  r = IStorage_CreateStorage(stg, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg2);
1434  ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1435 
1436  if (r == S_OK)
1437  {
1438  /* Create two substorages but only commit one */
1439  r = IStorage_CreateStorage(stg2, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg3);
1440  ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1441 
1442  if (r == S_OK)
1443  IStorage_Release(stg3);
1444 
1445  r = IStorage_Commit(stg, 0);
1446  ok(r==S_OK, "IStorage->Commit failed\n");
1447 
1448  r = IStorage_CreateStorage(stg2, stgname2, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg3);
1449  ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1450 
1451  if (r == S_OK)
1452  IStorage_Release(stg3);
1453 
1454  IStorage_Release(stg2);
1455  }
1456 
1457  /* now create a stream and storage, but don't commit them */
1458  stm = NULL;
1459  r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1460  ok(r==S_OK, "IStorage->CreateStream failed\n");
1461 
1462  r = IStream_Write(stm, "this is stream 2\n", 16, NULL);
1463  ok(r==S_OK, "IStream->Write failed\n");
1464 
1465  /* IStream::Commit does nothing for OLE storage streams */
1466  r = IStream_Commit(stm, STGC_ONLYIFCURRENT | STGC_DANGEROUSLYCOMMITMERELYTODISKCACHE);
1467  ok(r==S_OK, "IStream->Commit failed\n");
1468 
1469  r = IStorage_CreateStorage(stg, stgname2, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg2);
1470  ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1471 
1472  if (r == S_OK)
1473  IStorage_Release(stg2);
1474 
1475  IStream_Release(stm);
1476 
1477  IStorage_Release(stg);
1478 
1479  stm = NULL;
1480  stg = NULL;
1482  ok(r==S_OK, "StgOpenStorage failed\n");
1483 
1484  if (!stg)
1485  return;
1486 
1487  r = IStorage_OpenStream(stg, stmname, NULL, STGM_SHARE_DENY_NONE|STGM_READ, 0, &stm );
1488  ok(r==STG_E_INVALIDFLAG, "IStorage->OpenStream failed %08x\n", r);
1489 
1490  r = IStorage_OpenStream(stg, stmname, NULL, STGM_DELETEONRELEASE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
1491  ok(r==STG_E_INVALIDFUNCTION, "IStorage->OpenStream failed %08x\n", r);
1492 
1493  r = IStorage_OpenStream(stg, stmname, NULL, STGM_TRANSACTED|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
1494  ok(r==STG_E_INVALIDFUNCTION, "IStorage->OpenStream failed %08x\n", r);
1495 
1496  r = IStorage_OpenStorage(stg, stmname, NULL, STGM_TRANSACTED|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg2 );
1497  ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStream failed %08x\n", r);
1498 
1499  r = IStorage_OpenStream(stg, stmname, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
1500  ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStream should fail %08x\n", r);
1501  if (r == S_OK)
1502  IStream_Release(stm);
1503 
1504  r = IStorage_OpenStorage(stg, stgname2, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg2 );
1505  ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStorage should fail %08x\n", r);
1506  if (r == S_OK)
1507  IStorage_Release(stg2);
1508 
1509  r = IStorage_OpenStorage(stg, stmname2, NULL, STGM_TRANSACTED|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg2 );
1510  ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStream failed %08x\n", r);
1511 
1512  r = IStorage_OpenStream(stg, stmname2, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
1513  ok(r==S_OK, "IStorage->OpenStream should succeed %08x\n", r);
1514  if (r == S_OK)
1515  IStream_Release(stm);
1516 
1517  r = IStorage_OpenStorage(stg, stgname, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg2 );
1518  ok(r==S_OK, "IStorage->OpenStorage should succeed %08x\n", r);
1519  if (r == S_OK)
1520  {
1521  r = IStorage_OpenStorage(stg2, stgname, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg3 );
1522  ok(r==S_OK, "IStorage->OpenStorage should succeed %08x\n", r);
1523  if (r == S_OK)
1524  IStorage_Release(stg3);
1525 
1526  r = IStorage_OpenStorage(stg2, stgname2, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg3 );
1527  ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStorage should fail %08x\n", r);
1528  if (r == S_OK)
1529  IStorage_Release(stg3);
1530 
1531  IStorage_Release(stg2);
1532  }
1533 
1534  IStorage_Release(stg);
1535 
1537  ok(ret, "deleted file\n");
1538 }
1539 
1540 static void test_substorage_share(void)
1541 {
1542  IStorage *stg, *stg2, *stg3;
1543  IStream *stm, *stm2;
1544  HRESULT r;
1545  static const WCHAR stgname[] = { 'P','E','R','M','S','T','G',0 };
1546  static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 };
1547  static const WCHAR othername[] = { 'N','E','W','N','A','M','E',0 };
1548  BOOL ret;
1549 
1551 
1552  /* create the file */
1554  STGM_READWRITE, 0, &stg);
1555  ok(r==S_OK, "StgCreateDocfile failed\n");
1556 
1557  /* create a read/write storage and try to open it again */
1558  r = IStorage_CreateStorage(stg, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg2);
1559  ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1560 
1561  if (r == S_OK)
1562  {
1563  r = IStorage_OpenStorage(stg, stgname, NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg3);
1564  ok(r==STG_E_ACCESSDENIED, "IStorage->OpenStorage should fail %08x\n", r);
1565 
1566  if (r == S_OK)
1567  IStorage_Release(stg3);
1568 
1569  r = IStorage_OpenStorage(stg, stgname, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, 0, &stg3);
1570  ok(r==STG_E_ACCESSDENIED, "IStorage->OpenStorage should fail %08x\n", r);
1571 
1572  if (r == S_OK)
1573  IStorage_Release(stg3);
1574 
1575  /* cannot rename the storage while it's open */
1576  r = IStorage_RenameElement(stg, stgname, othername);
1577  ok(r==STG_E_ACCESSDENIED, "IStorage->RenameElement should fail %08x\n", r);
1578  if (SUCCEEDED(r)) IStorage_RenameElement(stg, othername, stgname);
1579 
1580  /* destroying an object while it's open invalidates it */
1581  r = IStorage_DestroyElement(stg, stgname);
1582  ok(r==S_OK, "IStorage->DestroyElement failed, hr=%08x\n", r);
1583 
1584  r = IStorage_CreateStream(stg2, stmname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm);
1585  ok(r==STG_E_REVERTED, "IStorage->CreateStream failed, hr=%08x\n", r);
1586 
1587  if (r == S_OK)
1588  IStream_Release(stm);
1589 
1590  IStorage_Release(stg2);
1591  }
1592 
1593  /* create a read/write stream and try to open it again */
1594  r = IStorage_CreateStream(stg, stmname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm);
1595  ok(r==S_OK, "IStorage->CreateStream failed, hr=%08x\n", r);
1596 
1597  if (r == S_OK)
1598  {
1599  r = IStorage_OpenStream(stg, stmname, NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &stm2);
1600  ok(r==STG_E_ACCESSDENIED, "IStorage->OpenStream should fail %08x\n", r);
1601 
1602  if (r == S_OK)
1603  IStream_Release(stm2);
1604 
1605  r = IStorage_OpenStream(stg, stmname, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm2);
1606  ok(r==STG_E_ACCESSDENIED, "IStorage->OpenStream should fail %08x\n", r);
1607 
1608  if (r == S_OK)
1609  IStream_Release(stm2);
1610 
1611  /* cannot rename the stream while it's open */
1612  r = IStorage_RenameElement(stg, stmname, othername);
1613  ok(r==STG_E_ACCESSDENIED, "IStorage->RenameElement should fail %08x\n", r);
1614  if (SUCCEEDED(r)) IStorage_RenameElement(stg, othername, stmname);
1615 
1616  /* destroying an object while it's open invalidates it */
1617  r = IStorage_DestroyElement(stg, stmname);
1618  ok(r==S_OK, "IStorage->DestroyElement failed, hr=%08x\n", r);
1619 
1620  r = IStream_Write(stm, "this shouldn't work\n", 20, NULL);
1621  ok(r==STG_E_REVERTED, "IStream_Write should fail %08x\n", r);
1622 
1623  IStream_Release(stm);
1624  }
1625 
1626  IStorage_Release(stg);
1627 
1629  ok(ret, "deleted file\n");
1630 }
1631 
1632 static void test_revert(void)
1633 {
1634  IStorage *stg = NULL, *stg2 = NULL, *stg3 = NULL;
1635  HRESULT r;
1636  IStream *stm = NULL, *stm2 = NULL;
1637  static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 };
1638  static const WCHAR stmname2[] = { 'F','O','O',0 };
1639  static const WCHAR stgname[] = { 'P','E','R','M','S','T','G',0 };
1640  static const WCHAR stgname2[] = { 'T','E','M','P','S','T','G',0 };
1641  STATSTG statstg;
1642  BOOL ret;
1643 
1645 
1646  /* create the file */
1648  STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
1649  ok(r==S_OK, "StgCreateDocfile failed\n");
1650 
1651  /* commit a new stream and storage */
1652  r = IStorage_CreateStream(stg, stmname2, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1653  ok(r==S_OK, "IStorage->CreateStream failed\n");
1654 
1655  r = IStream_Write(stm, "this is stream 1\n", 16, NULL);
1656  ok(r==S_OK, "IStream->Write failed\n");
1657 
1658  r = IStorage_CreateStorage(stg, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg2);
1659  ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1660 
1661  if (r == S_OK)
1662  {
1663  /* Create two substorages but only commit one */
1664  r = IStorage_CreateStorage(stg2, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg3);
1665  ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1666 
1667  if (r == S_OK)
1668  IStorage_Release(stg3);
1669 
1670  r = IStorage_Commit(stg, 0);
1671  ok(r==S_OK, "IStorage->Commit failed\n");
1672 
1673  r = IStorage_CreateStorage(stg2, stgname2, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg3);
1674  ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1675 
1676  if (r == S_OK)
1677  IStorage_Release(stg3);
1678  }
1679 
1680  /* now create a stream and storage, then revert */
1681  r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm2 );
1682  ok(r==S_OK, "IStorage->CreateStream failed\n");
1683 
1684  r = IStream_Write(stm2, "this is stream 2\n", 16, NULL);
1685  ok(r==S_OK, "IStream->Write failed\n");
1686 
1687  r = IStorage_CreateStorage(stg, stgname2, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg3);
1688  ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1689 
1690  r = IStorage_Revert(stg);
1691  ok(r==S_OK, "Storage_Revert failed with error 0x%08x\n", r);
1692 
1693  /* all open objects become invalid */
1694  r = IStream_Write(stm, "this shouldn't work\n", 20, NULL);
1695  ok(r==STG_E_REVERTED, "IStream_Write should fail %08x\n", r);
1696 
1697  r = IStream_Write(stm2, "this shouldn't work\n", 20, NULL);
1698  ok(r==STG_E_REVERTED, "IStream_Write should fail %08x\n", r);
1699 
1700  r = IStorage_Stat(stg2, &statstg, STATFLAG_NONAME);
1701  ok(r==STG_E_REVERTED, "IStorage_Stat should fail %08x\n", r);
1702 
1703  r = IStorage_Stat(stg3, &statstg, STATFLAG_NONAME);
1704  ok(r==STG_E_REVERTED, "IStorage_Stat should fail %08x\n", r);
1705 
1706  IStream_Release(stm);
1707  IStream_Release(stm2);
1708  IStorage_Release(stg2);
1709  IStorage_Release(stg3);
1710 
1711  r = IStorage_OpenStream(stg, stmname, NULL, STGM_SHARE_DENY_NONE|STGM_READ, 0, &stm );
1712  ok(r==STG_E_INVALIDFLAG, "IStorage->OpenStream failed %08x\n", r);
1713 
1714  r = IStorage_OpenStream(stg, stmname, NULL, STGM_DELETEONRELEASE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
1715  ok(r==STG_E_INVALIDFUNCTION, "IStorage->OpenStream failed %08x\n", r);
1716 
1717  r = IStorage_OpenStream(stg, stmname, NULL, STGM_TRANSACTED|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
1718  ok(r==STG_E_INVALIDFUNCTION, "IStorage->OpenStream failed %08x\n", r);
1719 
1720  r = IStorage_OpenStorage(stg, stmname, NULL, STGM_TRANSACTED|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg2 );
1721  ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStream failed %08x\n", r);
1722 
1723  r = IStorage_OpenStream(stg, stmname, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
1724  ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStream should fail %08x\n", r);
1725  if (r == S_OK)
1726  IStream_Release(stm);
1727 
1728  r = IStorage_OpenStorage(stg, stgname2, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg2 );
1729  ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStorage should fail %08x\n", r);
1730  if (r == S_OK)
1731  IStorage_Release(stg2);
1732 
1733  r = IStorage_OpenStorage(stg, stmname2, NULL, STGM_TRANSACTED|STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg2 );
1734  ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStream failed %08x\n", r);
1735 
1736  r = IStorage_OpenStream(stg, stmname2, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
1737  ok(r==S_OK, "IStorage->OpenStream should succeed %08x\n", r);
1738  if (r == S_OK)
1739  IStream_Release(stm);
1740 
1741  r = IStorage_OpenStorage(stg, stgname, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg2 );
1742  ok(r==S_OK, "IStorage->OpenStorage should succeed %08x\n", r);
1743  if (r == S_OK)
1744  {
1745  r = IStorage_OpenStorage(stg2, stgname, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg3 );
1746  ok(r==S_OK, "IStorage->OpenStorage should succeed %08x\n", r);
1747  if (r == S_OK)
1748  IStorage_Release(stg3);
1749 
1750  r = IStorage_OpenStorage(stg2, stgname2, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg3 );
1751  ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStorage should fail %08x\n", r);
1752  if (r == S_OK)
1753  IStorage_Release(stg3);
1754 
1755  IStorage_Release(stg2);
1756  }
1757 
1758  IStorage_Release(stg);
1759 
1761  ok(ret, "deleted file\n");
1762 
1763  /* Revert only invalidates objects in transacted mode */
1765  STGM_READWRITE, 0, &stg);
1766  ok(r==S_OK, "StgCreateDocfile failed\n");
1767 
1768  r = IStorage_CreateStream(stg, stmname2, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1769  ok(r==S_OK, "IStorage->CreateStream failed\n");
1770 
1771  r = IStorage_Revert(stg);
1772  ok(r==S_OK, "IStorage->Revert failed %08x\n", r);
1773 
1774  r = IStream_Write(stm, "this works\n", 11, NULL);
1775  ok(r==S_OK, "IStream_Write should succeed %08x\n", r);
1776 
1777  IStream_Release(stm);
1778  IStorage_Release(stg);
1779 
1781  ok(ret, "deleted file\n");
1782 }
1783 
1784 static void test_parent_free(void)
1785 {
1786  IStorage *stg = NULL, *stg2 = NULL, *stg3 = NULL;
1787  HRESULT r;
1788  IStream *stm = NULL;
1789  static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 };
1790  static const WCHAR stgname[] = { 'P','E','R','M','S','T','G',0 };
1791  ULONG ref;
1792  STATSTG statstg;
1793  BOOL ret;
1794 
1796 
1797  /* create the file */
1799  STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
1800  ok(r==S_OK, "StgCreateDocfile failed\n");
1801 
1802  /* create a new storage */
1803  r = IStorage_CreateStorage(stg, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg2);
1804  ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1805 
1806  if (r == S_OK)
1807  {
1808  /* now create a stream inside the new storage */
1809  r = IStorage_CreateStream(stg2, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1810  ok(r==S_OK, "IStorage->CreateStream failed\n");
1811 
1812  if (r == S_OK)
1813  {
1814  /* create a storage inside the new storage */
1815  r = IStorage_CreateStorage(stg2, stgname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stg3 );
1816  ok(r==S_OK, "IStorage->CreateStorage failed\n");
1817  }
1818 
1819  /* free the parent */
1820  ref = IStorage_Release(stg2);
1821  ok(ref == 0, "IStorage still has %u references\n", ref);
1822 
1823  /* child objects are invalid */
1824  if (r == S_OK)
1825  {
1826  r = IStream_Write(stm, "this should fail\n", 17, NULL);
1827  ok(r==STG_E_REVERTED, "IStream->Write should fail, hr=%x\n", r);
1828 
1829  IStream_Release(stm);
1830 
1831  r = IStorage_Stat(stg3, &statstg, STATFLAG_NONAME);
1832  ok(r==STG_E_REVERTED, "IStorage_Stat should fail %08x\n", r);
1833 
1834  r = IStorage_SetStateBits(stg3, 1, 1);
1835  ok(r==STG_E_REVERTED, "IStorage_Stat should fail %08x\n", r);
1836 
1837  IStorage_Release(stg3);
1838  }
1839  }
1840 
1841  IStorage_Release(stg);
1842 
1844  ok(ret, "deleted file\n");
1845 }
1846 
1847 static void test_nonroot_transacted(void)
1848 {
1849  IStorage *stg = NULL, *stg2 = NULL, *stg3 = NULL;
1850  HRESULT r;
1851  IStream *stm = NULL;
1852  static const WCHAR stgname[] = { 'P','E','R','M','S','T','G',0 };
1853  static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 };
1854  static const WCHAR stmname2[] = { 'F','O','O',0 };
1855  BOOL ret;
1856 
1858 
1859  /* create a transacted file */
1861  STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
1862  ok(r==S_OK, "StgCreateDocfile failed\n");
1863 
1864  /* create a transacted substorage */
1865  r = IStorage_CreateStorage(stg, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_TRANSACTED, 0, 0, &stg2);
1866  ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1867 
1868  if (r == S_OK)
1869  {
1870  /* create and commit stmname */
1871  r = IStorage_CreateStream(stg2, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1872  ok(r==S_OK, "IStorage->CreateStream failed\n");
1873  if (r == S_OK)
1874  IStream_Release(stm);
1875 
1876  IStorage_Commit(stg2, 0);
1877 
1878  /* create and revert stmname2 */
1879  r = IStorage_CreateStream(stg2, stmname2, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1880  ok(r==S_OK, "IStorage->CreateStream failed\n");
1881  if (r == S_OK)
1882  IStream_Release(stm);
1883 
1884  IStorage_Revert(stg2);
1885 
1886  /* check that Commit and Revert really worked */
1887  r = IStorage_OpenStream(stg2, stmname, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
1888  ok(r==S_OK, "IStorage->OpenStream should succeed %08x\n", r);
1889  if (r == S_OK)
1890  IStream_Release(stm);
1891 
1892  r = IStorage_OpenStream(stg2, stmname2, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
1893  ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStream should fail %08x\n", r);
1894  if (r == S_OK)
1895  IStream_Release(stm);
1896 
1897  IStorage_Release(stg2);
1898  }
1899 
1900  /* create a read-only transacted substorage */
1901  r = IStorage_OpenStorage(stg, stgname, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE | STGM_TRANSACTED, NULL, 0, &stg2);
1902  ok(r==S_OK, "IStorage->OpenStorage failed, hr=%08x\n", r);
1903 
1904  if (r == S_OK)
1905  {
1906  /* The storage can be modified. */
1907  r = IStorage_CreateStorage(stg2, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg3);
1908  ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1909  if (r == S_OK)
1910  IStorage_Release(stg3);
1911 
1912  /* But changes cannot be committed. */
1913  r = IStorage_Commit(stg2, 0);
1914  ok(r==STG_E_ACCESSDENIED, "IStorage->Commit should fail, hr=%08x\n", r);
1915 
1916  IStorage_Release(stg2);
1917  }
1918 
1919  IStorage_Release(stg);
1920 
1921  /* create a non-transacted file */
1923  STGM_READWRITE, 0, &stg);
1924  ok(r==S_OK, "StgCreateDocfile failed\n");
1925 
1926  /* create a transacted substorage */
1927  r = IStorage_CreateStorage(stg, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_TRANSACTED, 0, 0, &stg2);
1928  ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
1929 
1930  if (r == S_OK)
1931  {
1932  /* create and commit stmname */
1933  r = IStorage_CreateStream(stg2, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1934  ok(r==S_OK, "IStorage->CreateStream failed\n");
1935  if (r == S_OK)
1936  IStream_Release(stm);
1937 
1938  IStorage_Commit(stg2, 0);
1939 
1940  /* create and revert stmname2 */
1941  r = IStorage_CreateStream(stg2, stmname2, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm );
1942  ok(r==S_OK, "IStorage->CreateStream failed\n");
1943  if (r == S_OK)
1944  IStream_Release(stm);
1945 
1946  IStorage_Revert(stg2);
1947 
1948  /* check that Commit and Revert really worked */
1949  r = IStorage_OpenStream(stg2, stmname, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
1950  ok(r==S_OK, "IStorage->OpenStream should succeed %08x\n", r);
1951  if (r == S_OK)
1952  IStream_Release(stm);
1953 
1954  r = IStorage_OpenStream(stg2, stmname2, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &stm );
1955  ok(r==STG_E_FILENOTFOUND, "IStorage->OpenStream should fail %08x\n", r);
1956  if (r == S_OK)
1957  IStream_Release(stm);
1958 
1959  IStorage_Release(stg2);
1960  }
1961 
1962  IStorage_Release(stg);
1963 
1965  ok(ret, "deleted file\n");
1966 }
1967 
1968 static void test_ReadClassStm(void)
1969 {
1970  CLSID clsid, clsid2;
1971  HRESULT hr;
1972  IStream *pStream;
1973  static const LARGE_INTEGER llZero;
1974 
1975  hr = ReadClassStm(NULL, &clsid);
1976  ok(hr == E_INVALIDARG, "ReadClassStm should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1977 
1978  hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1979  ok_ole_success(hr, "CreateStreamOnHGlobal");
1980  hr = WriteClassStm(pStream, &test_stg_cls);
1981  ok_ole_success(hr, "WriteClassStm");
1982 
1983  hr = ReadClassStm(pStream, NULL);
1984  ok(hr == E_INVALIDARG, "ReadClassStm should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1985 
1986  memset(&clsid, 0xcc, sizeof(clsid));
1987  memset(&clsid2, 0xcc, sizeof(clsid2));
1988  hr = ReadClassStm(NULL, &clsid);
1989  ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1990  ok(IsEqualCLSID(&clsid, &clsid2), "got wrong clsid\n");
1991 
1992  /* test not rewound stream */
1993  hr = ReadClassStm(pStream, &clsid);
1994  ok(hr == STG_E_READFAULT, "ReadClassStm should have returned STG_E_READFAULT instead of 0x%08x\n", hr);
1995  ok(IsEqualCLSID(&clsid, &CLSID_NULL), "clsid should have been zeroed\n");
1996 
1997  hr = IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1998  ok_ole_success(hr, "IStream_Seek");
1999  hr = ReadClassStm(pStream, &clsid);
2000  ok_ole_success(hr, "ReadClassStm");
2001  ok(IsEqualCLSID(&clsid, &test_stg_cls), "clsid should have been set to CLSID_WineTest\n");
2002 
2003  IStream_Release(pStream);
2004 }
2005 
2006 struct access_res
2007 {
2008  BOOL gothandle;
2009  DWORD lasterr;
2010  BOOL ignore;
2011 };
2012 
2013 static const struct access_res create[16] =
2014 {
2015  { TRUE, ERROR_SUCCESS, TRUE },
2016  { TRUE, ERROR_SUCCESS, TRUE },
2017  { TRUE, ERROR_SUCCESS, FALSE },
2018  { TRUE, ERROR_SUCCESS, FALSE },
2022  { TRUE, ERROR_SUCCESS, FALSE },
2026  { TRUE, ERROR_SUCCESS, TRUE },
2030  { TRUE, ERROR_SUCCESS, TRUE }
2031 };
2032 
2033 static const struct access_res create_commit[16] =
2034 {
2035  { TRUE, ERROR_SUCCESS, TRUE },
2036  { TRUE, ERROR_SUCCESS, TRUE },
2037  { TRUE, ERROR_SUCCESS, FALSE },
2038  { TRUE, ERROR_SUCCESS, FALSE },
2042  { TRUE, ERROR_SUCCESS, FALSE },
2046  { TRUE, ERROR_SUCCESS, TRUE },
2050  { TRUE, ERROR_SUCCESS, TRUE }
2051 };
2052 
2053 static const struct access_res create_close[16] =
2054 {
2055  { TRUE, ERROR_SUCCESS, FALSE },
2056  { TRUE, ERROR_SUCCESS, FALSE },
2057  { TRUE, ERROR_SUCCESS, FALSE },
2058  { TRUE, ERROR_SUCCESS, FALSE },
2059  { TRUE, ERROR_SUCCESS, FALSE },
2060  { TRUE, ERROR_SUCCESS, FALSE },
2061  { TRUE, ERROR_SUCCESS, FALSE },
2062  { TRUE, ERROR_SUCCESS, FALSE },
2063  { TRUE, ERROR_SUCCESS, FALSE },
2064  { TRUE, ERROR_SUCCESS, FALSE },
2065  { TRUE, ERROR_SUCCESS, FALSE },
2066  { TRUE, ERROR_SUCCESS, FALSE },
2067  { TRUE, ERROR_SUCCESS, FALSE },
2068  { TRUE, ERROR_SUCCESS, FALSE },
2069  { TRUE, ERROR_SUCCESS, FALSE },
2070  { TRUE, ERROR_SUCCESS }
2071 };
2072 
2073 static const DWORD access_modes[4] = {
2074  0,
2075  GENERIC_READ,
2076  GENERIC_WRITE,
2078 };
2079 
2080 static const DWORD share_modes[4] = {
2081  0,
2085 };
2086 
2087 static void _test_file_access(LPCSTR file, const struct access_res *ares, DWORD line)
2088 {
2089  int i, j, idx = 0;
2090 
2091  for (i = 0; i < ARRAY_SIZE(access_modes); i++)
2092  {
2093  for (j = 0; j < ARRAY_SIZE(share_modes); j++)
2094  {
2095  DWORD lasterr;
2096  HANDLE hfile;
2097 
2098  if (ares[idx].ignore)
2099  continue;
2100 
2101  SetLastError(0xdeadbeef);
2104  lasterr = GetLastError();
2105 
2106  ok((hfile != INVALID_HANDLE_VALUE) == ares[idx].gothandle,
2107  "(%d, handle, %d): Expected %d, got %d\n",
2108  line, idx, ares[idx].gothandle,
2109  (hfile != INVALID_HANDLE_VALUE));
2110 
2111  ok(lasterr == ares[idx].lasterr ||
2112  broken(lasterr == 0xdeadbeef) /* win9x */,
2113  "(%d, lasterr, %d): Expected %d, got %d\n",
2114  line, idx, ares[idx].lasterr, lasterr);
2115 
2116  CloseHandle(hfile);
2117  idx++;
2118  }
2119  }
2120 }
2121 
2122 #define test_file_access(file, ares) _test_file_access(file, ares, __LINE__)
2123 
2124 static void test_access(void)
2125 {
2126  static const WCHAR fileW[] = {'w','i','n','e','t','e','s','t',0};
2127  static const char fileA[] = "winetest";
2128  IStorage *stg;
2129  HRESULT hr;
2130 
2131  /* STGM_TRANSACTED */
2134  ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
2135 
2136  test_file_access(fileA, create);
2137 
2138  hr = IStorage_Commit(stg, STGC_DEFAULT);
2139  ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
2140 
2142 
2143  IStorage_Release(stg);
2144 
2146 
2147  DeleteFileA(fileA);
2148 
2149  /* STGM_DIRECT */
2151  STGM_SHARE_EXCLUSIVE | STGM_DIRECT, 0, &stg);
2152  ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
2153 
2154  test_file_access(fileA, create);
2155 
2156  hr = IStorage_Commit(stg, STGC_DEFAULT);
2157  ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
2158 
2160 
2161  IStorage_Release(stg);
2162 
2164 
2165  DeleteFileA(fileA);
2166 
2167  /* STGM_SHARE_DENY_NONE */
2170  ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
2171 
2172  test_file_access(fileA, create);
2173 
2174  hr = IStorage_Commit(stg, STGC_DEFAULT);
2175  ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
2176 
2178 
2179  IStorage_Release(stg);
2180 
2182 
2183  DeleteFileA(fileA);
2184 
2185  /* STGM_SHARE_DENY_READ */
2188  ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
2189 
2190  test_file_access(fileA, create);
2191 
2192  hr = IStorage_Commit(stg, STGC_DEFAULT);
2193  ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
2194 
2196 
2197  IStorage_Release(stg);
2198 
2200 
2201  DeleteFileA(fileA);
2202 
2203  /* STGM_SHARE_DENY_WRITE */
2206  ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
2207 
2208  test_file_access(fileA, create);
2209 
2210  hr = IStorage_Commit(stg, STGC_DEFAULT);
2211  ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
2212 
2214 
2215  IStorage_Release(stg);
2216 
2218 
2219  DeleteFileA(fileA);
2220 
2221  /* STGM_DIRECT_SWMR | STGM_READ | STGM_SHARE_DENY_NONE - reader mode for direct SWMR mode */
2223  ok(hr == S_OK, "got %08x\n", hr);
2224  IStorage_Release(stg);
2225 
2227  ok(hr == S_OK || broken(hr == STG_E_INVALIDFLAG), "got %08x\n", hr);
2228  if(hr != S_OK)
2229  return;
2230 
2231  test_file_access(fileA, create);
2232 
2233  IStorage_Release(stg);
2235 
2236  DeleteFileA(fileA);
2237 }
2238 
2239 static void test_readonly(void)
2240 {
2241  IStorage *stg, *stg2, *stg3;
2242  IStream *stream;
2243  HRESULT hr;
2244  static const WCHAR fileW[] = {'w','i','n','e','t','e','s','t',0};
2245  static const WCHAR storageW[] = {'s','t','o','r','a','g','e',0};
2246  static const WCHAR streamW[] = {'s','t','r','e','a','m',0};
2247 
2249  ok(hr == S_OK, "should succeed, res=%x\n", hr);
2250  if (SUCCEEDED(hr))
2251  {
2252  hr = IStorage_CreateStorage( stg, storageW, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stg2 );
2253  ok(hr == S_OK, "should succeed, res=%x\n", hr);
2254  if (SUCCEEDED(hr))
2255  {
2256  hr = IStorage_CreateStream( stg2, streamW, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stream );
2257  ok(hr == S_OK, "should succeed, res=%x\n", hr);
2258  if (SUCCEEDED(hr))
2259  IStream_Release(stream);
2260  IStorage_Release(stg2);
2261  }
2262  IStorage_Release(stg);
2263  }
2264 
2265  /* re-open read only */
2267  ok(hr == S_OK, "should succeed, res=%x\n", hr);
2268  if (SUCCEEDED(hr))
2269  {
2270  hr = IStorage_OpenStorage( stg, storageW, NULL, STGM_SHARE_EXCLUSIVE | STGM_READ, NULL, 0, &stg2 );
2271  ok(hr == S_OK, "should succeed, res=%x\n", hr);
2272  if (SUCCEEDED(hr))
2273  {
2274  /* CreateStream on read-only storage, name exists */
2275  hr = IStorage_CreateStream( stg2, streamW, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READ, 0, 0, &stream );
2276  ok(hr == STG_E_ACCESSDENIED, "should fail, res=%x\n", hr);
2277  if (SUCCEEDED(hr))
2278  IStream_Release(stream);
2279 
2280  /* CreateStream on read-only storage, name does not exist */
2281  hr = IStorage_CreateStream( stg2, storageW, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READ, 0, 0, &stream );
2282  ok(hr == STG_E_ACCESSDENIED, "should fail, res=%x\n", hr);
2283  if (SUCCEEDED(hr))
2284  IStream_Release(stream);
2285 
2286  /* CreateStorage on read-only storage, name exists */
2287  hr = IStorage_CreateStorage( stg2, streamW, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READ, 0, 0, &stg3 );
2288  ok(hr == STG_E_FILEALREADYEXISTS, "should fail, res=%x\n", hr);
2289  if (SUCCEEDED(hr))
2290  IStorage_Release(stg3);
2291 
2292  /* CreateStorage on read-only storage, name does not exist */
2293  hr = IStorage_CreateStorage( stg2, storageW, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READ, 0, 0, &stg3 );
2294  ok(hr == STG_E_ACCESSDENIED, "should fail, res=%x\n", hr);
2295  if (SUCCEEDED(hr))
2296  IStorage_Release(stg3);
2297 
2298  /* DestroyElement on read-only storage, name exists */
2299  hr = IStorage_DestroyElement( stg2, streamW );
2300  ok(hr == STG_E_ACCESSDENIED, "should fail, res=%x\n", hr);
2301 
2302  /* DestroyElement on read-only storage, name does not exist */
2303  hr = IStorage_DestroyElement( stg2, storageW );
2304  ok(hr == STG_E_ACCESSDENIED, "should fail, res=%x\n", hr);
2305 
2306  IStorage_Release(stg2);
2307  }
2308 
2309  IStorage_Release(stg);
2310  }
2311 
2312  DeleteFileA("winetest");
2313 }
2314 
2315 static void test_simple(void)
2316 {
2317  /* Tests for STGM_SIMPLE mode */
2318 
2319  IStorage *stg, *stg2;
2320  HRESULT r;
2321  IStream *stm;
2322  static const WCHAR stgname[] = { 'S','t','g',0 };
2323  static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 };
2324  static const WCHAR stmname2[] = { 'S','m','a','l','l',0 };
2326  ULARGE_INTEGER upos;
2327  DWORD count;
2328  STATSTG stat;
2329 
2331 
2333  ok(r == S_OK, "got %08x\n", r);
2334 
2335  r = IStorage_CreateStorage(stg, stgname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stg2);
2336  ok(r == STG_E_INVALIDFUNCTION, "got %08x\n", r);
2337  if (SUCCEEDED(r)) IStorage_Release(stg2);
2338 
2339  r = IStorage_CreateStream(stg, stmname, STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm);
2340  ok(r == STG_E_INVALIDFLAG, "got %08x\n", r);
2341  r = IStorage_CreateStream(stg, stmname, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm);
2342  ok(r == S_OK, "got %08x\n", r);
2343 
2344  upos.QuadPart = 6000;
2345  r = IStream_SetSize(stm, upos);
2346  ok(r == S_OK, "got %08x\n", r);
2347 
2348  r = IStream_Write(stm, "foo", 3, &count);
2349  ok(r == S_OK, "got %08x\n", r);
2350  ok(count == 3, "got %d\n", count);
2351 
2352  pos.QuadPart = 0;
2353  r = IStream_Seek(stm, pos, STREAM_SEEK_CUR, &upos);
2354  ok(r == S_OK, "got %08x\n", r);
2355  ok(upos.QuadPart == 3, "got %d\n", upos.u.LowPart);
2356 
2357  r = IStream_Stat(stm, &stat, STATFLAG_NONAME);
2358  ok(r == S_OK ||
2359  broken(r == STG_E_INVALIDFUNCTION), /* NT4 and below */
2360  "got %08x\n", r);
2361  if (r == S_OK)
2362  ok(stat.cbSize.QuadPart == 3, "got %d\n", stat.cbSize.u.LowPart);
2363 
2364  pos.QuadPart = 1;
2365  r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &upos);
2366  ok(r == S_OK, "got %08x\n", r);
2367  ok(upos.QuadPart == 1, "got %d\n", upos.u.LowPart);
2368 
2369  r = IStream_Stat(stm, &stat, STATFLAG_NONAME);
2370  ok(r == S_OK ||
2371  broken(r == STG_E_INVALIDFUNCTION), /* NT4 and below */
2372  "got %08x\n", r);
2373  if (r == S_OK)
2374  ok(stat.cbSize.QuadPart == 1, "got %d\n", stat.cbSize.u.LowPart);
2375 
2376  IStream_Release(stm);
2377 
2378  r = IStorage_CreateStream(stg, stmname2, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, 0, &stm);
2379  ok(r == S_OK, "got %08x\n", r);
2380 
2381  upos.QuadPart = 100;
2382  r = IStream_SetSize(stm, upos);
2383  ok(r == S_OK, "got %08x\n", r);
2384 
2385  r = IStream_Write(stm, "foo", 3, &count);
2386  ok(r == S_OK, "got %08x\n", r);
2387  ok(count == 3, "got %d\n", count);
2388 
2389  IStream_Release(stm);
2390 
2391  IStorage_Commit(stg, STGC_DEFAULT);
2392  IStorage_Release(stg);
2393 
2395  if (r == STG_E_INVALIDFLAG)
2396  {
2397  win_skip("Flag combination is not supported on NT4 and below\n");
2399  return;
2400  }
2401  ok(r == S_OK, "got %08x\n", r);
2402 
2403  r = IStorage_OpenStorage(stg, stgname, NULL, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, NULL, 0, &stg2);
2404  ok(r == STG_E_INVALIDFUNCTION, "got %08x\n", r);
2405  if (SUCCEEDED(r)) IStorage_Release(stg2);
2406 
2407  r = IStorage_OpenStream(stg, stmname, NULL, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &stm);
2408  ok(r == S_OK, "got %08x\n", r);
2409 
2410  r = IStream_Stat(stm, &stat, STATFLAG_NONAME);
2411  ok(r == S_OK, "got %08x\n", r);
2412  ok(stat.cbSize.QuadPart == 6000, "got %d\n", stat.cbSize.u.LowPart);
2413 
2414  IStream_Release(stm);
2415 
2416  r = IStorage_OpenStream(stg, stmname2, NULL, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &stm);
2417  ok(r == S_OK, "got %08x\n", r);
2418 
2419  r = IStream_Stat(stm, &stat, STATFLAG_NONAME);
2420  ok(r == S_OK, "got %08x\n", r);
2421  ok(stat.cbSize.QuadPart == 4096, "got %d\n", stat.cbSize.u.LowPart);
2422 
2423  IStream_Release(stm);
2424 
2425 
2426  IStorage_Release(stg);
2427 
2429 }
2430 
2431 static void test_fmtusertypestg(void)
2432 {
2433  IStorage *stg;
2434  IEnumSTATSTG *stat;
2435  HRESULT hr;
2436  static const char fileA[] = {'f','m','t','t','e','s','t',0};
2437  static const WCHAR fileW[] = {'f','m','t','t','e','s','t',0};
2438  static WCHAR userTypeW[] = {'S','t','g','U','s','r','T','y','p','e',0};
2439  static const WCHAR strmNameW[] = {1,'C','o','m','p','O','b','j',0};
2440  static const STATSTG statstg_null;
2441 
2443  ok(hr == S_OK, "should succeed, res=%x\n", hr);
2444 
2445  if (SUCCEEDED(hr))
2446  {
2447  /* try to write the stream */
2448  hr = WriteFmtUserTypeStg(stg, 0, userTypeW);
2449  ok(hr == S_OK, "should succeed, res=%x\n", hr);
2450 
2451  /* check that the stream was created */
2452  hr = IStorage_EnumElements(stg, 0, NULL, 0, &stat);
2453  ok(hr == S_OK, "should succeed, res=%x\n", hr);
2454  if (SUCCEEDED(hr))
2455  {
2456  BOOL found = FALSE;
2457  STATSTG statstg;
2458  DWORD got;
2459  memset(&statstg, 0xad, sizeof(statstg));
2460  while ((hr = IEnumSTATSTG_Next(stat, 1, &statstg, &got)) == S_OK && got == 1)
2461  {
2462  if (strcmp_ww(statstg.pwcsName, strmNameW) == 0)
2463  found = TRUE;
2464  else
2465  ok(0, "found unexpected stream or storage\n");
2466  CoTaskMemFree(statstg.pwcsName);
2467  }
2468  ok(memcmp(&statstg, &statstg_null, sizeof(statstg)) == 0, "statstg is not zeroed\n");
2469  ok(found == TRUE, "expected storage to contain stream \\0001CompObj\n");
2470  IEnumSTATSTG_Release(stat);
2471  }
2472 
2473  /* re-write the stream */
2474  hr = WriteFmtUserTypeStg(stg, 0, userTypeW);
2475  ok(hr == S_OK, "should succeed, res=%x\n", hr);
2476 
2477  /* check that the stream is still there */
2478  hr = IStorage_EnumElements(stg, 0, NULL, 0, &stat);
2479  ok(hr == S_OK, "should succeed, res=%x\n", hr);
2480  if (SUCCEEDED(hr))
2481  {
2482  BOOL found = FALSE;
2483  STATSTG statstg;
2484  DWORD got;
2485  memset(&statstg, 0xad, sizeof(statstg));
2486  while ((hr = IEnumSTATSTG_Next(stat, 1, &statstg, &got)) == S_OK && got == 1)
2487  {
2488  if (strcmp_ww(statstg.pwcsName, strmNameW) == 0)
2489  found = TRUE;
2490  else
2491  ok(0, "found unexpected stream or storage\n");
2492  CoTaskMemFree(statstg.pwcsName);
2493  }
2494  ok(memcmp(&statstg, &statstg_null, sizeof(statstg)) == 0, "statstg is not zeroed\n");
2495  ok(found == TRUE, "expected storage to contain stream \\0001CompObj\n");
2496  IEnumSTATSTG_Release(stat);
2497  }
2498 
2499  IStorage_Release(stg);
2500  DeleteFileA( fileA );
2501  }
2502 }
2503 
2504 static void test_references(void)
2505 {
2506  IStorage *stg,*stg2;
2507  HRESULT hr;
2508  unsigned c1,c2;
2509  static const WCHAR StorName[] = { 'D','a','t','a','S','p','a','c','e','I','n','f','o',0 };
2510 
2512 
2514  ok(hr==S_OK, "StgCreateDocfile failed\n");
2515 
2516  if (SUCCEEDED(hr))
2517  {
2518  IStorage_Release(stg);
2519 
2521  ok(hr==S_OK, "StgOpenStorage failed (result=%x)\n",hr);
2522 
2523  if (SUCCEEDED(hr))
2524  {
2525  hr = IStorage_CreateStorage(stg,StorName,STGM_READWRITE | STGM_SHARE_EXCLUSIVE,0,0,&stg2);
2526  ok(hr == S_OK, "IStorage_CreateStorage failed (result=%x)\n",hr);
2527 
2528  if (SUCCEEDED(hr))
2529  {
2530  c1 = IStorage_AddRef(stg);
2531  ok(c1 == 2, "creating internal storage added references to ancestor\n");
2532  c1 = IStorage_AddRef(stg);
2533  IStorage_Release(stg2);
2534  c2 = IStorage_AddRef(stg) - 1;
2535  ok(c1 == c2, "releasing internal storage removed references to ancestor\n");
2536  }
2537  c1 = IStorage_Release(stg);
2538  while ( c1 ) c1 = IStorage_Release(stg);
2539  }
2540  }
2541 
2543 }
2544 
2545 /* dest
2546  * |-StorageA
2547  * | `StreamA: "StreamA"
2548  * |-StorageB
2549  * | `StreamB: "StreamB"
2550  * `StreamC: "StreamC"
2551  */
2553 {
2554  IStorage *stgA = NULL, *stgB = NULL;
2555  IStream *strmA = NULL, *strmB = NULL, *strmC = NULL;
2556  const ULONG strmA_name_size = lstrlenW(strmA_name) * sizeof(WCHAR);
2557  const ULONG strmB_name_size = lstrlenW(strmB_name) * sizeof(WCHAR);
2558  const ULONG strmC_name_size = lstrlenW(strmC_name) * sizeof(WCHAR);
2559  ULONG bytes;
2560  HRESULT hr;
2561 
2562  hr = IStorage_CreateStorage(dest, stgA_name, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stgA);
2563  ok(hr == S_OK, "IStorage_CreateStorage failed: 0x%08x\n", hr);
2564  if(FAILED(hr))
2565  goto cleanup;
2566 
2567  hr = IStorage_CreateStream(stgA, strmA_name, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &strmA);
2568  ok(hr == S_OK, "IStorage_CreateStream failed: 0x%08x\n", hr);
2569  if(FAILED(hr))
2570  goto cleanup;
2571 
2572  hr = IStream_Write(strmA, strmA_name, strmA_name_size, &bytes);
2573  ok(hr == S_OK && bytes == strmA_name_size, "IStream_Write failed: 0x%08x, %d of %d bytes written\n", hr, bytes, strmA_name_size);
2574 
2575  hr = IStorage_CreateStorage(dest, stgB_name, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stgB);
2576  ok(hr == S_OK, "IStorage_CreateStorage failed: 0x%08x\n", hr);
2577  if(FAILED(hr))
2578  goto cleanup;
2579 
2580  hr = IStorage_CreateStream(stgB, strmB_name, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &strmB);
2581  ok(hr == S_OK, "IStorage_CreateStream failed: 0x%08x\n", hr);
2582  if(FAILED(hr))
2583  goto cleanup;
2584 
2585  hr = IStream_Write(strmB, strmB_name, strmB_name_size, &bytes);
2586  ok(hr == S_OK && bytes == strmB_name_size, "IStream_Write failed: 0x%08x, %d of %d bytes written\n", hr, bytes, strmB_name_size);
2587 
2588  hr = IStorage_CreateStream(dest, strmC_name, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &strmC);
2589  ok(hr == S_OK, "IStorage_CreateStream failed: 0x%08x\n", hr);
2590  if(FAILED(hr))
2591  goto cleanup;
2592 
2593  hr = IStream_Write(strmC, strmC_name, strmC_name_size, &bytes);
2594  ok(hr == S_OK && bytes == strmC_name_size, "IStream_Write failed: 0x%08x, %d of %d bytes written\n", hr, bytes, strmC_name_size);
2595 
2596 cleanup:
2597  if(strmC)
2598  IStream_Release(strmC);
2599  if(strmB)
2600  IStream_Release(strmB);
2601  if(stgB)
2602  IStorage_Release(stgB);
2603  if(strmA)
2604  IStream_Release(strmA);
2605  if(stgA)
2606  IStorage_Release(stgA);
2607 
2608  return hr;
2609 }
2610 
2611 static void test_copyto(void)
2612 {
2613  IStorage *file1 = NULL, *file2 = NULL, *stg_tmp;
2614  IStream *strm_tmp;
2615  WCHAR buf[64];
2616  HRESULT hr;
2617 
2618  /* create & populate file1 */
2620  ok(hr == S_OK, "StgCreateDocfile failed: 0x%08x\n", hr);
2621  if(FAILED(hr))
2622  goto cleanup;
2623 
2624  hr = create_test_file(file1);
2625  if(FAILED(hr))
2626  goto cleanup;
2627 
2628  /* create file2 */
2630  ok(hr == S_OK, "StgCreateDocfile failed: 0x%08x\n", hr);
2631  if(FAILED(hr))
2632  goto cleanup;
2633 
2634  /* copy file1 into file2 */
2635  hr = IStorage_CopyTo(file1, 0, NULL, NULL, NULL);
2636  ok(hr == STG_E_INVALIDPOINTER, "CopyTo should give STG_E_INVALIDPONITER, gave: 0x%08x\n", hr);
2637 
2638  hr = IStorage_CopyTo(file1, 0, NULL, NULL, file2);
2639  ok(hr == S_OK, "CopyTo failed: 0x%08x\n", hr);
2640  if(FAILED(hr))
2641  goto cleanup;
2642 
2643  /* verify that all of file1 was copied */
2644  hr = IStorage_OpenStorage(file2, stgA_name, NULL,
2645  STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg_tmp);
2646  ok(hr == S_OK, "OpenStorage failed: 0x%08x\n", hr);
2647 
2648  if(SUCCEEDED(hr)){
2649  hr = IStorage_OpenStream(stg_tmp, strmA_name, NULL,
2650  STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp);
2651  ok(hr == S_OK, "OpenStream failed: 0x%08x\n", hr);
2652 
2653  if(SUCCEEDED(hr)){
2654  memset(buf, 0, sizeof(buf));
2655  hr = IStream_Read(strm_tmp, buf, sizeof(buf), NULL);
2656  ok(hr == S_OK, "Read failed: 0x%08x\n", hr);
2657  if(SUCCEEDED(hr))
2658  ok(strcmp_ww(buf, strmA_name) == 0,
2659  "Expected %s to be read, got %s\n", wine_dbgstr_w(strmA_name), wine_dbgstr_w(buf));
2660 
2661  IStream_Release(strm_tmp);
2662  }
2663 
2664  IStorage_Release(stg_tmp);
2665  }
2666 
2667  hr = IStorage_OpenStorage(file2, stgB_name, NULL,
2668  STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg_tmp);
2669  ok(hr == S_OK, "OpenStorage failed: 0x%08x\n", hr);
2670 
2671  if(SUCCEEDED(hr)){
2672  hr = IStorage_OpenStream(stg_tmp, strmB_name, NULL,
2673  STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp);
2674  ok(hr == S_OK, "OpenStream failed: 0x%08x\n", hr);
2675 
2676  if(SUCCEEDED(hr)){
2677  memset(buf, 0, sizeof(buf));
2678  hr = IStream_Read(strm_tmp, buf, sizeof(buf), NULL);
2679  ok(hr == S_OK, "Read failed: 0x%08x\n", hr);
2680  if(SUCCEEDED(hr))
2681  ok(strcmp_ww(buf, strmB_name) == 0,
2682  "Expected %s to be read, got %s\n", wine_dbgstr_w(strmB_name), wine_dbgstr_w(buf));
2683 
2684  IStream_Release(strm_tmp);
2685  }
2686 
2687  IStorage_Release(stg_tmp);
2688  }
2689 
2690  hr = IStorage_OpenStream(file2, strmC_name, NULL,
2691  STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp);
2692  ok(hr == S_OK, "OpenStream failed: 0x%08x\n", hr);
2693 
2694  if(SUCCEEDED(hr)){
2695  memset(buf, 0, sizeof(buf));
2696  hr = IStream_Read(strm_tmp, buf, sizeof(buf), NULL);
2697  ok(hr == S_OK, "Read failed: 0x%08x\n", hr);
2698  if(SUCCEEDED(hr))
2699  ok(strcmp_ww(buf, strmC_name) == 0,
2700  "Expected %s to be read, got %s\n", wine_dbgstr_w(strmC_name), wine_dbgstr_w(buf));
2701 
2702  IStream_Release(strm_tmp);
2703  }
2704 
2705 cleanup:
2706  if(file1)
2707  IStorage_Release(file1);
2708  if(file2)
2709  IStorage_Release(file2);
2710 
2713 }
2714 
2715 static void test_copyto_snbexclusions(void)
2716 {
2717  static const WCHAR *snb_exclude[] = {stgA_name, strmB_name, strmC_name, 0};
2718 
2719  IStorage *file1 = NULL, *file2 = NULL, *stg_tmp;
2720  IStream *strm_tmp;
2721  WCHAR buf[64];
2722  HRESULT hr;
2723 
2724  /* create & populate file1 */
2726  ok(hr == S_OK, "StgCreateDocfile failed: 0x%08x\n", hr);
2727  if(FAILED(hr))
2728  goto cleanup;
2729 
2730  hr = create_test_file(file1);
2731  if(FAILED(hr))
2732  goto cleanup;
2733 
2734  /* create file2 */
2736  ok(hr == S_OK, "StgCreateDocfile failed: 0x%08x\n", hr);
2737  if(FAILED(hr))
2738  goto cleanup;
2739 
2740  /* copy file1 to file2 with name exclusions */
2741  hr = IStorage_CopyTo(file1, 0, NULL, (SNB)snb_exclude, file2);
2742  ok(hr == S_OK, "CopyTo failed: 0x%08x\n", hr);
2743  if(FAILED(hr))
2744  goto cleanup;
2745 
2746  /* verify that file1 copied over, respecting exclusions */
2747  hr = IStorage_OpenStorage(file2, stgA_name, NULL,
2748  STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg_tmp);
2749  ok(hr == STG_E_FILENOTFOUND, "OpenStorage should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr);
2750  if(SUCCEEDED(hr))
2751  IStorage_Release(stg_tmp);
2752 
2753  hr = IStorage_OpenStream(file2, strmA_name, NULL,
2754  STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp);
2755  ok(hr == STG_E_FILENOTFOUND, "OpenStream should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr);
2756  if(SUCCEEDED(hr))
2757  IStream_Release(strm_tmp);
2758 
2759  hr = IStorage_OpenStorage(file2, stgB_name, NULL,
2760  STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg_tmp);
2761  ok(hr == S_OK, "OpenStorage failed: 0x%08x\n", hr);
2762 
2763  if(SUCCEEDED(hr)){
2764  hr = IStorage_OpenStream(stg_tmp, strmB_name, NULL,
2765  STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp);
2766  ok(hr == S_OK, "OpenStream failed: 0x%08x\n", hr);
2767 
2768  if(SUCCEEDED(hr)){
2769  memset(buf, 0, sizeof(buf));
2770  hr = IStream_Read(strm_tmp, buf, sizeof(buf), NULL);
2771  ok(hr == S_OK, "Read failed: 0x%08x\n", hr);
2772  if(SUCCEEDED(hr))
2773  ok(strcmp_ww(buf, strmB_name) == 0,
2774  "Expected %s to be read, got %s\n", wine_dbgstr_w(strmB_name), wine_dbgstr_w(buf));
2775 
2776  IStream_Release(strm_tmp);
2777  }
2778 
2779  IStorage_Release(stg_tmp);
2780  }
2781 
2782  hr = IStorage_OpenStream(file2, strmC_name, NULL,
2783  STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp);
2784  ok(hr == STG_E_FILENOTFOUND, "OpenStream should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr);
2785  if(SUCCEEDED(hr))
2786  IStream_Release(strm_tmp);
2787 
2788 cleanup:
2789  if(file1)
2790  IStorage_Release(file1);
2791  if(file2)
2792  IStorage_Release(file2);
2793 
2796 }
2797 
2799 {
2800  IStorage *file1 = NULL, *file2 = NULL, *stg_tmp;
2801  IStream *strm_tmp;
2802  WCHAR buf[64];
2803  HRESULT hr;
2804 
2805  /* create & populate file1 */
2807  ok(hr == S_OK, "StgCreateDocfile failed: 0x%08x\n", hr);
2808  if(FAILED(hr))
2809  goto cleanup;
2810 
2811  hr = create_test_file(file1);
2812  if(FAILED(hr))
2813  goto cleanup;
2814 
2815  /* create file2 */
2817  ok(hr == S_OK, "StgCreateDocfile failed: 0x%08x\n", hr);
2818  if(FAILED(hr))
2819  goto cleanup;
2820 
2821  /* copy file1 to file2 with iid exclusions */
2822  hr = IStorage_CopyTo(file1, 1, &IID_IStorage, NULL, file2);
2823  ok(hr == S_OK, "CopyTo failed: 0x%08x\n", hr);
2824  if(FAILED(hr))
2825  goto cleanup;
2826 
2827  /* verify that file1 copied over, respecting exclusions */
2828  hr = IStorage_OpenStorage(file2, stgA_name, NULL,
2829  STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg_tmp);
2830  ok(hr == STG_E_FILENOTFOUND, "OpenStorage should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr);
2831  if(SUCCEEDED(hr))
2832  IStorage_Release(stg_tmp);
2833 
2834  hr = IStorage_OpenStream(file2, strmA_name, NULL,
2835  STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp);
2836  ok(hr == STG_E_FILENOTFOUND, "OpenStream should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr);
2837  if(SUCCEEDED(hr))
2838  IStream_Release(strm_tmp);
2839 
2840  hr = IStorage_OpenStorage(file2, stgB_name, NULL,
2841  STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg_tmp);
2842  ok(hr == STG_E_FILENOTFOUND, "OpenStorage should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr);
2843  if(SUCCEEDED(hr))
2844  IStorage_Release(stg_tmp);
2845 
2846  hr = IStorage_OpenStream(file2, strmB_name, NULL,
2847  STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp);
2848  ok(hr == STG_E_FILENOTFOUND, "OpenStream should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr);
2849  if(SUCCEEDED(hr))
2850  IStream_Release(strm_tmp);
2851 
2852  hr = IStorage_OpenStream(file2, strmC_name, NULL,
2853  STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp);
2854  ok(hr == S_OK, "OpenStream failed: 0x%08x\n", hr);
2855 
2856  if(SUCCEEDED(hr)){
2857  memset(buf, 0, sizeof(buf));
2858  hr = IStream_Read(strm_tmp, buf, sizeof(buf), NULL);
2859  ok(hr == S_OK, "Read failed: 0x%08x\n", hr);
2860  if(SUCCEEDED(hr))
2861  ok(strcmp_ww(buf, strmC_name) == 0,
2862  "Expected %s to be read, got %s\n", wine_dbgstr_w(strmC_name), wine_dbgstr_w(buf));
2863 
2864  IStream_Release(strm_tmp);
2865  }
2866 
2867 cleanup:
2868  if(file1)
2869  IStorage_Release(file1);
2870  if(file2)
2871  IStorage_Release(file2);
2872 
2875 }
2876 
2878 {
2879  IStorage *file1 = NULL, *file2 = NULL, *stg_tmp;
2880  IStream *strm_tmp;
2881  HRESULT hr;
2882 
2883  /* create & populate file1 */
2885  ok(hr == S_OK, "StgCreateDocfile failed: 0x%08x\n", hr);
2886  if(FAILED(hr))
2887  goto cleanup;
2888 
2889  hr = create_test_file(file1);
2890  if(FAILED(hr))
2891  goto cleanup;
2892 
2893  /* create file2 */
2895  ok(hr == S_OK, "StgCreateDocfile failed: 0x%08x\n", hr);
2896  if(FAILED(hr))
2897  goto cleanup;
2898 
2899  /* copy file1 to file2 with iid exclusions */
2900  hr = IStorage_CopyTo(file1, 1, &IID_IStream, NULL, file2);
2901  ok(hr == S_OK, "CopyTo failed: 0x%08x\n", hr);
2902  if(FAILED(hr))
2903  goto cleanup;
2904 
2905  /* verify that file1 copied over, respecting exclusions */
2906  hr = IStorage_OpenStorage(file2, stgA_name, NULL,
2907  STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg_tmp);
2908  ok(hr == S_OK, "OpenStorage failed: 0x%08x\n", hr);
2909 
2910  if(SUCCEEDED(hr)){
2911  hr = IStorage_OpenStream(stg_tmp, strmA_name, NULL,
2912  STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp);
2913  ok(hr == STG_E_FILENOTFOUND, "OpenStream should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr);
2914  if(SUCCEEDED(hr))
2915  IStream_Release(strm_tmp);
2916 
2917  IStorage_Release(stg_tmp);
2918  }
2919 
2920  hr = IStorage_OpenStorage(file2, stgB_name, NULL,
2921  STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg_tmp);
2922  ok(hr == S_OK, "OpenStorage failed: 0x%08x\n", hr);
2923 
2924  if(SUCCEEDED(hr)){
2925  hr = IStorage_OpenStream(stg_tmp, strmB_name, NULL,
2926  STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp);
2927  ok(hr == STG_E_FILENOTFOUND, "OpenStream should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr);
2928  if(SUCCEEDED(hr))
2929  IStream_Release(strm_tmp);
2930 
2931  IStorage_Release(stg_tmp);
2932  }
2933 
2934  hr = IStorage_OpenStream(file2, strmC_name, NULL,
2935  STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &strm_tmp);
2936  ok(hr == STG_E_FILENOTFOUND, "OpenStream should give STG_E_FILENOTFOUND, gave: 0x%08x\n", hr);
2937  if(SUCCEEDED(hr))
2938  IStream_Release(strm_tmp);
2939 
2940 cleanup:
2941  if(file1)
2942  IStorage_Release(file1);
2943  if(file2)
2944  IStorage_Release(file2);
2945 
2948 }
2949 
2950 static void test_rename(void)
2951 {
2952  IStorage *stg, *stg2;
2953  IStream *stm;
2954  HRESULT r;
2955  static const WCHAR stgname[] = { 'P','E','R','M','S','T','G',0 };
2956  static const WCHAR stgname2[] = { 'S','T','G',0 };
2957  static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 };
2958  static const WCHAR stmname2[] = { 'E','N','T','S',0 };
2959  BOOL ret;
2960 
2962 
2963  /* create the file */
2965  STGM_READWRITE, 0, &stg);
2966  ok(r==S_OK, "StgCreateDocfile failed\n");
2967 
2968  /* create a substorage */
2969  r = IStorage_CreateStorage(stg, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg2);
2970  ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
2971 
2972  /* create a stream in the substorage */
2973  r = IStorage_CreateStream(stg2, stmname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm);
2974  ok(r==S_OK, "IStorage->CreateStream failed, hr=%08x\n", r);
2975  IStream_Release(stm);
2976 
2977  /* rename the stream */
2978  r = IStorage_RenameElement(stg2, stmname, stmname2);
2979  ok(r==S_OK, "IStorage->RenameElement failed, hr=%08x\n", r);
2980 
2981  /* cannot open stream with old name */
2982  r = IStorage_OpenStream(stg2, stmname, NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &stm);
2983  ok(r==STG_E_FILENOTFOUND, "IStorage_OpenStream should fail, hr=%08x\n", r);
2984  if (SUCCEEDED(r)) IStream_Release(stm);
2985 
2986  /* can open stream with new name */
2987  r = IStorage_OpenStream(stg2, stmname2, NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &stm);
2988  ok(r==S_OK, "IStorage_OpenStream failed, hr=%08x\n", r);
2989  if (SUCCEEDED(r)) IStream_Release(stm);
2990 
2991  IStorage_Release(stg2);
2992 
2993  /* rename the storage */
2994  IStorage_RenameElement(stg, stgname, stgname2);
2995 
2996  /* cannot open storage with old name */
2997  r = IStorage_OpenStorage(stg, stgname, NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg2);
2998  ok(r==STG_E_FILENOTFOUND, "IStorage_OpenStream should fail, hr=%08x\n", r);
2999  if (SUCCEEDED(r)) IStorage_Release(stg2);
3000 
3001  /* can open storage with new name */
3002  r = IStorage_OpenStorage(stg, stgname2, NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &stg2);
3003  ok(r==S_OK, "IStorage_OpenStream should fail, hr=%08x\n", r);
3004  if (SUCCEEDED(r))
3005  {
3006  /* opened storage still has the stream */
3007  r = IStorage_OpenStream(stg2, stmname2, NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &stm);
3008  ok(r==S_OK, "IStorage_OpenStream failed, hr=%08x\n", r);
3009  if (SUCCEEDED(r)) IStream_Release(stm);
3010 
3011  IStorage_Release(stg2);
3012  }
3013 
3014  IStorage_Release(stg);
3015 
3017  ok(ret, "deleted file\n");
3018 }
3019 
3020 static void test_toplevel_stat(void)
3021 {
3022  IStorage *stg = NULL;
3023  HRESULT r;
3024  STATSTG stat;
3025  char prev_dir[MAX_PATH];
3026  char temp[MAX_PATH];
3027  char full_path[MAX_PATH];
3028  LPSTR rel_pathA;
3029  WCHAR rel_path[MAX_PATH];
3030 
3032 
3034  STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
3035  ok(r==S_OK, "StgCreateDocfile failed\n");
3036 
3037  r = IStorage_Stat( stg, &stat, STATFLAG_DEFAULT );
3038  ok(r==S_OK, "Storage_Stat failed with error 0x%08x\n", r);
3039  ok(!strcmp_ww(stat.pwcsName, filename), "expected %s, got %s\n",
3041  CoTaskMemFree(stat.pwcsName);
3042 
3043  IStorage_Release( stg );
3044 
3046  ok(r==S_OK, "StgOpenStorage failed with error 0x%08x\n", r);
3047 
3048  r = IStorage_Stat( stg, &stat, STATFLAG_DEFAULT );
3049  ok(r==S_OK, "Storage_Stat failed with error 0x%08x\n", r);
3050  ok(!strcmp_ww(stat.pwcsName, filename), "expected %s, got %s\n",
3052  CoTaskMemFree(stat.pwcsName);
3053 
3054  IStorage_Release( stg );
3055 
3057 
3058  /* Stat always returns the full path, even for files opened with a relative path. */
3059  GetCurrentDirectoryA(MAX_PATH, prev_dir);
3060 
3062 
3064 
3065  GetFullPathNameA(filenameA, MAX_PATH, full_path, &rel_pathA);
3066  MultiByteToWideChar(CP_ACP, 0, rel_pathA, -1, rel_path, MAX_PATH);
3067 
3069  STGM_READWRITE |STGM_TRANSACTED, 0, &stg);
3070  ok(r==S_OK, "StgCreateDocfile failed\n");
3071 
3072  r = IStorage_Stat( stg, &stat, STATFLAG_DEFAULT );
3073  ok(r==S_OK, "Storage_Stat failed with error 0x%08x\n", r);
3074  ok(!strcmp_ww(stat.pwcsName, filename), "expected %s, got %s\n",
3076  CoTaskMemFree(stat.pwcsName);
3077 
3078  IStorage_Release( stg );
3079 
3080  r = StgOpenStorage( rel_path, NULL, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, NULL, 0, &stg);
3081  ok(r==S_OK, "StgOpenStorage failed with error 0x%08x\n", r);
3082 
3083  r = IStorage_Stat( stg, &stat, STATFLAG_DEFAULT );
3084  ok(r==S_OK, "Storage_Stat failed with error 0x%08x\n", r);
3085  ok(!strcmp_ww(stat.pwcsName, filename), "expected %s, got %s\n",
3087  CoTaskMemFree(stat.pwcsName);
3088 
3089  IStorage_Release( stg );
3090 
3091  SetCurrentDirectoryA(prev_dir);
3092 
3094 }
3095 
3096 static void test_substorage_enum(void)
3097 {
3098  IStorage *stg, *stg2;
3099  IEnumSTATSTG *ee;
3100  HRESULT r;
3101  ULONG ref;
3102  static const WCHAR stgname[] = { 'P','E','R','M','S','T','G',0 };
3103  BOOL ret;
3104 
3106 
3107  /* create the file */
3109  STGM_READWRITE, 0, &stg);
3110  ok(r==S_OK, "StgCreateDocfile failed\n");
3111 
3112  /* create a substorage */
3113  r = IStorage_CreateStorage(stg, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg2);
3114  ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
3115 
3116  /* create an enumelements */
3117  r = IStorage_EnumElements(stg2, 0, NULL, 0, &ee);
3118  ok(r==S_OK, "IStorage->EnumElements failed, hr=%08x\n", r);
3119 
3120  /* release the substorage */
3121  ref = IStorage_Release(stg2);
3122  todo_wine ok(ref==0, "storage not released\n");
3123 
3124  /* reopening fails, because the substorage is really still open */
3125  r = IStorage_OpenStorage(stg, stgname, NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg2);
3126  ok(r==STG_E_ACCESSDENIED, "IStorage->OpenStorage failed, hr=%08x\n", r);
3127 
3128  /* destroying the storage invalidates the enumerator */
3129  r = IStorage_DestroyElement(stg, stgname);
3130  ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
3131 
3132  r = IEnumSTATSTG_Reset(ee);
3133  ok(r==STG_E_REVERTED, "IEnumSTATSTG->Reset failed, hr=%08x\n", r);
3134 
3135  IEnumSTATSTG_Release(ee);
3136 
3137  IStorage_Release(stg);
3138 
3140  ok(ret, "deleted file\n");
3141 }
3142 
3143 static void test_copyto_locking(void)
3144 {
3145  IStorage *stg, *stg2, *stg3, *stg4;
3146  IStream *stm;
3147  HRESULT r;
3148  static const WCHAR stgname[] = { 'S','T','G','1',0 };
3149  static const WCHAR stgname2[] = { 'S','T','G','2',0 };
3150  static const WCHAR stmname[] = { 'C','O','N','T','E','N','T','S',0 };
3151  BOOL ret;
3152 
3154 
3155  /* create the file */
3157  STGM_READWRITE, 0, &stg);
3158  ok(r==S_OK, "StgCreateDocfile failed\n");
3159 
3160  /* create a substorage */
3161  r = IStorage_CreateStorage(stg, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg2);
3162  ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
3163 
3164  /* create another substorage */
3165  r = IStorage_CreateStorage(stg, stgname2, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg3);
3166  ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
3167 
3168  /* add a stream, and leave it open */
3169  r = IStorage_CreateStream(stg2, stmname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm);
3170  ok(r==S_OK, "IStorage->CreateStream failed, hr=%08x\n", r);
3171 
3172  /* Try to copy the storage while the stream is open */
3173  r = IStorage_CopyTo(stg2, 0, NULL, NULL, stg3);
3174  ok(r==S_OK, "IStorage->CopyTo failed, hr=%08x\n", r);
3175 
3176  IStream_Release(stm);
3177 
3178  /* create a substorage */
3179  r = IStorage_CreateStorage(stg2, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg4);
3180  ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
3181 
3182  /* Try to copy the storage while the substorage is open */
3183  r = IStorage_CopyTo(stg2, 0, NULL, NULL, stg3);
3184  ok(r==S_OK, "IStorage->CopyTo failed, hr=%08x\n", r);
3185 
3186  IStorage_Release(stg4);
3187  IStorage_Release(stg3);
3188  IStorage_Release(stg2);
3189  IStorage_Release(stg);
3190 
3192  ok(ret, "deleted file\n");
3193 }
3194 
3195 static void test_copyto_recursive(void)
3196 {
3197  IStorage *stg, *stg2, *stg3, *stg4;
3198  HRESULT r;
3199  static const WCHAR stgname[] = { 'S','T','G','1',0 };
3200  static const WCHAR stgname2[] = { 'S','T','G','2',0 };
3201  BOOL ret;
3202 
3204 
3205  /* create the file */
3207  STGM_READWRITE, 0, &stg);
3208  ok(r==S_OK, "StgCreateDocfile failed\n");
3209 
3210  /* create a substorage */
3211  r = IStorage_CreateStorage(stg, stgname, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stg2);
3212  ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
3213 
3214  /* copy the parent to the child */
3215  r = IStorage_CopyTo(stg, 0, NULL, NULL, stg2);
3216  ok(r==STG_E_ACCESSDENIED, "IStorage->CopyTo failed, hr=%08x\n", r);
3217 
3218  /* create a transacted substorage */
3219  r = IStorage_CreateStorage(stg, stgname2, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_TRANSACTED, 0, 0, &stg3);
3220  ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
3221 
3222  /* copy the parent to the transacted child */
3223  r = IStorage_CopyTo(stg, 0, NULL, NULL, stg2);
3224  ok(r==STG_E_ACCESSDENIED, "IStorage->CopyTo failed, hr=%08x\n", r);
3225 
3226  /* create a transacted subsubstorage */
3227  r = IStorage_CreateStorage(stg3, stgname2, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_TRANSACTED, 0, 0, &stg4);
3228  ok(r==S_OK, "IStorage->CreateStorage failed, hr=%08x\n", r);
3229 
3230  /* copy the parent to the transacted child of the transacted child */
3231  r = IStorage_CopyTo(stg, 0, NULL, NULL, stg4);
3232  ok(r==STG_E_ACCESSDENIED, "IStorage->CopyTo failed, hr=%08x\n", r);
3233 
3234  /* copy the parent but exclude storage objects */
3235  r = IStorage_CopyTo(stg, 1, &IID_IStorage, NULL, stg4);
3236  ok(r==S_OK, "IStorage->CopyTo failed, hr=%08x\n", r);
3237 
3238  IStorage_Release(stg4);
3239  IStorage_Release(stg3);
3240  IStorage_Release(stg2);
3241  IStorage_Release(stg);
3242 
3244  ok(ret, "deleted file\n");
3245 }
3246 
3248 {
3249  ILockBytes *ilb = NULL;
3250  IStorage *stg = NULL;
3251  HRESULT r;
3252  STATSTG stat;
3253  char junk[512];
3255 
3257  ok(r == S_OK, "CreateILockBytesOnHGlobal failed, hr=%x\n", r);
3258 
3259  offset.QuadPart = 0;
3260  memset(junk, 0xaa, 512);
3261  r = ILockBytes_WriteAt(ilb, offset, junk, 512, NULL);
3262  ok(r == S_OK, "ILockBytes_WriteAt failed, hr=%x\n", r);
3263 
3264  offset.QuadPart = 2000;
3265  r = ILockBytes_WriteAt(ilb, offset, junk, 512, NULL);
3266  ok(r == S_OK, "ILockBytes_WriteAt failed, hr=%x\n", r);
3267 
3269  ok(r == S_OK, "StgCreateDocfileOnILockBytes failed, hr=%x\n", r);
3270 
3271  IStorage_Release(stg);
3272 
3274  NULL, 0, &stg);
3275  ok(r == S_OK, "StgOpenStorageOnILockBytes failed, hr=%x\n", r);
3276 
3277  if (SUCCEEDED(r))
3278  {
3279  r = IStorage_Stat(stg, &stat, STATFLAG_NONAME);
3280  ok(r == S_OK, "StgOpenStorageOnILockBytes failed, hr=%x\n", r);
3281  ok(IsEqualCLSID(&stat.clsid, &GUID_NULL), "unexpected CLSID value\n");
3282 
3283  IStorage_Release(stg);
3284  }
3285 
3286  r = ILockBytes_Stat(ilb, &stat, STATFLAG_NONAME);
3287  ok(r == S_OK, "ILockBytes_Stat failed, hr=%x\n", r);
3288  ok(stat.cbSize.u.LowPart < 2512, "expected truncated size, got %d\n", stat.cbSize.u.LowPart);
3289 
3290  ILockBytes_Release(ilb);
3291 }
3292 
3293 static void test_convert(void)
3294 {
3295  static const WCHAR filename[] = {'s','t','o','r','a','g','e','.','s','t','g',0};
3296  IStorage *stg;
3297  HRESULT hr;
3298 
3299  hr = GetConvertStg(NULL);
3300  ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
3301 
3303  ok(hr == S_OK, "StgCreateDocfile failed\n");
3304  hr = GetConvertStg(stg);
3305  ok(hr == STG_E_FILENOTFOUND, "got 0x%08x\n", hr);
3306  hr = SetConvertStg(stg, TRUE);
3307  ok(hr == S_OK, "got 0x%08x\n", hr);
3308  hr = SetConvertStg(stg, TRUE);
3309  ok(hr == S_OK, "got 0x%08x\n", hr);
3310  hr = GetConvertStg(stg);
3311  ok(hr == S_OK, "got 0x%08x\n", hr);
3312  hr = SetConvertStg(stg, FALSE);
3313  ok(hr == S_OK, "got 0x%08x\n", hr);
3314  hr = GetConvertStg(stg);
3315  ok(hr == S_FALSE, "got 0x%08x\n", hr);
3316 
3317  IStorage_Release(stg);
3318 
3320 }
3321 
3322 static void test_direct_swmr(void)
3323 {
3324  static const WCHAR fileW[] = {'w','i','n','e','t','e','s','t',0};
3325  IDirectWriterLock *dwlock;
3326  ULONG ref, ref2;
3327  IStorage *stg;
3328  HRESULT hr;
3329 
3330  /* it's possible to create in writer mode */
3332 todo_wine
3333  ok(hr == S_OK, "got %08x\n", hr);
3334 if (hr == S_OK) {
3335  IStorage_Release(stg);
3336  DeleteFileW(fileW);
3337 }
3338 
3340  ok(hr == S_OK, "got %08x\n", hr);
3341  IStorage_Release(stg);
3342 
3343  /* reader mode */
3345  ok(hr == S_OK || broken(hr == STG_E_INVALIDFLAG), "got %08x\n", hr);
3346  if(hr == S_OK)
3347  {
3348  hr = IStorage_QueryInterface(stg, &IID_IDirectWriterLock, (void**)&dwlock);
3349  ok(hr == E_NOINTERFACE, "got %08x\n", hr);
3350  IStorage_Release(stg);
3351  }
3352 
3353  /* writer mode */
3355  ok(hr == S_OK, "got %08x\n", hr);
3356  if(hr == S_OK)
3357  {
3358  ref = IStorage_AddRef(stg);
3359  IStorage_Release(stg);
3360 
3361  hr = IStorage_QueryInterface(stg, &IID_IDirectWriterLock, (void**)&dwlock);
3362  ok(hr == S_OK, "got %08x\n", hr);
3363 
3364  ref2 = IStorage_AddRef(stg);
3365  IStorage_Release(stg);
3366  ok(ref2 == ref + 1, "got %u\n", ref2);
3367 
3368  IDirectWriterLock_Release(dwlock);
3369  IStorage_Release(stg);
3370  }
3371 
3372  DeleteFileW(fileW);
3373 }
3374 
3376 {
3381  const int *locked_bytes;
3382  const int *fail_ranges;
3384 };
3385 
3386 static const int priority_locked_bytes[] = { 0x158, 0x181, 0x193, -1 };
3387 static const int rwex_locked_bytes[] = { 0x193, 0x1a7, 0x1bb, 0x1cf, -1 };
3388 static const int rw_locked_bytes[] = { 0x193, 0x1a7, -1 };
3389 static const int nosn_locked_bytes[] = { 0x16c, 0x193, 0x1a7, 0x1cf, -1 };
3390 static const int rwdw_locked_bytes[] = { 0x193, 0x1a7, 0x1cf, -1 };
3391 static const int wodw_locked_bytes[] = { 0x1a7, 0x1cf, -1 };
3392 static const int tr_locked_bytes[] = { 0x193, -1 };
3393 static const int no_locked_bytes[] = { -1 };
3394 static const int roex_locked_bytes[] = { 0x193, 0x1bb, 0x1cf, -1 };
3395 
3396 static const int rwex_fail_ranges[] = { 0x193,0x1e3, -1 };
3397 static const int rw_fail_ranges[] = { 0x1bb,0x1e3, -1 };
3398 static const int rwdw_fail_ranges[] = { 0x1a7,0x1e3, -1 };
3399 static const int dw_fail_ranges[] = { 0x1a7,0x1cf, -1 };
3400 static const int tr_fail_ranges[] = { 0x1bb,0x1cf, -1 };
3401 static const int pr_fail_ranges[] = { 0x180,0x181, 0x1bb,0x1cf, -1 };
3402 static const int roex_fail_ranges[] = { 0x0,-1 };
3403 
3404 static const struct lock_test lock_tests[] = {
3420 };
3421 
3423 {
3424  HANDLE hfile;
3425 
3426  hfile =