Click here to Skip to main content
15,886,199 members
Articles / Desktop Programming / MFC

Driver to Hide Processes and Files

, ,
Rate me:
Please Sign up or sign in to vote.
4.57/5 (145 votes)
17 Aug 2009CPOL12 min read 655K   28.6K   369  
In this article, we describe the driver we created to hide processes and files in a system.
/*
 * Copyright (c) 1996,1997
 * Silicon Graphics Computer Systems, Inc.
 *
 * Copyright (c) 1999 
 * Boris Fomitchev
 *
 * This material is provided "as is", with absolutely no warranty expressed
 * or implied. Any use is at your own risk.
 *
 * Permission to use or copy this software for any purpose is hereby granted 
 * without fee, provided the above notices are retained on all copies.
 * Permission to modify the code and to distribute modified code is granted,
 * provided the above notices are retained, and a notice that the code was
 * modified is included with the above copyright notice.
 *
 */
#ifndef _STLP_FSTREAM_C
#define _STLP_FSTREAM_C

# ifndef _STLP_INTERNAL_FSTREAM_H
#  include <stl/_fstream.h>
# endif

# if defined (_STLP_EXPOSE_STREAM_IMPLEMENTATION)

_STLP_BEGIN_NAMESPACE

# if defined ( _STLP_NESTED_TYPE_PARAM_BUG )
// no wchar_t is supported for this mode
# define __BF_int_type__ int
# define __BF_pos_type__ streampos
# define __BF_off_type__ streamoff
# else
# define __BF_int_type__ _STLP_TYPENAME_ON_RETURN_TYPE basic_filebuf<_CharT, _Traits>::int_type
# define __BF_pos_type__ _STLP_TYPENAME_ON_RETURN_TYPE basic_filebuf<_CharT, _Traits>::pos_type
# define __BF_off_type__ _STLP_TYPENAME_ON_RETURN_TYPE basic_filebuf<_CharT, _Traits>::off_type
# endif


//----------------------------------------------------------------------
// Public basic_filebuf<> member functions

template <class _CharT, class _Traits>
basic_filebuf<_CharT, _Traits>::basic_filebuf()
     :  basic_streambuf<_CharT, _Traits>(), _M_base(),
    _M_constant_width(false), _M_always_noconv(false),
    _M_int_buf_dynamic(false),
    _M_in_input_mode(false), _M_in_output_mode(false),
    _M_in_error_mode(false), _M_in_putback_mode(false),
    _M_int_buf(0), _M_int_buf_EOS(0),
    _M_ext_buf(0), _M_ext_buf_EOS(0),
    _M_ext_buf_converted(0), _M_ext_buf_end(0),
    _M_state(_STLP_DEFAULT_CONSTRUCTED(_State_type)),
    _M_end_state(_STLP_DEFAULT_CONSTRUCTED(_State_type)),
    _M_mmap_base(0), _M_mmap_len(0),
    _M_saved_eback(0), _M_saved_gptr(0), _M_saved_egptr(0),
    _M_codecvt(0),
    _M_width(1), _M_max_width(1)
{
  this->_M_setup_codecvt(locale());
}

template <class _CharT, class _Traits>
basic_filebuf<_CharT, _Traits>::~basic_filebuf() {
  this->close();
  _M_deallocate_buffers();
}


template <class _CharT, class _Traits>
_STLP_TYPENAME_ON_RETURN_TYPE basic_filebuf<_CharT, _Traits>::int_type 
basic_filebuf<_CharT, _Traits>::underflow() 
{
  return _Underflow<_CharT, _Traits>::_M_doit(this);
}

