3 * Implemented using the documentation of the LAOLA project at
4 * <URL:http://wwwwbs.cs.tu-berlin.de/~schwartz/pmh/index.html>
5 * (Thanks to Martin Schwartz <schwartz@cs.tu-berlin.de>)
7 * Copyright 1998 Marcus Meissner
19 #include "interfaces.h"
26 static const BYTE STORAGE_magic
[8] ={0xd0,0xcf,0x11,0xe0,0xa1,0xb1,0x1a,0xe1};
27 static const BYTE STORAGE_notmagic
[8]={0x0e,0x11,0xfc,0x0d,0xd0,0xcf,0x11,0xe0};
28 static const BYTE STORAGE_oldmagic
[8]={0xd0,0xcf,0x11,0xe0,0x0e,0x11,0xfc,0x0d};
33 #define SMALLBLOCKS_PER_BIGBLOCK (BIGSIZE/SMALLSIZE)
35 #define READ_HEADER assert(STORAGE_get_big_block(hf,-1,(LPBYTE)&sth));assert(!memcmp(STORAGE_magic,sth.magic,sizeof(STORAGE_magic)));
36 static IStorage16_VTable stvt16
;
37 static IStorage16_VTable
*segstvt16
= NULL
;
38 static IStorage32_VTable stvt32
;
39 static IStream16_VTable strvt16
;
40 static IStream16_VTable
*segstrvt16
= NULL
;
41 static IStream32_VTable strvt32
;
43 ULONG WINAPI
IStorage16_AddRef(LPSTORAGE16
this);
44 static void _create_istorage16(LPSTORAGE16
*stg
);
45 static void _create_istream16(LPSTREAM16
*str
);
49 /******************************************************************************
50 * STORAGE_get_big_block [Internal]
52 * Reading OLE compound storage
55 STORAGE_get_big_block(HFILE32 hf
,int n
,BYTE
*block
) {
57 if (-1==_llseek32(hf
,(n
+1)*BIGSIZE
,SEEK_SET
)) {
58 WARN(ole
," seek failed (%ld)\n",GetLastError());
61 assert((n
+1)*BIGSIZE
==_llseek32(hf
,0,SEEK_CUR
));
62 if (BIGSIZE
!=_lread32(hf
,block
,BIGSIZE
)) {
63 WARN(ole
,"(block size %d): read didn't read (%ld)\n",n
,GetLastError());
71 STORAGE_put_big_block(HFILE32 hf
,int n
,BYTE
*block
) {
73 if (-1==_llseek32(hf
,(n
+1)*BIGSIZE
,SEEK_SET
)) {
74 WARN(ole
," seek failed (%ld)\n",GetLastError());
77 assert((n
+1)*BIGSIZE
==_llseek32(hf
,0,SEEK_CUR
));
78 if (BIGSIZE
!=_lwrite32(hf
,block
,BIGSIZE
)) {
79 WARN(ole
," write failed (%ld)\n",GetLastError());
86 STORAGE_get_next_big_blocknr(HFILE32 hf
,int blocknr
) {
87 INT32 bbs
[BIGSIZE
/sizeof(INT32
)];
88 struct storage_header sth
;
92 assert(blocknr
>>7<sth
.num_of_bbd_blocks
);
93 if (sth
.bbd_list
[blocknr
>>7]==0xffffffff)
95 if (!STORAGE_get_big_block(hf
,sth
.bbd_list
[blocknr
>>7],(LPBYTE
)bbs
))
97 assert(bbs
[blocknr
&0x7f]!=STORAGE_CHAINENTRY_FREE
);
98 return bbs
[blocknr
&0x7f];
102 STORAGE_get_nth_next_big_blocknr(HFILE32 hf
,int blocknr
,int nr
) {
103 INT32 bbs
[BIGSIZE
/sizeof(INT32
)];
105 struct storage_header sth
;
111 assert((blocknr
>>7)<sth
.num_of_bbd_blocks
);
112 assert(sth
.bbd_list
[blocknr
>>7]!=0xffffffff);
114 /* simple caching... */
115 if (lastblock
!=sth
.bbd_list
[blocknr
>>7]) {
116 assert(STORAGE_get_big_block(hf
,sth
.bbd_list
[blocknr
>>7],(LPBYTE
)bbs
));
117 lastblock
= sth
.bbd_list
[blocknr
>>7];
119 blocknr
= bbs
[blocknr
&0x7f];
124 /******************************************************************************
125 * STORAGE_get_root_pps_entry [Internal]
128 STORAGE_get_root_pps_entry(HFILE32 hf
,struct storage_pps_entry
*pstde
) {
131 struct storage_pps_entry
*stde
=(struct storage_pps_entry
*)block
;
132 struct storage_header sth
;
135 blocknr
= sth
.root_startblock
;
137 assert(STORAGE_get_big_block(hf
,blocknr
,block
));
139 if (!stde
[i
].pps_sizeofname
)
141 if (stde
[i
].pps_type
==5) {
146 blocknr
=STORAGE_get_next_big_blocknr(hf
,blocknr
);
152 STORAGE_get_small_block(HFILE32 hf
,int blocknr
,BYTE
*sblock
) {
155 struct storage_pps_entry root
;
158 assert(STORAGE_get_root_pps_entry(hf
,&root
));
159 bigblocknr
= STORAGE_get_nth_next_big_blocknr(hf
,root
.pps_sb
,blocknr
/SMALLBLOCKS_PER_BIGBLOCK
);
160 assert(bigblocknr
>=0);
161 assert(STORAGE_get_big_block(hf
,bigblocknr
,block
));
163 memcpy(sblock
,((LPBYTE
)block
)+SMALLSIZE
*(blocknr
&(SMALLBLOCKS_PER_BIGBLOCK
-1)),SMALLSIZE
);
168 STORAGE_put_small_block(HFILE32 hf
,int blocknr
,BYTE
*sblock
) {
171 struct storage_pps_entry root
;
175 assert(STORAGE_get_root_pps_entry(hf
,&root
));
176 bigblocknr
= STORAGE_get_nth_next_big_blocknr(hf
,root
.pps_sb
,blocknr
/SMALLBLOCKS_PER_BIGBLOCK
);
177 assert(bigblocknr
>=0);
178 assert(STORAGE_get_big_block(hf
,bigblocknr
,block
));
180 memcpy(((LPBYTE
)block
)+SMALLSIZE
*(blocknr
&(SMALLBLOCKS_PER_BIGBLOCK
-1)),sblock
,SMALLSIZE
);
181 assert(STORAGE_put_big_block(hf
,bigblocknr
,block
));
187 STORAGE_get_next_small_blocknr(HFILE32 hf
,int blocknr
) {
189 LPINT32 sbd
= (LPINT32
)block
;
191 struct storage_header sth
;
195 bigblocknr
= STORAGE_get_nth_next_big_blocknr(hf
,sth
.sbd_startblock
,blocknr
/128);
196 assert(bigblocknr
>=0);
197 assert(STORAGE_get_big_block(hf
,bigblocknr
,block
));
198 assert(sbd
[blocknr
& 127]!=STORAGE_CHAINENTRY_FREE
);
199 return sbd
[blocknr
& (128-1)];
203 STORAGE_get_nth_next_small_blocknr(HFILE32 hf
,int blocknr
,int nr
) {
206 LPINT32 sbd
= (LPINT32
)block
;
207 struct storage_header sth
;
212 while ((nr
--) && (blocknr
>=0)) {
213 if (lastblocknr
/128!=blocknr
/128) {
215 bigblocknr
= STORAGE_get_nth_next_big_blocknr(hf
,sth
.sbd_startblock
,blocknr
/128);
216 assert(bigblocknr
>=0);
217 assert(STORAGE_get_big_block(hf
,bigblocknr
,block
));
218 lastblocknr
= blocknr
;
220 assert(lastblocknr
>=0);
222 blocknr
=sbd
[blocknr
& (128-1)];
223 assert(blocknr
!=STORAGE_CHAINENTRY_FREE
);
229 STORAGE_get_pps_entry(HFILE32 hf
,int n
,struct storage_pps_entry
*pstde
) {
232 struct storage_pps_entry
*stde
= (struct storage_pps_entry
*)(((LPBYTE
)block
)+128*(n
&3));
233 struct storage_header sth
;
236 /* we have 4 pps entries per big block */
237 blocknr
= STORAGE_get_nth_next_big_blocknr(hf
,sth
.root_startblock
,n
/4);
239 assert(STORAGE_get_big_block(hf
,blocknr
,block
));
245 /******************************************************************************
246 * STORAGE_put_pps_entry [Internal]
249 STORAGE_put_pps_entry(HFILE32 hf
,int n
,struct storage_pps_entry
*pstde
) {
252 struct storage_pps_entry
*stde
= (struct storage_pps_entry
*)(((LPBYTE
)block
)+128*(n
&3));
253 struct storage_header sth
;
257 /* we have 4 pps entries per big block */
258 blocknr
= STORAGE_get_nth_next_big_blocknr(hf
,sth
.root_startblock
,n
/4);
260 assert(STORAGE_get_big_block(hf
,blocknr
,block
));
262 assert(STORAGE_put_big_block(hf
,blocknr
,block
));
266 /******************************************************************************
267 * STORAGE_look_for_named_pps [Internal]
270 STORAGE_look_for_named_pps(HFILE32 hf
,int n
,LPOLESTR32 name
) {
271 struct storage_pps_entry stde
;
276 if (1!=STORAGE_get_pps_entry(hf
,n
,&stde
))
279 if (!lstrcmp32W(name
,stde
.pps_rawname
))
281 if (stde
.pps_prev
!= -1) {
282 ret
=STORAGE_look_for_named_pps(hf
,stde
.pps_prev
,name
);
286 if (stde
.pps_next
!= -1) {
287 ret
=STORAGE_look_for_named_pps(hf
,stde
.pps_next
,name
);
294 /******************************************************************************
295 * STORAGE_dump_pps_entry [Internal]
301 STORAGE_dump_pps_entry(struct storage_pps_entry
*stde
) {
302 char name
[33],xguid
[50];
304 WINE_StringFromCLSID(&(stde
->pps_guid
),xguid
);
306 lstrcpyWtoA(name
,stde
->pps_rawname
);
307 if (!stde
->pps_sizeofname
)
309 DUMP("name: %s\n",name
);
310 DUMP("type: %d\n",stde
->pps_type
);
311 DUMP("prev pps: %ld\n",stde
->pps_prev
);
312 DUMP("next pps: %ld\n",stde
->pps_next
);
313 DUMP("dir pps: %ld\n",stde
->pps_dir
);
314 DUMP("guid: %s\n",xguid
);
315 if (stde
->pps_type
!=2) {
318 t
= DOSFS_FileTimeToUnixTime(&(stde
->pps_ft1
),NULL
);
319 DUMP("ts1: %s\n",ctime(&t
));
320 t
= DOSFS_FileTimeToUnixTime(&(stde
->pps_ft2
),NULL
);
321 DUMP("ts2: %s\n",ctime(&t
));
323 DUMP("startblock: %ld\n",stde
->pps_sb
);
324 DUMP("size: %ld\n",stde
->pps_size
);
328 STORAGE_init_storage(HFILE32 hf
) {
331 struct storage_header
*sth
;
332 struct storage_pps_entry
*stde
;
334 assert(-1!=_llseek32(hf
,0,SEEK_SET
));
335 /* block -1 is the storage header */
336 sth
= (struct storage_header
*)block
;
337 memcpy(sth
->magic
,STORAGE_magic
,8);
338 memset(sth
->unknown1
,0,sizeof(sth
->unknown1
));
339 memset(sth
->unknown2
,0,sizeof(sth
->unknown2
));
340 memset(sth
->unknown3
,0,sizeof(sth
->unknown3
));
341 sth
->num_of_bbd_blocks
= 1;
342 sth
->root_startblock
= 1;
343 sth
->sbd_startblock
= 0xffffffff;
344 memset(sth
->bbd_list
,0xff,sizeof(sth
->bbd_list
));
345 sth
->bbd_list
[0] = 0;
346 assert(BIGSIZE
==_lwrite32(hf
,block
,BIGSIZE
));
347 /* block 0 is the big block directory */
349 memset(block
,0xff,sizeof(block
)); /* mark all blocks as free */
350 bbs
[0]=STORAGE_CHAINENTRY_ENDOFCHAIN
; /* for this block */
351 bbs
[1]=STORAGE_CHAINENTRY_ENDOFCHAIN
; /* for directory entry */
352 assert(BIGSIZE
==_lwrite32(hf
,block
,BIGSIZE
));
353 /* block 1 is the root directory entry */
354 memset(block
,0x00,sizeof(block
));
355 stde
= (struct storage_pps_entry
*)block
;
356 lstrcpyAtoW(stde
->pps_rawname
,"RootEntry");
357 stde
->pps_sizeofname
= lstrlen32W(stde
->pps_rawname
)*2+2;
362 stde
->pps_sb
= 0xffffffff;
364 assert(BIGSIZE
==_lwrite32(hf
,block
,BIGSIZE
));
368 /******************************************************************************
369 * STORAGE_set_big_chain [Internal]
372 STORAGE_set_big_chain(HFILE32 hf
,int blocknr
,INT32 type
) {
374 LPINT32 bbd
= (LPINT32
)block
;
375 int nextblocknr
,bigblocknr
;
376 struct storage_header sth
;
379 assert(blocknr
!=type
);
381 bigblocknr
= sth
.bbd_list
[blocknr
/128];
382 assert(bigblocknr
>=0);
383 assert(STORAGE_get_big_block(hf
,bigblocknr
,block
));
385 nextblocknr
= bbd
[blocknr
&(128-1)];
386 bbd
[blocknr
&(128-1)] = type
;
389 assert(STORAGE_put_big_block(hf
,bigblocknr
,block
));
390 type
= STORAGE_CHAINENTRY_FREE
;
391 blocknr
= nextblocknr
;
397 STORAGE_set_small_chain(HFILE32 hf
,int blocknr
,INT32 type
) {
399 LPINT32 sbd
= (LPINT32
)block
;
400 int lastblocknr
,nextsmallblocknr
,bigblocknr
;
401 struct storage_header sth
;
405 assert(blocknr
!=type
);
406 lastblocknr
=-129;bigblocknr
=-2;
408 /* cache block ... */
409 if (lastblocknr
/128!=blocknr
/128) {
410 bigblocknr
= STORAGE_get_nth_next_big_blocknr(hf
,sth
.sbd_startblock
,blocknr
/128);
411 assert(bigblocknr
>=0);
412 assert(STORAGE_get_big_block(hf
,bigblocknr
,block
));
414 lastblocknr
= blocknr
;
415 nextsmallblocknr
= sbd
[blocknr
&(128-1)];
416 sbd
[blocknr
&(128-1)] = type
;
417 assert(STORAGE_put_big_block(hf
,bigblocknr
,block
));
420 type
= STORAGE_CHAINENTRY_FREE
;
421 blocknr
= nextsmallblocknr
;
426 /******************************************************************************
427 * STORAGE_get_free_big_blocknr [Internal]
430 STORAGE_get_free_big_blocknr(HFILE32 hf
) {
432 LPINT32 sbd
= (LPINT32
)block
;
433 int lastbigblocknr
,i
,curblock
,bigblocknr
;
434 struct storage_header sth
;
439 bigblocknr
= sth
.bbd_list
[curblock
];
440 while (curblock
<sth
.num_of_bbd_blocks
) {
441 assert(bigblocknr
>=0);
442 assert(STORAGE_get_big_block(hf
,bigblocknr
,block
));
444 if (sbd
[i
]==STORAGE_CHAINENTRY_FREE
) {
445 sbd
[i
] = STORAGE_CHAINENTRY_ENDOFCHAIN
;
446 assert(STORAGE_put_big_block(hf
,bigblocknr
,block
));
447 memset(block
,0x42,sizeof(block
));
448 assert(STORAGE_put_big_block(hf
,i
+curblock
*128,block
));
449 return i
+curblock
*128;
451 lastbigblocknr
= bigblocknr
;
452 bigblocknr
= sth
.bbd_list
[++curblock
];
454 bigblocknr
= curblock
*128;
455 /* since we have marked all blocks from 0 up to curblock*128-1
456 * the next free one is curblock*128, where we happily put our
457 * next large block depot.
459 memset(block
,0xff,sizeof(block
));
460 /* mark the block allocated and returned by this function */
461 sbd
[1] = STORAGE_CHAINENTRY_ENDOFCHAIN
;
462 assert(STORAGE_put_big_block(hf
,bigblocknr
,block
));
464 /* if we had a bbd block already (mostlikely) we need
465 * to link the new one into the chain
467 if (lastbigblocknr
!=-1)
468 assert(STORAGE_set_big_chain(hf
,lastbigblocknr
,bigblocknr
));
469 sth
.bbd_list
[curblock
]=bigblocknr
;
470 sth
.num_of_bbd_blocks
++;
471 assert(sth
.num_of_bbd_blocks
==curblock
+1);
472 assert(STORAGE_put_big_block(hf
,-1,(LPBYTE
)&sth
));
474 /* Set the end of the chain for the bigblockdepots */
475 assert(STORAGE_set_big_chain(hf
,bigblocknr
,STORAGE_CHAINENTRY_ENDOFCHAIN
));
476 /* add 1, for the first entry is used for the additional big block
477 * depot. (means we already used bigblocknr) */
478 memset(block
,0x42,sizeof(block
));
479 /* allocate this block (filled with 0x42) */
480 assert(STORAGE_put_big_block(hf
,bigblocknr
+1,block
));
485 /******************************************************************************
486 * STORAGE_get_free_small_blocknr [Internal]
489 STORAGE_get_free_small_blocknr(HFILE32 hf
) {
491 LPINT32 sbd
= (LPINT32
)block
;
492 int lastbigblocknr
,newblocknr
,i
,curblock
,bigblocknr
;
493 struct storage_pps_entry root
;
494 struct storage_header sth
;
497 bigblocknr
= sth
.sbd_startblock
;
501 while (bigblocknr
>=0) {
502 if (!STORAGE_get_big_block(hf
,bigblocknr
,block
))
505 if (sbd
[i
]==STORAGE_CHAINENTRY_FREE
) {
506 sbd
[i
]=STORAGE_CHAINENTRY_ENDOFCHAIN
;
507 newblocknr
= i
+curblock
*128;
512 lastbigblocknr
= bigblocknr
;
513 bigblocknr
= STORAGE_get_next_big_blocknr(hf
,bigblocknr
);
516 if (newblocknr
==-1) {
517 bigblocknr
= STORAGE_get_free_big_blocknr(hf
);
521 memset(block
,0xff,sizeof(block
));
522 sbd
[0]=STORAGE_CHAINENTRY_ENDOFCHAIN
;
523 if (!STORAGE_put_big_block(hf
,bigblocknr
,block
))
525 if (lastbigblocknr
==-1) {
526 sth
.sbd_startblock
= bigblocknr
;
527 if (!STORAGE_put_big_block(hf
,-1,(LPBYTE
)&sth
)) /* need to write it */
530 if (!STORAGE_set_big_chain(hf
,lastbigblocknr
,bigblocknr
))
533 if (!STORAGE_set_big_chain(hf
,bigblocknr
,STORAGE_CHAINENTRY_ENDOFCHAIN
))
535 newblocknr
= curblock
*128;
537 /* allocate enough big blocks for storing the allocated small block */
538 if (!STORAGE_get_root_pps_entry(hf
,&root
))
543 lastbigblocknr
= STORAGE_get_nth_next_big_blocknr(hf
,root
.pps_sb
,(root
.pps_size
-1)/BIGSIZE
);
544 while (root
.pps_size
< (newblocknr
*SMALLSIZE
+SMALLSIZE
-1)) {
545 /* we need to allocate more stuff */
546 bigblocknr
= STORAGE_get_free_big_blocknr(hf
);
550 if (root
.pps_sb
==-1) {
551 root
.pps_sb
= bigblocknr
;
552 root
.pps_size
+= BIGSIZE
;
554 if (!STORAGE_set_big_chain(hf
,lastbigblocknr
,bigblocknr
))
556 root
.pps_size
+= BIGSIZE
;
558 lastbigblocknr
= bigblocknr
;
560 if (!STORAGE_set_big_chain(hf
,lastbigblocknr
,STORAGE_CHAINENTRY_ENDOFCHAIN
))
562 if (!STORAGE_put_pps_entry(hf
,0,&root
))
567 /******************************************************************************
568 * STORAGE_get_free_pps_entry [Internal]
571 STORAGE_get_free_pps_entry(HFILE32 hf
) {
572 int blocknr
,i
,curblock
,lastblocknr
;
574 struct storage_pps_entry
*stde
= (struct storage_pps_entry
*)block
;
575 struct storage_header sth
;
578 blocknr
= sth
.root_startblock
;
582 if (!STORAGE_get_big_block(hf
,blocknr
,block
))
585 if (stde
[i
].pps_sizeofname
==0) /* free */
587 lastblocknr
= blocknr
;
588 blocknr
= STORAGE_get_next_big_blocknr(hf
,blocknr
);
591 assert(blocknr
==STORAGE_CHAINENTRY_ENDOFCHAIN
);
592 blocknr
= STORAGE_get_free_big_blocknr(hf
);
593 /* sth invalidated */
597 if (!STORAGE_set_big_chain(hf
,lastblocknr
,blocknr
))
599 if (!STORAGE_set_big_chain(hf
,blocknr
,STORAGE_CHAINENTRY_ENDOFCHAIN
))
601 memset(block
,0,sizeof(block
));
602 STORAGE_put_big_block(hf
,blocknr
,block
);
606 /******************************************************************************
607 * IStream16_QueryInterface [STORAGE.518]
609 HRESULT WINAPI
IStream16_QueryInterface(
610 LPSTREAM16
this,REFIID refiid
,LPVOID
*obj
614 WINE_StringFromCLSID((LPCLSID
)refiid
,xrefiid
);
615 TRACE(relay
,"(%p)->(%s,%p)\n",this,xrefiid
,obj
);
616 if (!memcmp(&IID_IUnknown
,refiid
,sizeof(IID_IUnknown
))) {
620 return OLE_E_ENUM_NOMORE
;
624 ULONG WINAPI
IStream16_AddRef(LPSTREAM16
this) {
625 return ++(this->ref
);
628 ULONG WINAPI
IStream16_Release(LPSTREAM16
this) {
629 FlushFileBuffers(this->hf
);
632 CloseHandle(this->hf
);
639 /******************************************************************************
640 * IStream16_Seek [STORAGE.523]
643 * Does not handle 64 bits
645 HRESULT WINAPI
IStream16_Seek(
646 LPSTREAM16
this,LARGE_INTEGER offset
,DWORD whence
,ULARGE_INTEGER
*newpos
648 TRACE(relay
,"(%p)->([%ld.%ld],%ld,%p)\n",this,offset
.HighPart
,offset
.LowPart
,whence
,newpos
);
651 /* unix SEEK_xx should be the same as win95 ones */
653 /* offset must be ==0 (<0 is invalid, and >0 cannot be handled
656 assert(offset
.HighPart
==0);
657 this->offset
.HighPart
= offset
.HighPart
;
658 this->offset
.LowPart
= offset
.LowPart
;
661 if (offset
.HighPart
< 0) {
662 /* FIXME: is this negation correct ? */
663 offset
.HighPart
= -offset
.HighPart
;
664 offset
.LowPart
= (0xffffffff ^ offset
.LowPart
)+1;
666 assert(offset
.HighPart
==0);
667 assert(this->offset
.LowPart
>= offset
.LowPart
);
668 this->offset
.LowPart
-= offset
.LowPart
;
670 assert(offset
.HighPart
==0);
671 this->offset
.LowPart
+= offset
.LowPart
;
675 assert(offset
.HighPart
==0);
676 this->offset
.LowPart
= this->stde
.pps_size
-offset
.LowPart
;
679 if (this->offset
.LowPart
>this->stde
.pps_size
)
680 this->offset
.LowPart
=this->stde
.pps_size
;
681 if (newpos
) *newpos
= this->offset
;
685 /******************************************************************************
686 * IStream16_Read [STORAGE.521]
688 HRESULT WINAPI
IStream16_Read(
689 LPSTREAM16
this,void *pv
,ULONG cb
,ULONG
*pcbRead
692 ULONG
*bytesread
=pcbRead
,xxread
;
695 TRACE(relay
,"(%p)->(%p,%ld,%p)\n",this,pv
,cb
,pcbRead
);
696 if (!pcbRead
) bytesread
=&xxread
;
699 if (cb
>this->stde
.pps_size
-this->offset
.LowPart
)
700 cb
=this->stde
.pps_size
-this->offset
.LowPart
;
701 if (this->stde
.pps_size
< 0x1000) {
702 /* use small block reader */
703 blocknr
= STORAGE_get_nth_next_small_blocknr(this->hf
,this->stde
.pps_sb
,this->offset
.LowPart
/SMALLSIZE
);
707 if (!STORAGE_get_small_block(this->hf
,blocknr
,block
)) {
708 WARN(ole
,"small block read failed!!!\n");
712 if (cc
>SMALLSIZE
-(this->offset
.LowPart
&(SMALLSIZE
-1)))
713 cc
=SMALLSIZE
-(this->offset
.LowPart
&(SMALLSIZE
-1));
714 memcpy((LPBYTE
)pv
,block
+(this->offset
.LowPart
&(SMALLSIZE
-1)),cc
);
715 this->offset
.LowPart
+=cc
;
719 blocknr
= STORAGE_get_next_small_blocknr(this->hf
,blocknr
);
722 /* use big block reader */
723 blocknr
= STORAGE_get_nth_next_big_blocknr(this->hf
,this->stde
.pps_sb
,this->offset
.LowPart
/BIGSIZE
);
727 if (!STORAGE_get_big_block(this->hf
,blocknr
,block
)) {
728 WARN(ole
,"big block read failed!!!\n");
732 if (cc
>BIGSIZE
-(this->offset
.LowPart
&(BIGSIZE
-1)))
733 cc
=BIGSIZE
-(this->offset
.LowPart
&(BIGSIZE
-1));
734 memcpy((LPBYTE
)pv
,block
+(this->offset
.LowPart
&(BIGSIZE
-1)),cc
);
735 this->offset
.LowPart
+=cc
;
739 blocknr
=STORAGE_get_next_big_blocknr(this->hf
,blocknr
);
745 /******************************************************************************
746 * IStream16_Write [STORAGE.522]
748 HRESULT WINAPI
IStream16_Write(
749 LPSTREAM16
this,const void *pv
,ULONG cb
,ULONG
*pcbWrite
752 ULONG
*byteswritten
=pcbWrite
,xxwritten
;
753 int oldsize
,newsize
,i
,curoffset
=0,lastblocknr
,blocknr
,cc
;
754 HFILE32 hf
= this->hf
;
756 if (!pcbWrite
) byteswritten
=&xxwritten
;
759 TRACE(relay
,"(%p)->(%p,%ld,%p)\n",this,pv
,cb
,pcbWrite
);
760 /* do we need to junk some blocks? */
761 newsize
= this->offset
.LowPart
+cb
;
762 oldsize
= this->stde
.pps_size
;
763 if (newsize
< oldsize
) {
764 if (oldsize
< 0x1000) {
765 /* only small blocks */
766 blocknr
=STORAGE_get_nth_next_small_blocknr(hf
,this->stde
.pps_sb
,newsize
/SMALLSIZE
);
770 /* will set the rest of the chain to 'free' */
771 if (!STORAGE_set_small_chain(hf
,blocknr
,STORAGE_CHAINENTRY_ENDOFCHAIN
))
774 if (newsize
>= 0x1000) {
775 blocknr
=STORAGE_get_nth_next_big_blocknr(hf
,this->stde
.pps_sb
,newsize
/BIGSIZE
);
778 /* will set the rest of the chain to 'free' */
779 if (!STORAGE_set_big_chain(hf
,blocknr
,STORAGE_CHAINENTRY_ENDOFCHAIN
))
782 /* Migrate large blocks to small blocks
783 * (we just migrate newsize bytes)
785 LPBYTE curdata
,data
= HeapAlloc(GetProcessHeap(),0,newsize
+BIGSIZE
);
787 blocknr
= this->stde
.pps_sb
;
790 if (!STORAGE_get_big_block(hf
,blocknr
,curdata
)) {
791 HeapFree(GetProcessHeap(),0,data
);
796 blocknr
= STORAGE_get_next_big_blocknr(hf
,blocknr
);
798 /* frees complete chain for this stream */
799 if (!STORAGE_set_big_chain(hf
,this->stde
.pps_sb
,STORAGE_CHAINENTRY_FREE
))
802 blocknr
= this->stde
.pps_sb
= STORAGE_get_free_small_blocknr(hf
);
807 if (!STORAGE_put_small_block(hf
,blocknr
,curdata
))
811 if (!STORAGE_set_small_chain(hf
,blocknr
,STORAGE_CHAINENTRY_ENDOFCHAIN
))
815 int newblocknr
= STORAGE_get_free_small_blocknr(hf
);
818 if (!STORAGE_set_small_chain(hf
,blocknr
,newblocknr
))
820 blocknr
= newblocknr
;
822 curdata
+= SMALLSIZE
;
824 HeapFree(GetProcessHeap(),0,data
);
827 this->stde
.pps_size
= newsize
;
830 if (newsize
> oldsize
) {
831 if (oldsize
>= 0x1000) {
832 /* should return the block right before the 'endofchain' */
833 blocknr
= STORAGE_get_nth_next_big_blocknr(hf
,this->stde
.pps_sb
,this->stde
.pps_size
/BIGSIZE
);
835 lastblocknr
= blocknr
;
836 for (i
=oldsize
/BIGSIZE
;i
<newsize
/BIGSIZE
;i
++) {
837 blocknr
= STORAGE_get_free_big_blocknr(hf
);
840 if (!STORAGE_set_big_chain(hf
,lastblocknr
,blocknr
))
842 lastblocknr
= blocknr
;
844 if (!STORAGE_set_big_chain(hf
,blocknr
,STORAGE_CHAINENTRY_ENDOFCHAIN
))
847 if (newsize
< 0x1000) {
848 /* find startblock */
850 this->stde
.pps_sb
= blocknr
= STORAGE_get_free_small_blocknr(hf
);
852 blocknr
= STORAGE_get_nth_next_small_blocknr(hf
,this->stde
.pps_sb
,this->stde
.pps_size
/SMALLSIZE
);
856 /* allocate required new small blocks */
857 lastblocknr
= blocknr
;
858 for (i
=oldsize
/SMALLSIZE
;i
<newsize
/SMALLSIZE
;i
++) {
859 blocknr
= STORAGE_get_free_small_blocknr(hf
);
862 if (!STORAGE_set_small_chain(hf
,lastblocknr
,blocknr
))
864 lastblocknr
= blocknr
;
866 /* and terminate the chain */
867 if (!STORAGE_set_small_chain(hf
,lastblocknr
,STORAGE_CHAINENTRY_ENDOFCHAIN
))
871 /* no single block allocated yet */
872 blocknr
=STORAGE_get_free_big_blocknr(hf
);
875 this->stde
.pps_sb
= blocknr
;
877 /* Migrate small blocks to big blocks */
878 LPBYTE curdata
,data
= HeapAlloc(GetProcessHeap(),0,oldsize
+BIGSIZE
);
880 blocknr
= this->stde
.pps_sb
;
884 if (!STORAGE_get_small_block(hf
,blocknr
,curdata
)) {
885 HeapFree(GetProcessHeap(),0,data
);
888 curdata
+= SMALLSIZE
;
890 blocknr
= STORAGE_get_next_small_blocknr(hf
,blocknr
);
892 /* free small block chain */
893 if (!STORAGE_set_small_chain(hf
,this->stde
.pps_sb
,STORAGE_CHAINENTRY_FREE
))
896 blocknr
= this->stde
.pps_sb
= STORAGE_get_free_big_blocknr(hf
);
899 /* put the data into the big blocks */
900 cc
= this->stde
.pps_size
;
902 if (!STORAGE_put_big_block(hf
,blocknr
,curdata
))
906 if (!STORAGE_set_big_chain(hf
,blocknr
,STORAGE_CHAINENTRY_ENDOFCHAIN
))
910 int newblocknr
= STORAGE_get_free_big_blocknr(hf
);
913 if (!STORAGE_set_big_chain(hf
,blocknr
,newblocknr
))
915 blocknr
= newblocknr
;
919 HeapFree(GetProcessHeap(),0,data
);
921 /* generate big blocks to fit the new data */
922 lastblocknr
= blocknr
;
923 for (i
=oldsize
/BIGSIZE
;i
<newsize
/BIGSIZE
;i
++) {
924 blocknr
= STORAGE_get_free_big_blocknr(hf
);
927 if (!STORAGE_set_big_chain(hf
,lastblocknr
,blocknr
))
929 lastblocknr
= blocknr
;
931 /* terminate chain */
932 if (!STORAGE_set_big_chain(hf
,lastblocknr
,STORAGE_CHAINENTRY_ENDOFCHAIN
))
936 this->stde
.pps_size
= newsize
;
939 /* There are just some cases where we didn't modify it, we write it out
942 if (!STORAGE_put_pps_entry(hf
,this->ppsent
,&(this->stde
)))
945 /* finally the write pass */
946 if (this->stde
.pps_size
< 0x1000) {
947 blocknr
= STORAGE_get_nth_next_small_blocknr(hf
,this->stde
.pps_sb
,this->offset
.LowPart
/SMALLSIZE
);
950 /* we ensured that it is allocated above */
952 /* Read old block everytime, since we can have
953 * overlapping data at START and END of the write
955 if (!STORAGE_get_small_block(hf
,blocknr
,block
))
958 cc
= SMALLSIZE
-(this->offset
.LowPart
&(SMALLSIZE
-1));
961 memcpy( ((LPBYTE
)block
)+(this->offset
.LowPart
&(SMALLSIZE
-1)),
962 (LPBYTE
)(pv
+curoffset
),
965 if (!STORAGE_put_small_block(hf
,blocknr
,block
))
970 this->offset
.LowPart
+= cc
;
972 blocknr
= STORAGE_get_next_small_blocknr(hf
,blocknr
);
975 blocknr
= STORAGE_get_nth_next_big_blocknr(hf
,this->stde
.pps_sb
,this->offset
.LowPart
/BIGSIZE
);
978 /* we ensured that it is allocated above, so it better is */
980 /* read old block everytime, since we can have
981 * overlapping data at START and END of the write
983 if (!STORAGE_get_big_block(hf
,blocknr
,block
))
986 cc
= BIGSIZE
-(this->offset
.LowPart
&(BIGSIZE
-1));
989 memcpy( ((LPBYTE
)block
)+(this->offset
.LowPart
&(BIGSIZE
-1)),
990 (LPBYTE
)(pv
+curoffset
),
993 if (!STORAGE_put_big_block(hf
,blocknr
,block
))
998 this->offset
.LowPart
+= cc
;
1000 blocknr
= STORAGE_get_next_big_blocknr(hf
,blocknr
);
1006 /******************************************************************************
1007 * _create_istream16 [Internal]
1009 static void _create_istream16(LPSTREAM16
*str
) {
1012 if (!strvt16
.fnQueryInterface
) {
1013 HMODULE16 wp
= GetModuleHandle16("STORAGE");
1015 #define VTENT(x) strvt16.fn##x = (void*)WIN32_GetProcAddress16(wp,"IStream16_"#x);
1016 VTENT(QueryInterface
)
1031 segstrvt16
= SEGPTR_NEW(IStream16_VTable
);
1032 memcpy(segstrvt16
,&strvt16
,sizeof(strvt16
));
1033 segstrvt16
= (LPSTREAM16_VTABLE
)SEGPTR_GET(segstrvt16
);
1035 #define VTENT(x) strvt16.fn##x = IStream16_##x;
1036 VTENT(QueryInterface
)
1053 segstrvt16
= &strvt16
;
1056 lpst
= SEGPTR_NEW(IStream16
);
1057 lpst
->lpvtbl
= segstrvt16
;
1059 lpst
->thisptr
= SEGPTR_GET(lpst
);
1060 *str
= (void*)lpst
->thisptr
;
1063 /*****************************************************************************
1064 * IStream32_QueryInterface [???]
1066 HRESULT WINAPI
IStream32_QueryInterface(
1067 LPSTREAM32
this,REFIID refiid
,LPVOID
*obj
1071 WINE_StringFromCLSID((LPCLSID
)refiid
,xrefiid
);
1072 TRACE(relay
,"(%p)->(%s,%p)\n",this,xrefiid
,obj
);
1073 if (!memcmp(&IID_IUnknown
,refiid
,sizeof(IID_IUnknown
))) {
1077 return OLE_E_ENUM_NOMORE
;
1081 ULONG WINAPI
IStream32_AddRef(LPSTREAM32
this) {
1082 return ++(this->ref
);
1085 ULONG WINAPI
IStream32_Release(LPSTREAM32
this) {
1086 FlushFileBuffers(this->hf
);
1089 CloseHandle(this->hf
);
1096 static IStream32_VTable strvt32
= {
1097 IStream32_QueryInterface
,
1111 /******************************************************************************
1112 * IStorage16_QueryInterface [STORAGE.500]
1114 HRESULT WINAPI
IStorage16_QueryInterface(
1115 LPSTORAGE16
this,REFIID refiid
,LPVOID
*obj
1119 WINE_StringFromCLSID((LPCLSID
)refiid
,xrefiid
);
1120 TRACE(relay
,"(%p)->(%s,%p)\n",this,xrefiid
,obj
);
1122 if (!memcmp(&IID_IUnknown
,refiid
,sizeof(IID_IUnknown
))) {
1126 return OLE_E_ENUM_NOMORE
;
1129 ULONG WINAPI
IStorage16_AddRef(LPSTORAGE16
this) {
1130 return ++(this->ref
);
1133 ULONG WINAPI
IStorage16_Release(LPSTORAGE16
this) {
1141 HRESULT WINAPI
IStorage16_Stat(
1142 LPSTORAGE16
this,STATSTG
*pstatstg
, DWORD grfStatFlag
1144 TRACE(ole
,"(%p)->(%p,0x%08lx)\n",
1145 this,pstatstg
,grfStatFlag
1147 pstatstg
->pwcsName
=(LPOLESTR16
)SEGPTR_GET(SEGPTR_STRDUP_WtoA(this->stde
.pps_rawname
));
1148 pstatstg
->type
= this->stde
.pps_type
;
1149 pstatstg
->cbSize
.LowPart
= this->stde
.pps_size
;
1150 pstatstg
->mtime
= this->stde
.pps_ft1
; /* FIXME */ /* why? */
1151 pstatstg
->atime
= this->stde
.pps_ft2
; /* FIXME */
1152 pstatstg
->ctime
= this->stde
.pps_ft2
; /* FIXME */
1153 pstatstg
->grfMode
= 0; /* FIXME */
1154 pstatstg
->grfLocksSupported
= 0; /* FIXME */
1155 pstatstg
->clsid
= this->stde
.pps_guid
;
1156 pstatstg
->grfStateBits
= 0; /* FIXME */
1157 pstatstg
->reserved
= 0;
1161 /******************************************************************************
1162 * IStorage16_Commit [STORAGE.509]
1164 HRESULT WINAPI
IStorage16_Commit(
1165 LPSTORAGE16
this,DWORD commitflags
1167 FIXME(ole
,"(%p)->(0x%08lx),STUB!\n",
1173 HRESULT WINAPI
IStorage16_CopyTo(LPSTORAGE16
this,DWORD ciidExclude
,const IID
*rgiidExclude
,SNB16 SNB16Exclude
,IStorage16
*pstgDest
) {
1177 WINE_StringFromCLSID(rgiidExclude
,xguid
);
1179 strcpy(xguid
,"<no guid>");
1180 FIXME(ole
,"IStorage16(%p)->(0x%08lx,%s,%p,%p),stub!\n",
1181 this,ciidExclude
,xguid
,SNB16Exclude
,pstgDest
1188 HRESULT WINAPI
IStorage16_CreateStorage(
1189 LPSTORAGE16
this,LPCOLESTR16 pwcsName
,DWORD grfMode
,DWORD dwStgFormat
,DWORD reserved2
, IStorage16
**ppstg
1193 struct storage_pps_entry stde
;
1194 struct storage_header sth
;
1195 HFILE32 hf
=this->hf
;
1199 TRACE(ole
,"(%p)->(%s,0x%08lx,0x%08lx,0x%08lx,%p)\n",
1200 this,pwcsName
,grfMode
,dwStgFormat
,reserved2
,ppstg
1202 if (grfMode
& STGM_TRANSACTED
)
1203 FIXME(ole
,"We do not support transacted Compound Storage. Using direct mode.\n");
1204 _create_istorage16(ppstg
);
1205 lpstg
= (LPSTORAGE16
)PTR_SEG_TO_LIN(*ppstg
);
1206 lpstg
->hf
= this->hf
;
1208 ppsent
=STORAGE_get_free_pps_entry(lpstg
->hf
);
1212 if (stde
.pps_dir
==-1) {
1213 stde
.pps_dir
= ppsent
;
1216 FIXME(ole
," use prev chain too ?\n");
1218 if (1!=STORAGE_get_pps_entry(lpstg
->hf
,x
,&stde
))
1220 while (stde
.pps_next
!=-1) {
1222 if (1!=STORAGE_get_pps_entry(lpstg
->hf
,x
,&stde
))
1225 stde
.pps_next
= ppsent
;
1227 assert(STORAGE_put_pps_entry(lpstg
->hf
,x
,&stde
));
1228 assert(1==STORAGE_get_pps_entry(lpstg
->hf
,ppsent
,&(lpstg
->stde
)));
1229 lstrcpyAtoW(lpstg
->stde
.pps_rawname
,pwcsName
);
1230 lpstg
->stde
.pps_sizeofname
= lstrlen32A(pwcsName
)*2+2;
1231 lpstg
->stde
.pps_next
= -1;
1232 lpstg
->stde
.pps_prev
= -1;
1233 lpstg
->stde
.pps_dir
= -1;
1234 lpstg
->stde
.pps_sb
= -1;
1235 lpstg
->stde
.pps_size
= 0;
1236 lpstg
->stde
.pps_type
= 1;
1237 lpstg
->ppsent
= ppsent
;
1238 /* FIXME: timestamps? */
1239 if (!STORAGE_put_pps_entry(lpstg
->hf
,ppsent
,&(lpstg
->stde
)))
1244 /******************************************************************************
1245 * IStorage16_CreateStream [STORAGE.503]
1247 HRESULT WINAPI
IStorage16_CreateStream(
1248 LPSTORAGE16
this,LPCOLESTR16 pwcsName
,DWORD grfMode
,DWORD reserved1
,DWORD reserved2
, IStream16
**ppstm
1252 struct storage_pps_entry stde
;
1254 TRACE(ole
,"(%p)->(%s,0x%08lx,0x%08lx,0x%08lx,%p)\n",
1255 this,pwcsName
,grfMode
,reserved1
,reserved2
,ppstm
1257 if (grfMode
& STGM_TRANSACTED
)
1258 FIXME(ole
,"We do not support transacted Compound Storage. Using direct mode.\n");
1259 _create_istream16(ppstm
);
1260 lpstr
= (LPSTREAM16
)PTR_SEG_TO_LIN(*ppstm
);
1261 lpstr
->hf
= FILE_Dup(this->hf
);
1262 lpstr
->offset
.LowPart
= 0;
1263 lpstr
->offset
.HighPart
= 0;
1265 ppsent
=STORAGE_get_free_pps_entry(lpstr
->hf
);
1269 if (stde
.pps_next
==-1)
1272 while (stde
.pps_next
!=-1) {
1274 if (1!=STORAGE_get_pps_entry(lpstr
->hf
,x
,&stde
))
1277 stde
.pps_next
= ppsent
;
1278 assert(STORAGE_put_pps_entry(lpstr
->hf
,x
,&stde
));
1279 assert(1==STORAGE_get_pps_entry(lpstr
->hf
,ppsent
,&(lpstr
->stde
)));
1280 lstrcpyAtoW(lpstr
->stde
.pps_rawname
,pwcsName
);
1281 lpstr
->stde
.pps_sizeofname
= lstrlen32A(pwcsName
)*2+2;
1282 lpstr
->stde
.pps_next
= -1;
1283 lpstr
->stde
.pps_prev
= -1;
1284 lpstr
->stde
.pps_dir
= -1;
1285 lpstr
->stde
.pps_sb
= -1;
1286 lpstr
->stde
.pps_size
= 0;
1287 lpstr
->stde
.pps_type
= 2;
1288 lpstr
->ppsent
= ppsent
;
1289 /* FIXME: timestamps? */
1290 if (!STORAGE_put_pps_entry(lpstr
->hf
,ppsent
,&(lpstr
->stde
)))
1295 /******************************************************************************
1296 * IStorage16_OpenStorage [STORAGE.506]
1298 HRESULT WINAPI
IStorage16_OpenStorage(
1299 LPSTORAGE16
this,LPCOLESTR16 pwcsName
, IStorage16
*pstgPrio
, DWORD grfMode
, SNB16 snbExclude
, DWORD reserved
, IStorage16
**ppstg
1305 TRACE(relay
,"(%p)->(%s,%p,0x%08lx,%p,0x%08lx,%p)\n",
1306 this,pwcsName
,pstgPrio
,grfMode
,snbExclude
,reserved
,ppstg
1308 if (grfMode
& STGM_TRANSACTED
)
1309 FIXME(ole
,"We do not support transacted Compound Storage. Using direct mode.\n");
1310 _create_istorage16(ppstg
);
1311 lpstg
= (LPSTREAM16
)PTR_SEG_TO_LIN(*ppstg
);
1312 lpstg
->hf
= FILE_Dup(this->hf
);
1313 lstrcpyAtoW(name
,pwcsName
);
1314 newpps
= STORAGE_look_for_named_pps(lpstg
->hf
,this->stde
.pps_dir
,name
);
1316 IStream16_Release(lpstg
);
1320 if (1!=STORAGE_get_pps_entry(lpstg
->hf
,newpps
,&(lpstg
->stde
))) {
1321 IStream16_Release(lpstg
);
1324 lpstg
->ppsent
= newpps
;
1328 HRESULT WINAPI
IStorage16_OpenStream(
1329 LPSTORAGE16
this,LPCOLESTR16 pwcsName
, void *reserved1
, DWORD grfMode
, DWORD reserved2
, IStream16
**ppstm
1335 TRACE(relay
,"(%p)->(%s,%p,0x%08lx,0x%08lx,%p)\n",
1336 this,pwcsName
,reserved1
,grfMode
,reserved2
,ppstm
1338 if (grfMode
& STGM_TRANSACTED
)
1339 FIXME(ole
,"We do not support transacted Compound Storage. Using direct mode.\n");
1340 _create_istream16(ppstm
);
1341 lpstr
= (LPSTREAM16
)PTR_SEG_TO_LIN(*ppstm
);
1342 lpstr
->hf
= FILE_Dup(this->hf
);
1343 lstrcpyAtoW(name
,pwcsName
);
1344 newpps
= STORAGE_look_for_named_pps(lpstr
->hf
,this->stde
.pps_dir
,name
);
1346 IStream16_Release(lpstr
);
1350 if (1!=STORAGE_get_pps_entry(lpstr
->hf
,newpps
,&(lpstr
->stde
))) {
1351 IStream16_Release(lpstr
);
1354 lpstr
->offset
.LowPart
= 0;
1355 lpstr
->offset
.HighPart
= 0;
1356 lpstr
->ppsent
= newpps
;
1360 static void _create_istorage16(LPSTORAGE16
*stg
) {
1363 if (!stvt16
.fnQueryInterface
) {
1364 HMODULE16 wp
= GetModuleHandle16("STORAGE");
1366 #define VTENT(x) stvt16.fn##x = (void*)WIN32_GetProcAddress16(wp,"IStorage16_"#x);
1367 VTENT(QueryInterface
)
1372 VTENT(CreateStorage
)
1375 VTENT(MoveElementTo
)
1379 VTENT(DestroyElement
)
1380 VTENT(RenameElement
)
1381 VTENT(SetElementTimes
)
1386 segstvt16
= SEGPTR_NEW(IStorage16_VTable
);
1387 memcpy(segstvt16
,&stvt16
,sizeof(stvt16
));
1388 segstvt16
= (LPSTORAGE16_VTABLE
)SEGPTR_GET(segstvt16
);
1390 #define VTENT(x) stvt16.fn##x = IStorage16_##x;
1391 VTENT(QueryInterface
)
1396 VTENT(CreateStorage
)
1400 /* not (yet) implemented ...
1401 VTENT(MoveElementTo)
1404 VTENT(DestroyElement)
1405 VTENT(RenameElement)
1406 VTENT(SetElementTimes)
1412 segstvt16
= &stvt16
;
1415 lpst
= SEGPTR_NEW(IStorage16
);
1416 lpst
->lpvtbl
= segstvt16
;
1418 lpst
->thisptr
= SEGPTR_GET(lpst
);
1419 *stg
= (void*)lpst
->thisptr
;
1422 /******************************************************************************
1423 * IStorage32_QueryInterface [???]
1425 HRESULT WINAPI
IStorage32_QueryInterface(
1426 LPSTORAGE32
this,REFIID refiid
,LPVOID
*obj
1430 WINE_StringFromCLSID((LPCLSID
)refiid
,xrefiid
);
1431 TRACE(relay
,"(%p)->(%s,%p)\n",this,xrefiid
,obj
);
1433 if (!memcmp(&IID_IUnknown
,refiid
,sizeof(IID_IUnknown
))) {
1437 return OLE_E_ENUM_NOMORE
;
1440 ULONG WINAPI
IStorage32_AddRef(LPSTORAGE32
this) {
1441 return ++(this->ref
);
1444 ULONG WINAPI
IStorage32_Release(LPSTORAGE32
this) {
1448 HeapFree(GetProcessHeap(),0,this);
1452 HRESULT WINAPI
IStorage32_CreateStream(
1453 LPSTORAGE32
this,LPCOLESTR32 pwcsName
,DWORD grfMode
,DWORD reserved1
,DWORD reserved2
, IStream32
**ppstm
1455 TRACE(ole
,"(%p)->(%p,0x%08lx,0x%08lx,0x%08lx,%p)\n",
1456 this,pwcsName
,grfMode
,reserved1
,reserved2
,ppstm
1458 *ppstm
= (IStream32
*)HeapAlloc(GetProcessHeap(),0,sizeof(IStream32
));
1459 (*ppstm
)->lpvtbl
= &strvt32
;
1465 HRESULT WINAPI
IStorage32_OpenStream(
1466 LPSTORAGE32
this,LPCOLESTR32 pwcsName
, void *reserved1
, DWORD grfMode
, DWORD reserved2
, IStream32
**ppstm
1468 TRACE(ole
,"(%p)->(%p,%p,0x%08lx,0x%08lx,%p)\n",
1469 this,pwcsName
,reserved1
,grfMode
,reserved2
,ppstm
1471 *ppstm
= (IStream32
*)HeapAlloc(GetProcessHeap(),0,sizeof(IStream32
));
1472 (*ppstm
)->lpvtbl
= &strvt32
;
1477 static IStorage32_VTable stvt32
= {
1478 IStorage32_QueryInterface
,
1481 IStorage32_CreateStream
,
1482 IStorage32_OpenStream
,
1495 /******************************************************************************
1496 * Storage API functions
1499 /******************************************************************************
1500 * StgCreateDocFile16 [STORAGE.1]
1502 OLESTATUS WINAPI
StgCreateDocFile16(
1503 LPCOLESTR16 pwcsName
,DWORD grfMode
,DWORD reserved
,IStorage16
**ppstgOpen
1508 struct storage_pps_entry stde
;
1510 TRACE(ole
,"(%s,0x%08lx,0x%08lx,%p)\n",
1511 pwcsName
,grfMode
,reserved
,ppstgOpen
1513 _create_istorage16(ppstgOpen
);
1514 hf
= CreateFile32A(pwcsName
,GENERIC_READ
|GENERIC_WRITE
,0,NULL
,CREATE_NEW
,0,0);
1515 if (hf
==INVALID_HANDLE_VALUE32
) {
1516 WARN(ole
,"couldn't open file for storage:%ld\n",GetLastError());
1519 lpstg
= (LPSTORAGE16
)PTR_SEG_TO_LIN(*ppstgOpen
);
1521 /* FIXME: check for existance before overwriting? */
1522 if (!STORAGE_init_storage(hf
)) {
1527 while (!ret
) { /* neither 1 nor <0 */
1528 ret
=STORAGE_get_pps_entry(hf
,i
,&stde
);
1529 if ((ret
==1) && (stde
.pps_type
==5)) {
1537 IStorage16_Release(lpstg
); /* will remove it */
1543 /******************************************************************************
1544 * StgCreateDocFile32 [OLE32.144]
1546 OLESTATUS WINAPI
StgCreateDocFile32(
1547 LPCOLESTR32 pwcsName
,DWORD grfMode
,DWORD reserved
,IStorage32
**ppstgOpen
1549 TRACE(ole
,"(%p,0x%08lx,0x%08lx,%p)\n",
1550 pwcsName
,grfMode
,reserved
,ppstgOpen
1552 *ppstgOpen
= (IStorage32
*)HeapAlloc(GetProcessHeap(),0,sizeof(IStorage32
));
1553 (*ppstgOpen
)->ref
= 1;
1554 (*ppstgOpen
)->lpvtbl
= &stvt32
;
1558 OLESTATUS WINAPI
StgIsStorageFile16(LPCOLESTR16 fn
) {
1563 TRACE(ole
,"(\'%s\')\n",fn
);
1564 hf
= OpenFile32(fn
,&ofs
,OF_SHARE_DENY_NONE
);
1565 if (hf
==HFILE_ERROR32
)
1566 return STG_E_FILENOTFOUND
;
1567 if (24!=_lread32(hf
,magic
,24)) {
1568 WARN(ole
," too short\n");
1572 if (!memcmp(magic
,STORAGE_magic
,8)) {
1573 WARN(ole
," -> YES\n");
1577 if (!memcmp(magic
,STORAGE_notmagic
,8)) {
1578 WARN(ole
," -> NO\n");
1582 if (!memcmp(magic
,STORAGE_oldmagic
,8)) {
1583 WARN(ole
," -> old format\n");
1585 return STG_E_OLDFORMAT
;
1587 WARN(ole
," -> Invalid header.\n");
1589 return STG_E_INVALIDHEADER
;
1593 StgIsStorageFile32(LPCOLESTR32 fn
)
1595 LPOLESTR16 xfn
= HEAP_strdupWtoA(GetProcessHeap(),0,fn
);
1596 OLESTATUS ret
= StgIsStorageFile16(xfn
);
1598 HeapFree(GetProcessHeap(),0,xfn
);
1604 OLESTATUS WINAPI
StgOpenStorage16(
1605 const OLECHAR16
* pwcsName
,IStorage16
*pstgPriority
,DWORD grfMode
,
1606 SNB16 snbExclude
,DWORD reserved
, IStorage16
**ppstgOpen
1611 struct storage_pps_entry stde
;
1613 TRACE(ole
,"(%s,%p,0x%08lx,%p,%ld,%p)\n",
1614 pwcsName
,pstgPriority
,grfMode
,snbExclude
,reserved
,ppstgOpen
1616 _create_istorage16(ppstgOpen
);
1617 hf
= CreateFile32A(pwcsName
,GENERIC_READ
,0,NULL
,0,0,0);
1618 if (hf
==INVALID_HANDLE_VALUE32
) {
1619 WARN(ole
,"Couldn't open file for storage\n");
1622 lpstg
= (LPSTORAGE16
)PTR_SEG_TO_LIN(*ppstgOpen
);
1626 while (!ret
) { /* neither 1 nor <0 */
1627 ret
=STORAGE_get_pps_entry(hf
,i
,&stde
);
1628 if ((ret
==1) && (stde
.pps_type
==5)) {
1635 IStorage16_Release(lpstg
); /* will remove it */
1642 /******************************************************************************
1643 * StgOpenStorage32 [OLE32.148]
1645 OLESTATUS WINAPI
StgOpenStorage32(
1646 const OLECHAR32
* pwcsName
,IStorage32
*pstgPriority
,DWORD grfMode
,
1647 SNB32 snbExclude
,DWORD reserved
, IStorage32
**ppstgOpen
1649 FIXME(ole
,"StgOpenStorage32(%p,%p,0x%08lx,%p,%ld,%p),stub!\n",
1650 pwcsName
,pstgPriority
,grfMode
,snbExclude
,reserved
,
1652 *ppstgOpen
= (IStorage32
*)HeapAlloc(GetProcessHeap(),0,sizeof(IStorage32
));
1653 (*ppstgOpen
)->ref
= 1;
1654 (*ppstgOpen
)->lpvtbl
= &stvt32
;