OWLNext    7.0
Borland's Object Windows Library for the modern age
Loading...
Searching...
No Matches
stgdoc.cpp
Go to the documentation of this file.
1//----------------------------------------------------------------------------
2// ObjectWindows
3// Copyright (c) 1993, 1996 by Borland International, All Rights Reserved
4/// \file
5/// Implementation of classes TStorageDocument, TDocFile, and associated streams
6//
7//----------------------------------------------------------------------------
8#include <ocf/pch.h>
9
10#include <owl/docview.h> // force Windows headers in before OLE
11#include <owl/string.h>
12#include <ocf/stgdoc.h>
13#include <stdio.h>
14
15#include <streambuf>
16
17namespace ocf {
18
19using namespace owl;
20
21using namespace std;
22
24
25//
26// Simple refcount debug assistant
27//
28#if defined(CHECK_REFCOUNT)
29static void RefCountCheck(IStorage * si) {
30 uint32 count = si->AddRef();
31 count = si->Release();
32}
33#else
34# define RefCountCheck(si)
35#endif
36
37const int B_size = 516; // default buffer size
38const _TCHAR DefaultStreamName[] = _T("Contents");
39
40//
41// class TStorageBuf
42// ~~~~~ ~~~~~~~~~~~
43class TStorageBuf : public streambuf {
44 bool buffered_;
45 char *base_;
46 char *ebuf_;
47 public:
48 // Constructors, destructor
49 //
50 TStorageBuf * open(IStorage& stg, LPCTSTR name, int omode);
51 TStorageBuf(); // make a closed TStorageBuf
52 virtual ~TStorageBuf();
53
54 int is_open() { return opened; } // is the file open
55 IStream* fd() { return strm; }
56
57 TStorageBuf * close(); // flush and close file
58// TStorageBuf * attach(IStream*); // attach this TStorageBuf to opened IStream
59
60 int_type eof(){
61 return traits_type::eof();
62 }
63
64 virtual int_type overflow(int_type c = traits_type::eof());
65 virtual int_type underflow();
66 virtual int sync();
67 virtual streambuf * setbuf(char_type *, streamsize);
68
69 virtual pos_type seekoff(off_type off, ios_base::seekdir way,
70 ios_base::openmode which = ios_base::in |
71 ios_base::out);
72 virtual pos_type seekpos(pos_type sp,
73 ios_base::openmode which =
74 ios_base::in | ios_base::out);
75 int out_waiting(){
76 return pptr() ? (int)(pptr() - pbase()) : 0;
77 }
78
79 void setb(char *beg, char *end, int = 0){
80 streamsize size_buf = end - beg;
81 buffered_ = beg && size_buf;
82 setbuf(beg, size_buf);
83 }
84
85 int unbuffered(){
86 return !buffered_;
87 }
88
89 char *base(){
90 return base_;
91 }
92
93 int blen(){
94 return (int) (ebuf_ - base_);
95 }
96
97 protected:
98// IStorage* stg; // parent storage
99 IStream* strm;
100 int mode; // the opened mode
101 short opened; // non-zero if stream is open
102 uint64 last_seek;
103 char lahead[2]; // current input char if unbuffered
104};
105
106//
107// class TStorageStreamBase
108// ~~~~~ ~~~~~~~~~~~~~~~~~~
109class TStorageStreamBase : virtual public ios {
110 public:
111 TStorageStreamBase(IStorage& stg, LPCTSTR name, int mode);
112 ~TStorageStreamBase() {}
113 void setbuf(char *, int);
114 void close();
115
116 TStorageBuf buf;
117};
118
119//
120// class TStorageInStream
121// ~~~~~ ~~~~~~~~~~~~~~~~
122class TStorageInStream : public TStorageStreamBase,
123 public TInStream {
124 public:
125 TStorageInStream(TStorageDocument& doc, LPCTSTR name, int mode)
126 : TInStream(doc, name, mode),
127 TStorageStreamBase(*doc.StorageI,name, mode) {}
128 ~TStorageInStream() {}
129};
130
131//
132// class TStorageOutStream
133// ~~~~~ ~~~~~~~~~~~~~~~~~
134class TStorageOutStream : public TStorageStreamBase,
135 public TOutStream {
136 public:
137 TStorageOutStream(TStorageDocument& doc, LPCTSTR name, int mode)
138 : TOutStream(doc, name, mode),
139 TStorageStreamBase(*doc.StorageI,name, mode) {}
140 ~TStorageOutStream() {}
141};
142
143inline long IosToStgOpenMode(int omode)
144{
145 return ((omode & (ofRead|ofWrite)) - 1);
146}
147
148inline long IosToStgShareMode(int omode)
149{
150 return ((omode & shMask) - shCompat) >> 5;
151}
152
153inline long IosToStgTempMode(int omode)
154{
155 return (omode & ofTemporary) ? STGM_DELETEONRELEASE : 0;
156}
157
158inline long IosToStgMode(int omode)
159{
160 return IosToStgOpenMode(omode) |
163}
164
169
170inline int StgToIosOpenMode(long grfMode)
171{
172 return (int)((grfMode & stgRdWrMask) + 1);
173}
174
176{
177 return (int)(((grfMode & stgShareMask) << 5) + shCompat);
178}
179
180inline int StgToIosTempMode(long grfMode)
181{
183}
184
185inline int StgToIosMode(long grfMode)
186{
187 return StgToIosOpenMode(grfMode) |
189 (int)((grfMode & stgModeMask) >> 4);
190}
191
192//----------------------------------------------------------------------------
193// class TStorageDocument
194//
195
196//
197//
198//
200{
201 ReleaseDoc();
202 SetDirty(false); // ~TDocument() will Close() after destroying children
203}
204
205//
206/// Release the IStorage and close the document
207//
208bool
210{
211 CanRelease = true; // now we can release the storage
212 return Close();
213}
214
215//
216/// Open the compound file with a given path
217//
218bool
220{
221 if (StorageI)
222 return true;
223
224 do { // establish try block
225 HRESULT hr;
227 int pmode = 0;
228
229 if (!omode)
230 omode = GetOpenMode();
231
232 if (GetParentDoc()) {
234 if (!(GetParentDoc()->Open(pmode ? pmode : omode, name)))
235 return false;
236 }
237 ++OpenCount;
238 if (!omode)
239 omode = pmode;
240 if (!(omode & (ofRead | ofWrite)))
241 break;
242
243 // Provide default share mode flags & enforce root storage restrictions
244 // when in direct mode
245 //
246 if (!(omode & shMask)) {
247 if (!(omode & ofTransacted) && !GetParentDoc()) { // direct mode root stg
248 if (omode & ofWrite)
249 omode |= ofRead | shNone; // let others do nothing if we are writing
250 else
251 omode |= shRead; // let others only read if we are readonly
252 }
253 else {
254 if (omode & ofWrite)
255 omode |= shRead; // let others only read if we are writing
256 else
257 omode |= shReadWrite; // let others read/write if we are readonly
258 }
259 }
260
261 ThisOpen = omode;
262 SetOpenMode(omode); // remember the open mode
263 if (name && name[0])
265 else
266 name = GetDocPath();
268 long childMode = (grfMode & ~stgShareMask) | STGM_SHARE_EXCLUSIVE;
269
270 bool stgopen = true;
271 bool stgcreate = false;
272
273 if (omode & ofWrite) {
274 if (omode & (ofNoReplace)) {
275 stgopen = false;
276 stgcreate = true;
277 }
278 else if (!(omode & (ofNoCreate))) {
279 stgcreate = true;
280 if (omode & ofTruncate || !(omode & (ofAtEnd | ofAppend))) {
281 stgopen = false;
284 }
285 }
286 }
287 if (GetParentDoc()) {
288 if (!GetParentDoc()->GetProperty(FindProperty(_T("IStorage Instance")),
289 &parentStg, 0))
290 break;
291 if (stgopen) {
292 hr = parentStg->OpenStorage(OleStr(name), 0, childMode, 0, 0, &StorageI);
293 if (SUCCEEDED(hr))
294 stgcreate = false;
295 }
296 if (stgcreate) {
297 hr = parentStg->CreateStorage(OleStr(name), childMode, 0, 0, &StorageI);
298 }
299 }
300 else {
301 if (stgopen) {
302 hr = ::StgOpenStorage(OleStr(name), 0, grfMode, 0, 0, &StorageI);
303 if (SUCCEEDED(hr))
304 stgcreate = false;
305 }
306 if (stgcreate) {
307 hr = ::StgCreateDocfile(OleStr(name), grfMode, 0, &StorageI);
308 }
309 }
310 RefCountCheck(StorageI);
311
312 if (!SUCCEEDED(hr))
313 break;
314 NotifyViews(vnDocOpened,ThisOpen);
315 return true; // successful return
316 } while (0); // dummy for break scoping, never executed
317
318 // exception handling
319 //
320 if (GetParentDoc())
321 GetParentDoc()->Close();
322 --OpenCount;
323
324 return false;
325}
326
327//
328/// Give an IStorage to document. This typically happens for OLE servers.
329//
330bool
332{
333 if (stg == StorageI)
334 return true; // already set
335
336 if (StorageI) {
337 RefCountCheck(StorageI);
338 if (remember) {
339 StorageI->Release(); // Release the ole one
340 OrgStorageI = 0;
341 }
342 else
343 OrgStorageI = StorageI;
344 }
345
346 StorageI = stg;
347 if (!StorageI)
348 return true; // done
349
350 StorageI->AddRef();
351 RefCountCheck(StorageI);
352
354 if (!SUCCEEDED(stg->Stat(&stgInfo, 0)))
355 return false;
356
358
359 ThisOpen = GetOpenMode();
360 if (remember)
361 {
362 if (stgInfo.pwcsName)
363 SetDocPath(OleStr(stgInfo.pwcsName));
364 else
365 SetDocPath(_T(" "));
366 }
367
368 if (stgInfo.pwcsName) {
371 memmgr->Free(stgInfo.pwcsName); // Free the string from the Stat call
372 memmgr->Release();
373 }
374 }
375
376// NotifyViews(vnDocOpened,ThisOpen);
377 return true;
378}
379
380//
381/// Restore the original root IStorage before the save operation
382//
383bool
385{
386 if (OrgStorageI) {
387 if (StorageI)
388 StorageI->Release();
389
390 StorageI = OrgStorageI;
391 OrgStorageI = 0;
392 }
393
394 return true;
395}
396
397//
398/// Get a new IStorage, typically in a SaveAs situation. Release StorageI and
399/// set it to the new storage if all OK.
400//
403{
404 PRECONDITION(StorageI);
405
407 if (!SUCCEEDED(StorageI->Stat(&stgInfo, STATFLAG_NONAME)))
408 return 0;
409
410 // Create another root storage based on the new doc path
411 // Should close the current document and open a new one.
412 //
413 IStorage* newStorage = 0;
414
415 HRESULT hr;
416 hr = ::StgOpenStorage(OleStr(GetDocPath()), 0, stgInfo.grfMode, 0, 0, &newStorage);
417 if (!SUCCEEDED(hr))
419
420 if (SUCCEEDED(hr)) {
421 StorageI->Release(); // Release the old root storage
422 StorageI = newStorage;
423 }
424
425 return newStorage;
426}
427
428//
429/// Create an IStorage based on a memory handle
430//
431bool
433{
434 int pmode = 0;
435
436 if (!omode)
437 omode = GetOpenMode();
438
439 if (!omode)
440 omode = pmode;
441 if (!(omode & (ofRead | ofWrite)))
442 return false;
443 if (!(omode & shMask))
444 omode |= shNone;
445
446 ThisOpen = omode;
447 SetOpenMode(omode); // remember the open mode
450 return false;
451 if (!SUCCEEDED(StgCreateDocfileOnILockBytes(LockBytes, grfMode, 0, &StorageI))) {
452 LockBytes->Release();
453 LockBytes = 0;
454 return false;
455 }
456 ++OpenCount;
458 return true;
459}
460
461//
462/// Replace the IStorage with an istorage based on a memory handle
463//
464bool
466{
467 int pmode = 0;
468
469 if (!omode)
470 omode = GetOpenMode();
471
472 if (!omode)
473 omode = pmode;
474 if (!(omode & (ofRead | ofWrite)))
475 return false;
476 if (!(omode & shMask))
477 omode |= shNone;
478
479 ThisOpen = omode;
480 SetOpenMode(omode); // remember the open mode
481 long grfMode = IosToStgMode(omode);
483 return false;
484
485 IStorage* storageI = 0;
486 if (!SUCCEEDED(StgOpenStorageOnILockBytes(LockBytes, 0, grfMode, 0, 0, &storageI))) {
488 grfMode |STGM_CREATE, 0, &storageI))) {
489 LockBytes->Release();
490 LockBytes = 0;
491 return false;
492 }
493
494 if (!storageI)
495 return false;
496 }
497
499
500 // Don't change the embedded flag
501 bool embed = IsEmbedded();
504
505 storageI->Release(); // release extra refcount held by SetStorage
506 return true;
507}
508
509//
510/// Get the global handle from ILockBytes
511//
512bool
514{
515 if (!LockBytes)
516 return false;
517
519 return true;
520}
521
522//
523//
524//
525bool
527{
528 if (!StorageI || !CanRelease)
529 return true;
530
531 if (StorageI)
532 StorageI->Release();
533
534 StorageI = 0;
535 NotifyViews(vnDocClosed,ThisOpen);
536 SetDirty(false);
537 CanRelease = false;
538 if (GetParentDoc())
539 GetParentDoc()->Close();
540 return true;
541}
542
543//
544void
545TStorageDocument::DetachStream(TStream& strm)
546{
549}
550
551//
552//
553//
556{
558 if (omode == (ofParent))
559 omode = IsOpen() ? ThisOpen : GetOpenMode();
560 if (!(omode & ofRead))
561 return 0;
563 return 0;
564
565 inStream = new TStorageInStream(*this, strmId, omode);
566 if (inStream && !inStream->good()) {
567 delete inStream;
568 TStorageDocument::Close(); // close
569 return 0;
570 }
571
572 return inStream;
573}
574
575//
576//
577//
580{
582 if (omode == (ofParent))
583 omode = IsOpen() ? ThisOpen : GetOpenMode();
584 if (!(omode & ofWrite))
585 return 0;
587 return 0;
588 outStream = new TStorageOutStream(*this, strmId, omode); // change
589 if (outStream && !outStream->good()) {
590 delete outStream;
591 TStorageDocument::Close(); // change
592 return 0;
593 }
594 SetDirty(); // we don't really know at this point if it will be dirty!!
595 return outStream;
596}
597
598//
599//
600//
601bool
607
608//
609//
610//
611bool
613{
614 if (!TDocument::Commit(force)) // flush views and child docs
615 return false;
616 if (!StorageI)
617 return true; // return OK if storage already released
618
620 SetDirty(false);
621 return true;
622}
623
624//
625//
626//
627bool
629{
630 HRESULT hr = StorageI->Commit(0); // try 2phase commit first
631 if (!SUCCEEDED(hr)) // check for STG_S_TRYOVERWRITE, but GetScode not in lib
632 hr = StorageI->Commit(STGC_OVERWRITE); // try less robust method
633 if (!SUCCEEDED(hr))
634 return false;
635
636 return true;
637}
638
639//
640//
641//
642bool
644{
645 if (!StorageI)
646 return true; // return OK if storage already released
647 if (!TDocument::Revert(clear) || !SUCCEEDED(StorageI->Revert()))
648 return false;
649 SetDirty(false);
650 return true;
651}
652
653//
654//
655//
656static LPCTSTR PropNames[] = {
657 _T("Create Time"), // CreateTime
658 _T("Modify Time"), // ModifyTime
659 _T("Access Time"), // AccessTime
660 _T("Storage Size"), // StorageSize
661 _T("IStorage Instance"),// IStorageInstance
662};
663
664//
665//
666//
667static int PropFlags[] = {
668 pfGetBinary|pfGetText, // CreateTime
669 pfGetBinary|pfGetText, // ModifyTime
670 pfGetBinary|pfGetText, // AccessTime
671 pfGetBinary|pfGetText, // StorageSize
672 pfGetBinary, // IStorage
673};
674
675//
676//
677//
680{
681 if (index <= PrevProperty)
682 return TDocument::PropertyName(index);
683 else if (index < NextProperty)
684 return PropNames[index-PrevProperty-1];
685 else
686 return 0;
687}
688
689//
690//
691//
692int
694{
695 if (index <= PrevProperty)
696 return TDocument::PropertyFlags(index);
697 else if (index < NextProperty)
698 return PropFlags[index-PrevProperty-1];
699 else
700 return 0;
701}
702
703//
704//
705//
706int
708{
709 for (int i = 0; i < NextProperty-PrevProperty-1; i++)
710 if (_tcscmp(PropNames[i], name) == 0)
711 return i+PrevProperty+1;
712 return 0;
713}
714
715//
716//
717//
718int
720{
721 // Formats a file date + time string.
722 //
723 const auto formatFileTime = [](const FILETIME& pft, void* dest, int textlen) -> int
724 {
725 tchar buf[40];
726 int len;
727
728 if (!textlen)
729 {
730 *(FILETIME*) dest = pft;
731 return sizeof(FILETIME);
732 }
733 SYSTEMTIME dt;
735 len = _sntprintf(buf, COUNTOF(buf), _T("%d/%d/%d %02d:%02d:%02d.%02d"),
736 dt.wMonth, dt.wDay, dt.wYear,
737 dt.wHour, dt.wMinute, dt.wSecond, dt.wMilliseconds / 10);
738 if (textlen > len)
739 textlen = len;
740 memcpy(dest, buf, textlen * sizeof(tchar));
741 *((LPTSTR) dest + textlen) = _T('\0');
742 return len;
743 };
744
746
747 switch (prop) {
748 case IStorageInstance:
749 if (textlen)
750 return 0;
751 *(IStorage**)dest = StorageI;
752 return sizeof(IStorage*);
753
754 default:
755 if (StorageI) {
756 StorageI->Stat(&stgInfo, STATFLAG_NONAME);
757 switch (prop) {
758 case StorageSize:
759 if (!textlen) {
760 *(ulong *)dest = (uint32)(*(uint64*)&stgInfo.cbSize);
761 return sizeof(ulong);
762 }
763 else {
764 TCHAR buf[10];
765 int len = _stprintf(buf, _T("%ld"), (uint32)(*(uint64*)&stgInfo.cbSize));
766 if (textlen > len)
767 textlen = len;
768 memcpy(dest, buf, textlen);
769 *((LPTSTR)dest + textlen) = 0;
770 return len;
771 }
772 case AccessTime:
773 return formatFileTime(stgInfo.atime, dest, textlen);
774 case CreateTime:
775 return formatFileTime(stgInfo.ctime, dest, textlen);
776 case ModifyTime:
777 return formatFileTime(stgInfo.mtime, dest, textlen);
778 }
779 }
781 }
782}
783
784//
785//
786//
787bool
789{
790 // docfile properties currently not settable
791 //
793}
794
796
797#if OWL_PERSISTENT_STREAMS
798
799//
800//
801//
802void*
803TStorageDocument::Streamer::Read(ipstream& is, uint32 /*version*/) const
804{
805 owl::ReadBaseObject((TDocument*)GetObject(), is);
806 return GetObject();
807}
808
809//
810//
811//
812void
813TStorageDocument::Streamer::Write(opstream& os) const
814{
815 owl::WriteBaseObject((TDocument*)GetObject(), os);
816}
817
818#endif
819
820//----------------------------------------------------------------------------
821// class TStorageStreamBase
822//
823
824//
825//
826//
827TStorageStreamBase::TStorageStreamBase(IStorage& stg, LPCTSTR name, int mode)
828:
829 buf()
830{
831 ios::init(&buf);
832
833 if (buf.is_open())
834 clear(ios::failbit); // fail - already open
835 else if (buf.open(stg, name, mode))
836 clear(ios::goodbit); // successful open
837 else
838 clear(ios::badbit); // open failed
839}
840
841void TStorageStreamBase::setbuf(char* newbuf, int len)
842{
843 if (buf.setbuf(newbuf, len))
844 clear(ios::goodbit);
845 else
846#if defined(BI_COMP_BORLANDC)
847 setstate(ios::failbit);
848#else
849 clear(ios::failbit);
850#endif
851}
852
853void TStorageStreamBase::close()
854{
855 if (buf.close())
856 clear(ios::goodbit);
857 else
858#if defined(BI_COMP_BORLANDC)
859 setstate(ios::failbit);
860#else
861 clear(ios::failbit);
862#endif
863}
864
865//----------------------------------------------------------------------------
866// class TStorageBuf
867//
868
869//
870// make a closed TStorageBuf
871//
872TStorageBuf::TStorageBuf()
873:
874 buffered_(false),
875 base_(0),
876 ebuf_(0)
877{
878 mode = 0;
879 opened = 0;
880 char* p = new char[B_size];
881 if (p) {
882 setb(p, p+B_size, 1); // ~streambuf() will delete buffer
883 setp(p+4, p+4);
884 setg(p, p+4, p+4);
885 }
886}
887
888//
889/// We assume that mode= means that we attached to an already-open file,
890/// and should not now close it. We do flush it in any case.
891//
892TStorageBuf::~TStorageBuf()
893{
894 if (mode)
895 close();
896 else
897 overflow(eof());
898 delete[] base_;
899}
900
901//
902/// Open or create IStream with mode and protection, attach to this TStorageBuf.
903//
904TStorageBuf* TStorageBuf::open(IStorage& stg, LPCTSTR name, int omode)
905{
906//int share = omode & shMask;
907//if (share < shCompat)
908// share = shNone;
909//how = (share-shCompat) >> 5;
910
911 if (opened || !omode)
912 return 0;
913
914 if (!name)
916
917 bool stgopen = true;
918 bool stgcreate = false;
919 uint32 how = STGM_SHARE_EXCLUSIVE; // must open streams and child stg exclusive
920
921 if (omode & ofWrite) {
922 if (!(mode & (ofAtEnd | ofAppend | ofRead)))
923 omode |= ofTruncate; // output implies truncate unless in, app, or ate
924 if (omode & ofRead)
926 else
927 how |= STGM_WRITE;
928 if (omode & (ofNoReplace)) {
929 stgopen = false;
930 stgcreate = true;
931 }
932 else if (!(omode & (ofNoCreate))) {
933 stgcreate = true;
934 if (omode & ofTruncate) {
935 stgopen = false;
936 how |= STGM_CREATE;
937 }
938 }
939 }
940 else if (omode & ofRead)
941 how |= STGM_READ;
942 else
943 return 0; // must specfify in, out, or in/out
944
945//if (omode & ofAppend) // what does this mean for docfile?!!
946// how |= O_APPEND;
947
948 // Now try to open or create
949 //
950 if (stgopen) {
951 HRESULT hr = stg.OpenStream(OleStr(name), 0, how, 0, &strm);
952 if (SUCCEEDED(hr))
953 stgcreate = false;
954 else
955 return 0;
956 }
957 if (stgcreate) {
958 HRESULT hr = stg.CreateStream(OleStr(name), how, 0, 0, &strm);
959 if (!SUCCEEDED(hr))
960 return 0;
961 }
962
963 // Finish up
964 //
965 opened = 1;
966 mode = omode;
967 LARGE_INTEGER uli = {0,0};
968 if ((omode & ofAtEnd) != 0
969 && !SUCCEEDED(strm->Seek(uli, STREAM_SEEK_END, (ULARGE_INTEGER*)&last_seek))) {
970 strm->Release();
971 strm = 0;
972 return 0;
973 }
974 char* b = base(); // buffer address
975 int pb = b ? ((blen() > 8) ? 4 : 1) : 0; // putback area size
976 setp(b+pb, b+pb);
977 setg(b, b+pb, b+pb);
978
979 return this;
980}
981
982#if 0
983//
984// attach this TStorageBuf to open IStream -- assume fd is actually open
985//
986TStorageBuf* TStorageBuf::attach(IStream* f)
987{
988 STATSTG stat;
989 if (opened)
990 return 0;
991
992 if (f->Stat(&stat, STATFLAG_NONAME) != 0)
993 return 0;
994
995 if (f->CreateStream(STREAMNAME,stat.grfMode & ~STGM_TRANSACTED,0,0,&strm)!)
996 return 0;
997
998 stg = f; // assumed to be valid
999 opened = 1;
1000 int rwmode = stat.grfMode & (STGM_READ | STGM_WRITE | STGM_READWRITE);
1001 mode = rwmode != STGM_WRITE ? ofRead : 0;
1002 if (rwmode != STGM_READ)
1003 mode |= ofWrite;
1004
1005 char* b = base(); // buffer address
1006 if (!b) {
1007 b = new char[B_size];
1008 if (b)
1009 setb(b, b+B_size, 1); // ~streambuf() will delete buffer
1010 }
1011 int pb = b ? ((blen() > 8) ? 4 : 1) : 0; // putback area size
1012 setp(b+pb, b+pb);
1013 setg(b, b+pb, b+pb);
1014 return this;
1015}
1016
1017#endif
1018
1019//
1020//
1021//
1022streambuf*
1023TStorageBuf::setbuf(char_type* b, streamsize len)
1024{
1025 if (opened && base())
1026 return 0; // already open with a buffer -- no change
1027
1028 int pb; // putback area size
1029 if (b && len > 0) // use b as the new buffer
1030 pb = (len > 8) ? 4 : 1; // guard against tiny buffers
1031 else { // unbuffered
1032 len = pb = 0;
1033 b = 0;
1034 }
1035 delete[] base_;
1036 base_ = b;
1037 ebuf_ = b + len;
1038 setp(b+pb, b+pb);
1039 setg(b, b+pb, b+pb);
1040 return this;
1041}
1042
1043//
1044/// Seek file to position.
1045/// We take a simple approach, and don't check for small position changes
1046/// within the current buffer.
1047//
1048TStorageBuf::pos_type TStorageBuf::seekoff(off_type off,
1049 ios_base::seekdir dir, ios_base::openmode /* which */)
1050{
1051 int64 loff = static_cast<int64>(off);
1052 int count = out_waiting();
1053
1054 if (count) { // flush the output
1055 ulong actual;
1056 HRESULT hr = strm->Write(pbase(), (ulong)count, &actual);
1057 if (!SUCCEEDED(hr) || (int)actual != count)
1058 return eof();
1059 }
1060 else if (dir == ios::cur) {
1061 count = static_cast<int>(in_avail());
1062 if (count != 0) {
1063 loff -= count;
1064
1065 // If we're in text mode, need to allow for newlines in the buffer
1066 //
1067 if ((mode & ofBinary) == 0) {
1068 char *tptr = gptr();
1069 while (tptr != egptr())
1070 if (*tptr++ == _T('\n'))
1071 loff--;
1072 }
1073 }
1074 }
1075
1076 uint32 w = (dir == ios::beg) ? STREAM_SEEK_SET
1077 : ((dir == ios::cur) ? STREAM_SEEK_CUR
1078 : /* ios::end */ STREAM_SEEK_END);
1079 int64 i64pos = loff;
1080 if (!SUCCEEDED(strm->Seek(*(LARGE_INTEGER*)&i64pos, w, (ULARGE_INTEGER*)&last_seek)))
1081 return eof(); //?!!
1082 if (!unbuffered() && base()) { // set up get and put areas
1083 int pb = (blen() > 8) ? 4 : 1; // putback area size
1084 char *b = base();
1085 setp(b+pb, b+pb);
1086 setg(b, b+pb, b+pb);
1087 }
1088 return (uint32)last_seek;
1089}
1090
1091TStorageBuf::pos_type TStorageBuf::seekpos(pos_type sp,
1092 ios_base::openmode which){
1093 return seekoff(streamoff(sp), ios::beg, which);
1094}
1095
1096//
1097//
1098//
1099int TStorageBuf::sync()
1100{
1101 if (!opened)
1102 return eof();
1103
1104 ulong actual;
1105 int count = out_waiting();
1106 if (count) {
1107 char* curp;
1108 char* srcp = pbase();
1109 char* endp = srcp + count;
1110
1111 // Convert LF's to CR/LF if text mode
1112 //
1113 if ((mode & ofBinary) == 0) {
1114 for (curp = srcp; curp < endp; curp++) {
1115 if (*curp == _T('\n')) {
1116 *curp = _T('\r');
1117 count = (int)(curp - srcp + 1);
1118 HRESULT hr = strm->Write(srcp, (unsigned long)count, &actual);
1119 if (!SUCCEEDED(hr) || (int)actual != count)
1120 return eof();
1121 *(srcp = curp) = _T('\n');
1122 }
1123 }
1124 count = (int)(curp - srcp); // write what remains in the buffer below
1125 }
1126 HRESULT hr = strm->Write(srcp, (ulong)count, &actual);
1127 if (!SUCCEEDED(hr) || (int)actual != count)
1128 return eof();
1129
1130 // Reset get and put areas
1131 //
1132 int pb = (blen() > 8) ? 4 : 1; // putback area size
1133 char *b = base();
1134 setp(b+pb, b+blen());
1135 setg(b, b+pb, b+pb);
1136
1137 }
1138 else if (in_avail()) {
1139 int64 i64 = int64(long(-in_avail()));
1140 if (!SUCCEEDED(strm->Seek(*(LARGE_INTEGER*)&i64, STREAM_SEEK_CUR, (ULARGE_INTEGER*)&last_seek)))
1141 return eof();
1142 setg(eback(), gptr(), gptr());
1143 setp(gptr(), gptr());
1144 }
1145 return 0;
1146}
1147
1148//
1149//
1150//
1151TStorageBuf::int_type TStorageBuf::underflow()
1152{
1153 ulong actual;
1154 uint count; // input character count
1155 int c; // the return value
1156
1157 if (!opened || (mode & (ofRead | ofWrite)) == ofWrite)
1158 return eof();
1159
1160 if (in_avail()) // no action needed
1161 return (utchar)*gptr();
1162
1163 if (!unbuffered() && base()) { // this is buffered
1164 if (sync() != 0)
1165 return eof();
1166
1167 // find buffer data
1168 //
1169 int pb = (blen() > 8) ? 4 : 1; // putback area size
1170 char* begp = base() + pb;
1171
1172 // read in a new buffer
1173 //
1174 HRESULT hr = strm->Read(begp, blen()-pb, &actual);
1175 if (!SUCCEEDED(hr))
1176 return eof();
1177 count = (unsigned)actual;
1178
1179 // remove CR's if text mode
1180 //
1181 if ((mode & ofBinary) == 0) {
1182 char* endp = begp + count;
1183 char* dstp = 0;
1184 char* srcp = 0;
1185 char* curp;
1186
1187 for (curp = begp; curp < endp; curp++) {
1188 if (*curp == _T('\r')) {
1189 if (dstp) {
1190 memcpy(dstp, srcp, (int)(curp - srcp));
1191 dstp += (int)(curp - srcp);
1192 }
1193 else
1194 dstp = curp;
1195 srcp = curp + 1;
1196 }
1197 }
1198 if (dstp) {
1199 endp = dstp + (int)(curp - srcp);
1200 if (curp != srcp)
1201 memcpy(dstp, srcp, (int)(curp - srcp));
1202 }
1203 count = (int)(endp - begp);
1204 }
1205
1206 // set up get and put areas
1207 //
1208 setg(base(), begp, begp + count);
1209 setp(begp, begp);
1210
1211 if (count)
1212 c = (utchar)*gptr();
1213
1214 }
1215 else { // this is not buffered
1216 for (;;) {
1217 HRESULT hr = strm->Read(lahead, 1, &actual);
1218 if (!SUCCEEDED(hr) || actual == 0) {
1219 c = eof();
1220 setg(0, 0, 0);
1221 }
1222 else {
1223 c = (utchar)lahead[0];
1224 if ((mode & ofBinary) == 0 && c == _T('\r'))
1225 continue;
1226 setg(lahead, lahead, lahead+1);
1227 }
1228 break;
1229 }
1230 }
1231 if (!count)
1232 c = eof(); // end of file
1233 return c;
1234}
1235
1236//
1237/// always flush
1238//
1239TStorageBuf::int_type TStorageBuf::overflow(int_type c)
1240{
1241 if (!opened || (mode & (ofRead | ofWrite)) == ofRead)
1242 return eof();
1243
1244 if (unbuffered() || !base()) {
1245 if (c != eof()) {
1246 int count;
1247 char b[2];
1248 if (c == _T('\n') && (mode & ofBinary) == 0) {
1249 b[0] = _T('\r');
1250 b[1] = (char)c;
1251 count = 2;
1252 }
1253 else {
1254 b[0] = (char)c;
1255 count = 1;
1256 }
1257 ulong actual = 0;
1258 strm->Write(&c, (ulong)count, &actual);
1259 if ((int)actual != count)
1260 return eof();
1261 }
1262 }
1263 else { // now we know this is buffered and state is not bad
1264
1265 // resets get and put areas
1266 //
1267 if (sync() != 0)
1268 return eof();
1269
1270 // reset get and put areas
1271 //
1272 int pb = (blen() > 8) ? 4 : 1; // putback area size
1273 char *b = base();
1274 setp(b+pb, b+blen());
1275 setg(b, b+pb, b+pb);
1276
1277 if (c != eof()) {
1278 sputc(c);
1279 gbump(1); // pptr and gptr must be the same
1280 }
1281 }
1282 return 1;
1283}
1284
1285//
1286/// flush and close file
1287//
1288TStorageBuf* TStorageBuf::close()
1289{
1290 if (!opened)
1291 return 0; // nothing to do
1292
1293 int ores = 0; // result of overflow()
1294 if (out_waiting() && overflow(eof()) == eof())
1295 ores = 1;
1296 if ((mode & ofWrite) /* && !strm->Commit(0) */)
1297 ores = 1;
1298
1299 strm->Release(); /// Question: should we release if commit fails?!!
1300 strm = 0;
1301 opened = 0;
1302 return ores ? 0 : this;
1303}
1304
1305} // OCF namespace
1306
1307//==============================================================================
1308
1309
#define PRECONDITION(condition)
Definition checks.h:227
LPCTSTR PropertyName(int index)
Definition stgdoc.cpp:679
int FindProperty(LPCTSTR name)
Definition stgdoc.cpp:707
int GetProperty(int index, void *dest, int textlen=0)
Definition stgdoc.cpp:719
friend class TStorageInStream
Definition stgdoc.h:97
bool Commit(bool force=false)
Definition stgdoc.cpp:612
virtual bool OpenHandle(int omode, HANDLE hGlobal)
Create an IStorage based on a memory handle.
Definition stgdoc.cpp:432
virtual bool SetStorage(IStorage *stg, bool remember=true)
Give an IStorage to document. This typically happens for OLE servers.
Definition stgdoc.cpp:331
bool Open(int omode, LPCTSTR stgId)
Open the compound file with a given path.
Definition stgdoc.cpp:219
virtual bool ReleaseDoc()
Release the IStorage and close the document.
Definition stgdoc.cpp:209
friend class TStorageOutStream
Definition stgdoc.h:98
bool IsOpen()
Return 'true' if the storage document object has opened an OLE storage.
Definition stgdoc.h:122
bool Revert(bool clear=false)
Definition stgdoc.cpp:643
owl::TInStream * InStream(int omode, LPCTSTR strmId=0)
Definition stgdoc.cpp:555
owl::TOutStream * OutStream(int omode, LPCTSTR strmId=0)
Definition stgdoc.cpp:579
virtual bool GetHandle(HGLOBAL *handle)
Get the global handle from ILockBytes.
Definition stgdoc.cpp:513
virtual bool SetHandle(int omode, HANDLE hGlobal, bool create=false, bool remember=false)
Replace the IStorage with an istorage based on a memory handle.
Definition stgdoc.cpp:465
bool SetProperty(int index, const void *src)
Definition stgdoc.cpp:788
virtual IStorage * GetNewStorage()
Get a new IStorage, typically in a SaveAs situation.
Definition stgdoc.cpp:402
int PropertyFlags(int index)
Definition stgdoc.cpp:693
virtual bool RestoreStorage()
Restore the original root IStorage before the save operation.
Definition stgdoc.cpp:384
bool SetDocPath(LPCTSTR path)
Definition stgdoc.cpp:602
bool CommitTransactedStorage()
Definition stgdoc.cpp:628
An abstract base class, TDocument is the base class for all document objects and serves as an interfa...
Definition docview.h:187
virtual int GetProperty(int index, void *dest, int textlen=0)
Retrieves the property identified by the given index.
Definition document.cpp:224
virtual void DetachStream(TStream &strm)
called from TStream destructor
Definition document.cpp:452
bool NotifyViews(int eventId, TParam2=0, TView *exclude=nullptr)
Notifies the views of this document, and the views of any child documents, of a change.
Definition document.cpp:629
virtual bool SetProperty(int index, const void *src)
native type
Definition document.cpp:286
LPCTSTR GetDocPath() const
Returns the directory path for the document.
Definition docview.h:874
virtual LPCTSTR PropertyName(int index)
locale invariant name
Definition document.cpp:147
virtual bool Close()
close document, does not delete or detach
Definition document.cpp:793
virtual int PropertyFlags(int index)
pfXxxxx bit array
Definition document.cpp:166
virtual bool SetDocPath(LPCTSTR path)
Sets the document path for Open and Save operations.
Definition document.cpp:357
void SetOpenMode(int mode)
Sets the mode and protection flag values for the current document.
Definition docview.h:996
void SetDirty(bool dirty=true)
Updates the document's dirty flag using the specified parameter.
Definition docview.h:888
bool IsEmbedded() const
Returns true if the document is embedded in an OLE 2 container.
Definition docview.h:911
virtual bool Commit(bool force=false)
save current data, force write
Definition document.cpp:584
int GetOpenMode() const
Gets the mode and protection flag values for the current document.
Definition docview.h:987
void SetEmbedded(bool embed)
Marks the document as being embedded in an OLE 2 container.
Definition docview.h:920
TDocument * GetParentDoc()
Returns either the parent document of the current document or 0 if there is no parent document.
Definition docview.h:858
virtual bool Revert(bool clear=false)
abort changes, no reload if true
Definition document.cpp:604
Derived from TStream and istream, TInStream is a base class used to define input streams for document...
Definition docview.h:594
Derived from TStream and ostream, TOutStream is a base class used to create output storage streams fo...
Definition docview.h:605
An abstract base class, TStream provides links between streams and documents, views,...
Definition docview.h:568
ipstream, a specialized input stream derivative of pstream, is the base class for reading (extracting...
Definition objstrm.h:391
Base class for writing streamable objects.
Definition objstrm.h:480
#define _tcscmp
Definition cygwin.h:75
#define _stprintf
Definition cygwin.h:88
#define _T(x)
Definition cygwin.h:51
Definition of classes TDocument, TView, TWindowView, TStream, TInStream, TOutStream.
void ReadBaseObject(Base *base, ipstream &in)
Definition objstrm.h:1159
#define IMPLEMENT_STREAMABLE1(cls, base1)
Definition objstrm.h:1725
void WriteBaseObject(Base *base, opstream &out)
Definition objstrm.h:1150
const uint pfGetText
property accessible as text format
Definition docview.h:122
const uint vnDocClosed
document has just been closed
Definition docview.h:108
const uint vnDocOpened
document has just been opened
Definition docview.h:107
const uint pfGetBinary
property accessible as native non-text format
Definition docview.h:123
@ ofRead
ios::in, open for reading
Definition docview.h:63
@ ofTruncate
ios::trunc, truncate file if already exists
Definition docview.h:68
@ shMask
Definition docview.h:95
@ shRead
DENY_WRITE functionality.
Definition docview.h:91
@ ofParent
use open mode of parent storage
Definition docview.h:62
@ ofNoReplace
ios::noreplace, open fails if file already exists
Definition docview.h:79
@ ofPriority
STGM_PRIORITY, temporary efficient peeking.
Definition docview.h:86
@ ofPreserve
STGM_CONVERT, backup old data of same name.
Definition docview.h:85
@ ofAppend
ios::app, append mode: all additions at eof
Definition docview.h:67
@ ofWrite
ios::out, open for writing
Definition docview.h:64
@ ofAtEnd
ios::ate, seek to eof upon original open
Definition docview.h:66
@ ofTransacted
STGM_TRANSACTED, supports commit and revert.
Definition docview.h:84
@ shReadWrite
DENY_NONE functionality.
Definition docview.h:93
@ shNone
EXCLUSIVE functionality.
Definition docview.h:90
@ ofNoCreate
ios::nocreate, open fails if file doesn't exist
Definition docview.h:74
@ shCompat
for non-compliant applications, avoid if possible
Definition docview.h:89
@ ofTemporary
STGM_DELETEONRELEASE, delete when destructed.
Definition docview.h:87
Include for OC, gets common headers when precompiled headers are enabled.
Object Component Framework (COM encapsulation)
Definition appdesc.h:22
long IosToStgMode(int omode)
Definition stgdoc.cpp:158
int StgToIosShareMode(long grfMode)
Definition stgdoc.cpp:175
int StgToIosMode(long grfMode)
Definition stgdoc.cpp:185
int StgToIosTempMode(long grfMode)
Definition stgdoc.cpp:180
const int stgRdWrMask
Definition stgdoc.cpp:165
int StgToIosOpenMode(long grfMode)
Definition stgdoc.cpp:170
const long stgModeMask
Definition stgdoc.cpp:168
long IosToStgTempMode(int omode)
Definition stgdoc.cpp:153
const int stgShareMask
Definition stgdoc.cpp:166
const TCHAR DefaultStreamName[]
Definition stgdoc.cpp:38
long IosToStgShareMode(int omode)
Definition stgdoc.cpp:148
long IosToStgOpenMode(int omode)
Definition stgdoc.cpp:143
Object Windows Library (OWLNext Core)
Definition animctrl.h:22
__int64 int64
Definition number.h:36
unsigned long ulong
Definition number.h:26
const int B_size
Definition filedoc.cpp:534
unsigned long uint32
Definition number.h:34
OWL_DIAGINFO
Definition animctrl.cpp:14
unsigned __int64 uint64
Definition number.h:43
unsigned int uint
Definition number.h:25
unsigned char utchar
Definition defs.h:78
interface _ICLASS IStorage
Definition ocdoc.h:25
#define RefCountCheck(si)
Definition ocstorag.cpp:31
interface _ICLASS IStream
Definition ocstorag.h:26
#define COUNTOF(s)
Array element count Important: Only use this with an argument of array type.
Definition defs.h:376
Definition of class TString, a flexible universal string envelope class.
#define OleStr(s)
Definition string.h:128