template <class _CharT, class _Traits>
basic_filebuf<_CharT, _Traits>* 
basic_filebuf<_CharT, _Traits>::close()
{
  bool __ok = this->is_open();

  if (_M_in_output_mode) {
    __ok = __ok && !_Traits::eq_int_type(this->overflow(traits_type::eof()),
                                         traits_type::eof());
    __ok == __ok && this->_M_unshift();
  }
  else if (_M_in_input_mode)
      this->_M_exit_input_mode();

  // Note order of arguments.  We close the file even if __ok is false.
  __ok = _M_base._M_close() && __ok;

  // Restore the initial state, except that we don't deallocate the buffer
  // or mess with the cached codecvt information.
  _M_state = _M_end_state = _State_type();
  _M_ext_buf_converted = _M_ext_buf_end = 0;

  _M_mmap_base = 0;
  _M_mmap_len = 0;

  this->setg(0, 0, 0);
  this->setp(0, 0);

  _M_saved_eback = _M_saved_gptr = _M_saved_egptr = 0;

  _M_in_input_mode = _M_in_output_mode = _M_in_error_mode = _M_in_putback_mode
    = false;

  return __ok ? this : 0;
}

// This member function is called whenever we exit input mode.
// It unmaps the memory-mapped file, if any, and sets
// _M_in_input_mode to false.  
template <class _CharT, class _Traits>
void basic_filebuf<_CharT, _Traits>::_M_exit_input_mode()
{
   if (_M_mmap_base != 0)
     _M_base._M_unmap(_M_mmap_base, _M_mmap_len); 
   _M_in_input_mode = false;
   _M_mmap_base = 0;
}


//----------------------------------------------------------------------
// basic_filebuf<> overridden protected virtual member functions

template <class _CharT, class _Traits>
streamsize basic_filebuf<_CharT, _Traits>::showmanyc()
{
  // Is there any possibility that reads can succeed?
  if (!this->is_open() || _M_in_output_mode || _M_in_error_mode)
    return -1;

  else if (_M_in_putback_mode)
    return this->egptr() - this->gptr();

  else if (_M_constant_width) {
    streamoff __pos  = _M_base._M_seek(0, ios_base::cur);
    streamoff __size = _M_base._M_file_size();
    return __pos >= 0 && __size > __pos ? __size - __pos : 0;
  }

  else 
    return 0;
}


// Make a putback position available, if necessary, by switching to a 
// special internal buffer used only for putback.  The buffer is
// [_M_pback_buf, _M_pback_buf + _S_pback_buf_size), but the base
// class only sees a piece of it at a time.  (We want to make sure
// that we don't try to read a character that hasn't been initialized.)
// The end of the putback buffer is always _M_pback_buf + _S_pback_buf_size,
// but the beginning is usually not _M_pback_buf.
template <class _CharT, class _Traits>
__BF_int_type__ 
basic_filebuf<_CharT, _Traits>::pbackfail(int_type __c)
{
  const int_type __eof = traits_type::eof();

  // If we aren't already in input mode, pushback is impossible.
  if (!_M_in_input_mode)
    return __eof;

  // We can use the ordinary get buffer if there's enough space, and
  // if it's a buffer that we're allowed to write to.
  if (this->gptr() != this->eback() &&
      (traits_type::eq_int_type(__c, __eof) ||
       traits_type::eq(traits_type::to_char_type(__c), this->gptr()[-1]) ||
       !_M_mmap_base)) {
    this->gbump(-1);
    if (traits_type::eq_int_type(__c, __eof) ||
        traits_type::eq(traits_type::to_char_type(__c), *this->gptr()))
      return traits_type::to_int_type(*this->gptr());
  }
  else if (!traits_type::eq_int_type(__c, __eof)) {
    // Are we in the putback buffer already?
    _CharT* __pback_end = _M_pback_buf + __STATIC_CAST(int,_S_pback_buf_size);
    if (_M_in_putback_mode) {
      // Do we have more room in the putback buffer?
      if (this->eback() != _M_pback_buf) 
        this->setg(this->egptr() - 1, this->egptr() - 1, __pback_end);
      else
        return __eof;           // No more room in the buffer, so fail.
    }
    else {                      // We're not yet in the putback buffer.
      _M_saved_eback = this->eback();
      _M_saved_gptr  = this->gptr();
      _M_saved_egptr = this->egptr();
      this->setg(__pback_end - 1, __pback_end - 1, __pback_end);
      _M_in_putback_mode = true;
    }
  }
  else
    return __eof;

  // We have made a putback position available.  Assign to it, and return.
  *this->gptr() = traits_type::to_char_type(__c);
  return __c;
}

