OWLNext    7.0
Borland's Object Windows Library for the modern age
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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