1 //-------------------------------------------------------------------------
2 //
3 //  For conditions of distribution and use, see copyright notice
4 //  in Flashpix.h
5 //
6 //  Copyright (c) 1999 Digital Imaging Group, Inc.
7 //
8 //  Contents:   CExposedStream code
9 //
10 //  Notes:      See the header file expst.hxx for details
11 //
12 //--------------------------------------------------------------------------
13 
14 #include "exphead.cxx"
15 
16 #include "expst.hxx"
17 #include "logfile.hxx"
18 
19 #ifndef min
20 #define min(a, b) ((a)<(b) ? (a) : (b))
21 #endif
22 #ifndef max
23 #define max(a, b) ((a)>(b) ? (a) : (b))
24 #endif
25 
26 // Maximum stream size supported by exposed streams
27 // This is MAX_ULONG with one subtracted so that
28 // the seek pointer has a spot to sit even at the
29 // end of the stream
30 #define CBMAXSTREAM 0xfffffffeUL
31 // Maximum seek pointer value
32 #define CBMAXSEEK (CBMAXSTREAM+1)
33 
34 //+--------------------------------------------------------------
35 //
36 //  Member:     CExposedStream::CExposedStream, public
37 //
38 //  Synopsis:   Empty object constructor
39 //
40 //---------------------------------------------------------------
41 
42 
CExposedStream()43 CExposedStream::CExposedStream()
44 {
45     olDebugOut((DEB_ITRACE, "In  CExposedStream::CExposedStream()\n"));
46     _cReferences = 0;
47     _ulAccessLockBase = 0;
48     _ulPos = 0;
49     _pst = NULL;
50     _pdfParent = NULL;
51     _fDirty = FALSE;
52 #ifdef NEWPROPS
53     _pb = NULL;
54     _cbUsed = 0;
55     _cbOriginalStreamSize = 0;
56     _fChangePending = FALSE;
57 #endif
58 
59     olDebugOut((DEB_ITRACE, "Out CExposedStream::CExposedStream\n"));
60 }
61 
62 //+--------------------------------------------------------------
63 //
64 //  Member:     CExposedStream::Init, public
65 //
66 //  Synopsis:   Base constructor
67 //
68 //  Arguments:  [pst] - Direct stream
69 //              [pdfParent] - the storage parent
70 //              [df]  - Permission flags
71 //              [pdfn] - name of stream
72 //              [ulPos] - offset
73 //
74 //  Returns:    Appropriate status code
75 //
76 //  Note:       We add "this" as a child to the parent to
77 //              1) Check for multiple instantiation of a child
78 //              2) Uses the RevertFromAbove() function to check
79 //                 for reverted state.
80 //
81 //---------------------------------------------------------------
82 
Init(CDirectStream * pst,CExposedDocFile * pdfParent,const DFLAGS df,const CDfName * pdfn,const ULONG ulPos)83 SCODE CExposedStream::Init(CDirectStream *pst,
84                            CExposedDocFile* pdfParent,
85                            const DFLAGS df,
86                            const CDfName *pdfn,
87                            const ULONG ulPos)
88 {
89     olDebugOut((DEB_ITRACE, "In  CExposedStream::Init("
90                 "%p, %lu)\n", pst, ulPos));
91     _ulPos = ulPos;
92     _pst = pst;
93     _pdfParent = pdfParent;
94     _df = df;
95     _dfn.Set(pdfn->GetLength(), pdfn->GetBuffer());
96     olAssert(pdfParent);
97     _pdfParent->AddChild(this);
98     _cReferences = 1;
99     _sig = CEXPOSEDSTREAM_SIG;
100     olDebugOut((DEB_ITRACE, "Out CExposedStream::Init\n"));
101     return S_OK;
102 }
103 
104 
105 //+--------------------------------------------------------------
106 //
107 //  Member:     CExposedStream::Read, public
108 //
109 //  Synopsis:   Read from a stream
110 //
111 //  Arguments:  [pb] - Buffer
112 //              [cb] - Count of bytes to read
113 //              [pcbRead] - Return number of bytes read
114 //
115 //  Returns:    Appropriate status code
116 //
117 //  Modifies:   [pcbRead]
118 //
119 //---------------------------------------------------------------
120 
121 
Read(VOID HUGEP * pb,ULONG cb,ULONG * pcbRead)122 STDMETHODIMP CExposedStream::Read(VOID HUGEP *pb, ULONG cb, ULONG *pcbRead)
123 {
124     SCODE sc;
125     ULONG cbRead = 0;
126 
127     olLog(("%p::In  CExposedStream::Read(%p, %lu, %p)\n",
128            this, pb, cb, pcbRead));
129     olDebugOut((DEB_ITRACE, "In CExposedStream::Read(%p,%lu,%p)\n",
130                  pb, cb, pcbRead));
131     if (pcbRead)
132         olChkTo(EH_BadPtr, ValidateOutBuffer(pcbRead, sizeof(ULONG)));
133     olChk(ValidateHugeOutBuffer(pb, cb));
134     olChk(Validate());
135     olChk(CheckReverted());
136 
137     if (!P_READ(_df))
138         sc = STG_E_ACCESSDENIED;
139     else
140         sc = _pst->ReadAt(_ulPos, pb, cb,
141                           (ULONG STACKBASED *)&cbRead);
142     olAssert( CBMAXSEEK - _ulPos >= cbRead);
143     _ulPos+=cbRead;
144 
145     olDebugOut((DEB_ITRACE, "Out CExposedStream::Read => %lu\n", cbRead));
146 
147 EH_Err:
148     if (pcbRead)
149     {
150         *pcbRead = cbRead;
151         olLog(("%p::Out CExposedStream::Read() *pcbRead==%lu, ret=%lx\n",
152                this, SAFE_DREF(pcbRead), sc));
153     }
154     else
155     {
156         olLog(("%p::Out CExposedStream::Read().  ret == %lx\n", this, sc));
157     }
158 
159 EH_BadPtr:
160     return ResultFromScode(sc);
161 }
162 
163 //+--------------------------------------------------------------
164 //
165 //  Member:     CExposedStream::Write, public
166 //
167 //  Synopsis:   Write to a stream
168 //
169 //  Arguments:  [pb] - Buffer
170 //              [cb] - Count of bytes to write
171 //              [pcbWritten] - Return of bytes written
172 //
173 //  Returns:    Appropriate status code
174 //
175 //  Modifies:   [pcbWritten]
176 //
177 //---------------------------------------------------------------
178 
179 
Write(VOID const HUGEP * pb,ULONG cb,ULONG * pcbWritten)180 STDMETHODIMP CExposedStream::Write(
181         VOID const HUGEP *pb,
182         ULONG cb,
183         ULONG *pcbWritten)
184 {
185     SCODE sc;
186     ULONG cbWritten = 0;
187 
188     olLog(("%p::In  CExposedStream::Write(%p, %lu, %p)\n",
189            this, pb, cb, pcbWritten));
190     olDebugOut((DEB_ITRACE,
191                 "In CExposedStream::Write(%p, %lu, %p)\n",
192                 pb, cb, pcbWritten));
193 
194     if (pcbWritten)
195     {
196         olChkTo(EH_BadPtr,
197                 ValidateOutBuffer(pcbWritten, sizeof(ULONG)));
198     }
199     olChk(ValidateHugeBuffer(pb, cb));
200     olChk(Validate());
201     olChk(CheckReverted());
202     if (!P_WRITE(_df))
203         sc = STG_E_ACCESSDENIED;
204     else
205     {
206         sc = _pst->WriteAt(_ulPos, pb, cb,
207                            (ULONG STACKBASED *)&cbWritten);
208         if (SUCCEEDED(sc))
209             SetDirty();
210     }
211     olAssert( CBMAXSEEK - _ulPos >= cbWritten);
212     _ulPos += cbWritten;
213 
214     olDebugOut((DEB_ITRACE, "Out CExposedStream::Write => %lu\n",
215                 cbWritten));
216 EH_Err:
217     if (pcbWritten)
218     {
219         *pcbWritten = cbWritten;
220         olLog(("%p::Out CExposedStream::Write().  *pcbWritten == %lu, ret = %lx\n",
221                this, *pcbWritten, sc));
222     }
223     else
224     {
225         olLog(("%p::Out CExposedStream::Write().  ret == %lx\n",this, sc));
226     }
227 
228 EH_BadPtr:
229     return ResultFromScode(sc);
230 }
231 
232 //+--------------------------------------------------------------
233 //
234 //  Member:     CExposedStream::Seek, public
235 //
236 //  Synopsis:   Seek to a point in a stream
237 //
238 //  Arguments:  [dlibMove] - Offset to move by
239 //              [dwOrigin] - SEEK_SET, SEEK_CUR, SEEK_END
240 //              [plibNewPosition] - Return of new offset
241 //
242 //  Returns:    Appropriate status code
243 //
244 //  Modifies:   [plibNewPosition]
245 //
246 //---------------------------------------------------------------
247 
248 
Seek(LARGE_INTEGER dlibMove,DWORD dwOrigin,ULARGE_INTEGER * plibNewPosition)249 STDMETHODIMP CExposedStream::Seek(LARGE_INTEGER dlibMove,
250                                   DWORD dwOrigin,
251                                   ULARGE_INTEGER *plibNewPosition)
252 {
253     SCODE sc;
254     LONG lMove;
255     ULARGE_INTEGER ulPos;
256     ULONG cbSize;
257 
258     olLog(("%p::In  CExposedStream::Seek(%ld, %lu, %p)\n",
259            this, LIGetLow(dlibMove), dwOrigin, plibNewPosition));
260     olDebugOut((DEB_ITRACE, "In  CExposedStream::Seek(%ld, %lu, %p)\n",
261                 LIGetLow(dlibMove), dwOrigin, plibNewPosition));
262 
263     if (plibNewPosition)
264     {
265         olChk(ValidateOutBuffer(plibNewPosition, sizeof(ULARGE_INTEGER)));
266         ULISet32(*plibNewPosition, 0);
267     }
268     if (dwOrigin != STREAM_SEEK_SET && dwOrigin != STREAM_SEEK_CUR &&
269         dwOrigin != STREAM_SEEK_END)
270         olErr(EH_Err, STG_E_INVALIDFUNCTION);
271 
272     // Truncate dlibMove to 32 bits
273     if (dwOrigin == STREAM_SEEK_SET)
274     {
275         // Make sure we don't seek too far
276         if (LIGetHigh(dlibMove) != 0)
277             LISet32(dlibMove, /*(LONG)*/0xffffffff);
278     }
279     else
280     {
281         // High dword must be zero for positive values or -1 for
282         // negative values
283         // Additionally, for negative values, the low dword can't
284         // exceed -0x80000000 because the 32nd bit is the sign
285         // bit
286         if (LIGetHigh(dlibMove) > 0 ||
287             (LIGetHigh(dlibMove) == 0 &&
288              LIGetLow(dlibMove) >= 0x80000000))
289             LISet32(dlibMove, 0x7fffffff);
290         else if (LIGetHigh(dlibMove) < -1 ||
291                  (LIGetHigh(dlibMove) == -1 &&
292                   LIGetLow(dlibMove) <= 0x7fffffff))
293             LISet32(dlibMove, /*(LONG)*/0x80000000);
294     }
295 
296     lMove = (LONG)LIGetLow(dlibMove);
297     olChk(Validate());
298     olChk(CheckReverted());
299     ULISet32(ulPos, _ulPos);
300     switch(dwOrigin)
301     {
302     case STREAM_SEEK_SET:
303         ULISetLow(ulPos, (ULONG)lMove);
304         break;
305     case STREAM_SEEK_END:
306         olChk(GetSize(&cbSize));
307         if (lMove < 0)
308         {
309             if ((ULONG)(-lMove) > cbSize)
310                 olErr(EH_Err, STG_E_INVALIDFUNCTION);
311         }
312         else if ((ULONG)lMove > CBMAXSEEK-cbSize)
313             lMove = (LONG)(CBMAXSEEK-cbSize);
314         ULISetLow(ulPos, cbSize+lMove);
315         break;
316     case STREAM_SEEK_CUR:
317         if (lMove < 0)
318         {
319             if ((ULONG)(-lMove) > _ulPos)
320                 olErr(EH_Err, STG_E_INVALIDFUNCTION);
321         }
322         else if ((ULONG)lMove > CBMAXSEEK - _ulPos)
323             lMove = (LONG)(CBMAXSEEK- _ulPos);
324         ULISetLow(ulPos, _ulPos+lMove);
325         break;
326     }
327     _ulPos = ULIGetLow(ulPos);
328     if (plibNewPosition)
329         *plibNewPosition = ulPos;
330 
331     olDebugOut((DEB_ITRACE, "Out CExposedStream::Seek => %lu\n",
332                 ULIGetLow(ulPos)));
333 EH_Err:
334     olLog(("%p::Out CExposedStream::Seek().  ulPos == %lu,  ret == %lx\n",
335            this, ULIGetLow(ulPos), sc));
336     return ResultFromScode(sc);
337 }
338 
339 //+--------------------------------------------------------------
340 //
341 //  Member:     CExposedStream::SetSize, public
342 //
343 //  Synopsis:   Sets the size of a stream
344 //
345 //  Arguments:  [ulNewSize] - New size
346 //
347 //  Returns:    Appropriate status code
348 //
349 //---------------------------------------------------------------
SetSize(ULONG cb)350 SCODE CExposedStream::SetSize(ULONG cb)
351 {
352     olDebugOut((DEB_ITRACE,
353                 "In CExposedStream::SetSize(ULONG %lu)\n", cb));
354     SCODE sc;
355 
356     olChk(Validate());
357     olChk(CheckReverted());
358     if (!P_WRITE(_df))
359         sc = STG_E_ACCESSDENIED;
360     else
361     {
362         olChk(_pst->SetSize(cb));
363         SetDirty();
364     }
365 
366 EH_Err:
367     olDebugOut((DEB_ITRACE, "Out  CExposedStream::SetSize()\n"));
368     return sc;
369 }
370 
371 //+--------------------------------------------------------------
372 //
373 //  Member:     CExposedStream::SetSize, public
374 //
375 //  Synopsis:   Sets the size of a stream
376 //
377 //  Arguments:  [ulNewSize] - New size
378 //
379 //  Returns:    Appropriate status code
380 //
381 //---------------------------------------------------------------
382 
SetSize(ULARGE_INTEGER ulNewSize)383 STDMETHODIMP CExposedStream::SetSize(ULARGE_INTEGER ulNewSize)
384 {
385     SCODE sc;
386 
387     olLog(("%p::In  CExposedStream::SetSize(%lu)\n",
388            this, ULIGetLow(ulNewSize)));
389     olDebugOut((DEB_ITRACE, "In  CExposedStream::SetSize(%lu)\n",
390                 ULIGetLow(ulNewSize)));
391 
392     if (ULIGetHigh(ulNewSize) != 0)
393         olErr(EH_Err, STG_E_INVALIDFUNCTION);
394     olChk(SetSize(ULIGetLow(ulNewSize)));
395 
396     olDebugOut((DEB_ITRACE, "Out CExposedStream::SetSize\n"));
397 EH_Err:
398     olLog(("%p::Out CExposedStream::SetSize().  ret == %lx\n", this, sc));
399     return ResultFromScode(sc);
400 }
401 
402 //+--------------------------------------------------------------
403 //
404 //  Member:     CExposedStream::CopyTo, public
405 //
406 //  Synopsis:   Copies information from one stream to another
407 //
408 //  Arguments:  [pstm] - Destination
409 //              [cb] - Number of bytes to copy
410 //              [pcbRead] - Return number of bytes read
411 //              [pcbWritten] - Return number of bytes written
412 //
413 //  Returns:    Appropriate status code
414 //
415 //  Modifies:   [pcbRead]
416 //              [pcbWritten]
417 //
418 //  Notes:      We do our best to handle overlap correctly.  This allows
419 //              CopyTo to be used to insert and remove space within a
420 //              stream.
421 //
422 //              In the error case, we make no gurantees as to the
423 //              validity of pcbRead, pcbWritten, or either stream's
424 //              seek position.
425 //
426 //---------------------------------------------------------------
427 
428 
CopyTo(IStream * pstm,ULARGE_INTEGER cb,ULARGE_INTEGER * pcbRead,ULARGE_INTEGER * pcbWritten)429 STDMETHODIMP CExposedStream::CopyTo(IStream *pstm,
430                                     ULARGE_INTEGER cb,
431                                     ULARGE_INTEGER *pcbRead,
432                                     ULARGE_INTEGER *pcbWritten)
433 {
434     SCODE sc;
435     ULONG ulCopySize;
436     ULONG ulSrcSize;
437     ULONG ulSrcOrig;
438     ULARGE_INTEGER uliDestOrig;
439     LARGE_INTEGER liDestPos;
440     BYTE *pb = NULL;
441     BOOL fOverlap;
442     ULONG ulBytesCopied = 0;
443 
444     olLog(("%p::In  CExposedStream::CopyTo(%p, %lu, %p, %p)\n",
445            this, pstm, ULIGetLow(cb), pcbRead, pcbWritten));
446     olDebugOut((DEB_TRACE, "In  CExposedStream::CopyTo("
447                 "%p, %lu, %p, %p)\n", pstm, ULIGetLow(cb),
448                 pcbRead, pcbWritten));
449 
450     if (pcbRead) // okay to set to NULL => not interested
451     {
452         olChk(ValidateOutBuffer(pcbRead, sizeof(ULARGE_INTEGER)));
453         ULISet32(*pcbRead, 0);
454     }
455     if (pcbWritten) // okay to set to NULL => not interested
456     {
457         olChk(ValidateOutBuffer(pcbWritten, sizeof(ULARGE_INTEGER)));
458         ULISet32(*pcbWritten, 0);
459     }
460 
461     olChk(ValidateInterface(pstm, IID_IStream));
462     olChk(Validate());
463     olChk(CheckReverted());
464 
465     //  Bound the size of the copy
466     //  1.  The maximum we can copy is 0xffffffff
467 
468     if (ULIGetHigh(cb) == 0)
469         ulCopySize = ULIGetLow(cb);
470     else
471         ulCopySize = 0xffffffff;
472 
473     //  2.  We can only copy what's available in the source stream
474 
475     olChk(GetSize(&ulSrcSize));
476 
477     ulSrcOrig = _ulPos;
478     if (ulSrcSize < ulSrcOrig)
479     {
480         //  Nothing in source to copy
481         ulCopySize = 0;
482     }
483     else if ((ulSrcSize - ulSrcOrig) < ulCopySize)
484     {
485         //  Shrink ulCopySize to fit bytes in source
486         ulCopySize = ulSrcSize - ulSrcOrig;
487     }
488 
489     //  3.  We can only copy what will fit in the destination
490 
491     LISet32(liDestPos, 0);
492     olHChk(pstm->Seek(liDestPos, STREAM_SEEK_CUR, &uliDestOrig));
493     olAssert(ULIGetHigh(uliDestOrig) == 0);
494 
495     if (ulCopySize > CBMAXSEEK - ULIGetLow(uliDestOrig))
496         ulCopySize = CBMAXSEEK - ULIGetLow(uliDestOrig);
497 
498     //  We are allowed to fail here with out-of-memory
499     olMem(pb = new BYTE[STREAMBUFFERSIZE]);
500 
501     // Since we have no reliable way to determine if the source and
502     // destination represent the same stream, we assume they
503     // do and always handle overlap.
504 
505     fOverlap = (ULIGetLow(uliDestOrig) > ulSrcOrig &&
506                 ULIGetLow(uliDestOrig) < ulSrcOrig + ulCopySize);
507 
508     ULONG ulSrcCopyOffset;
509     ULONG ulDstCopyOffset;
510     if (fOverlap)
511     {
512         //  We're going to copy back to front, so determine the
513         //  stream end positions
514         ulSrcCopyOffset = ulSrcOrig + ulCopySize;
515 
516         //  uliDestOrig is the destination starting offset
517         ulDstCopyOffset = ULIGetLow(uliDestOrig) + ulCopySize;
518     }
519 
520     while (ulCopySize > 0)
521     {
522         //  We can only copy up to STREAMBUFFERSIZE bytes at a time
523         ULONG cbPart = min(ulCopySize, STREAMBUFFERSIZE);
524 
525         if (fOverlap)
526         {
527             //  We're copying back to front so we need to seek to
528             //  set up the streams correctly
529 
530             ulSrcCopyOffset -= cbPart;
531             ulDstCopyOffset -= cbPart;
532 
533             //  Set source stream position
534             _ulPos = ulSrcCopyOffset;
535 
536             //  Set destination stream position
537             LISet32(liDestPos, ulDstCopyOffset);
538             olHChk(pstm->Seek(liDestPos, STREAM_SEEK_SET, NULL));
539         }
540 
541         {
542             ULONG ulRead;
543             olHChk(Read(pb, cbPart, &ulRead));
544             if (cbPart != ulRead)
545             {
546                 //  There was no error, but we were unable to read cbPart
547                 //  bytes.  Something's wrong (the underlying ILockBytes?)
548                 //  but we can't control it;  just return an error.
549                 olErr(EH_Err, STG_E_READFAULT);
550             }
551         }
552 
553 
554         {
555             ULONG ulWritten;
556             olHChk(pstm->Write(pb, cbPart, &ulWritten));
557             if (cbPart != ulWritten)
558             {
559                 //  There was no error, but we were unable to write
560                 //  ulWritten bytes.  We can't trust the pstm
561                 //  implementation, so all we can do here is return
562                 //  an error.
563                 olErr(EH_Err, STG_E_WRITEFAULT);
564             }
565         }
566 
567         olAssert(ulCopySize >= cbPart);
568         ulCopySize -= cbPart;
569         ulBytesCopied += cbPart;
570     }
571 
572     if (fOverlap)
573     {
574         //  Set the seek pointers to the correct location
575         _ulPos = ulSrcOrig + ulBytesCopied;
576 
577         LISet32(liDestPos, ULIGetLow(uliDestOrig) + ulBytesCopied);
578         olHChk(pstm->Seek(liDestPos, STREAM_SEEK_SET, NULL));
579     }
580 
581     if (pcbRead)
582         ULISet32(*pcbRead, ulBytesCopied);
583     if (pcbWritten)
584         ULISet32(*pcbWritten, ulBytesCopied);
585 
586     olDebugOut((DEB_ITRACE, "Out CExposedStream::CopyTo => %lu, %lu\n",
587                 pcbRead ? ULIGetLow(*pcbRead) : 0,
588                 pcbWritten ? ULIGetLow(*pcbWritten) : 0));
589     // Fall through
590 EH_Err:
591     delete [] pb;
592     olLog(("%p::Out CExposedStream::CopyTo().  "
593            "cbRead == %lu, cbWritten == %lu, ret == %lx\n",
594            this, pcbRead ? ULIGetLow(*pcbRead) : 0,
595            pcbWritten ? ULIGetLow(*pcbWritten) : 0, sc));
596     return ResultFromScode(sc);
597 }
598 
599 //+--------------------------------------------------------------
600 //
601 //  Member:     CExposedStream::Release, public
602 //
603 //  Synopsis:   Releases a stream
604 //
605 //  Returns:    Appropriate status code
606 //
607 //---------------------------------------------------------------
608 
609 
STDMETHODIMP_(ULONG)610 STDMETHODIMP_(ULONG) CExposedStream::Release(void)
611 {
612     LONG lRet;
613 
614     olLog(("%p::In  CExposedStream::Release()\n", this));
615     olDebugOut((DEB_ITRACE, "In  CExposedStream::Release()\n"));
616 
617     if (FAILED(Validate()))
618         return 0;
619     olAssert(_cReferences > 0);
620     lRet = AtomicDec(&_cReferences);
621     if (lRet == 0)
622     {
623         Commit(0); //  flush data
624         delete this;
625     }
626     else if (lRet < 0)
627         lRet = 0;
628 
629     olDebugOut((DEB_ITRACE, "Out CExposedStream::Release\n"));
630     olLog(("%p::Out CExposedStream::Release().  ret == %lu\n", this, lRet));
631     FreeLogFile();
632     return lRet;
633 }
634 
635 //+--------------------------------------------------------------
636 //
637 //  Member:     CExposedStream::Stat, public
638 //
639 //  Synopsis:   Fills in a buffer of information about this object
640 //
641 //  Arguments:  [pstatstg] - Buffer
642 //
643 //  Returns:    Appropriate status code
644 //
645 //  Modifies:   [pstatstg]
646 //
647 //---------------------------------------------------------------
648 
649 
STDMETHODIMP_(SCODE)650 STDMETHODIMP_(SCODE) CExposedStream::Stat(STATSTGW *pstatstg, DWORD grfStatFlag)
651 {
652     SCODE sc;
653 
654     olLog(("%p::In  CExposedStream::Stat(%p)\n", this, pstatstg));
655     olDebugOut((DEB_ITRACE, "In  CExposedStream::Stat(%p)\n",
656                 pstatstg));
657 
658     olChkTo(EH_RetSc, ValidateOutBuffer(pstatstg, sizeof(STATSTGW)));
659     olChk(VerifyStatFlag(grfStatFlag));
660     olChk(Validate());
661     olChk(CheckReverted());
662     pstatstg->grfMode = DFlagsToMode(_df);
663 
664     pstatstg->clsid = CLSID_NULL;  // irrelevant for streams
665     pstatstg->grfStateBits = 0;    // irrelevant for streams
666     pstatstg->type = STGTY_STREAM;
667     pstatstg->grfLocksSupported = 0;
668     pstatstg->reserved = 0;
669 
670     // we null these values 'cos they are not interesting for
671     // direct streams ...
672     pstatstg->ctime.dwLowDateTime = pstatstg->ctime.dwHighDateTime = 0;
673     pstatstg->mtime.dwLowDateTime = pstatstg->mtime.dwHighDateTime = 0;
674     pstatstg->atime.dwLowDateTime = pstatstg->atime.dwHighDateTime = 0;
675     pstatstg->pwcsName = NULL;
676     if ((grfStatFlag & STATFLAG_NONAME) == 0)
677     {                       // fill in name
678         olChk(DfAllocWCS((WCHAR *)_dfn.GetBuffer(),
679                          &pstatstg->pwcsName));
680         wcscpy(pstatstg->pwcsName, (WCHAR *)_dfn.GetBuffer());
681     }
682     ULONG cbSize;
683     GetSize(&cbSize);
684     ULISet32(pstatstg->cbSize, cbSize);
685 
686     olDebugOut((DEB_ITRACE, "Out CExposedStream::Stat\n"));
687 EH_Err:
688     if (FAILED(sc))
689         memset(pstatstg, 0, sizeof(STATSTGW));
690 EH_RetSc:
691     olLog(("%p::Out CExposedStream::Stat().  ret == %lx\n",
692            this, sc));
693     return sc;
694 }
695 
696 //+--------------------------------------------------------------
697 //
698 //  Member:     CExposedStream::Clone, public
699 //
700 //  Synopsis:   Clones a stream
701 //
702 //  Returns:    Appropriate status code
703 //
704 //---------------------------------------------------------------
705 
706 
Clone(IStream ** ppstm)707 STDMETHODIMP CExposedStream::Clone(IStream **ppstm)
708 {
709     CExposedStream *pst;
710     SCODE sc;
711 
712     olLog(("%p::In  CExposedStream::Clone(%p)\n", this, ppstm));
713     olDebugOut((DEB_ITRACE, "In  CExposedStream::Clone(%p)\n", ppstm));
714 
715     olChk(ValidateOutPtrBuffer(ppstm));
716     *ppstm = NULL;
717     olChk(Validate());
718     olChk(CheckReverted());
719     olMemTo(EH_pst, pst = new CExposedStream);
720     olChkTo(EH_pst, pst->Init(_pst, _pdfParent, _df, &_dfn, _ulPos));
721     _pst->AddRef();
722     *ppstm = pst;
723 
724     olDebugOut((DEB_ITRACE, "Out CExposedStream::Clone => %p\n", *ppstm));
725     return ResultFromScode(sc);
726 
727 EH_pst:
728     delete pst;
729 EH_Err:
730     olLog(("%p::Out CExposedStream::Clone(). *ppstm == %p, ret == %lx\n",
731            this, SAFE_DREFppstm, sc));
732     return ResultFromScode(sc);
733 }
734 
735 //+--------------------------------------------------------------
736 //
737 //  Member:     CExposedStream::AddRef, public
738 //
739 //  Synopsis:   Increments the ref count
740 //
741 //  Returns:    Appropriate status code
742 //
743 //---------------------------------------------------------------
744 
STDMETHODIMP_(ULONG)745 STDMETHODIMP_(ULONG) CExposedStream::AddRef(void)
746 {
747     ULONG ulRet;
748 
749     olLog(("%p::In  CExposedStream::AddRef()\n", this));
750     olDebugOut((DEB_ITRACE, "In  CExposedStream::AddRef()\n"));
751 
752     if (FAILED(Validate()))
753         return 0;
754     AtomicInc(&_cReferences);
755     ulRet = _cReferences;
756 
757     olDebugOut((DEB_ITRACE, "Out CExposedStream::AddRef\n"));
758     olLog(("%p::Out CExposedStream::AddRef().  ret == %lu\n", this, ulRet));
759     return ulRet;
760 }
761 
762 //+--------------------------------------------------------------
763 //
764 //  Member:     CExposedStream::LockRegion, public
765 //
766 //  Synopsis:   Nonfunctional
767 //
768 //  Returns:    Appropriate status code
769 //
770 //---------------------------------------------------------------
771 
LockRegion(ULARGE_INTEGER libOffset,ULARGE_INTEGER cb,DWORD dwLockType)772 STDMETHODIMP CExposedStream::LockRegion(ULARGE_INTEGER libOffset,
773                                         ULARGE_INTEGER cb,
774                                         DWORD dwLockType)
775 {
776     olDebugOut((DEB_ITRACE, "In  CExposedStream::LockRegion("
777                 "%lu, %lu\n", ULIGetLow(cb), dwLockType));
778     olDebugOut((DEB_ITRACE, "Out CExposedStream::LockRegion\n"));
779     olLog(("%p::INVALID CALL TO CExposedStream::LockRegion()\n"));
780     UNREFERENCED_PARM(libOffset);
781     UNREFERENCED_PARM(cb);
782     UNREFERENCED_PARM(dwLockType);
783     olAssert(FALSE && aMsg("function not implemented!"));
784     return ResultFromScode(STG_E_INVALIDFUNCTION);
785 }
786 
787 //+--------------------------------------------------------------
788 //
789 //  Member:     CExposedStream::UnlockRegion, public
790 //
791 //  Synopsis:   Nonfunctional
792 //
793 //  Returns:    Appropriate status code
794 //
795 //---------------------------------------------------------------
796 
UnlockRegion(ULARGE_INTEGER libOffset,ULARGE_INTEGER cb,DWORD dwLockType)797 STDMETHODIMP CExposedStream::UnlockRegion(ULARGE_INTEGER libOffset,
798                                           ULARGE_INTEGER cb,
799                                           DWORD dwLockType)
800 {
801     olDebugOut((DEB_ITRACE, "In  CExposedStream::UnlockRegion(%lu, %lu)\n",
802                 ULIGetLow(cb), dwLockType));
803     olDebugOut((DEB_ITRACE, "Out CExposedStream::UnlockRegion\n"));
804     olLog(("%p::INVALID CALL TO CExposedStream::UnlockRegion()\n"));
805     UNREFERENCED_PARM(libOffset);
806     UNREFERENCED_PARM(cb);
807     UNREFERENCED_PARM(dwLockType);
808     olAssert(FALSE && aMsg("function not implemented!"));
809     return ResultFromScode(STG_E_INVALIDFUNCTION);
810 }
811 
812 //+--------------------------------------------------------------
813 //
814 //  Member:     CExposedStream::Commit, public
815 //
816 //  Returns:    Appropriate status code
817 //
818 //---------------------------------------------------------------
819 
820 
Commit(DWORD grfCommitFlags)821 STDMETHODIMP CExposedStream::Commit(DWORD grfCommitFlags)
822 {
823     SCODE sc;
824     olDebugOut((DEB_ITRACE, "In  CExposedStream::Commit(%lu)\n",
825                 grfCommitFlags));
826     olLog(("%p::In  CExposedStream::Commit(%lx)\n", this, grfCommitFlags));
827 
828     olChk(Validate());
829     olChk(CheckReverted());
830 
831     if (_fDirty)
832     {   //  We're a stream so we must have a parent
833         //  We dirty all parents up to the next
834         //  transacted storage
835         _pdfParent->SetDirty();
836         sc = _pdfParent->GetBaseMS()
837             ->Flush(FLUSH_CACHE(grfCommitFlags));
838     }
839 
840     olDebugOut((DEB_ITRACE, "Out CExposedStream::Commit\n"));
841 EH_Err:
842     olLog(("%p::Out CExposedStream::Commit().  ret == %lx", this, sc));
843     return ResultFromScode(sc);
844 }
845 
846 //+--------------------------------------------------------------
847 //
848 //  Member:     CExposedStream::Revert, public
849 //
850 //  Synopsis:   No-op in current implementation
851 //
852 //  Returns:    Appropriate status code
853 //
854 //---------------------------------------------------------------
855 
856 
Revert(void)857 STDMETHODIMP CExposedStream::Revert(void)
858 {
859     olDebugOut((DEB_ITRACE, "In  CExposedStream::Revert()\n"));
860     olDebugOut((DEB_ITRACE, "Out CExposedStream::Revert\n"));
861 
862     olLog(("%p::In  CExposedStream::Revert()\n", this));
863     olLog(("%p::Out CExposedStream::Revert().  ret == %lx", this, S_OK));
864 
865     return ResultFromScode(STG_E_UNIMPLEMENTEDFUNCTION);
866 }
867 
868 //+--------------------------------------------------------------
869 //
870 //  Member:     CExposedStream::QueryInterface, public
871 //
872 //  Synopsis:   Returns an object for the requested interface
873 //
874 //  Arguments:  [iid] - Interface ID
875 //              [ppvObj] - Object return
876 //
877 //  Returns:    Appropriate status code
878 //
879 //  Modifies:   [ppvObj]
880 //
881 //---------------------------------------------------------------
882 
883 
QueryInterface(REFIID iid,void ** ppvObj)884 STDMETHODIMP CExposedStream::QueryInterface(REFIID iid, void **ppvObj)
885 {
886     SCODE sc;
887 
888     olLog(("%p::In  CExposedStream::QueryInterface(?, %p)\n",
889            this, ppvObj));
890     olDebugOut((DEB_ITRACE, "In  CExposedStream::QueryInterface(?, %p)\n",
891                 ppvObj));
892     olChk(ValidateOutPtrBuffer(ppvObj));
893     *ppvObj = NULL;
894     olChk(ValidateIid(iid));
895     olChk(Validate());
896     olChk(CheckReverted());
897     if (IsEqualIID(iid, IID_IStream) || IsEqualIID(iid, IID_IUnknown))
898     {
899         olChk(AddRef());
900         *ppvObj = this;
901     }
902     else
903         olErr(EH_Err, E_NOINTERFACE);
904     sc = S_OK;
905 
906     olDebugOut((DEB_ITRACE, "Out CExposedStream::QueryInterface => %p\n",
907                 ppvObj));
908 EH_Err:
909     olLog(("%p::Out CExposedStream::QueryInterface().  *ppvObj == %p, ret == %lx\n",
910            this, *ppvObj, sc));
911     return ResultFromScode(sc);
912 }
913 
914 //+--------------------------------------------------------------
915 //
916 //  Member: CExposedStream::RevertFromAbove, public (virtual)
917 //
918 //  Synopsis: Parent has asked for reversion
919 //
920 //---------------------------------------------------------------
921 
RevertFromAbove(void)922 void CExposedStream::RevertFromAbove(void)
923 {
924     msfDebugOut((DEB_ITRACE,
925                  "In CExposedStream::RevertFromAbove:%p()\n", this));
926     _df |= DF_REVERTED;
927     _pst->Release();
928 #if DBG == 1
929     _pst = NULL;
930 #endif
931     msfDebugOut((DEB_ITRACE, "Out CExposedStream::RevertFromAbove\n"));
932 }
933 
934 #ifdef NEWPROPS
935 //+-------------------------------------------------------------------
936 //
937 //  Member:     CExposedStream::Open
938 //
939 //  Synopsis:   Opens mapped view of exposed stream. Called by
940 //              NtCreatePropertySet et al.
941 //
942 //  Notes:      Gets the size of the underlying stream and reads it
943 //              into memory so that it can be "mapped."
944 //
945 //--------------------------------------------------------------------
946 
Open(IN VOID * powner,OUT LONG * phr)947 VOID CExposedStream::Open(IN VOID *powner, OUT LONG *phr)
948 {
949     LONG& sc = *phr;
950     sc = S_OK;
951 
952     // If given a pointer to the owner of this mapped stream,
953     // save it. This could be NULL. (i.e. when called from ReOpen)
954     if( NULL != powner  )
955         _powner = (BYTE*) powner;
956 
957     if (_pb == NULL)
958     {
959         VOID *pv;
960         _cbUsed = 0;
961         olChk(CheckReverted());
962         _pst->GetSize(&_cbOriginalStreamSize);
963 
964         if (_cbOriginalStreamSize > CBMAXPROPSETSTREAM)
965             olErr(EH_Err, STG_E_INVALIDHEADER);
966 
967         _cbUsed = _cbOriginalStreamSize;
968         olMemTo(EH_Err, pv = new BYTE[_cbOriginalStreamSize]);
969         _pb = (BYTE*) pv;
970         olChkTo(EH_Read,
971                     _pst->ReadAt(0, pv, _cbOriginalStreamSize, &_cbUsed));
972         olAssert(_cbOriginalStreamSize == _cbUsed &&
973                  "CExposedStream did not read in all the info!");
974 
975         // Notify our owner that we have new data
976         if (*phr == S_OK && _powner != NULL && 0 != _cbUsed)
977         {
978             *phr = RtlOnMappedStreamEvent((VOID*)_powner, pv, _cbUsed );
979         }
980 
981     }
982     olDebugOut((DEB_PROP_MAP, "CExposedStream(%X):Open returns normally\n", this));
983     return;
984 
985 // Error handling
986 EH_Read:
987     delete[] _pb;
988     _pb = NULL;
989     _cbUsed = 0;
990 
991 EH_Err:
992     olDebugOut((DEB_PROP_MAP,
993                 "CExposedStream(%X):Open exception returns %08X\n",
994                 this, *phr));
995     return;
996 }
997 
998 //+-------------------------------------------------------------------
999 //
1000 //  Member:     CExposedStream::Close
1001 //
1002 //  Synopsis:   Operates on mapped view of exposed stream. Called by
1003 //              NtCreatePropertySet et al.
1004 //
1005 //  Notes:      Does nothing because the object may be mapped in
1006 //              another process.
1007 //
1008 //--------------------------------------------------------------------
1009 
Close(OUT LONG * phr)1010 VOID CExposedStream::Close(OUT LONG *phr)
1011 {
1012     // Write the changes.  We don't need to Commit them,
1013     // they will be implicitely committed when the
1014     // Stream is Released.
1015 
1016     *phr = Write();
1017 
1018     if( FAILED(*phr) )
1019     {
1020         olDebugOut( (DEB_PROP_MAP,
1021                      "CPubStream(%08X)::Close exception returns %08X\n",
1022                      this, *phr));
1023     }
1024 
1025     return;
1026 }
1027 
1028 //+-------------------------------------------------------------------
1029 //
1030 //  Member:     CExposedStream::ReOpen
1031 //
1032 //  Synopsis:   Operates on mapped view of exposed stream. Called by
1033 //              NtCreatePropertySet et al.
1034 //
1035 //  Notes:      Combined open and map.
1036 //
1037 //--------------------------------------------------------------------
1038 
ReOpen(IN OUT VOID ** ppv,OUT LONG * phr)1039 VOID CExposedStream::ReOpen(IN OUT VOID **ppv, OUT LONG *phr)
1040 {
1041     *ppv = NULL;
1042     Open( (void*)NULL,          // unspecified owner
1043           phr);
1044     if ( SUCCEEDED(*phr) )
1045         *ppv = _pb;
1046 }
1047 
1048 //+-------------------------------------------------------------------
1049 //
1050 //  Member:     CExposedStream::Quiesce
1051 //
1052 //  Synopsis:   Operates on mapped view of exposed stream. Called by
1053 //              NtCreatePropertySet et al.
1054 //
1055 //  Notes:      Meaningless for docfile mapped stream.
1056 //
1057 //--------------------------------------------------------------------
1058 
Quiesce(VOID)1059 VOID CExposedStream::Quiesce(VOID)
1060 {
1061     olAssert(_pb != NULL);
1062     DfpdbgCheckUnusedMemory();
1063 }
1064 
1065 //+-------------------------------------------------------------------
1066 //
1067 //  Member:     CExposedStream::Map
1068 //
1069 //  Synopsis:   Operates on mapped view of exposed stream. Called by
1070 //              NtCreatePropertySet et al.
1071 //
1072 //  Notes:      Return the address of the "mapping" buffer.
1073 //
1074 //--------------------------------------------------------------------
1075 
Map(BOOLEAN fCreate,VOID ** ppv)1076 VOID CExposedStream::Map(BOOLEAN fCreate, VOID **ppv)
1077 {
1078     UNREFERENCED_PARM(fCreate);
1079     olAssert(_pb != NULL);
1080     DfpdbgCheckUnusedMemory();
1081     *ppv = _pb;
1082 }
1083 
1084 //+-------------------------------------------------------------------
1085 //
1086 //  Member:     CExposedStream::Unmap
1087 //
1088 //  Synopsis:   Operates on mapped view of exposed stream. Called by
1089 //              NtCreatePropertySet et al.
1090 //
1091 //  Notes:      Unmapping is merely zeroing the pointer.  We don't
1092 //              flush because that's done explicitly by the
1093 //              CPropertyStorage class.
1094 //
1095 //
1096 //--------------------------------------------------------------------
1097 
Unmap(BOOLEAN fFlush,VOID ** pv)1098 VOID CExposedStream::Unmap(BOOLEAN fFlush, VOID **pv)
1099 {
1100     UNREFERENCED_PARM(fFlush);
1101     DfpdbgCheckUnusedMemory();
1102     *pv = NULL;
1103 }
1104 
1105 //+-------------------------------------------------------------------
1106 //
1107 //  Member:     CExposedStream::Flush
1108 //
1109 //  Synopsis:   Operates on mapped view of exposed stream. Called by
1110 //              NtCreatePropertySet et al.
1111 //              Flush the memory property set to disk and commit it.
1112 //
1113 //--------------------------------------------------------------------
1114 
Flush(OUT LONG * phr)1115 VOID CExposedStream::Flush(OUT LONG *phr)
1116 {
1117     *phr = S_OK;
1118     // write out any data we have cached to the stream
1119     if (S_OK == (*phr = Write()))
1120     {
1121         // commit the stream
1122         (*phr) = Commit(STGC_DEFAULT);
1123     }
1124 
1125     return;
1126 }
1127 
1128 //+-------------------------------------------------------------------
1129 //
1130 //  Member:     CExposedStream::GetSize
1131 //
1132 //  Synopsis:   Returns size of exposed stream. Called by
1133 //              NtCreatePropertySet et al.
1134 //
1135 //  Notes:
1136 //--------------------------------------------------------------------
1137 
GetSize(OUT LONG * phr)1138 ULONG CExposedStream::GetSize(OUT LONG *phr)
1139 {
1140     *phr = S_OK;
1141     if (_pb == NULL)
1142         Open((void*)NULL,       // unspecified owner
1143              phr);
1144 
1145     if( SUCCEEDED(*phr) )
1146     {
1147         olAssert(_pb != NULL);
1148         DfpdbgCheckUnusedMemory();
1149     }
1150 
1151     return _cbUsed;
1152 }
1153 
1154 //+-------------------------------------------------------------------
1155 //
1156 //  Member:     CExposedStream::SetSize
1157 //
1158 //  Synopsis:   Sets size of "map." Called by
1159 //              NtCreatePropertySet et al.
1160 //
1161 //  Arguments:  [cb] -- requested size.
1162 //    [fPersistent] -- FALSE if expanding in-memory read-only image
1163 //              [ppv] -- new mapped address.
1164 //
1165 //  Signals:    Not enough disk space.
1166 //
1167 //
1168 //--------------------------------------------------------------------
1169 
SetSize(ULONG cb,IN BOOLEAN fPersistent,VOID ** ppv,OUT LONG * phr)1170 VOID  CExposedStream::SetSize(ULONG cb, IN BOOLEAN fPersistent,
1171                               VOID **ppv, OUT LONG *phr)
1172 {
1173     *phr = S_OK;
1174     LONG& sc=*phr;
1175     BYTE *pbNew;
1176 
1177     olAssert(cb != 0);
1178     DfpdbgCheckUnusedMemory();
1179     olChk(CheckReverted());
1180 
1181     //
1182     // if we are growing the data, we should grow the stream
1183     //
1184     if (fPersistent && cb > _cbUsed)
1185     {
1186         olChk(_pst->SetSize(cb));
1187     }
1188 
1189     olMem(pbNew = new BYTE[cb]);
1190 
1191     memcpy(pbNew, _pb, (cb < _cbUsed) ? cb : _cbUsed); // smaller of the 2
1192     delete[] _pb;
1193 
1194     _pb = pbNew;
1195     _cbUsed = cb;
1196     *ppv = _pb;
1197 
1198     DfpdbgFillUnusedMemory();
1199 
1200 EH_Err:
1201     olDebugOut((DEB_PROP_MAP, "CPubStream(%08X):SetSize %s returns hr=%08X\n",
1202         this, *phr != S_OK ? "exception" : "", *phr));
1203     return;
1204 }
1205 
1206 
1207 //+-------------------------------------------------------------------
1208 //
1209 //  Member:     CExposedStream::QueryTimeStamps
1210 //
1211 //  Synopsis:   Operates on mapped view of exposed stream. Called by
1212 //              NtCreatePropertySet et al.
1213 //
1214 //  Notes:
1215 //
1216 //--------------------------------------------------------------------
1217 
QueryTimeStamps(STATPROPSETSTG * pspss,BOOLEAN fNonSimple) const1218 VOID CExposedStream::QueryTimeStamps(STATPROPSETSTG *pspss,
1219                                      BOOLEAN fNonSimple) const
1220 {
1221     UNREFERENCED_PARM(fNonSimple);
1222     UNREFERENCED_PARM(pspss);
1223 }
1224 
1225 //+-------------------------------------------------------------------
1226 //
1227 //  Member:     CExposedStream::QueryModifyTime
1228 //
1229 //  Synopsis:   Operates on mapped view of exposed stream. Called by
1230 //              NtCreatePropertySet et al.
1231 //
1232 //  Notes:
1233 //
1234 //--------------------------------------------------------------------
1235 
QueryModifyTime(OUT LONGLONG * pll) const1236 BOOLEAN CExposedStream::QueryModifyTime(OUT LONGLONG *pll) const
1237 {
1238     UNREFERENCED_PARM(pll);
1239     return (FALSE);
1240 }
1241 
1242 //+-------------------------------------------------------------------
1243 //
1244 //  Member:     CExposedStream::QuerySecurity
1245 //
1246 //  Synopsis:   Operates on mapped view of exposed stream. Called by
1247 //              NtCreatePropertySet et al.
1248 //
1249 //  Notes:
1250 //
1251 //--------------------------------------------------------------------
1252 
QuerySecurity(OUT ULONG * pul) const1253 BOOLEAN CExposedStream::QuerySecurity(OUT ULONG *pul) const
1254 {
1255     UNREFERENCED_PARM(pul);
1256     return FALSE;
1257 }
1258 
1259 //+-------------------------------------------------------------------
1260 //
1261 //  Member:     CExposedStream::IsWriteable
1262 //
1263 //  Synopsis:   Operates on mapped view of exposed stream. Called by
1264 //              NtCreatePropertySet et al.
1265 //
1266 //  Notes:
1267 //
1268 //--------------------------------------------------------------------
1269 
IsWriteable() const1270 BOOLEAN CExposedStream::IsWriteable() const
1271 {
1272     return TRUE;
1273 }
1274 
1275 //+-------------------------------------------------------------------
1276 //
1277 //  Member:     CExposedStream::SetChangePending
1278 //
1279 //  Synopsis:   Operates on mapped view of exposed stream. Called by
1280 //              NtCreatePropertySet et al.
1281 //
1282 //  Notes:
1283 //
1284 //--------------------------------------------------------------------
1285 
1286 #if DBGPROP
SetChangePending(BOOLEAN f)1287 BOOLEAN CExposedStream::SetChangePending(BOOLEAN f)
1288 {
1289     BOOL fOld = _fChangePending;
1290     _fChangePending = f;
1291     return(_fChangePending);
1292 }
1293 #endif
1294 
1295 //+-------------------------------------------------------------------
1296 //
1297 //  Member:     CExposedStream::IsNtMappedStream
1298 //
1299 //  Synopsis:   Operates on mapped view of exposed stream. Called by
1300 //              NtCreatePropertySet et al.
1301 //
1302 //  Notes:
1303 //
1304 //--------------------------------------------------------------------
1305 
1306 #if DBGPROP
IsNtMappedStream(VOID) const1307 BOOLEAN CExposedStream::IsNtMappedStream(VOID) const
1308 {
1309     return FALSE;
1310 }
1311 #endif
1312 
1313 //+-------------------------------------------------------------------
1314 //
1315 //  Member:     CExposedStream::GetHandle
1316 //
1317 //  Synopsis:   Operates on mapped view of exposed stream. Called by
1318 //              NtCreatePropertySet et al.
1319 //
1320 //  Notes:
1321 //
1322 //--------------------------------------------------------------------
1323 
GetHandle(VOID) const1324 HANDLE CExposedStream::GetHandle(VOID) const
1325 {
1326     return INVALID_HANDLE_VALUE;
1327 }
1328 
1329 //+-------------------------------------------------------------------
1330 //
1331 //  Member:     CExposedStream::SetModified
1332 //
1333 //  Synopsis:   Operates on mapped view of exposed stream. Called by
1334 //              NtCreatePropertySet et al.
1335 //
1336 //  Notes:
1337 //
1338 //--------------------------------------------------------------------
1339 
SetModified(VOID)1340 VOID CExposedStream::SetModified(VOID)
1341 {
1342     _fDirty = TRUE;
1343 }
1344 
1345 //+-------------------------------------------------------------------
1346 //
1347 //  Member:     CExposedStream::IsModified
1348 //
1349 //  Synopsis:   Operates on mapped view of exposed stream. Called by
1350 //              NtCreatePropertySet et al.
1351 //
1352 //  Notes:
1353 //
1354 //--------------------------------------------------------------------
1355 
IsModified(VOID) const1356 BOOLEAN CExposedStream::IsModified(VOID) const
1357 {
1358     return _fDirty;
1359 }
1360 
1361 #if DBG
1362 //+-------------------------------------------------------------------
1363 //
1364 //  Member:     CExposedStream::DfpdbgFillUnusedMemory
1365 //
1366 //--------------------------------------------------------------------
1367 
DfpdbgFillUnusedMemory(VOID)1368 VOID CExposedStream::DfpdbgFillUnusedMemory(VOID)
1369 {
1370     if (_pb == NULL)
1371         return;
1372 
1373     BYTE * pbEndPlusOne = _pb + BytesCommitted();
1374 
1375     for (BYTE *pbUnused = _pb + _cbUsed;
1376          pbUnused < pbEndPlusOne;
1377          pbUnused++)
1378     {
1379         *pbUnused = (BYTE)(DWORD)pbUnused;
1380     }
1381 }
1382 
1383 
1384 //+-------------------------------------------------------------------
1385 //
1386 //  Member:     CExposedStream::DfpdbgCheckUnusedMemory
1387 //
1388 //--------------------------------------------------------------------
1389 
DfpdbgCheckUnusedMemory(VOID)1390 VOID CExposedStream::DfpdbgCheckUnusedMemory(VOID)
1391 {
1392 
1393     if (_pb == NULL)
1394         return;
1395 
1396     if (_cbUsed == 0)
1397         return;
1398 
1399     BYTE * pbEndPlusOne = _pb + BytesCommitted();
1400 
1401     for (BYTE *pbUnused =  _pb + _cbUsed;
1402          pbUnused < pbEndPlusOne;
1403          pbUnused ++)
1404     {
1405         olAssert(*pbUnused == (BYTE)(DWORD)pbUnused);
1406     }
1407 }
1408 
1409 #endif    // DBG
1410 
1411 
1412 //+-------------------------------------------------------------------
1413 //
1414 //  Member:     CExposedStream::Write, private
1415 //
1416 //  Synopsis:   Writes a mapped view of an exposed Stream to the
1417 //              underlying Stream.  Used by RtlCreatePropertySet et al.
1418 //
1419 //  Notes:      The Stream is not commited.  To commit the Stream, in
1420 //              addition to writing it, the Flush method should be used.
1421 //              The Commit is omitted so that it can be skipped in
1422 //              the Property Set Close path, thus eliminating a
1423 //              performance penalty.
1424 //
1425 //--------------------------------------------------------------------
1426 
Write(VOID)1427 HRESULT CExposedStream::Write(VOID)
1428 {
1429     HRESULT hr;
1430     ULONG cbWritten;
1431 
1432     if (!_fDirty ||!_pb)
1433     {
1434         olDebugOut((DEB_PROP_MAP,
1435                  "CExposedStream(%08X):Flush returns with not-dirty\n", this));
1436 
1437         // flushing a stream which isn't a property stream
1438         // this could be optimized by propagating a 'no property streams'
1439         // flag up the storage hierachy such that FlushBufferedData is
1440         // not even called for non-property streams.
1441         return S_OK;
1442     }
1443 
1444     hr=CheckReverted();
1445     if (S_OK!=hr) goto Exit;
1446     olAssert( _pst != NULL );
1447     olAssert( _pb != NULL );
1448     olAssert( _powner != NULL );
1449 
1450     // notify our owner that we are about to perform a write
1451     hr = RtlOnMappedStreamEvent( (void*)_powner, (void*) _pb, _cbUsed );
1452     if ( S_OK != hr ) goto Exit;
1453 
1454     hr = _pst->WriteAt(0, _pb, _cbUsed, &cbWritten);
1455 
1456     if( S_OK != hr ) goto Exit;
1457     // notify our owner that we are done with the write
1458     hr = RtlOnMappedStreamEvent( (VOID*)_powner, (VOID *) _pb, _cbUsed );
1459     if( S_OK != hr ) goto Exit;
1460 
1461     if (_cbUsed < _cbOriginalStreamSize)
1462     {
1463         // if the stream is shrinking, this is a good time to do it.
1464         hr = _pst->SetSize(_cbUsed);
1465         if (S_OK!=hr) goto Exit;
1466     }
1467 
1468 Exit:
1469     if (hr == S_OK || hr == STG_E_REVERTED)
1470     {
1471         _fDirty = FALSE;
1472     }
1473 
1474     olDebugOut((DEB_PROP_MAP, "CPubStream(%08X):Flush %s returns hr=%08X\n",
1475         this, hr != S_OK ? "exception" : "", hr));
1476 
1477     return hr;
1478 }
1479 
1480 //+--------------------------------------------------------------
1481 //
1482 //  Member:         CExposedStream::FlushBufferedData, public
1483 //
1484 //  Synopsis:   Flush out the property buffers.
1485 //
1486 //---------------------------------------------------------------
1487 
FlushBufferedData()1488 SCODE CExposedStream::FlushBufferedData()
1489 {
1490     SCODE sc = S_OK;
1491 
1492     olDebugOut((DEB_ITRACE, "In  CExposedStream::FlushBufferedData:%p()\n",
1493                 this));
1494 
1495     Flush(&sc);
1496 
1497     olDebugOut((DEB_PROP_MAP,
1498                 "CExposedStream(%08X):FlushBufferedData returns %08X\n",
1499                 this, sc));
1500 
1501     return sc;
1502 }
1503 
1504 #endif // ifdef NEWPROPS
1505 
1506 
1507 
1508 
1509 
1510