// This member function flushes the put area, and also outputs the
// character __c (unless __c is eof).  Invariant: we always leave room
// in the internal buffer for one character more than the base class knows
// about.  We see the internal buffer as [_M_int_buf, _M_int_buf_EOS), but
// the base class only sees [_M_int_buf, _M_int_buf_EOS - 1).
template <class _CharT, class _Traits>
__BF_int_type__
basic_filebuf<_CharT, _Traits>::overflow(int_type __c)
{
  // Switch to output mode, if necessary.
  if (!_M_in_output_mode)
    if (!_M_switch_to_output_mode())
      return traits_type::eof();

  _CharT* __ibegin = this->_M_int_buf;
  _CharT* __iend   = this->pptr();
  this->setp(_M_int_buf, _M_int_buf_EOS - 1);

  // Put __c at the end of the internal buffer.
  if (!traits_type::eq_int_type(__c, traits_type::eof()))
    *__iend++ = __c;

  // For variable-width encodings, output may take more than one pass.
  while (__ibegin != __iend) {
    const _CharT* __inext = __ibegin;
    char* __enext         = _M_ext_buf;
    typename _Codecvt::result __status
      = _M_codecvt->out(_M_state, __ibegin, __iend, __inext,
                                  _M_ext_buf, _M_ext_buf_EOS, __enext);
    if (__status == _Codecvt::noconv)
      return _Noconv_output<_Traits>::_M_doit(this, __ibegin, __iend)
        ? traits_type::not_eof(__c)
        : _M_output_error();

    // For a constant-width encoding we know that the external buffer
    // is large enough, so failure to consume the entire internal buffer
    // or to produce the correct number of external characters, is an error.
    // For a variable-width encoding, however, we require only that we 
    // consume at least one internal character
    else if (__status != _Codecvt::error && 
             ((__inext == __iend && (__enext - _M_ext_buf == 
                                     _M_width * (__iend - __ibegin))) ||
              (!_M_constant_width && __inext != __ibegin))) {
        // We successfully converted part or all of the internal buffer.
      ptrdiff_t __n = __enext - _M_ext_buf;
      if (_M_write(_M_ext_buf, __n))
        __ibegin += __inext - __ibegin;
      else
        return _M_output_error();
    }
    else
      return _M_output_error();
  }

  return traits_type::not_eof(__c);
}

// This member function must be called before any I/O has been
// performed on the stream, otherwise it has no effect.
//
// __buf == 0 && __n == 0 means to make ths stream unbuffered.
// __buf != 0 && __n > 0 means to use __buf as the stream's internal
// buffer, rather than the buffer that would otherwise be allocated
// automatically.  __buf must be a pointer to an array of _CharT whose
// size is at least __n.
template <class _CharT, class _Traits>
basic_streambuf<_CharT, _Traits>*
basic_filebuf<_CharT, _Traits>::setbuf(_CharT* __buf, streamsize __n)
{
  if (!_M_in_input_mode &&! _M_in_output_mode && !_M_in_error_mode &&
      _M_int_buf == 0) {
    if (__buf == 0 && __n == 0)
      _M_allocate_buffers(0, 1);
    else if (__buf != 0 && __n > 0)
      _M_allocate_buffers(__buf, __n);
  }
  return this;
}

