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 ICOM_VTABLE(IStorage16) stvt16;
37 static ICOM_VTABLE(IStorage16) *segstvt16 = NULL;
38 static ICOM_VTABLE(IStorage32) stvt32;
39 static ICOM_VTABLE(IStream16) strvt16;
40 static ICOM_VTABLE(IStream16) *segstrvt16 = NULL;
41 static ICOM_VTABLE(IStream32) strvt32;
43 /*ULONG WINAPI IStorage16_AddRef(LPSTORAGE16 this);*/
44 static void _create_istorage16(LPSTORAGE16 *stg);
45 static void _create_istream16(LPSTREAM16 *str);
50 /******************************************************************************
51 * STORAGE_get_big_block [Internal]
53 * Reading OLE compound storage
56 STORAGE_get_big_block(HFILE32 hf,int n,BYTE *block) {
58 if (-1==_llseek32(hf,(n+1)*BIGSIZE,SEEK_SET)) {
59 WARN(ole," seek failed (%ld)\n",GetLastError());
62 assert((n+1)*BIGSIZE==_llseek32(hf,0,SEEK_CUR));
63 if (BIGSIZE!=_lread32(hf,block,BIGSIZE)) {
64 WARN(ole,"(block size %d): read didn't read (%ld)\n",n,GetLastError());
71 /******************************************************************************
72 * STORAGE_put_big_block [INTERNAL]
75 STORAGE_put_big_block(HFILE32 hf,int n,BYTE *block) {
77 if (-1==_llseek32(hf,(n+1)*BIGSIZE,SEEK_SET)) {
78 WARN(ole," seek failed (%ld)\n",GetLastError());
81 assert((n+1)*BIGSIZE==_llseek32(hf,0,SEEK_CUR));
82 if (BIGSIZE!=_lwrite32(hf,block,BIGSIZE)) {
83 WARN(ole," write failed (%ld)\n",GetLastError());
89 /******************************************************************************
90 * STORAGE_get_next_big_blocknr [INTERNAL]
93 STORAGE_get_next_big_blocknr(HFILE32 hf,int blocknr) {
94 INT32 bbs[BIGSIZE/sizeof(INT32)];
95 struct storage_header sth;
99 assert(blocknr>>7<sth.num_of_bbd_blocks);
100 if (sth.bbd_list[blocknr>>7]==0xffffffff)
102 if (!STORAGE_get_big_block(hf,sth.bbd_list[blocknr>>7],(LPBYTE)bbs))
104 assert(bbs[blocknr&0x7f]!=STORAGE_CHAINENTRY_FREE);
105 return bbs[blocknr&0x7f];
108 /******************************************************************************
109 * STORAGE_get_nth_next_big_blocknr [INTERNAL]
112 STORAGE_get_nth_next_big_blocknr(HFILE32 hf,int blocknr,int nr) {
113 INT32 bbs[BIGSIZE/sizeof(INT32)];
115 struct storage_header sth;
121 assert((blocknr>>7)<sth.num_of_bbd_blocks);
122 assert(sth.bbd_list[blocknr>>7]!=0xffffffff);
124 /* simple caching... */
125 if (lastblock!=sth.bbd_list[blocknr>>7]) {
126 assert(STORAGE_get_big_block(hf,sth.bbd_list[blocknr>>7],(LPBYTE)bbs));
127 lastblock = sth.bbd_list[blocknr>>7];
129 blocknr = bbs[blocknr&0x7f];
134 /******************************************************************************
135 * STORAGE_get_root_pps_entry [Internal]
138 STORAGE_get_root_pps_entry(HFILE32 hf,struct storage_pps_entry *pstde) {
141 struct storage_pps_entry *stde=(struct storage_pps_entry*)block;
142 struct storage_header sth;
145 blocknr = sth.root_startblock;
147 assert(STORAGE_get_big_block(hf,blocknr,block));
149 if (!stde[i].pps_sizeofname)
151 if (stde[i].pps_type==5) {
156 blocknr=STORAGE_get_next_big_blocknr(hf,blocknr);
161 /******************************************************************************
162 * STORAGE_get_small_block [INTERNAL]
165 STORAGE_get_small_block(HFILE32 hf,int blocknr,BYTE *sblock) {
168 struct storage_pps_entry root;
171 assert(STORAGE_get_root_pps_entry(hf,&root));
172 bigblocknr = STORAGE_get_nth_next_big_blocknr(hf,root.pps_sb,blocknr/SMALLBLOCKS_PER_BIGBLOCK);
173 assert(bigblocknr>=0);
174 assert(STORAGE_get_big_block(hf,bigblocknr,block));
176 memcpy(sblock,((LPBYTE)block)+SMALLSIZE*(blocknr&(SMALLBLOCKS_PER_BIGBLOCK-1)),SMALLSIZE);
180 /******************************************************************************
181 * STORAGE_put_small_block [INTERNAL]
184 STORAGE_put_small_block(HFILE32 hf,int blocknr,BYTE *sblock) {
187 struct storage_pps_entry root;
191 assert(STORAGE_get_root_pps_entry(hf,&root));
192 bigblocknr = STORAGE_get_nth_next_big_blocknr(hf,root.pps_sb,blocknr/SMALLBLOCKS_PER_BIGBLOCK);
193 assert(bigblocknr>=0);
194 assert(STORAGE_get_big_block(hf,bigblocknr,block));
196 memcpy(((LPBYTE)block)+SMALLSIZE*(blocknr&(SMALLBLOCKS_PER_BIGBLOCK-1)),sblock,SMALLSIZE);
197 assert(STORAGE_put_big_block(hf,bigblocknr,block));
201 /******************************************************************************
202 * STORAGE_get_next_small_blocknr [INTERNAL]
205 STORAGE_get_next_small_blocknr(HFILE32 hf,int blocknr) {
207 LPINT32 sbd = (LPINT32)block;
209 struct storage_header sth;
213 bigblocknr = STORAGE_get_nth_next_big_blocknr(hf,sth.sbd_startblock,blocknr/128);
214 assert(bigblocknr>=0);
215 assert(STORAGE_get_big_block(hf,bigblocknr,block));
216 assert(sbd[blocknr & 127]!=STORAGE_CHAINENTRY_FREE);
217 return sbd[blocknr & (128-1)];
220 /******************************************************************************
221 * STORAGE_get_nth_next_small_blocknr [INTERNAL]
224 STORAGE_get_nth_next_small_blocknr(HFILE32 hf,int blocknr,int nr) {
227 LPINT32 sbd = (LPINT32)block;
228 struct storage_header sth;
233 while ((nr--) && (blocknr>=0)) {
234 if (lastblocknr/128!=blocknr/128) {
236 bigblocknr = STORAGE_get_nth_next_big_blocknr(hf,sth.sbd_startblock,blocknr/128);
237 assert(bigblocknr>=0);
238 assert(STORAGE_get_big_block(hf,bigblocknr,block));
239 lastblocknr = blocknr;
241 assert(lastblocknr>=0);
243 blocknr=sbd[blocknr & (128-1)];
244 assert(blocknr!=STORAGE_CHAINENTRY_FREE);
249 /******************************************************************************
250 * STORAGE_get_pps_entry [INTERNAL]
253 STORAGE_get_pps_entry(HFILE32 hf,int n,struct storage_pps_entry *pstde) {
256 struct storage_pps_entry *stde = (struct storage_pps_entry*)(((LPBYTE)block)+128*(n&3));
257 struct storage_header sth;
260 /* we have 4 pps entries per big block */
261 blocknr = STORAGE_get_nth_next_big_blocknr(hf,sth.root_startblock,n/4);
263 assert(STORAGE_get_big_block(hf,blocknr,block));
269 /******************************************************************************
270 * STORAGE_put_pps_entry [Internal]
273 STORAGE_put_pps_entry(HFILE32 hf,int n,struct storage_pps_entry *pstde) {
276 struct storage_pps_entry *stde = (struct storage_pps_entry*)(((LPBYTE)block)+128*(n&3));
277 struct storage_header sth;
281 /* we have 4 pps entries per big block */
282 blocknr = STORAGE_get_nth_next_big_blocknr(hf,sth.root_startblock,n/4);
284 assert(STORAGE_get_big_block(hf,blocknr,block));
286 assert(STORAGE_put_big_block(hf,blocknr,block));
290 /******************************************************************************
291 * STORAGE_look_for_named_pps [Internal]
294 STORAGE_look_for_named_pps(HFILE32 hf,int n,LPOLESTR32 name) {
295 struct storage_pps_entry stde;
300 if (1!=STORAGE_get_pps_entry(hf,n,&stde))
303 if (!lstrcmp32W(name,stde.pps_rawname))
305 if (stde.pps_prev != -1) {
306 ret=STORAGE_look_for_named_pps(hf,stde.pps_prev,name);
310 if (stde.pps_next != -1) {
311 ret=STORAGE_look_for_named_pps(hf,stde.pps_next,name);
318 /******************************************************************************
319 * STORAGE_dump_pps_entry [Internal]
325 STORAGE_dump_pps_entry(struct storage_pps_entry *stde) {
326 char name[33],xguid[50];
328 WINE_StringFromCLSID(&(stde->pps_guid),xguid);
330 lstrcpyWtoA(name,stde->pps_rawname);
331 if (!stde->pps_sizeofname)
333 DUMP("name: %s\n",name);
334 DUMP("type: %d\n",stde->pps_type);
335 DUMP("prev pps: %ld\n",stde->pps_prev);
336 DUMP("next pps: %ld\n",stde->pps_next);
337 DUMP("dir pps: %ld\n",stde->pps_dir);
338 DUMP("guid: %s\n",xguid);
339 if (stde->pps_type !=2) {
342 t = DOSFS_FileTimeToUnixTime(&(stde->pps_ft1),NULL);
343 DUMP("ts1: %s\n",ctime(&t));
344 t = DOSFS_FileTimeToUnixTime(&(stde->pps_ft2),NULL);
345 DUMP("ts2: %s\n",ctime(&t));
347 DUMP("startblock: %ld\n",stde->pps_sb);
348 DUMP("size: %ld\n",stde->pps_size);
351 /******************************************************************************
352 * STORAGE_init_storage [INTERNAL]
355 STORAGE_init_storage(HFILE32 hf) {
358 struct storage_header *sth;
359 struct storage_pps_entry *stde;
361 assert(-1!=_llseek32(hf,0,SEEK_SET));
362 /* block -1 is the storage header */
363 sth = (struct storage_header*)block;
364 memcpy(sth->magic,STORAGE_magic,8);
365 memset(sth->unknown1,0,sizeof(sth->unknown1));
366 memset(sth->unknown2,0,sizeof(sth->unknown2));
367 memset(sth->unknown3,0,sizeof(sth->unknown3));
368 sth->num_of_bbd_blocks = 1;
369 sth->root_startblock = 1;
370 sth->sbd_startblock = 0xffffffff;
371 memset(sth->bbd_list,0xff,sizeof(sth->bbd_list));
372 sth->bbd_list[0] = 0;
373 assert(BIGSIZE==_lwrite32(hf,block,BIGSIZE));
374 /* block 0 is the big block directory */
376 memset(block,0xff,sizeof(block)); /* mark all blocks as free */
377 bbs[0]=STORAGE_CHAINENTRY_ENDOFCHAIN; /* for this block */
378 bbs[1]=STORAGE_CHAINENTRY_ENDOFCHAIN; /* for directory entry */
379 assert(BIGSIZE==_lwrite32(hf,block,BIGSIZE));
380 /* block 1 is the root directory entry */
381 memset(block,0x00,sizeof(block));
382 stde = (struct storage_pps_entry*)block;
383 lstrcpyAtoW(stde->pps_rawname,"RootEntry");
384 stde->pps_sizeofname = lstrlen32W(stde->pps_rawname)*2+2;
389 stde->pps_sb = 0xffffffff;
391 assert(BIGSIZE==_lwrite32(hf,block,BIGSIZE));
395 /******************************************************************************
396 * STORAGE_set_big_chain [Internal]
399 STORAGE_set_big_chain(HFILE32 hf,int blocknr,INT32 type) {
401 LPINT32 bbd = (LPINT32)block;
402 int nextblocknr,bigblocknr;
403 struct storage_header sth;
406 assert(blocknr!=type);
408 bigblocknr = sth.bbd_list[blocknr/128];
409 assert(bigblocknr>=0);
410 assert(STORAGE_get_big_block(hf,bigblocknr,block));
412 nextblocknr = bbd[blocknr&(128-1)];
413 bbd[blocknr&(128-1)] = type;
416 assert(STORAGE_put_big_block(hf,bigblocknr,block));
417 type = STORAGE_CHAINENTRY_FREE;
418 blocknr = nextblocknr;
423 /******************************************************************************
424 * STORAGE_set_small_chain [Internal]
427 STORAGE_set_small_chain(HFILE32 hf,int blocknr,INT32 type) {
429 LPINT32 sbd = (LPINT32)block;
430 int lastblocknr,nextsmallblocknr,bigblocknr;
431 struct storage_header sth;
435 assert(blocknr!=type);
436 lastblocknr=-129;bigblocknr=-2;
438 /* cache block ... */
439 if (lastblocknr/128!=blocknr/128) {
440 bigblocknr = STORAGE_get_nth_next_big_blocknr(hf,sth.sbd_startblock,blocknr/128);
441 assert(bigblocknr>=0);
442 assert(STORAGE_get_big_block(hf,bigblocknr,block));
444 lastblocknr = blocknr;
445 nextsmallblocknr = sbd[blocknr&(128-1)];
446 sbd[blocknr&(128-1)] = type;
447 assert(STORAGE_put_big_block(hf,bigblocknr,block));
450 type = STORAGE_CHAINENTRY_FREE;
451 blocknr = nextsmallblocknr;
456 /******************************************************************************
457 * STORAGE_get_free_big_blocknr [Internal]
460 STORAGE_get_free_big_blocknr(HFILE32 hf) {
462 LPINT32 sbd = (LPINT32)block;
463 int lastbigblocknr,i,curblock,bigblocknr;
464 struct storage_header sth;
469 bigblocknr = sth.bbd_list[curblock];
470 while (curblock<sth.num_of_bbd_blocks) {
471 assert(bigblocknr>=0);
472 assert(STORAGE_get_big_block(hf,bigblocknr,block));
474 if (sbd[i]==STORAGE_CHAINENTRY_FREE) {
475 sbd[i] = STORAGE_CHAINENTRY_ENDOFCHAIN;
476 assert(STORAGE_put_big_block(hf,bigblocknr,block));
477 memset(block,0x42,sizeof(block));
478 assert(STORAGE_put_big_block(hf,i+curblock*128,block));
479 return i+curblock*128;
481 lastbigblocknr = bigblocknr;
482 bigblocknr = sth.bbd_list[++curblock];
484 bigblocknr = curblock*128;
485 /* since we have marked all blocks from 0 up to curblock*128-1
486 * the next free one is curblock*128, where we happily put our
487 * next large block depot.
489 memset(block,0xff,sizeof(block));
490 /* mark the block allocated and returned by this function */
491 sbd[1] = STORAGE_CHAINENTRY_ENDOFCHAIN;
492 assert(STORAGE_put_big_block(hf,bigblocknr,block));
494 /* if we had a bbd block already (mostlikely) we need
495 * to link the new one into the chain
497 if (lastbigblocknr!=-1)
498 assert(STORAGE_set_big_chain(hf,lastbigblocknr,bigblocknr));
499 sth.bbd_list[curblock]=bigblocknr;
500 sth.num_of_bbd_blocks++;
501 assert(sth.num_of_bbd_blocks==curblock+1);
502 assert(STORAGE_put_big_block(hf,-1,(LPBYTE)&sth));
504 /* Set the end of the chain for the bigblockdepots */
505 assert(STORAGE_set_big_chain(hf,bigblocknr,STORAGE_CHAINENTRY_ENDOFCHAIN));
506 /* add 1, for the first entry is used for the additional big block
507 * depot. (means we already used bigblocknr) */
508 memset(block,0x42,sizeof(block));
509 /* allocate this block (filled with 0x42) */
510 assert(STORAGE_put_big_block(hf,bigblocknr+1,block));
515 /******************************************************************************
516 * STORAGE_get_free_small_blocknr [Internal]
519 STORAGE_get_free_small_blocknr(HFILE32 hf) {
521 LPINT32 sbd = (LPINT32)block;
522 int lastbigblocknr,newblocknr,i,curblock,bigblocknr;
523 struct storage_pps_entry root;
524 struct storage_header sth;
527 bigblocknr = sth.sbd_startblock;
531 while (bigblocknr>=0) {
532 if (!STORAGE_get_big_block(hf,bigblocknr,block))
535 if (sbd[i]==STORAGE_CHAINENTRY_FREE) {
536 sbd[i]=STORAGE_CHAINENTRY_ENDOFCHAIN;
537 newblocknr = i+curblock*128;
542 lastbigblocknr = bigblocknr;
543 bigblocknr = STORAGE_get_next_big_blocknr(hf,bigblocknr);
546 if (newblocknr==-1) {
547 bigblocknr = STORAGE_get_free_big_blocknr(hf);
551 memset(block,0xff,sizeof(block));
552 sbd[0]=STORAGE_CHAINENTRY_ENDOFCHAIN;
553 if (!STORAGE_put_big_block(hf,bigblocknr,block))
555 if (lastbigblocknr==-1) {
556 sth.sbd_startblock = bigblocknr;
557 if (!STORAGE_put_big_block(hf,-1,(LPBYTE)&sth)) /* need to write it */
560 if (!STORAGE_set_big_chain(hf,lastbigblocknr,bigblocknr))
563 if (!STORAGE_set_big_chain(hf,bigblocknr,STORAGE_CHAINENTRY_ENDOFCHAIN))
565 newblocknr = curblock*128;
567 /* allocate enough big blocks for storing the allocated small block */
568 if (!STORAGE_get_root_pps_entry(hf,&root))
573 lastbigblocknr = STORAGE_get_nth_next_big_blocknr(hf,root.pps_sb,(root.pps_size-1)/BIGSIZE);
574 while (root.pps_size < (newblocknr*SMALLSIZE+SMALLSIZE-1)) {
575 /* we need to allocate more stuff */
576 bigblocknr = STORAGE_get_free_big_blocknr(hf);
580 if (root.pps_sb==-1) {
581 root.pps_sb = bigblocknr;
582 root.pps_size += BIGSIZE;
584 if (!STORAGE_set_big_chain(hf,lastbigblocknr,bigblocknr))
586 root.pps_size += BIGSIZE;
588 lastbigblocknr = bigblocknr;
590 if (!STORAGE_set_big_chain(hf,lastbigblocknr,STORAGE_CHAINENTRY_ENDOFCHAIN))
592 if (!STORAGE_put_pps_entry(hf,0,&root))
597 /******************************************************************************
598 * STORAGE_get_free_pps_entry [Internal]
601 STORAGE_get_free_pps_entry(HFILE32 hf) {
602 int blocknr,i,curblock,lastblocknr;
604 struct storage_pps_entry *stde = (struct storage_pps_entry*)block;
605 struct storage_header sth;
608 blocknr = sth.root_startblock;
612 if (!STORAGE_get_big_block(hf,blocknr,block))
615 if (stde[i].pps_sizeofname==0) /* free */
617 lastblocknr = blocknr;
618 blocknr = STORAGE_get_next_big_blocknr(hf,blocknr);
621 assert(blocknr==STORAGE_CHAINENTRY_ENDOFCHAIN);
622 blocknr = STORAGE_get_free_big_blocknr(hf);
623 /* sth invalidated */
627 if (!STORAGE_set_big_chain(hf,lastblocknr,blocknr))
629 if (!STORAGE_set_big_chain(hf,blocknr,STORAGE_CHAINENTRY_ENDOFCHAIN))
631 memset(block,0,sizeof(block));
632 STORAGE_put_big_block(hf,blocknr,block);
636 /* --- IStream16 implementation */
638 typedef struct _IStream16 {
639 /* IUnknown fields */
640 ICOM_VTABLE(IStream16)* lpvtbl;
642 /* IStream16 fields */
643 SEGPTR thisptr; /* pointer to this struct as segmented */
644 struct storage_pps_entry stde;
647 ULARGE_INTEGER offset;
650 /******************************************************************************
651 * IStream16_QueryInterface [STORAGE.518]
653 HRESULT WINAPI IStream16_fnQueryInterface(
654 LPUNKNOWN iface,REFIID refiid,LPVOID *obj
656 ICOM_THIS(IStream16,iface);
658 WINE_StringFromCLSID((LPCLSID)refiid,xrefiid);
659 TRACE(relay,"(%p)->(%s,%p)\n",this,xrefiid,obj);
660 if (!memcmp(&IID_IUnknown,refiid,sizeof(IID_IUnknown))) {
664 return OLE_E_ENUM_NOMORE;
668 /******************************************************************************
669 * IStream16_AddRef [STORAGE.519]
671 ULONG WINAPI IStream16_fnAddRef(LPUNKNOWN iface) {
672 ICOM_THIS(IStream16,iface);
673 return ++(this->ref);
676 /******************************************************************************
677 * IStream16_Release [STORAGE.520]
679 ULONG WINAPI IStream16_fnRelease(LPUNKNOWN iface) {
680 ICOM_THIS(IStream16,iface);
681 FlushFileBuffers(this->hf);
684 CloseHandle(this->hf);
691 /******************************************************************************
692 * IStream16_Seek [STORAGE.523]
695 * Does not handle 64 bits
697 HRESULT WINAPI IStream16_fnSeek(
698 LPSTREAM16 iface,LARGE_INTEGER offset,DWORD whence,ULARGE_INTEGER *newpos
700 ICOM_THIS(IStream16,iface);
701 TRACE(relay,"(%p)->([%ld.%ld],%ld,%p)\n",this,offset.HighPart,offset.LowPart,whence,newpos);
704 /* unix SEEK_xx should be the same as win95 ones */
706 /* offset must be ==0 (<0 is invalid, and >0 cannot be handled
709 assert(offset.HighPart==0);
710 this->offset.HighPart = offset.HighPart;
711 this->offset.LowPart = offset.LowPart;
714 if (offset.HighPart < 0) {
715 /* FIXME: is this negation correct ? */
716 offset.HighPart = -offset.HighPart;
717 offset.LowPart = (0xffffffff ^ offset.LowPart)+1;
719 assert(offset.HighPart==0);
720 assert(this->offset.LowPart >= offset.LowPart);
721 this->offset.LowPart -= offset.LowPart;
723 assert(offset.HighPart==0);
724 this->offset.LowPart+= offset.LowPart;
728 assert(offset.HighPart==0);
729 this->offset.LowPart = this->stde.pps_size-offset.LowPart;
732 if (this->offset.LowPart>this->stde.pps_size)
733 this->offset.LowPart=this->stde.pps_size;
734 if (newpos) *newpos = this->offset;
738 /******************************************************************************
739 * IStream16_Read [STORAGE.521]
741 HRESULT WINAPI IStream16_fnRead(
742 LPSTREAM16 iface,void *pv,ULONG cb,ULONG *pcbRead
744 ICOM_THIS(IStream16,iface);
746 ULONG *bytesread=pcbRead,xxread;
749 TRACE(relay,"(%p)->(%p,%ld,%p)\n",this,pv,cb,pcbRead);
750 if (!pcbRead) bytesread=&xxread;
753 if (cb>this->stde.pps_size-this->offset.LowPart)
754 cb=this->stde.pps_size-this->offset.LowPart;
755 if (this->stde.pps_size < 0x1000) {
756 /* use small block reader */
757 blocknr = STORAGE_get_nth_next_small_blocknr(this->hf,this->stde.pps_sb,this->offset.LowPart/SMALLSIZE);
761 if (!STORAGE_get_small_block(this->hf,blocknr,block)) {
762 WARN(ole,"small block read failed!!!\n");
766 if (cc>SMALLSIZE-(this->offset.LowPart&(SMALLSIZE-1)))
767 cc=SMALLSIZE-(this->offset.LowPart&(SMALLSIZE-1));
768 memcpy((LPBYTE)pv,block+(this->offset.LowPart&(SMALLSIZE-1)),cc);
769 this->offset.LowPart+=cc;
773 blocknr = STORAGE_get_next_small_blocknr(this->hf,blocknr);
776 /* use big block reader */
777 blocknr = STORAGE_get_nth_next_big_blocknr(this->hf,this->stde.pps_sb,this->offset.LowPart/BIGSIZE);
781 if (!STORAGE_get_big_block(this->hf,blocknr,block)) {
782 WARN(ole,"big block read failed!!!\n");
786 if (cc>BIGSIZE-(this->offset.LowPart&(BIGSIZE-1)))
787 cc=BIGSIZE-(this->offset.LowPart&(BIGSIZE-1));
788 memcpy((LPBYTE)pv,block+(this->offset.LowPart&(BIGSIZE-1)),cc);
789 this->offset.LowPart+=cc;
793 blocknr=STORAGE_get_next_big_blocknr(this->hf,blocknr);
799 /******************************************************************************
800 * IStream16_Write [STORAGE.522]
802 HRESULT WINAPI IStream16_fnWrite(
803 LPSTREAM16 iface,const void *pv,ULONG cb,ULONG *pcbWrite
805 ICOM_THIS(IStream16,iface);
807 ULONG *byteswritten=pcbWrite,xxwritten;
808 int oldsize,newsize,i,curoffset=0,lastblocknr,blocknr,cc;
809 HFILE32 hf = this->hf;
811 if (!pcbWrite) byteswritten=&xxwritten;
814 TRACE(relay,"(%p)->(%p,%ld,%p)\n",this,pv,cb,pcbWrite);
815 /* do we need to junk some blocks? */
816 newsize = this->offset.LowPart+cb;
817 oldsize = this->stde.pps_size;
818 if (newsize < oldsize) {
819 if (oldsize < 0x1000) {
820 /* only small blocks */
821 blocknr=STORAGE_get_nth_next_small_blocknr(hf,this->stde.pps_sb,newsize/SMALLSIZE);
825 /* will set the rest of the chain to 'free' */
826 if (!STORAGE_set_small_chain(hf,blocknr,STORAGE_CHAINENTRY_ENDOFCHAIN))
829 if (newsize >= 0x1000) {
830 blocknr=STORAGE_get_nth_next_big_blocknr(hf,this->stde.pps_sb,newsize/BIGSIZE);
833 /* will set the rest of the chain to 'free' */
834 if (!STORAGE_set_big_chain(hf,blocknr,STORAGE_CHAINENTRY_ENDOFCHAIN))
837 /* Migrate large blocks to small blocks
838 * (we just migrate newsize bytes)
840 LPBYTE curdata,data = HeapAlloc(GetProcessHeap(),0,newsize+BIGSIZE);
842 blocknr = this->stde.pps_sb;
845 if (!STORAGE_get_big_block(hf,blocknr,curdata)) {
846 HeapFree(GetProcessHeap(),0,data);
851 blocknr = STORAGE_get_next_big_blocknr(hf,blocknr);
853 /* frees complete chain for this stream */
854 if (!STORAGE_set_big_chain(hf,this->stde.pps_sb,STORAGE_CHAINENTRY_FREE))
857 blocknr = this->stde.pps_sb = STORAGE_get_free_small_blocknr(hf);
862 if (!STORAGE_put_small_block(hf,blocknr,curdata))
866 if (!STORAGE_set_small_chain(hf,blocknr,STORAGE_CHAINENTRY_ENDOFCHAIN))
870 int newblocknr = STORAGE_get_free_small_blocknr(hf);
873 if (!STORAGE_set_small_chain(hf,blocknr,newblocknr))
875 blocknr = newblocknr;
877 curdata += SMALLSIZE;
879 HeapFree(GetProcessHeap(),0,data);
882 this->stde.pps_size = newsize;
885 if (newsize > oldsize) {
886 if (oldsize >= 0x1000) {
887 /* should return the block right before the 'endofchain' */
888 blocknr = STORAGE_get_nth_next_big_blocknr(hf,this->stde.pps_sb,this->stde.pps_size/BIGSIZE);
890 lastblocknr = blocknr;
891 for (i=oldsize/BIGSIZE;i<newsize/BIGSIZE;i++) {
892 blocknr = STORAGE_get_free_big_blocknr(hf);
895 if (!STORAGE_set_big_chain(hf,lastblocknr,blocknr))
897 lastblocknr = blocknr;
899 if (!STORAGE_set_big_chain(hf,blocknr,STORAGE_CHAINENTRY_ENDOFCHAIN))
902 if (newsize < 0x1000) {
903 /* find startblock */
905 this->stde.pps_sb = blocknr = STORAGE_get_free_small_blocknr(hf);
907 blocknr = STORAGE_get_nth_next_small_blocknr(hf,this->stde.pps_sb,this->stde.pps_size/SMALLSIZE);
911 /* allocate required new small blocks */
912 lastblocknr = blocknr;
913 for (i=oldsize/SMALLSIZE;i<newsize/SMALLSIZE;i++) {
914 blocknr = STORAGE_get_free_small_blocknr(hf);
917 if (!STORAGE_set_small_chain(hf,lastblocknr,blocknr))
919 lastblocknr = blocknr;
921 /* and terminate the chain */
922 if (!STORAGE_set_small_chain(hf,lastblocknr,STORAGE_CHAINENTRY_ENDOFCHAIN))
926 /* no single block allocated yet */
927 blocknr=STORAGE_get_free_big_blocknr(hf);
930 this->stde.pps_sb = blocknr;
932 /* Migrate small blocks to big blocks */
933 LPBYTE curdata,data = HeapAlloc(GetProcessHeap(),0,oldsize+BIGSIZE);
935 blocknr = this->stde.pps_sb;
939 if (!STORAGE_get_small_block(hf,blocknr,curdata)) {
940 HeapFree(GetProcessHeap(),0,data);
943 curdata += SMALLSIZE;
945 blocknr = STORAGE_get_next_small_blocknr(hf,blocknr);
947 /* free small block chain */
948 if (!STORAGE_set_small_chain(hf,this->stde.pps_sb,STORAGE_CHAINENTRY_FREE))
951 blocknr = this->stde.pps_sb = STORAGE_get_free_big_blocknr(hf);
954 /* put the data into the big blocks */
955 cc = this->stde.pps_size;
957 if (!STORAGE_put_big_block(hf,blocknr,curdata))
961 if (!STORAGE_set_big_chain(hf,blocknr,STORAGE_CHAINENTRY_ENDOFCHAIN))
965 int newblocknr = STORAGE_get_free_big_blocknr(hf);
968 if (!STORAGE_set_big_chain(hf,blocknr,newblocknr))
970 blocknr = newblocknr;
974 HeapFree(GetProcessHeap(),0,data);
976 /* generate big blocks to fit the new data */
977 lastblocknr = blocknr;
978 for (i=oldsize/BIGSIZE;i<newsize/BIGSIZE;i++) {
979 blocknr = STORAGE_get_free_big_blocknr(hf);
982 if (!STORAGE_set_big_chain(hf,lastblocknr,blocknr))
984 lastblocknr = blocknr;
986 /* terminate chain */
987 if (!STORAGE_set_big_chain(hf,lastblocknr,STORAGE_CHAINENTRY_ENDOFCHAIN))
991 this->stde.pps_size = newsize;
994 /* There are just some cases where we didn't modify it, we write it out
997 if (!STORAGE_put_pps_entry(hf,this->ppsent,&(this->stde)))
1000 /* finally the write pass */
1001 if (this->stde.pps_size < 0x1000) {
1002 blocknr = STORAGE_get_nth_next_small_blocknr(hf,this->stde.pps_sb,this->offset.LowPart/SMALLSIZE);
1005 /* we ensured that it is allocated above */
1007 /* Read old block everytime, since we can have
1008 * overlapping data at START and END of the write
1010 if (!STORAGE_get_small_block(hf,blocknr,block))
1013 cc = SMALLSIZE-(this->offset.LowPart&(SMALLSIZE-1));
1016 memcpy( ((LPBYTE)block)+(this->offset.LowPart&(SMALLSIZE-1)),
1017 (LPBYTE)(pv+curoffset),
1020 if (!STORAGE_put_small_block(hf,blocknr,block))
1025 this->offset.LowPart += cc;
1026 *byteswritten += cc;
1027 blocknr = STORAGE_get_next_small_blocknr(hf,blocknr);
1030 blocknr = STORAGE_get_nth_next_big_blocknr(hf,this->stde.pps_sb,this->offset.LowPart/BIGSIZE);
1033 /* we ensured that it is allocated above, so it better is */
1035 /* read old block everytime, since we can have
1036 * overlapping data at START and END of the write
1038 if (!STORAGE_get_big_block(hf,blocknr,block))
1041 cc = BIGSIZE-(this->offset.LowPart&(BIGSIZE-1));
1044 memcpy( ((LPBYTE)block)+(this->offset.LowPart&(BIGSIZE-1)),
1045 (LPBYTE)(pv+curoffset),
1048 if (!STORAGE_put_big_block(hf,blocknr,block))
1053 this->offset.LowPart += cc;
1054 *byteswritten += cc;
1055 blocknr = STORAGE_get_next_big_blocknr(hf,blocknr);
1061 /******************************************************************************
1062 * _create_istream16 [Internal]
1064 static void _create_istream16(LPSTREAM16 *str) {
1067 if (!strvt16.bvt.fnQueryInterface) {
1068 HMODULE16 wp = GetModuleHandle16("STORAGE");
1070 /* FIXME: what is this WIN32_GetProcAddress16. Should the name be IStream16_QueryInterface of IStream16_fnQueryInterface */
1071 #define VTENT(xfn) strvt16.bvt.fn##xfn = (void*)WIN32_GetProcAddress16(wp,"IStream16_"#xfn);
1072 VTENT(QueryInterface)
1076 #define VTENT(xfn) strvt16.fn##xfn = (void*)WIN32_GetProcAddress16(wp,"IStream16_"#xfn);
1089 segstrvt16 = SEGPTR_NEW(ICOM_VTABLE(IStream16));
1090 memcpy(segstrvt16,&strvt16,sizeof(strvt16));
1091 segstrvt16 = (ICOM_VTABLE(IStream16)*)SEGPTR_GET(segstrvt16);
1093 #define VTENT(xfn) strvt16.bvt.fn##xfn = IStream16_fn##xfn;
1094 VTENT(QueryInterface)
1098 #define VTENT(xfn) strvt16.fn##xfn = IStream16_fn##xfn;
1113 segstrvt16 = &strvt16;
1116 lpst = SEGPTR_NEW(_IStream16);
1117 lpst->lpvtbl = segstrvt16;
1119 lpst->thisptr = SEGPTR_GET(lpst);
1120 *str = (void*)lpst->thisptr;
1124 /* --- IStream32 implementation */
1126 typedef struct _IStream32 {
1127 /* IUnknown fields */
1128 ICOM_VTABLE(IStream32)* lpvtbl;
1130 /* IStream32 fields */
1131 struct storage_pps_entry stde;
1134 ULARGE_INTEGER offset;
1137 /*****************************************************************************
1138 * IStream32_QueryInterface [VTABLE]
1140 HRESULT WINAPI IStream32_fnQueryInterface(
1141 LPUNKNOWN iface,REFIID refiid,LPVOID *obj
1143 ICOM_THIS(IStream32,iface);
1146 WINE_StringFromCLSID((LPCLSID)refiid,xrefiid);
1147 TRACE(relay,"(%p)->(%s,%p)\n",this,xrefiid,obj);
1148 if (!memcmp(&IID_IUnknown,refiid,sizeof(IID_IUnknown))) {
1152 return OLE_E_ENUM_NOMORE;
1156 /******************************************************************************
1157 * IStream32_AddRef [VTABLE]
1159 ULONG WINAPI IStream32_fnAddRef(LPUNKNOWN iface) {
1160 ICOM_THIS(IStream32,iface);
1161 return ++(this->ref);
1164 /******************************************************************************
1165 * IStream32_Release [VTABLE]
1167 ULONG WINAPI IStream32_fnRelease(LPUNKNOWN iface) {
1168 ICOM_THIS(IStream32,iface);
1169 FlushFileBuffers(this->hf);
1172 CloseHandle(this->hf);
1179 static ICOM_VTABLE(IStream32) strvt32 = {
1181 IStream32_fnQueryInterface,
1196 /* --- IStorage16 implementation */
1198 typedef struct _IStorage16 {
1199 /* IUnknown fields */
1200 ICOM_VTABLE(IStorage16)* lpvtbl;
1202 /* IStorage16 fields */
1203 SEGPTR thisptr; /* pointer to this struct as segmented */
1204 struct storage_pps_entry stde;
1209 /******************************************************************************
1210 * IStorage16_QueryInterface [STORAGE.500]
1212 HRESULT WINAPI IStorage16_fnQueryInterface(
1213 LPUNKNOWN iface,REFIID refiid,LPVOID *obj
1215 ICOM_THIS(IStorage16,iface);
1218 WINE_StringFromCLSID((LPCLSID)refiid,xrefiid);
1219 TRACE(relay,"(%p)->(%s,%p)\n",this,xrefiid,obj);
1221 if (!memcmp(&IID_IUnknown,refiid,sizeof(IID_IUnknown))) {
1225 return OLE_E_ENUM_NOMORE;
1228 /******************************************************************************
1229 * IStorage16_AddRef [STORAGE.501]
1231 ULONG WINAPI IStorage16_fnAddRef(LPUNKNOWN iface) {
1232 ICOM_THIS(IStorage16,iface);
1233 return ++(this->ref);
1236 /******************************************************************************
1237 * IStorage16_Release [STORAGE.502]
1239 ULONG WINAPI IStorage16_fnRelease(LPUNKNOWN iface) {
1240 ICOM_THIS(IStorage16,iface);
1248 /******************************************************************************
1249 * IStorage16_Stat [STORAGE.517]
1251 HRESULT WINAPI IStorage16_fnStat(
1252 LPSTORAGE16 iface,STATSTG *pstatstg, DWORD grfStatFlag
1254 ICOM_THIS(IStorage16,iface);
1255 TRACE(ole,"(%p)->(%p,0x%08lx)\n",
1256 this,pstatstg,grfStatFlag
1258 pstatstg->pwcsName=(LPOLESTR16)SEGPTR_GET(SEGPTR_STRDUP_WtoA(this->stde.pps_rawname));
1259 pstatstg->type = this->stde.pps_type;
1260 pstatstg->cbSize.LowPart = this->stde.pps_size;
1261 pstatstg->mtime = this->stde.pps_ft1; /* FIXME */ /* why? */
1262 pstatstg->atime = this->stde.pps_ft2; /* FIXME */
1263 pstatstg->ctime = this->stde.pps_ft2; /* FIXME */
1264 pstatstg->grfMode = 0; /* FIXME */
1265 pstatstg->grfLocksSupported = 0; /* FIXME */
1266 pstatstg->clsid = this->stde.pps_guid;
1267 pstatstg->grfStateBits = 0; /* FIXME */
1268 pstatstg->reserved = 0;
1272 /******************************************************************************
1273 * IStorage16_Commit [STORAGE.509]
1275 HRESULT WINAPI IStorage16_fnCommit(
1276 LPSTORAGE16 iface,DWORD commitflags
1278 ICOM_THIS(IStorage16,iface);
1279 FIXME(ole,"(%p)->(0x%08lx),STUB!\n",
1285 /******************************************************************************
1286 * IStorage16_CopyTo [STORAGE.507]
1288 HRESULT WINAPI IStorage16_fnCopyTo(LPSTORAGE16 iface,DWORD ciidExclude,const IID *rgiidExclude,SNB16 SNB16Exclude,IStorage16 *pstgDest) {
1289 ICOM_THIS(IStorage16,iface);
1293 WINE_StringFromCLSID(rgiidExclude,xguid);
1295 strcpy(xguid,"<no guid>");
1296 FIXME(ole,"IStorage16(%p)->(0x%08lx,%s,%p,%p),stub!\n",
1297 this,ciidExclude,xguid,SNB16Exclude,pstgDest
1303 /******************************************************************************
1304 * IStorage16_CreateStorage [STORAGE.505]
1306 HRESULT WINAPI IStorage16_fnCreateStorage(
1307 LPSTORAGE16 iface,LPCOLESTR16 pwcsName,DWORD grfMode,DWORD dwStgFormat,DWORD reserved2, IStorage16 **ppstg
1309 ICOM_THIS(IStorage16,iface);
1312 struct storage_pps_entry stde;
1313 struct storage_header sth;
1314 HFILE32 hf=this->hf;
1318 TRACE(ole,"(%p)->(%s,0x%08lx,0x%08lx,0x%08lx,%p)\n",
1319 this,pwcsName,grfMode,dwStgFormat,reserved2,ppstg
1321 if (grfMode & STGM_TRANSACTED)
1322 FIXME(ole,"We do not support transacted Compound Storage. Using direct mode.\n");
1323 _create_istorage16(ppstg);
1324 lpstg = (_IStorage16*)PTR_SEG_TO_LIN(*ppstg);
1325 lpstg->hf = this->hf;
1327 ppsent=STORAGE_get_free_pps_entry(lpstg->hf);
1331 if (stde.pps_dir==-1) {
1332 stde.pps_dir = ppsent;
1335 FIXME(ole," use prev chain too ?\n");
1337 if (1!=STORAGE_get_pps_entry(lpstg->hf,x,&stde))
1339 while (stde.pps_next!=-1) {
1341 if (1!=STORAGE_get_pps_entry(lpstg->hf,x,&stde))
1344 stde.pps_next = ppsent;
1346 assert(STORAGE_put_pps_entry(lpstg->hf,x,&stde));
1347 assert(1==STORAGE_get_pps_entry(lpstg->hf,ppsent,&(lpstg->stde)));
1348 lstrcpyAtoW(lpstg->stde.pps_rawname,pwcsName);
1349 lpstg->stde.pps_sizeofname = lstrlen32A(pwcsName)*2+2;
1350 lpstg->stde.pps_next = -1;
1351 lpstg->stde.pps_prev = -1;
1352 lpstg->stde.pps_dir = -1;
1353 lpstg->stde.pps_sb = -1;
1354 lpstg->stde.pps_size = 0;
1355 lpstg->stde.pps_type = 1;
1356 lpstg->ppsent = ppsent;
1357 /* FIXME: timestamps? */
1358 if (!STORAGE_put_pps_entry(lpstg->hf,ppsent,&(lpstg->stde)))
1363 /******************************************************************************
1364 * IStorage16_CreateStream [STORAGE.503]
1366 HRESULT WINAPI IStorage16_fnCreateStream(
1367 LPSTORAGE16 iface,LPCOLESTR16 pwcsName,DWORD grfMode,DWORD reserved1,DWORD reserved2, IStream16 **ppstm
1369 ICOM_THIS(IStorage16,iface);
1372 struct storage_pps_entry stde;
1374 TRACE(ole,"(%p)->(%s,0x%08lx,0x%08lx,0x%08lx,%p)\n",
1375 this,pwcsName,grfMode,reserved1,reserved2,ppstm
1377 if (grfMode & STGM_TRANSACTED)
1378 FIXME(ole,"We do not support transacted Compound Storage. Using direct mode.\n");
1379 _create_istream16(ppstm);
1380 lpstr = (_IStream16*)PTR_SEG_TO_LIN(*ppstm);
1381 lpstr->hf = FILE_Dup(this->hf);
1382 lpstr->offset.LowPart = 0;
1383 lpstr->offset.HighPart = 0;
1385 ppsent=STORAGE_get_free_pps_entry(lpstr->hf);
1389 if (stde.pps_next==-1)
1392 while (stde.pps_next!=-1) {
1394 if (1!=STORAGE_get_pps_entry(lpstr->hf,x,&stde))
1397 stde.pps_next = ppsent;
1398 assert(STORAGE_put_pps_entry(lpstr->hf,x,&stde));
1399 assert(1==STORAGE_get_pps_entry(lpstr->hf,ppsent,&(lpstr->stde)));
1400 lstrcpyAtoW(lpstr->stde.pps_rawname,pwcsName);
1401 lpstr->stde.pps_sizeofname = lstrlen32A(pwcsName)*2+2;
1402 lpstr->stde.pps_next = -1;
1403 lpstr->stde.pps_prev = -1;
1404 lpstr->stde.pps_dir = -1;
1405 lpstr->stde.pps_sb = -1;
1406 lpstr->stde.pps_size = 0;
1407 lpstr->stde.pps_type = 2;
1408 lpstr->ppsent = ppsent;
1409 /* FIXME: timestamps? */
1410 if (!STORAGE_put_pps_entry(lpstr->hf,ppsent,&(lpstr->stde)))
1415 /******************************************************************************
1416 * IStorage16_OpenStorage [STORAGE.506]
1418 HRESULT WINAPI IStorage16_fnOpenStorage(
1419 LPSTORAGE16 iface,LPCOLESTR16 pwcsName, IStorage16 *pstgPrio, DWORD grfMode, SNB16 snbExclude, DWORD reserved, IStorage16 **ppstg
1421 ICOM_THIS(IStorage16,iface);
1426 TRACE(relay,"(%p)->(%s,%p,0x%08lx,%p,0x%08lx,%p)\n",
1427 this,pwcsName,pstgPrio,grfMode,snbExclude,reserved,ppstg
1429 if (grfMode & STGM_TRANSACTED)
1430 FIXME(ole,"We do not support transacted Compound Storage. Using direct mode.\n");
1431 _create_istorage16(ppstg);
1432 lpstg = (_IStream16*)PTR_SEG_TO_LIN(*ppstg);
1433 lpstg->hf = FILE_Dup(this->hf);
1434 lstrcpyAtoW(name,pwcsName);
1435 newpps = STORAGE_look_for_named_pps(lpstg->hf,this->stde.pps_dir,name);
1437 IStream16_fnRelease((IUnknown*)lpstg);
1441 if (1!=STORAGE_get_pps_entry(lpstg->hf,newpps,&(lpstg->stde))) {
1442 IStream16_fnRelease((IUnknown*)lpstg);
1445 lpstg->ppsent = newpps;
1449 /******************************************************************************
1450 * IStorage16_OpenStream [STORAGE.504]
1452 HRESULT WINAPI IStorage16_fnOpenStream(
1453 LPSTORAGE16 iface,LPCOLESTR16 pwcsName, void *reserved1, DWORD grfMode, DWORD reserved2, IStream16 **ppstm
1455 ICOM_THIS(IStorage16,iface);
1460 TRACE(relay,"(%p)->(%s,%p,0x%08lx,0x%08lx,%p)\n",
1461 this,pwcsName,reserved1,grfMode,reserved2,ppstm
1463 if (grfMode & STGM_TRANSACTED)
1464 FIXME(ole,"We do not support transacted Compound Storage. Using direct mode.\n");
1465 _create_istream16(ppstm);
1466 lpstr = (_IStream16*)PTR_SEG_TO_LIN(*ppstm);
1467 lpstr->hf = FILE_Dup(this->hf);
1468 lstrcpyAtoW(name,pwcsName);
1469 newpps = STORAGE_look_for_named_pps(lpstr->hf,this->stde.pps_dir,name);
1471 IStream16_fnRelease((IUnknown*)lpstr);
1475 if (1!=STORAGE_get_pps_entry(lpstr->hf,newpps,&(lpstr->stde))) {
1476 IStream16_fnRelease((IUnknown*)lpstr);
1479 lpstr->offset.LowPart = 0;
1480 lpstr->offset.HighPart = 0;
1481 lpstr->ppsent = newpps;
1485 /******************************************************************************
1486 * _create_istorage16 [INTERNAL]
1488 static void _create_istorage16(LPSTORAGE16 *stg) {
1491 if (!stvt16.bvt.fnQueryInterface) {
1492 HMODULE16 wp = GetModuleHandle16("STORAGE");
1494 #define VTENT(xfn) stvt16.bvt.fn##xfn = (void*)WIN32_GetProcAddress16(wp,"IStorage16_"#xfn);
1495 VTENT(QueryInterface)
1499 #define VTENT(xfn) stvt16.fn##xfn = (void*)WIN32_GetProcAddress16(wp,"IStorage16_"#xfn);
1502 VTENT(CreateStorage)
1505 VTENT(MoveElementTo)
1509 VTENT(DestroyElement)
1510 VTENT(RenameElement)
1511 VTENT(SetElementTimes)
1516 segstvt16 = SEGPTR_NEW(ICOM_VTABLE(IStorage16));
1517 memcpy(segstvt16,&stvt16,sizeof(stvt16));
1518 segstvt16 = (ICOM_VTABLE(IStorage16)*)SEGPTR_GET(segstvt16);
1520 #define VTENT(xfn) stvt16.bvt.fn##xfn = IStorage16_fn##xfn;
1521 VTENT(QueryInterface)
1525 #define VTENT(xfn) stvt16.fn##xfn = IStorage16_fn##xfn;
1528 VTENT(CreateStorage)
1532 /* not (yet) implemented ...
1533 VTENT(MoveElementTo)
1536 VTENT(DestroyElement)
1537 VTENT(RenameElement)
1538 VTENT(SetElementTimes)
1544 segstvt16 = &stvt16;
1547 lpst = SEGPTR_NEW(_IStorage16);
1548 lpst->lpvtbl = segstvt16;
1550 lpst->thisptr = SEGPTR_GET(lpst);
1551 *stg = (void*)lpst->thisptr;
1555 /* --- IStorage32 implementation */
1557 typedef struct _IStorage32 {
1558 /* IUnknown fields */
1559 ICOM_VTABLE(IStorage32)* lpvtbl;
1561 /* IStorage32 fields */
1562 struct storage_pps_entry stde;
1567 /******************************************************************************
1568 * IStorage32_QueryInterface [VTABLE]
1570 HRESULT WINAPI IStorage32_fnQueryInterface(
1571 LPUNKNOWN iface,REFIID refiid,LPVOID *obj
1573 ICOM_THIS(IStorage32,iface);
1576 WINE_StringFromCLSID((LPCLSID)refiid,xrefiid);
1577 TRACE(relay,"(%p)->(%s,%p)\n",this,xrefiid,obj);
1579 if (!memcmp(&IID_IUnknown,refiid,sizeof(IID_IUnknown))) {
1583 return OLE_E_ENUM_NOMORE;
1586 /******************************************************************************
1587 * IStorage32_AddRef [VTABLE]
1589 ULONG WINAPI IStorage32_fnAddRef(LPUNKNOWN iface) {
1590 ICOM_THIS(IStorage32,iface);
1591 return ++(this->ref);
1594 /******************************************************************************
1595 * IStorage32_Release [VTABLE]
1597 ULONG WINAPI IStorage32_fnRelease(LPUNKNOWN iface) {
1598 ICOM_THIS(IStorage32,iface);
1602 HeapFree(GetProcessHeap(),0,this);
1606 /******************************************************************************
1607 * IStorage32_CreateStream [VTABLE]
1609 HRESULT WINAPI IStorage32_fnCreateStream(
1610 LPSTORAGE32 iface,LPCOLESTR32 pwcsName,DWORD grfMode,DWORD reserved1,DWORD reserved2, IStream32 **ppstm
1612 ICOM_THIS(IStorage32,iface);
1613 TRACE(ole,"(%p)->(%p,0x%08lx,0x%08lx,0x%08lx,%p)\n",
1614 this,pwcsName,grfMode,reserved1,reserved2,ppstm
1616 *ppstm = (IStream32*)HeapAlloc(GetProcessHeap(),0,sizeof(IStream32));
1617 ((_IStream32*)(*ppstm))->lpvtbl= &strvt32;
1618 ((_IStream32*)(*ppstm))->ref = 1;
1623 /******************************************************************************
1624 * IStorage32_OpenStream [VTABLE]
1626 HRESULT WINAPI IStorage32_fnOpenStream(
1627 LPSTORAGE32 iface,LPCOLESTR32 pwcsName, void *reserved1, DWORD grfMode, DWORD reserved2, IStream32 **ppstm
1629 ICOM_THIS(IStorage32,iface);
1630 TRACE(ole,"(%p)->(%p,%p,0x%08lx,0x%08lx,%p)\n",
1631 this,pwcsName,reserved1,grfMode,reserved2,ppstm
1633 *ppstm = (IStream32*)HeapAlloc(GetProcessHeap(),0,sizeof(IStream32));
1634 ((_IStream32*)(*ppstm))->lpvtbl= &strvt32;
1635 ((_IStream32*)(*ppstm))->ref = 1;
1639 static ICOM_VTABLE(IStorage32) stvt32 = {
1641 IStorage32_fnQueryInterface,
1642 IStorage32_fnAddRef,
1643 IStorage32_fnRelease
1645 IStorage32_fnCreateStream,
1646 IStorage32_fnOpenStream,
1662 /******************************************************************************
1663 * Storage API functions
1666 /******************************************************************************
1667 * StgCreateDocFile16 [STORAGE.1]
1669 OLESTATUS WINAPI StgCreateDocFile16(
1670 LPCOLESTR16 pwcsName,DWORD grfMode,DWORD reserved,IStorage16 **ppstgOpen
1675 struct storage_pps_entry stde;
1677 TRACE(ole,"(%s,0x%08lx,0x%08lx,%p)\n",
1678 pwcsName,grfMode,reserved,ppstgOpen
1680 _create_istorage16(ppstgOpen);
1681 hf = CreateFile32A(pwcsName,GENERIC_READ|GENERIC_WRITE,0,NULL,CREATE_NEW,0,0);
1682 if (hf==INVALID_HANDLE_VALUE32) {
1683 WARN(ole,"couldn't open file for storage:%ld\n",GetLastError());
1686 lpstg = (_IStorage16*)PTR_SEG_TO_LIN(*ppstgOpen);
1688 /* FIXME: check for existance before overwriting? */
1689 if (!STORAGE_init_storage(hf)) {
1694 while (!ret) { /* neither 1 nor <0 */
1695 ret=STORAGE_get_pps_entry(hf,i,&stde);
1696 if ((ret==1) && (stde.pps_type==5)) {
1704 IStorage16_fnRelease((IUnknown*)lpstg); /* will remove it */
1710 /******************************************************************************
1711 * StgCreateDocFile32 [OLE32.144]
1713 OLESTATUS WINAPI StgCreateDocFile32(
1714 LPCOLESTR32 pwcsName,DWORD grfMode,DWORD reserved,IStorage32 **ppstgOpen
1716 TRACE(ole,"(%p,0x%08lx,0x%08lx,%p)\n",
1717 pwcsName,grfMode,reserved,ppstgOpen
1719 *ppstgOpen = (IStorage32*)HeapAlloc(GetProcessHeap(),0,sizeof(IStorage32));
1720 ((_IStorage32*)(*ppstgOpen))->ref = 1;
1721 ((_IStorage32*)(*ppstgOpen))->lpvtbl = &stvt32;
1725 /******************************************************************************
1726 * StgIsStorageFile16 [STORAGE.5]
1728 OLESTATUS WINAPI StgIsStorageFile16(LPCOLESTR16 fn) {
1733 TRACE(ole,"(\'%s\')\n",fn);
1734 hf = OpenFile32(fn,&ofs,OF_SHARE_DENY_NONE);
1735 if (hf==HFILE_ERROR32)
1736 return STG_E_FILENOTFOUND;
1737 if (24!=_lread32(hf,magic,24)) {
1738 WARN(ole," too short\n");
1742 if (!memcmp(magic,STORAGE_magic,8)) {
1743 WARN(ole," -> YES\n");
1747 if (!memcmp(magic,STORAGE_notmagic,8)) {
1748 WARN(ole," -> NO\n");
1752 if (!memcmp(magic,STORAGE_oldmagic,8)) {
1753 WARN(ole," -> old format\n");
1755 return STG_E_OLDFORMAT;
1757 WARN(ole," -> Invalid header.\n");
1759 return STG_E_INVALIDHEADER;
1762 /******************************************************************************
1763 * StgIsStorageFile32 [OLE32.146]
1766 StgIsStorageFile32(LPCOLESTR32 fn)
1768 LPOLESTR16 xfn = HEAP_strdupWtoA(GetProcessHeap(),0,fn);
1769 OLESTATUS ret = StgIsStorageFile16(xfn);
1771 HeapFree(GetProcessHeap(),0,xfn);
1776 /******************************************************************************
1777 * StgOpenStorage16 [STORAGE.3]
1779 OLESTATUS WINAPI StgOpenStorage16(
1780 const OLECHAR16 * pwcsName,IStorage16 *pstgPriority,DWORD grfMode,
1781 SNB16 snbExclude,DWORD reserved, IStorage16 **ppstgOpen
1786 struct storage_pps_entry stde;
1788 TRACE(ole,"(%s,%p,0x%08lx,%p,%ld,%p)\n",
1789 pwcsName,pstgPriority,grfMode,snbExclude,reserved,ppstgOpen
1791 _create_istorage16(ppstgOpen);
1792 hf = CreateFile32A(pwcsName,GENERIC_READ,0,NULL,0,0,0);
1793 if (hf==INVALID_HANDLE_VALUE32) {
1794 WARN(ole,"Couldn't open file for storage\n");
1797 lpstg = (_IStorage16*)PTR_SEG_TO_LIN(*ppstgOpen);
1801 while (!ret) { /* neither 1 nor <0 */
1802 ret=STORAGE_get_pps_entry(hf,i,&stde);
1803 if ((ret==1) && (stde.pps_type==5)) {
1810 IStorage16_fnRelease((IUnknown*)lpstg); /* will remove it */
1817 /******************************************************************************
1818 * StgOpenStorage32 [OLE32.148]
1820 OLESTATUS WINAPI StgOpenStorage32(
1821 const OLECHAR32 * pwcsName,IStorage32 *pstgPriority,DWORD grfMode,
1822 SNB32 snbExclude,DWORD reserved, IStorage32 **ppstgOpen
1824 FIXME(ole,"StgOpenStorage32(%p,%p,0x%08lx,%p,%ld,%p),stub!\n",
1825 pwcsName,pstgPriority,grfMode,snbExclude,reserved,
1827 *ppstgOpen = (IStorage32*)HeapAlloc(GetProcessHeap(),0,sizeof(IStorage32));
1828 ((_IStorage32*)(*ppstgOpen))->ref = 1;
1829 ((_IStorage32*)(*ppstgOpen))->lpvtbl = &stvt32;