template <class _CharT, class _Traits>
__BF_pos_type__
basic_filebuf<_CharT, _Traits>::seekoff(off_type __off,
                                        ios_base::seekdir __whence,
                                        ios_base::openmode /* dummy */)
{
  if (this->is_open() &&
      (__off == 0 || (_M_constant_width && this->_M_base._M_in_binary_mode()))) {

    if (!_M_seek_init(__off != 0 || __whence != ios_base::cur))
      return pos_type(-1);

    // Seek to beginning or end, regardless of whether we're in input mode.
    if (__whence == ios_base::beg || __whence == ios_base::end)
      return _M_seek_return(_M_base._M_seek(_M_width * __off, __whence),
                            _State_type());

    // Seek relative to current position.  Complicated if we're in input mode.
    else if (__whence == ios_base::cur) {

      if (!_M_in_input_mode)
        return _M_seek_return(_M_base._M_seek(_M_width * __off, __whence),
                              _State_type());
      else if (_M_mmap_base != 0) {
        // __off is relative to gptr().  We need to do a bit of arithmetic
        // to get an offset relative to the external file pointer.
        streamoff __adjust = _M_mmap_len - (this->gptr() - (_CharT*) _M_mmap_base);

        // if __off == 0, we do not need to exit input mode and to shift file pointer
        if (__off == 0) {
          return pos_type(_M_base._M_seek(0, ios_base::cur) - __adjust);
        }
        else
          return _M_seek_return(_M_base._M_seek(__off - __adjust, ios_base::cur), _State_type());
      }
      else if (_M_constant_width) { // Get or set the position.  

        streamoff __iadj = _M_width * (this->gptr() - this->eback());
        
        // Compensate for offset relative to gptr versus offset relative
        // to external pointer.  For a text-oriented stream, where the 
        // compensation is more than just pointer arithmetic, we may get
        // but not set the current position.
        
        if (__iadj <= _M_ext_buf_end - _M_ext_buf) {
          
          streamoff __eadj =  _M_base._M_get_offset(_M_ext_buf + __iadj, _M_ext_buf_end);

          if (__off == 0) {
            return pos_type(_M_base._M_seek(0, ios_base::cur) - __eadj);
          }  else {
            return _M_seek_return(_M_base._M_seek(__off - __eadj, ios_base::cur), _State_type());
          }
        }
        else
          return pos_type(-1);
      }
      else {                    // Get the position.  Encoding is var width.
        // Get position in internal buffer.
        ptrdiff_t __ipos = this->gptr() - this->eback();
        
        // Get corresponding position in external buffer.
        _State_type __state = _M_state;
        int __epos = _M_codecvt->length(__state, _M_ext_buf, _M_ext_buf_end,
                                        __ipos);

        // Sanity check (expensive): make sure __epos is the right answer.
        _State_type __tmp_state = _M_state;
        _Filebuf_Tmp_Buf<_CharT> __buf(__ipos);
        _CharT* __ibegin = __buf._M_ptr;
        _CharT* __inext  = __ibegin;

        const char* __dummy;
        typename _Codecvt::result __status
          = _M_codecvt->in(__tmp_state,
                           _M_ext_buf, _M_ext_buf + __epos, __dummy,
                           __ibegin, __ibegin + __ipos, __inext);
        if (__status != _Codecvt::error &&
            (__status == _Codecvt::noconv ||
             (__inext == __ibegin + __ipos &&
              equal(this->gptr(), this->eback(), __ibegin,
                    _Eq_traits<traits_type>())))) {
          // Get the current position (at the end of the external buffer),
          // then adjust it.  Again, it might be a text-oriented stream.
          streamoff __cur = _M_base._M_seek(0, ios_base::cur);
          streamoff __adj =
            _M_base._M_get_offset(_M_ext_buf, _M_ext_buf + __epos) -
            _M_base._M_get_offset(_M_ext_buf, _M_ext_buf_end);
          if (__cur != -1 && __cur + __adj >= 0)
            return _M_seek_return(__cur + __adj, __state);
          else
            return pos_type(-1);
        }
        else                    // We failed the sanity check.
          return pos_type(-1);
      }
    }
    else                        // Unrecognized value for __whence.
      return pos_type(-1);
  }
  else
    return pos_type(-1);
}


template <class _CharT, class _Traits>
__BF_pos_type__
basic_filebuf<_CharT, _Traits>::seekpos(pos_type __pos,
                                        ios_base::openmode /* dummy */)
{
  if (this->is_open()) {
    if (!_M_seek_init(true))
      return pos_type(-1);

    streamoff __off = off_type(__pos);
    if (__off != -1 && _M_base._M_seek(__off, ios_base::beg) != -1) {
      _M_state = __pos.state();
      return _M_seek_return(__off, __pos.state());
    }
    else
      return pos_type(-1);
  }
  else
    return pos_type(-1);
}


template <class _CharT, class _Traits>
int basic_filebuf<_CharT, _Traits>::sync()
{
  if (_M_in_output_mode)
    return traits_type::eq_int_type(this->overflow(traits_type::eof()),
                                    traits_type::eof())
      ? -1
      : 0;
  else
    return 0;
}


// Change the filebuf's locale.  This member function has no effect
// unless it is called before any I/O is performed on the stream.
template <class _CharT, class _Traits>
void basic_filebuf<_CharT, _Traits>::imbue(const locale& __loc)
{
  if (!_M_in_input_mode &&! _M_in_output_mode && !_M_in_error_mode) {
    this->_M_setup_codecvt(__loc);
  }
}

//----------------------------------------------------------------------
// basic_filebuf<> helper functions.

//----------------------------------------
// Helper functions for switching between modes.

// This member function is called if we're performing the first I/O
// operation on a filebuf, or if we're performing an input operation 
// immediately after a seek.
template <class _CharT, class _Traits>
bool basic_filebuf<_CharT, _Traits>::_M_switch_to_input_mode()
{

  if (this->is_open() && (((int)_M_base.__o_mode() & (int)ios_base::in) !=0)
      && (_M_in_output_mode == 0) && (_M_in_error_mode == 0)) {
    if (!_M_int_buf && !_M_allocate_buffers())
      return false;

    _M_ext_buf_converted = _M_ext_buf;
    _M_ext_buf_end       = _M_ext_buf;

    _M_end_state    = _M_state;

    _M_in_input_mode = true;
    return true;
  }
  else

    return false;
}


// This member function is called if we're performing the first I/O
// operation on a filebuf, or if we're performing an output operation 
// immediately after a seek.
template <class _CharT, class _Traits>
bool basic_filebuf<_CharT, _Traits>::_M_switch_to_output_mode()
{
  if (this->is_open() && (_M_base.__o_mode() & (int)ios_base::out) &&
      _M_in_input_mode == 0 && _M_in_error_mode == 0) {

    if (!_M_int_buf && !_M_allocate_buffers())
      return false;

    // In append mode, every write does an implicit seek to the end
    // of the file.  Whenever leaving output mode, the end of file
    // get put in the initial shift state.
    if (_M_base.__o_mode() & ios_base::app)
      _M_state = _State_type();

    this->setp(_M_int_buf, _M_int_buf_EOS - 1);
    _M_in_output_mode = true;

    return true;
  }
  else
    return false;
}


//----------------------------------------
// Helper functions for input

// This member function is called if there is an error during input.
// It puts the filebuf in error mode, clear the get area buffer, and
// returns eof.
// returns eof.  Error mode is sticky; it is cleared only by close or
// seek.

template <class _CharT, class _Traits>
__BF_int_type__
basic_filebuf<_CharT, _Traits>::_M_input_error()
{
   this->_M_exit_input_mode();   
  _M_in_output_mode = false;
  _M_in_error_mode = true;
  this->setg(0, 0, 0);
  return traits_type::eof();
}

template <class _CharT, class _Traits>
__BF_int_type__ 
basic_filebuf<_CharT, _Traits>::_M_underflow_aux() 
{
  // We have the state and file position from the end of the internal
  // buffer.  This round, they become the beginning of the internal buffer.
  _M_state    = _M_end_state;

  // Fill the external buffer.  Start with any leftover characters that
  // didn't get converted last time.
  if (_M_ext_buf_end > _M_ext_buf_converted)

    _M_ext_buf_end = copy(_M_ext_buf_converted, _M_ext_buf_end, _M_ext_buf);
    // boris : copy_backward did not work
    //_M_ext_buf_end = copy_backward(_M_ext_buf_converted, _M_ext_buf_end, 
    //_M_ext_buf+ (_M_ext_buf_end - _M_ext_buf_converted));
  else
    _M_ext_buf_end = _M_ext_buf;

  // Now fill the external buffer with characters from the file.  This is
  // a loop because occasonally we don't get enough external characters
  // to make progress.
  while (true) {
    ptrdiff_t __n = _M_base._M_read(_M_ext_buf_end, _M_ext_buf_EOS - _M_ext_buf_end);
 
    // Don't enter error mode for a failed read.  Error mode is sticky,
    // and we might succeed if we try again.
    if (__n <= 0)
      return traits_type::eof();

    // Convert the external buffer to internal characters.  
    _M_ext_buf_end += __n;
    const char*   __enext;
    _CharT* __inext;

    typename _Codecvt::result __status
      = _M_codecvt->in(_M_end_state,
                       _M_ext_buf, _M_ext_buf_end, __enext,
                       _M_int_buf, _M_int_buf_EOS, __inext);

    // Error conditions: (1) Return value of error.  (2) Producing internal
    // characters without consuming external characters.  (3) In fixed-width
    // encodings, producing an internal sequence whose length is inconsistent
    // with that of the internal sequence.  (4) Failure to produce any 
    // characters if we have enough characters in the external buffer, where
    // "enough" means the largest possible width of a single character.
    if (__status == _Codecvt::noconv)
      return _Noconv_input<_Traits>::_M_doit(this);

    else if (__status == _Codecvt::error ||
             (__inext != _M_int_buf && __enext == _M_ext_buf) ||
             (_M_constant_width &&
              //         __inext - _M_int_buf != _M_width * (__enext - _M_ext_buf)) ||
              (__inext - _M_int_buf) *  _M_width != (__enext - _M_ext_buf)) ||
             (__inext == _M_int_buf && __enext - _M_ext_buf >= _M_max_width))
      return _M_input_error();
    
    else if (__inext != _M_int_buf) {
      _M_ext_buf_converted = _M_ext_buf + (__enext - _M_ext_buf);
      this->setg(_M_int_buf, _M_int_buf, __inext);
      return traits_type::to_int_type(*_M_int_buf);
    }
    // We need to go around the loop again to get more external characters.
  } 
}

//----------------------------------------
// Helper functions for output

// This member function is called if there is an error during output.
// It puts the filebuf in error mode, clear the put area buffer, and
// returns eof.  Error mode is sticky; it is cleared only by close or
// seek.
template <class _CharT, class _Traits>
__BF_int_type__
basic_filebuf<_CharT, _Traits>::_M_output_error()
{
  _M_in_output_mode = false;
  _M_in_input_mode = false;
  _M_in_error_mode = true;
  this->setp(0, 0);
  return traits_type::eof();
}


// Write whatever sequence of characters is necessary to get back to
// the initial shift state.  This function overwrites the external
// buffer, changes the external file position, and changes the state.
// Precondition: the internal buffer is empty.
template <class _CharT, class _Traits>
bool basic_filebuf<_CharT, _Traits>::_M_unshift()
{
  if (_M_in_output_mode && !_M_constant_width) {
    typename _Codecvt::result __status;
    do {
      char* __enext = _M_ext_buf;
      __status = _M_codecvt->unshift(_M_state,
                                     _M_ext_buf, _M_ext_buf_EOS, __enext);
      if (__status == _Codecvt::noconv ||
          (__enext == _M_ext_buf && __status == _Codecvt::ok))
        return true;
      else if (__status == _Codecvt::error)
        return false;
      else if (!_M_write(_M_ext_buf, __enext - _M_ext_buf))
        return false;
    } while(__status == _Codecvt::partial);
  }

  return true;
}


//----------------------------------------
// Helper functions for buffer allocation and deallocation

// This member function is called when we're initializing a filebuf's
// internal and external buffers.  The argument is the size of the
// internal buffer; the external buffer is sized using the character
// width in the current encoding.  Preconditions: the buffers are currently
// null.  __n >= 1.  __buf is either a null pointer or a pointer to an 
// array show size is at least __n.

// We need __n >= 1 for two different reasons.  For input, the base
// class always needs a buffer because of the sementics of underflow().
// For output, we want to have an internal buffer that's larger by one
// element than the buffer that the base class knows about.  (See 
// basic_filebuf<>::overflow() for the reason.)
template <class _CharT, class _Traits>
bool 
basic_filebuf<_CharT, _Traits>::_M_allocate_buffers(_CharT* __buf, streamsize __n)
{

  if (__buf == 0) {
    _M_int_buf = __STATIC_CAST(_CharT*,malloc(__n * sizeof(_CharT)));
    if (! _M_int_buf)
      return false;
    _M_int_buf_dynamic = true;
  }
  else {
    _M_int_buf = __buf;
    _M_int_buf_dynamic = false;
  }
  
  size_t __ebufsiz = (max)(__n * (max)(_M_codecvt->encoding(), 1),
                      streamsize(_M_codecvt->max_length()));

  _M_ext_buf = __STATIC_CAST(char*,malloc(__ebufsiz));
  if (!_M_ext_buf) {
    _M_deallocate_buffers();
    return false;
  }

  _M_int_buf_EOS = _M_int_buf + __n;
  _M_ext_buf_EOS = _M_ext_buf + __ebufsiz;
  return true;
}

// Abbreviation for the most common case.
template <class _CharT, class _Traits>
bool basic_filebuf<_CharT, _Traits>::_M_allocate_buffers()
{
  // Choose a buffer that's at least 4096 characters long and that's a
  // multiple of the page size.
  streamsize __default_bufsiz =
    ((_M_base.__page_size() + 4095UL) / _M_base.__page_size()) * _M_base.__page_size();
  return _M_allocate_buffers(0, __default_bufsiz);
}

template <class _CharT, class _Traits>
void basic_filebuf<_CharT, _Traits>::_M_deallocate_buffers()
{
  if (_M_int_buf_dynamic)
    free(_M_int_buf);
  free(_M_ext_buf);
  _M_int_buf     = 0;
  _M_int_buf_EOS = 0;
  _M_ext_buf     = 0;
  _M_ext_buf_EOS = 0;
}


//----------------------------------------
// Helper functiosn for seek and imbue

template <class _CharT, class _Traits>
bool basic_filebuf<_CharT, _Traits>::_M_seek_init(bool __do_unshift) {
  // If we're in error mode, leave it.
   _M_in_error_mode = false;
   
  // Flush the output buffer if we're in output mode, and (conditionally)
  // emit an unshift sequence.
  if (_M_in_output_mode) {
    bool __ok = !traits_type::eq_int_type(this->overflow(traits_type::eof()),
                                          traits_type::eof());
    if (__do_unshift)
      __ok = __ok && this->_M_unshift();
    if (!__ok) {
      _M_in_output_mode = false;
      _M_in_error_mode = true;
      this->setp(0, 0);
      return false;
    }
  }

  // Discard putback characters, if any.
  if (_M_in_input_mode && _M_in_putback_mode)
    _M_exit_putback_mode();

  return true;
}


// Change the filebuf's locale.  This member function has no effect
// unless it is called before any I/O is performed on the stream.
template <class _CharT, class _Traits>
void basic_filebuf<_CharT, _Traits>::_M_setup_codecvt(const locale& __loc)
{
  _M_codecvt = &use_facet<_Codecvt>(__loc) ;
  int __encoding    = _M_codecvt->encoding();

  _M_width          = (max)(__encoding, 1);
  _M_max_width      = _M_codecvt->max_length();
  _M_constant_width = __encoding > 0;
  _M_always_noconv  = _M_codecvt->always_noconv();
}

_STLP_END_NAMESPACE

# undef __BF_int_type__
# undef __BF_pos_type__
# undef __BF_off_type__

# endif /* defined (_STLP_EXPOSE_STREAM_IMPLEMENTATION) */

#endif /* _STLP_FSTREAM_C */

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Chief Technology Officer Apriorit Inc.
United States United States
ApriorIT is a software research and development company specializing in cybersecurity and data management technology engineering. We work for a broad range of clients from Fortune 500 technology leaders to small innovative startups building unique solutions.

As Apriorit offers integrated research&development services for the software projects in such areas as endpoint security, network security, data security, embedded Systems, and virtualization, we have strong kernel and driver development skills, huge system programming expertise, and are reals fans of research projects.

Our specialty is reverse engineering, we apply it for security testing and security-related projects.

A separate department of Apriorit works on large-scale business SaaS solutions, handling tasks from business analysis, data architecture design, and web development to performance optimization and DevOps.

Official site: https://www.apriorit.com
Clutch profile: https://clutch.co/profile/apriorit
This is a Organisation

33 members

Written By
Software Developer Codedgers Inc
Ukraine Ukraine
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Written By
Software Developer (Junior) ApriorIT
Ukraine Ukraine
Sergey Popenko.
22 years old.
The Driver Team`s software developer.
Master of the Applied Math faculty, the Dnipropetrovsk National University, Ukraine.

Comments and Discussions