text:
// NtfsHandler.cpp

#include "StdAfx.h"

// #define SHOW_DEBUG_INFO
// #define SHOW_DEBUG_INFO2

#if defined(SHOW_DEBUG_INFO) || defined(SHOW_DEBUG_INFO2)
#include <stdio.h>
#endif

#include "../../../C/CpuArch.h"

#include "Common/Buffer.h"
#include "Common/ComTry.h"
#include "Common/IntToString.h"
#include "Common/MyCom.h"
#include "Common/StringConvert.h"

#include "Windows/PropVariant.h"
#include "Windows/Time.h"

#include "../Common/ProgressUtils.h"
#include "../Common/RegisterArc.h"
#include "../Common/StreamUtils.h"

#include "../Compress/CopyCoder.h"

#include "Common/DummyOutStream.h"

#ifdef SHOW_DEBUG_INFO
#define PRF(x) x
#else
#define PRF(x)
#endif

#ifdef SHOW_DEBUG_INFO2
#define PRF2(x) x
#else
#define PRF2(x)
#endif

#define Get16(p) GetUi16(p)
#define Get32(p) GetUi32(p)
#define Get64(p) GetUi64(p)

#define G16(p, dest) dest = Get16(p);
#define G32(p, dest) dest = Get32(p);
#define G64(p, dest) dest = Get64(p);

namespace NArchive {
namespace Ntfs {

static const UInt32 kNumSysRecs = 16;
static const UInt32 kRecIndex_Volume = 3;
static const UInt32 kRecIndex_BadClus = 8;

struct CHeader
{
  Byte SectorSizeLog;
  Byte ClusterSizeLog;
  // Byte MediaType;
  UInt32 NumHiddenSectors;
  UInt64 NumClusters;
  UInt64 MftCluster;
  UInt64 SerialNumber;
  UInt16 SectorsPerTrack;
  UInt16 NumHeads;

  UInt64 GetPhySize() const { return NumClusters << ClusterSizeLog; }
  UInt32 ClusterSize() const { return (UInt32)1 << ClusterSizeLog; }
  bool Parse(const Byte *p);
};

static int GetLog(UInt32 num)
{
  for (int i = 0; i < 31; i++)
    if (((UInt32)1 << i) == num)
      return i;
  return -1;
}

bool CHeader::Parse(const Byte *p)
{
  if (p[0x1FE] != 0x55 || p[0x1FF] != 0xAA)
    return false;

  int codeOffset = 0;
  switch (p[0])
  {
    case 0xE9: codeOffset = 3 + (Int16)Get16(p + 1); break;
    case 0xEB: if (p[2] != 0x90) return false; codeOffset = 2 + (signed char)p[1]; break;
    default: return false;
  }
  Byte sectorsPerClusterLog;

  if (memcmp(p + 3, "NTFS    ", 8) != 0)
    return false;
  {
    int s = GetLog(Get16(p + 11));
    if (s < 9 || s > 12)
      return false;
    SectorSizeLog = (Byte)s;
    s = GetLog(p[13]);
    if (s < 0)
      return false;
    sectorsPerClusterLog = (Byte)s;
    ClusterSizeLog = SectorSizeLog + sectorsPerClusterLog;
  }

  for (int i = 14; i < 21; i++)
    if (p[i] != 0)
      return false;

  // MediaType = p[21];
  if (Get16(p + 22) != 0) // NumFatSectors
    return false;
  G16(p + 24, SectorsPerTrack);
  G16(p + 26, NumHeads);
  G32(p + 28, NumHiddenSectors);
  if (Get32(p + 32) != 0) // NumSectors32
    return false;

  // DriveNumber = p[0x24];
  if (p[0x25] != 0) // CurrentHead
    return false;
  /*
  NTFS-HDD:   p[0x26] = 0x80
  NTFS-FLASH: p[0x26] = 0
  */
  if (p[0x26] != 0x80 && p[0x26] != 0) // ExtendedBootSig
    return false;
  if (p[0x27] != 0) // reserved
    return false;
  UInt64 numSectors = Get64(p + 0x28);
  NumClusters = numSectors >> sectorsPerClusterLog;

  G64(p + 0x30, MftCluster);
  // G64(p + 0x38, Mft2Cluster);
  G64(p + 0x48, SerialNumber);
  UInt32 numClustersInMftRec;
  UInt32 numClustersInIndexBlock;
  G32(p + 0x40, numClustersInMftRec);
  G32(p + 0x44, numClustersInIndexBlock);
  return (numClustersInMftRec < 256 && numClustersInIndexBlock < 256);
}

struct CMftRef
{
  UInt64 Val;
  UInt64 GetIndex() const { return Val & (((UInt64)1 << 48) - 1); }
  UInt16 GetNumber() const { return (UInt16)(Val >> 48); }
  bool IsBaseItself() const { return Val == 0; }
};

#define ATNAME(n) ATTR_TYPE_ ## n
#define DEF_ATTR_TYPE(v, n) ATNAME(n) = v

enum
{
  DEF_ATTR_TYPE(0x00, UNUSED),
  DEF_ATTR_TYPE(0x10, STANDARD_INFO),
  DEF_ATTR_TYPE(0x20, ATTRIBUTE_LIST),
  DEF_ATTR_TYPE(0x30, FILE_NAME),
  DEF_ATTR_TYPE(0x40, OBJECT_ID),
  DEF_ATTR_TYPE(0x50, SECURITY_DESCRIPTOR),
  DEF_ATTR_TYPE(0x60, VOLUME_NAME),
  DEF_ATTR_TYPE(0x70, VOLUME_INFO),
  DEF_ATTR_TYPE(0x80, DATA),
  DEF_ATTR_TYPE(0x90, INDEX_ROOT),
  DEF_ATTR_TYPE(0xA0, INDEX_ALLOCATION),
  DEF_ATTR_TYPE(0xB0, BITMAP),
  DEF_ATTR_TYPE(0xC0, REPARSE_POINT),
  DEF_ATTR_TYPE(0xD0, EA_INFO),
  DEF_ATTR_TYPE(0xE0, EA),
  DEF_ATTR_TYPE(0xF0, PROPERTY_SET),
  DEF_ATTR_TYPE(0x100, LOGGED_UTILITY_STREAM),
  DEF_ATTR_TYPE(0x1000, FIRST_USER_DEFINED_ATTRIBUTE)
};

static const Byte kFileNameType_Posix = 0;
static const Byte kFileNameType_Win32 = 1;
static const Byte kFileNameType_Dos = 2;
static const Byte kFileNameType_Win32Dos = 3;

struct CFileNameAttr
{
  CMftRef ParentDirRef;
  // UInt64 CTime;
  // UInt64 MTime;
  // UInt64 ThisRecMTime;
  // UInt64 ATime;
  // UInt64 AllocatedSize;
  // UInt64 DataSize;
  // UInt16 PackedEaSize;
  UString Name;
  UInt32 Attrib;
  Byte NameType;

  bool IsDos() const { return NameType == kFileNameType_Dos; }
  bool Parse(const Byte *p, unsigned size);
};

static void GetString(const Byte *p, unsigned length, UString &res)
{
  wchar_t *s = res.GetBuffer(length);
  for (unsigned i = 0; i < length; i++)
    s[i] = Get16(p + i * 2);
  s[length] = 0;
  res.ReleaseBuffer();
}

bool CFileNameAttr::Parse(const Byte *p, unsigned size)
{
  if (size < 0x42)
    return false;
  G64(p + 0x00, ParentDirRef.Val);
  // G64(p + 0x08, CTime);
  // G64(p + 0x10, MTime);
  // G64(p + 0x18, ThisRecMTime);
  // G64(p + 0x20, ATime);
  // G64(p + 0x28, AllocatedSize);
  // G64(p + 0x30, DataSize);
  G32(p + 0x38, Attrib);
  // G16(p + 0x3C, PackedEaSize);
  NameType = p[0x41];
  unsigned length = p[0x40];
  if (0x42 + length > size)
    return false;
  GetString(p + 0x42, length, Name);
  return true;
}

struct CSiAttr
{
  UInt64 CTime;
  UInt64 MTime;
  // UInt64 ThisRecMTime;
  UInt64 ATime;
  UInt32 Attrib;

  /*
  UInt32 MaxVersions;
  UInt32 Version;
  UInt32 ClassId;
  UInt32 OwnerId;
  UInt32 SecurityId;
  UInt64 QuotaCharged;
  */

  bool Parse(const Byte *p, unsigned size);
};

bool CSiAttr::Parse(const Byte *p, unsigned size)
{
  if (size < 0x24)
    return false;
  G64(p + 0x00, CTime);
  G64(p + 0x08, MTime);
  // G64(p + 0x10, ThisRecMTime);
  G64(p + 0x18, ATime);
  G32(p + 0x20, Attrib);
  return true;
}

static const UInt64 kEmptyExtent = (UInt64)(Int64)-1;

struct CExtent
{
  UInt64 Virt;
  UInt64 Phy;

  bool IsEmpty() const { return Phy == kEmptyExtent; }
};

struct CVolInfo
{
  Byte MajorVer;
  Byte MinorVer;
  // UInt16 Flags;

  bool Parse(const Byte *p, unsigned size);
};

bool CVolInfo::Parse(const Byte *p, unsigned size)
{
  if (size < 12)
    return false;
  MajorVer = p[8];
  MinorVer = p[9];
  // Flags = Get16(p + 10);
  return true;
}

struct CAttr
{
  UInt32 Type;
  // UInt32 Length;
  UString Name;
  // UInt16 Flags;
  // UInt16 Instance;
  CByteBuffer Data;
  Byte NonResident;

  // Non-Resident
  Byte CompressionUnit;
  UInt64 LowVcn;
  UInt64 HighVcn;
  UInt64 AllocatedSize;
  UInt64 Size;
  UInt64 PackSize;
  UInt64 InitializedSize;

  // Resident
  // UInt16 ResidentFlags;

  bool IsCompressionUnitSupported() const { return CompressionUnit == 0 || CompressionUnit == 4; }

  UInt32 Parse(const Byte *p, unsigned size);
  bool ParseFileName(CFileNameAttr &a) const { return a.Parse(Data, (unsigned)Data.GetCapacity()); }
  bool ParseSi(CSiAttr &a) const { return a.Parse(Data, (unsigned)Data.GetCapacity()); }
  bool ParseVolInfo(CVolInfo &a) const { return a.Parse(Data, (unsigned)Data.GetCapacity()); }
  bool ParseExtents(CRecordVector<CExtent> &extents, UInt64 numClustersMax, int compressionUnit) const;
  UInt64 GetSize() const { return NonResident ? Size : Data.GetCapacity(); }
  UInt64 GetPackSize() const
  {
    if (!NonResident)
      return Data.GetCapacity();
    if (CompressionUnit != 0)
      return PackSize;
    return AllocatedSize;
  }
};

#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; }

static int CompareAttr(void *const *elem1, void *const *elem2, void *)
{
  const CAttr &a1 = *(*((const CAttr **)elem1));
  const CAttr &a2 = *(*((const CAttr **)elem2));
  RINOZ(MyCompare(a1.Type, a2.Type));
  RINOZ(MyCompare(a1.Name, a2.Name));
  return MyCompare(a1.LowVcn, a2.LowVcn);
}

UInt32 CAttr::Parse(const Byte *p, unsigned size)
{
  if (size < 4)
    return 0;
  G32(p, Type);
  if (Type == 0xFFFFFFFF)
    return 4;
  if (size < 0x18)
    return 0;
  PRF(printf(" T=%2X", Type));

  UInt32 length = Get32(p + 0x04);
  PRF(printf(" L=%3d", length));
  if (length > size)
    return 0;
  NonResident = p[0x08];
  {
    int nameLength = p[9];
    UInt32 nameOffset = Get16(p + 0x0A);
    if (nameLength != 0)
    {
      if (nameOffset + nameLength * 2 > length)
        return 0;
      GetString(p + nameOffset, nameLength, Name);
      PRF(printf(" N=%S", Name));
    }
  }

  // G16(p + 0x0C, Flags);
  // G16(p + 0x0E, Instance);
  // PRF(printf(" F=%4X", Flags));
  // PRF(printf(" Inst=%d", Instance));

  UInt32 dataSize;
  UInt32 offs;
  if (NonResident)
  {
    if (length < 0x40)
      return 0;
    PRF(printf(" NR"));
    G64(p + 0x10, LowVcn);
    G64(p + 0x18, HighVcn);
    G64(p + 0x28, AllocatedSize);
    G64(p + 0x30, Size);
    G64(p + 0x38, InitializedSize);
    G16(p + 0x20, offs);
    CompressionUnit = p[0x22];

    PackSize = Size;
    if (CompressionUnit != 0)
    {
      if (length < 0x48)
        return 0;
      G64(p + 0x40, PackSize);
      PRF(printf(" PS=%I64x", PackSize));
    }

    // PRF(printf("\n"));
    PRF(printf(" ASize=%4I64d", AllocatedSize));
    PRF(printf(" Size=%I64d", Size));
    PRF(printf(" IS=%I64d", InitializedSize));
    PRF(printf(" Low=%I64d", LowVcn));
    PRF(printf(" High=%I64d", HighVcn));
    PRF(printf(" CU=%d", (int)CompressionUnit));
    dataSize = length - offs;
  }
  else
  {
    if (length < 0x18)
      return 0;
    PRF(printf(" RES"));
    dataSize = Get32(p + 0x10);
    PRF(printf(" dataSize=%3d", dataSize));
    offs = Get16(p + 0x14);
    // G16(p + 0x16, ResidentFlags);
    // PRF(printf(" ResFlags=%4X", ResidentFlags));
  }
  if (offs > length || dataSize > length || length - dataSize < offs)
    return 0;
  Data.SetCapacity(dataSize);
  memcpy(Data, p + offs, dataSize);
  #ifdef SHOW_DEBUG_INFO
  PRF(printf("  : "));
  for (unsigned i = 0; i < Data.GetCapacity(); i++)
  {
    PRF(printf(" %02X", (int)Data[i]));
  }
  #endif
  return length;
}

bool CAttr::ParseExtents(CRecordVector<CExtent> &extents, UInt64 numClustersMax, int compressionUnit) const
{
  const Byte *p = Data;
  unsigned size = (unsigned)Data.GetCapacity();
  UInt64 vcn = LowVcn;
  UInt64 lcn = 0;
  UInt64 highVcn1 = HighVcn + 1;
  if (LowVcn != extents.Back().Virt || highVcn1 > (UInt64)1 << 63)
    return false;

  extents.DeleteBack();

  PRF2(printf("\n# ParseExtents # LowVcn = %4I64X # HighVcn = %4I64X", LowVcn, HighVcn));

  while (size > 0)
  {
    Byte b = *p++;
    size--;
    if (b == 0)
      break;
    UInt32 num = b & 0xF;
    if (num == 0 || num > 8 || num > size)
      return false;

    int i;
    UInt64 vSize = p[num - 1];
    for (i = (int)num - 2; i >= 0; i--)
      vSize = (vSize << 8) | p[i];
    if (vSize == 0)
      return false;
    p += num;
    size -= num;
    if ((highVcn1 - vcn) < vSize)
      return false;

    num = (b >> 4) & 0xF;
    if (num > 8 || num > size)
      return false;
    CExtent e;
    e.Virt = vcn;
    if (num == 0)
    {
      if (compressionUnit == 0)
        return false;
      e.Phy = kEmptyExtent;
    }
    else
    {
      Int64 v = (signed char)p[num - 1];
      for (i = (int)num - 2; i >= 0; i--)
        v = (v << 8) | p[i];
      p += num;
      size -= num;
      lcn += v;
      if (lcn > numClustersMax)
        return false;
      e.Phy = lcn;
    }
    extents.Add(e);
    vcn += vSize;
  }
  CExtent e;
  e.Phy = kEmptyExtent;
  e.Virt = vcn;
  extents.Add(e);
  return (highVcn1 == vcn);
}

static const UInt64 kEmptyTag = (UInt64)(Int64)-1;

static const int kNumCacheChunksLog = 1;
static const UInt32 kNumCacheChunks = (1 << kNumCacheChunksLog);

class CInStream:
  public IInStream,
  public CMyUnknownImp
{
  UInt64 _virtPos;
  UInt64 _physPos;
  UInt64 _curRem;
  bool _sparseMode;
  size_t _compressedPos;

  UInt64 _tags[kNumCacheChunks];
  int _chunkSizeLog;
  CByteBuffer _inBuf;
  CByteBuffer _outBuf;
public:
  CMyComPtr<IInStream> Stream;
  UInt64 Size;
  UInt64 InitializedSize;
  int BlockSizeLog;
  int CompressionUnit;
  bool InUse;
  CRecordVector<CExtent> Extents;

  HRESULT SeekToPhys() { return Stream->Seek(_physPos, STREAM_SEEK_SET, NULL); }

  UInt32 GetCuSize() const { return (UInt32)1 << (BlockSizeLog + CompressionUnit); }
  HRESULT InitAndSeek(int compressionUnit)
  {
    CompressionUnit = compressionUnit;
    if (compressionUnit != 0)
    {
      UInt32 cuSize = GetCuSize();
      _inBuf.SetCapacity(cuSize);
      _chunkSizeLog = BlockSizeLog + CompressionUnit;
      _outBuf.SetCapacity(kNumCacheChunks << _chunkSizeLog);
    }
    for (int i = 0; i < kNumCacheChunks; i++)
      _tags[i] = kEmptyTag;

    _sparseMode = false;
    _curRem = 0;
    _virtPos = 0;
    _physPos = 0;
    const CExtent &e = Extents[0];
    if (!e.IsEmpty())
      _physPos = e.Phy << BlockSizeLog;
    return SeekToPhys();
  }

  MY_UNKNOWN_IMP1(IInStream)

  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
  STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
};

static size_t Lznt1Dec(Byte *dest, size_t outBufLim, size_t destLen, const Byte *src, size_t srcLen)
{
  size_t destSize = 0;
  while (destSize < destLen)
  {
    if (srcLen < 2 || (destSize & 0xFFF) != 0)
      break;
    UInt32 v = Get16(src);
    if (v == 0)
      break;
    src += 2;
    srcLen -= 2;
    UInt32 comprSize = (v & 0xFFF) + 1;
    if (comprSize > srcLen)
      break;
    srcLen -= comprSize;
    if ((v & 0x8000) == 0)
    {
      if (comprSize != (1 << 12))
        break;
      memcpy(dest + destSize, src, comprSize);
      src += comprSize;
      destSize += comprSize;
    }
    else
    {
      if (destSize + (1 << 12) > outBufLim || (src[0] & 1) != 0)
        return 0;
      int numDistBits = 4;
      UInt32 sbOffset = 0;
      UInt32 pos = 0;

      do
      {
        comprSize--;
        for (UInt32 mask = src[pos++] | 0x100; mask > 1 && comprSize > 0; mask >>= 1)
        {
          if ((mask & 1) == 0)
          {
            if (sbOffset >= (1 << 12))
              return 0;
            dest[destSize++] = src[pos++];
            sbOffset++;
            comprSize--;
          }
          else
          {
            if (comprSize < 2)
              return 0;
            UInt32 v = Get16(src + pos);
            pos += 2;
            comprSize -= 2;

            while (((sbOffset - 1) >> numDistBits) != 0)
              numDistBits++;

            UInt32 len = (v & (0xFFFF >> numDistBits)) + 3;
            if (sbOffset + len > (1 << 12))
              return 0;
            UInt32 dist = (v >> (16 - numDistBits));
            if (dist >= sbOffset)
              return 0;
            Int32 offs = -1 - dist;
            Byte *p = dest + destSize;
            for (UInt32 t = 0; t < len; t++)
              p[t] = p[t + offs];
            destSize += len;
            sbOffset += len;
          }
        }
      }
      while (comprSize > 0);
      src += pos;
    }
  }
  return destSize;
}

STDMETHODIMP CInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
{
  if (processedSize != NULL)
    *processedSize = 0;
  if (_virtPos >= Size)
    return (Size == _virtPos) ? S_OK: E_FAIL;
  if (size == 0)
    return S_OK;
  UInt64 rem = Size - _virtPos;
  if (size > rem)
    size = (UInt32)rem;
  if (_virtPos >= InitializedSize)
  {
    memset((Byte *)data, 0, size);
    _virtPos += size;
    *processedSize = size;
    return S_OK;
  }
  rem = InitializedSize - _virtPos;
  if (size > rem)
    size = (UInt32)rem;

  while (_curRem == 0)
  {
    UInt64 cacheTag = _virtPos >> _chunkSizeLog;
    UInt32 cacheIndex = (UInt32)cacheTag & (kNumCacheChunks - 1);
    if (_tags[cacheIndex] == cacheTag)
    {
      UInt32 chunkSize = (UInt32)1 << _chunkSizeLog;
      UInt32 offset = (UInt32)_virtPos & (chunkSize - 1);
      UInt32 cur = MyMin(chunkSize - offset, size);
      memcpy(data, _outBuf + (cacheIndex << _chunkSizeLog) + offset, cur);
      *processedSize = cur;
      _virtPos += cur;
      return S_OK;
    }

    PRF2(printf("\nVirtPos = %6d", _virtPos));

    UInt32 comprUnitSize = (UInt32)1 << CompressionUnit;
    UInt64 virtBlock = _virtPos >> BlockSizeLog;
    UInt64 virtBlock2 = virtBlock & ~((UInt64)comprUnitSize - 1);

    int left = 0, right = Extents.Size();
    for (;;)
    {
      int mid = (left + right) / 2;
      if (mid == left)
        break;
      if (virtBlock2 < Extents[mid].Virt)
        right = mid;
      else
        left = mid;
    }

    bool isCompressed = false;
    UInt64 virtBlock2End = virtBlock2 + comprUnitSize;
    if (CompressionUnit != 0)
      for (int i = left; i < Extents.Size(); i++)
      {
        const CExtent &e = Extents[i];
        if (e.Virt >= virtBlock2End)
          break;
        if (e.IsEmpty())
        {
          isCompressed = true;
          break;
        }
      }

    int i;
    for (i = left; Extents[i + 1].Virt <= virtBlock; i++);

    _sparseMode = false;
    if (!isCompressed)
    {
      const CExtent &e = Extents[i];
      UInt64 newPos = (e.Phy << BlockSizeLog) + _virtPos - (e.Virt << BlockSizeLog);
      if (newPos != _physPos)
      {
        _physPos = newPos;
        RINOK(SeekToPhys());
      }
      UInt64 next = Extents[i + 1].Virt;
      if (next > virtBlock2End)
        next &= ~((UInt64)comprUnitSize - 1);
      next <<= BlockSizeLog;
      if (next > Size)
        next = Size;
      _curRem = next - _virtPos;
      break;
    }
    bool thereArePhy = false;
    for (int i2 = left; i2 < Extents.Size(); i2++)
    {
      const CExtent &e = Extents[i2];
      if (e.Virt >= virtBlock2End)
        break;
      if (!e.IsEmpty())
      {
        thereArePhy = true;
        break;
      }
    }
    if (!thereArePhy)
    {
      _curRem = (Extents[i + 1].Virt << BlockSizeLog) - _virtPos;
      _sparseMode = true;
      break;
    }

    size_t offs = 0;
    UInt64 curVirt = virtBlock2;
    for (i = left; i < Extents.Size(); i++)
    {
      const CExtent &e = Extents[i];
      if (e.IsEmpty())
        break;
      if (e.Virt >= virtBlock2End)
        return S_FALSE;
      UInt64 newPos = (e.Phy + (curVirt - e.Virt)) << BlockSizeLog;
      if (newPos != _physPos)
      {
        _physPos = newPos;
        RINOK(SeekToPhys());
      }
      UInt64 numChunks = Extents[i + 1].Virt - curVirt;
      if (curVirt + numChunks > virtBlock2End)
        numChunks = virtBlock2End - curVirt;
      size_t compressed = (size_t)numChunks << BlockSizeLog;
      RINOK(ReadStream_FALSE(Stream, _inBuf + offs, compressed));
      curVirt += numChunks;
      _physPos += compressed;
      offs += compressed;
    }
    size_t destLenMax = GetCuSize();
    size_t destLen = destLenMax;
    UInt64 rem = Size - (virtBlock2 << BlockSizeLog);
    if (destLen > rem)
      destLen = (size_t)rem;

    Byte *dest = _outBuf + (cacheIndex << _chunkSizeLog);
    size_t destSizeRes = Lznt1Dec(dest, destLenMax, destLen, _inBuf, offs);
    _tags[cacheIndex] = cacheTag;

    // some files in Vista have destSize > destLen
    if (destSizeRes < destLen)
    {
      memset(dest, 0, destLenMax);
      if (InUse)
        return S_FALSE;
    }
  }
  if (size > _curRem)
    size = (UInt32)_curRem;
  HRESULT res = S_OK;
  if (_sparseMode)
    memset(data, 0, size);
  else
  {
    res = Stream->Read(data, size, &size);
    _physPos += size;
  }
  if (processedSize != NULL)
    *processedSize = size;
  _virtPos += size;
  _curRem -= size;
  return res;
}

STDMETHODIMP CInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
{
  UInt64 newVirtPos = offset;
  switch(seekOrigin)
  {
    case STREAM_SEEK_SET: break;
    case STREAM_SEEK_CUR: newVirtPos += _virtPos; break;
    case STREAM_SEEK_END: newVirtPos += Size; break;
    default: return STG_E_INVALIDFUNCTION;
  }
  if (_virtPos != newVirtPos)
    _curRem = 0;
  _virtPos = newVirtPos;
  if (newPosition)
    *newPosition = newVirtPos;
  return S_OK;
}

class CByteBufStream:
  public IInStream,
  public CMyUnknownImp
{
  UInt64 _virtPos;
public:
  CByteBuffer Buf;
  void Init() { _virtPos = 0; }

  MY_UNKNOWN_IMP1(IInStream)

  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
  STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
};

STDMETHODIMP CByteBufStream::Read(void *data, UInt32 size, UInt32 *processedSize)
{
  if (processedSize != NULL)
    *processedSize = 0;
  if (_virtPos >= Buf.GetCapacity())
    return (_virtPos == Buf.GetCapacity()) ? S_OK: E_FAIL;
  UInt64 rem = Buf.GetCapacity() - _virtPos;
  if (rem < size)
    size = (UInt32)rem;
  memcpy(data, Buf + (size_t)_virtPos, size);
  if (processedSize != NULL)
    *processedSize = size;
  _virtPos += size;
  return S_OK;
}

STDMETHODIMP CByteBufStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
{
  switch(seekOrigin)
  {
    case STREAM_SEEK_SET: _virtPos = offset; break;
    case STREAM_SEEK_CUR: _virtPos += offset; break;
    case STREAM_SEEK_END: _virtPos = Buf.GetCapacity() + offset; break;
    default: return STG_E_INVALIDFUNCTION;
  }
  if (newPosition)
    *newPosition = _virtPos;
  return S_OK;
}

static HRESULT DataParseExtents(int clusterSizeLog, const CObjectVector<CAttr> &attrs,
    int attrIndex, int attrIndexLim, UInt64 numPhysClusters, CRecordVector<CExtent> &Extents)
{
  CExtent e;
  e.Virt = 0;
  e.Phy = kEmptyExtent;
  Extents.Add(e);
  const CAttr &attr0 = attrs[attrIndex];

  if (attr0.AllocatedSize < attr0.Size ||
      (attrs[attrIndexLim - 1].HighVcn + 1) != (attr0.AllocatedSize >> clusterSizeLog) ||
      (attr0.AllocatedSize & ((1 << clusterSizeLog) - 1)) != 0)
    return S_FALSE;

  for (int i = attrIndex; i < attrIndexLim; i++)
    if (!attrs[i].ParseExtents(Extents, numPhysClusters, attr0.CompressionUnit))
      return S_FALSE;

  UInt64 packSizeCalc = 0;
  for (int k = 0; k < Extents.Size(); k++)
  {
    CExtent &e = Extents[k];
    if (!e.IsEmpty())
      packSizeCalc += (Extents[k + 1].Virt - e.Virt) << clusterSizeLog;
    PRF2(printf("\nSize = %4I64X", Extents[k + 1].Virt - e.Virt));
    PRF2(printf("  Pos = %4I64X", e.Phy));
  }

  if (attr0.CompressionUnit != 0)
  {
    if (packSizeCalc != attr0.PackSize)
      return S_FALSE;
  }
  else
  {
    if (packSizeCalc != attr0.AllocatedSize)
      return S_FALSE;
  }
  return S_OK;
}

struct CDataRef
{
  int Start;
  int Num;
};

static const UInt32 kMagic_FILE = 0x454c4946;
static const UInt32 kMagic_BAAD = 0x44414142;

struct CMftRec
{
  UInt32 Magic;
  // UInt64 Lsn;
  UInt16 SeqNumber;
  UInt16 Flags;
  // UInt16 LinkCount;
  // UInt16 NextAttrInstance;
  CMftRef BaseMftRef;
  // UInt32 ThisRecNumber;
  UInt32 MyNumNameLinks;

  CObjectVector<CAttr> DataAttrs;
  CObjectVector<CFileNameAttr> FileNames;
  CRecordVector<CDataRef> DataRefs;

  CSiAttr SiAttr;

  void MoveAttrsFrom(CMftRec &src)
  {
    DataAttrs += src.DataAttrs;
    FileNames += src.FileNames;
    src.DataAttrs.ClearAndFree();
    src.FileNames.ClearAndFree();
  }

  UInt64 GetPackSize() const
  {
    UInt64 res = 0;
    for (int i = 0; i < DataRefs.Size(); i++)
      res += DataAttrs[DataRefs[i].Start].GetPackSize();
    return res;
  }

  bool Parse(Byte *p, int sectorSizeLog, UInt32 numSectors, UInt32 recNumber, CObjectVector<CAttr> *attrs);

  bool IsEmpty() const { return (Magic <= 2); }
  bool IsFILE() const { return (Magic == kMagic_FILE); }
  bool IsBAAD() const { return (Magic == kMagic_BAAD); }

  bool InUse() const { return (Flags & 1) != 0; }
  bool IsDir() const { return (Flags & 2) != 0; }

  void ParseDataNames();
  HRESULT GetStream(IInStream *mainStream, int dataIndex,
      int clusterSizeLog, UInt64 numPhysClusters, IInStream **stream) const;
  int GetNumExtents(int dataIndex, int clusterSizeLog, UInt64 numPhysClusters) const;

  UInt64 GetSize(int dataIndex) const { return DataAttrs[DataRefs[dataIndex].Start].GetSize(); }

  CMftRec(): MyNumNameLinks(0) {}
};

void CMftRec::ParseDataNames()
{
  DataRefs.Clear();
  DataAttrs.Sort(CompareAttr, 0);

  for (int i = 0; i < DataAttrs.Size();)
  {
    CDataRef ref;
    ref.Start = i;
    for (i++; i < DataAttrs.Size(); i++)
      if (DataAttrs[ref.Start].Name != DataAttrs[i].Name)
        break;
    ref.Num = i - ref.Start;
    DataRefs.Add(ref);
  }
}

HRESULT CMftRec::GetStream(IInStream *mainStream, int dataIndex,
    int clusterSizeLog, UInt64 numPhysClusters, IInStream **destStream) const
{
  *destStream = 0;
  CByteBufStream *streamSpec = new CByteBufStream;
  CMyComPtr<IInStream> streamTemp = streamSpec;

  if (dataIndex < 0)
    return E_FAIL;

  if (dataIndex < DataRefs.Size())
  {
    const CDataRef &ref = DataRefs[dataIndex];
    int numNonResident = 0;
    int i;
    for (i = ref.Start; i < ref.Start + ref.Num; i++)
      if (DataAttrs[i].NonResident)
        numNonResident++;

    const CAttr &attr0 = DataAttrs[ref.Start];

    if (numNonResident != 0 || ref.Num != 1)
    {
      if (numNonResident != ref.Num || !attr0.IsCompressionUnitSupported())
        return S_FALSE;
      CInStream *streamSpec = new CInStream;
      CMyComPtr<IInStream> streamTemp = streamSpec;
      RINOK(DataParseExtents(clusterSizeLog, DataAttrs, ref.Start, ref.Start + ref.Num, numPhysClusters, streamSpec->Extents));
      streamSpec->Size = attr0.Size;
      streamSpec->InitializedSize = attr0.InitializedSize;
      streamSpec->Stream = mainStream;
      streamSpec->BlockSizeLog = clusterSizeLog;
      streamSpec->InUse = InUse();
      RINOK(streamSpec->InitAndSeek(attr0.CompressionUnit));
      *destStream = streamTemp.Detach();
      return S_OK;
    }
    streamSpec->Buf = attr0.Data;
  }
  streamSpec->Init();
  *destStream = streamTemp.Detach();
  return S_OK;
}

int CMftRec::GetNumExtents(int dataIndex, int clusterSizeLog, UInt64 numPhysClusters) const
{
  if (dataIndex < 0)
    return 0;
  {
    const CDataRef &ref = DataRefs[dataIndex];
    int numNonResident = 0;
    int i;
    for (i = ref.Start; i < ref.Start + ref.Num; i++)
      if (DataAttrs[i].NonResident)
        numNonResident++;

    const CAttr &attr0 = DataAttrs[ref.Start];

    if (numNonResident != 0 || ref.Num != 1)
    {
      if (numNonResident != ref.Num || !attr0.IsCompressionUnitSupported())
        return 0; // error;
      CRecordVector<CExtent> extents;
      if (DataParseExtents(clusterSizeLog, DataAttrs, ref.Start, ref.Start + ref.Num, numPhysClusters, extents) != S_OK)
        return 0; // error;
      return extents.Size() - 1;
    }
    // if (attr0.Data.GetCapacity() != 0)
    //   return 1;
    return 0;
  }
}

bool CMftRec::Parse(Byte *p, int sectorSizeLog, UInt32 numSectors, UInt32 recNumber,
    CObjectVector<CAttr> *attrs)
{
  G32(p, Magic);
  if (!IsFILE())
    return IsEmpty() || IsBAAD();

  UInt32 usaOffset;
  UInt32 numUsaItems;
  G16(p + 0x04, usaOffset);
  G16(p + 0x06, numUsaItems);

  if ((usaOffset & 1) != 0 || usaOffset + numUsaItems * 2 > ((UInt32)1 << sectorSizeLog) - 2 ||
      numUsaItems == 0 || numUsaItems - 1 != numSectors)
    return false;

  UInt16 usn = Get16(p + usaOffset);
  // PRF(printf("\nusn = %d", usn));
  for (UInt32 i = 1; i < numUsaItems; i++)
  {
    void *pp = p + (i << sectorSizeLog)  - 2;
    if (Get16(pp) != usn)
      return false;
    SetUi16(pp, Get16(p + usaOffset + i * 2));
  }

  // G64(p + 0x08, Lsn);
  G16(p + 0x10, SeqNumber);
  // G16(p + 0x12, LinkCount);
  // PRF(printf(" L=%d", LinkCount));
  UInt32 attrOffs = Get16(p + 0x14);
  G16(p + 0x16, Flags);
  PRF(printf(" F=%4X", Flags));

  UInt32 bytesInUse = Get32(p + 0x18);
  UInt32 bytesAlloc = Get32(p + 0x1C);
  G64(p + 0x20, BaseMftRef.Val);
  if (BaseMftRef.Val != 0)
  {
    PRF(printf("  BaseRef=%d", (int)BaseMftRef.Val));
    // return false; // Check it;
  }
  // G16(p + 0x28, NextAttrInstance);
  if (usaOffset >= 0x30)
    if (Get32(p + 0x2C) != recNumber) // NTFS 3.1+
      return false;

  UInt32 limit = numSectors << sectorSizeLog;
  if (attrOffs >= limit || (attrOffs & 7) != 0 || bytesInUse > limit
      || bytesAlloc != limit)
    return false;

  for (UInt32 t = attrOffs; t < limit;)
  {
    CAttr attr;
    // PRF(printf("\n  %2d:", Attrs.Size()));
    PRF(printf("\n"));
    UInt32 length = attr.Parse(p + t, limit - t);
    if (length == 0 || limit - t < length)
      return false;
    t += length;
    if (attr.Type == 0xFFFFFFFF)
      break;
    switch(attr.Type)
    {
      case ATTR_TYPE_FILE_NAME:
      {
        CFileNameAttr fna;
        if (!attr.ParseFileName(fna))
          return false;
        FileNames.Add(fna);
        PRF(printf("  flags = %4x", (int)fna.NameType));
        PRF(printf("\n  %S", fna.Name));
        break;
      }
      case ATTR_TYPE_STANDARD_INFO:
        if (!attr.ParseSi(SiAttr))
          return false;
        break;
      case ATTR_TYPE_DATA:
        DataAttrs.Add(attr);
        break;
      default:
        if (attrs)
          attrs->Add(attr);
        break;
    }
  }

  return true;
}

struct CItem
{
  int RecIndex;
  int DataIndex;
  CMftRef ParentRef;
  UString Name;
  UInt32 Attrib;

  bool IsDir() const { return (DataIndex < 0); }
};

struct CDatabase
{
  CHeader Header;
  CObjectVector<CItem> Items;
  CObjectVector<CMftRec> Recs;
  CMyComPtr<IInStream> InStream;
  IArchiveOpenCallback *OpenCallback;

  CByteBuffer ByteBuf;

  CObjectVector<CAttr> VolAttrs;

  ~CDatabase() { ClearAndClose(); }

  void Clear();
  void ClearAndClose();

  UString GetItemPath(Int32 index) const;
  HRESULT Open();
  HRESULT ReadDir(Int32 parent, UInt32 cluster, int level);

  HRESULT SeekToCluster(UInt64 cluster);

  int FindMtfRec(const CMftRef &ref) const
  {
    UInt64 val = ref.GetIndex();
    int left = 0, right = Items.Size();
    while (left != right)
    {
      int mid = (left + right) / 2;
      UInt64 midValue = Items[mid].RecIndex;
      if (val == midValue)
        return mid;
      if (val < midValue)
        right = mid;
      else
        left = mid + 1;
    }
    return -1;
  }

};

HRESULT CDatabase::SeekToCluster(UInt64 cluster)
{
  return InStream->Seek(cluster << Header.ClusterSizeLog, STREAM_SEEK_SET, NULL);
}

void CDatabase::Clear()
{
  Items.Clear();
  Recs.Clear();
}

void CDatabase::ClearAndClose()
{
  Clear();
  InStream.Release();
}

#define MY_DIR_PREFIX(x) L"[" x L"]" WSTRING_PATH_SEPARATOR

UString CDatabase::GetItemPath(Int32 index) const
{
  const CItem *item = &Items[index];
  UString name = item->Name;
  for (int j = 0; j < 256; j++)
  {
    CMftRef ref = item->ParentRef;
    index = FindMtfRec(ref);
    if (ref.GetIndex() == 5)
      return name;
    if (index < 0 || Recs[Items[index].RecIndex].SeqNumber != ref.GetNumber())
      return MY_DIR_PREFIX(L"UNKNOWN") + name;
    item = &Items[index];
    name = item->Name + WCHAR_PATH_SEPARATOR + name;
  }
  return MY_DIR_PREFIX(L"BAD") + name;
}

HRESULT CDatabase::Open()
{
  Clear();

  static const UInt32 kHeaderSize = 512;
  Byte buf[kHeaderSize];
  RINOK(ReadStream_FALSE(InStream, buf, kHeaderSize));
  if (!Header.Parse(buf))
    return S_FALSE;
  UInt64 fileSize;
  RINOK(InStream->Seek(0, STREAM_SEEK_END, &fileSize));
  if (fileSize < Header.GetPhySize())
    return S_FALSE;

  SeekToCluster(Header.MftCluster);

  CMftRec mftRec;
  UInt32 numSectorsInRec;
  int recSizeLog;
  CMyComPtr<IInStream> mftStream;
  {
    UInt32 blockSize = 1 << 12;
    ByteBuf.SetCapacity(blockSize);
    RINOK(ReadStream_FALSE(InStream, ByteBuf, blockSize));

    UInt32 allocSize = Get32(ByteBuf + 0x1C);
    recSizeLog = GetLog(allocSize);
    if (recSizeLog < Header.SectorSizeLog)
      return false;
    numSectorsInRec = 1 << (recSizeLog - Header.SectorSizeLog);
    if (!mftRec.Parse(ByteBuf, Header.SectorSizeLog, numSectorsInRec, NULL, 0))
      return S_FALSE;
    if (!mftRec.IsFILE())
      return S_FALSE;
    mftRec.ParseDataNames();
    if (mftRec.DataRefs.IsEmpty())
      return S_FALSE;
    RINOK(mftRec.GetStream(InStream, 0, Header.ClusterSizeLog, Header.NumClusters, &mftStream));
    if (!mftStream)
      return S_FALSE;
  }

  UInt64 mftSize = mftRec.DataAttrs[0].Size;
  if ((mftSize >> 4) > Header.GetPhySize())
    return S_FALSE;

  UInt64 numFiles = mftSize >> recSizeLog;
  if (numFiles > (1 << 30))
    return S_FALSE;
  if (OpenCallback)
  {
    RINOK(OpenCallback->SetTotal(&numFiles, &mftSize));
  }
  const UInt32 kBufSize = (1 << 15);
  if (kBufSize < (1 << recSizeLog))
    return S_FALSE;

  ByteBuf.SetCapacity((size_t)kBufSize);
  Recs.Reserve((int)numFiles);
  for (UInt64 pos64 = 0;;)
  {
    if (OpenCallback)
    {
      UInt64 numFiles = Recs.Size();
      if ((numFiles & 0x3FF) == 0)
      {
        RINOK(OpenCallback->SetCompleted(&numFiles, &pos64));
      }
    }
    UInt32 readSize = kBufSize;
    UInt64 rem = mftSize - pos64;
    if (readSize > rem)
      readSize = (UInt32)rem;
    if (readSize < ((UInt32)1 << recSizeLog))
      break;
    RINOK(ReadStream_FALSE(mftStream, ByteBuf, (size_t)readSize));
    pos64 += readSize;
    for (int i = 0; ((UInt32)(i + 1) << recSizeLog) <= readSize; i++)
    {
      PRF(printf("\n---------------------"));
      PRF(printf("\n%5d:", Recs.Size()));
      Byte *p = ByteBuf + ((UInt32)i << recSizeLog);
      CMftRec rec;
      if (!rec.Parse(p, Header.SectorSizeLog, numSectorsInRec, (UInt32)Recs.Size(),
          (Recs.Size() == kRecIndex_Volume) ? &VolAttrs: NULL))
        return S_FALSE;
      Recs.Add(rec);
    }
  }

  int i;
  for (i = 0; i < Recs.Size(); i++)
  {
    CMftRec &rec = Recs[i];
    if (!rec.BaseMftRef.IsBaseItself())
    {
      UInt64 refIndex = rec.BaseMftRef.GetIndex();
      if (refIndex > (UInt32)Recs.Size())
        return S_FALSE;
      CMftRec &refRec = Recs[(int)refIndex];
      bool moveAttrs = (refRec.SeqNumber == rec.BaseMftRef.GetNumber() && refRec.BaseMftRef.IsBaseItself());
      if (rec.InUse() && refRec.InUse())
      {
        if (!moveAttrs)
          return S_FALSE;
      }
      else if (rec.InUse() || refRec.InUse())
        moveAttrs = false;
      if (moveAttrs)
        refRec.MoveAttrsFrom(rec);
    }
  }

  for (i = 0; i < Recs.Size(); i++)
    Recs[i].ParseDataNames();

  for (i = 0; i < Recs.Size(); i++)
  {
    CMftRec &rec = Recs[i];
    if (!rec.IsFILE() || !rec.BaseMftRef.IsBaseItself())
      continue;
    int numNames = 0;
    // printf("\n%4d: ", i);
    for (int t = 0; t < rec.FileNames.Size(); t++)
    {
      const CFileNameAttr &fna = rec.FileNames[t];
      // printf("%4d %S  | ", (int)fna.NameType, fna.Name);
      if (fna.IsDos())
        continue;
      int numDatas = rec.DataRefs.Size();

      // For hard linked files we show substreams only for first Name.
      if (numDatas > 1 && numNames > 0)
        numDatas = 1;
      numNames++;

      if (rec.IsDir())
      {
        CItem item;
        item.Name = fna.Name;
        item.RecIndex = i;
        item.DataIndex = -1;
        item.ParentRef = fna.ParentDirRef;
        item.Attrib = rec.SiAttr.Attrib | 0x10;
        // item.Attrib = fna.Attrib;
        Items.Add(item);
      }
      for (int di = 0; di < numDatas; di++)
      {
        CItem item;
        item.Name = fna.Name;
        item.Attrib = rec.SiAttr.Attrib;
        const UString &subName = rec.DataAttrs[rec.DataRefs[di].Start].Name;
        if (!subName.IsEmpty())
        {
          // $BadClus:$Bad is sparse file for all clusters. So we skip it.
          if (i == kRecIndex_BadClus && subName == L"$Bad")
            continue;
          item.Name += L":";
          item.Name += subName;
          item.Attrib = fna.Attrib;
        }

        PRF(printf("\n%3d", i));
        PRF(printf("  attrib=%2x", rec.SiAttr.Attrib));
        PRF(printf(" %S", item.Name));

        item.RecIndex = i;
        item.DataIndex = di;
        item.ParentRef = fna.ParentDirRef;

        Items.Add(item);
        rec.MyNumNameLinks++;
      }
    }
    rec.FileNames.ClearAndFree();
  }

  return S_OK;
}

class CHandler:
  public IInArchive,
  public IInArchiveGetStream,
  public CMyUnknownImp,
  CDatabase
{
public:
  MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream)
  INTERFACE_IInArchive(;)
  STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);
};

STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
{
  COM_TRY_BEGIN
  IInStream *stream2;
  const CItem &item = Items[index];
  const CMftRec &rec = Recs[item.RecIndex];
  HRESULT res = rec.GetStream(InStream, item.DataIndex, Header.ClusterSizeLog, Header.NumClusters, &stream2);
  *stream = (ISequentialInStream *)stream2;
  return res;
  COM_TRY_END
}

static const STATPROPSTG kProps[] =
{
  { NULL, kpidPath, VT_BSTR},
  { NULL, kpidIsDir, VT_BOOL},
  { NULL, kpidSize, VT_UI8},
  { NULL, kpidPackSize, VT_UI8},
  { NULL, kpidMTime, VT_FILETIME},
  { NULL, kpidCTime, VT_FILETIME},
  { NULL, kpidATime, VT_FILETIME},
  { NULL, kpidAttrib, VT_UI4},
  { NULL, kpidLinks, VT_UI4},
  { NULL, kpidNumBlocks, VT_UI4}
};

static const STATPROPSTG kArcProps[] =
{
  { NULL, kpidVolumeName, VT_BSTR},
  { NULL, kpidFileSystem, VT_BSTR},
  { NULL, kpidClusterSize, VT_UI4},
  { NULL, kpidPhySize, VT_UI8},
  { NULL, kpidHeadersSize, VT_UI8},
  { NULL, kpidCTime, VT_FILETIME},

  { NULL, kpidSectorSize, VT_UI4},
  { NULL, kpidId, VT_UI8}
  // { NULL, kpidSectorsPerTrack, VT_UI4},
  // { NULL, kpidNumHeads, VT_UI4},
  // { NULL, kpidHiddenSectors, VT_UI4}
};

IMP_IInArchive_Props
IMP_IInArchive_ArcProps

static void NtfsTimeToProp(UInt64 t, NWindows::NCOM::CPropVariant &prop)
{
  FILETIME ft;
  ft.dwLowDateTime = (DWORD)t;
  ft.dwHighDateTime = (DWORD)(t >> 32);
  prop = ft;
}

STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
{
  COM_TRY_BEGIN
  NWindows::NCOM::CPropVariant prop;

  const CMftRec *volRec = (Recs.Size() > kRecIndex_Volume ? &Recs[kRecIndex_Volume] : NULL);

  switch(propID)
  {
    case kpidClusterSize: prop = Header.ClusterSize(); break;
    case kpidPhySize: prop = Header.GetPhySize(); break;
    /*
    case kpidHeadersSize:
    {
      UInt64 val = 0;
      for (int i = 0; i < kNumSysRecs; i++)
      {
        printf("\n%2d: %8I64d ", i, Recs[i].GetPackSize());
        if (i == 8)
          i = i
        val += Recs[i].GetPackSize();
      }
      prop = val;
      break;
    }
    */
    case kpidCTime: if (volRec) NtfsTimeToProp(volRec->SiAttr.CTime, prop); break;break;
    case kpidVolumeName:
    {
      for (int i = 0; i < VolAttrs.Size(); i++)
      {
        const CAttr &attr = VolAttrs[i];
        if (attr.Type == ATTR_TYPE_VOLUME_NAME)
        {
          UString name;
          GetString(attr.Data, (int)attr.Data.GetCapacity() / 2, name);
          prop = name;
          break;
        }
      }
      break;
    }
    case kpidFileSystem:
    {
      AString s = "NTFS";
      for (int i = 0; i < VolAttrs.Size(); i++)
      {
        const CAttr &attr = VolAttrs[i];
        if (attr.Type == ATTR_TYPE_VOLUME_INFO)
        {
          CVolInfo vi;
          if (attr.ParseVolInfo(vi))
          {
            s += ' ';
            char temp[16];
            ConvertUInt32ToString(vi.MajorVer, temp);
            s += temp;
            s += '.';
            ConvertUInt32ToString(vi.MinorVer, temp);
            s += temp;
          }
          break;
        }
      }
      prop = s;
      break;
    }
    case kpidSectorSize: prop = (UInt32)1 << Header.SectorSizeLog; break;
    case kpidId: prop = Header.SerialNumber; break;
    // case kpidMediaType: prop = Header.MediaType; break;
    // case kpidSectorsPerTrack: prop = Header.SectorsPerTrack; break;
    // case kpidNumHeads: prop = Header.NumHeads; break;
    // case kpidHiddenSectors: prop = Header.NumHiddenSectors; break;
  }
  prop.Detach(value);
  return S_OK;
  COM_TRY_END
}

STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
{
  COM_TRY_BEGIN
  NWindows::NCOM::CPropVariant prop;
  const CItem &item = Items[index];
  const CMftRec &rec = Recs[item.RecIndex];

  const CAttr *data= NULL;
  if (item.DataIndex >= 0)
    data = &rec.DataAttrs[rec.DataRefs[item.DataIndex].Start];

  switch(propID)
  {
    case kpidPath:
    {
      UString name = GetItemPath(index);
      const wchar_t *prefix = NULL;
      if (!rec.InUse())
        prefix = MY_DIR_PREFIX(L"DELETED");
      else if (item.RecIndex < kNumSysRecs)
        prefix = MY_DIR_PREFIX(L"SYSTEM");
      if (prefix)
        name = prefix + name;
      prop = name;
      break;
    }

    case kpidIsDir: prop = item.IsDir(); break;
    case kpidMTime: NtfsTimeToProp(rec.SiAttr.MTime, prop); break;

    case kpidCTime: NtfsTimeToProp(rec.SiAttr.CTime, prop); break;
    case kpidATime: NtfsTimeToProp(rec.SiAttr.ATime, prop); break;
    case kpidAttrib:
      prop = item.Attrib;
      break;
    case kpidLinks: prop = rec.MyNumNameLinks; break;
    case kpidSize: if (data) prop = data->GetSize(); break;
    case kpidPackSize: if (data) prop = data->GetPackSize(); break;
    case kpidNumBlocks: if (data) prop = (UInt32)rec.GetNumExtents(item.DataIndex, Header.ClusterSizeLog, Header.NumClusters); break;
  }
  prop.Detach(value);
  return S_OK;
  COM_TRY_END
}

STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *callback)
{
  COM_TRY_BEGIN
  {
    OpenCallback = callback;
    InStream = stream;
    HRESULT res;
    try
    {
      res = CDatabase::Open();
      if (res == S_OK)
        return S_OK;
    }
    catch(...)
    {
      Close();
      throw;
    }
    Close();
    return res;
  }
  COM_TRY_END
}

STDMETHODIMP CHandler::Close()
{
  ClearAndClose();
  return S_OK;
}

STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
    Int32 testMode, IArchiveExtractCallback *extractCallback)
{
  COM_TRY_BEGIN
  bool allFilesMode = (numItems == (UInt32)-1);
  if (allFilesMode)
    numItems = Items.Size();
  if (numItems == 0)
    return S_OK;
  UInt32 i;
  UInt64 totalSize = 0;
  for (i = 0; i < numItems; i++)
  {
    const CItem &item = Items[allFilesMode ? i : indices[i]];
    const CMftRec &rec = Recs[item.RecIndex];
    if (!rec.IsDir())
      totalSize += rec.GetSize(item.DataIndex);
  }
  RINOK(extractCallback->SetTotal(totalSize));

  UInt64 totalPackSize;
  totalSize = totalPackSize = 0;

  CByteBuffer buf;
  UInt32 clusterSize = Header.ClusterSize();
  buf.SetCapacity(clusterSize);

  NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();
  CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;

  CLocalProgress *lps = new CLocalProgress;
  CMyComPtr<ICompressProgressInfo> progress = lps;
  lps->Init(extractCallback, false);

  CDummyOutStream *outStreamSpec = new CDummyOutStream;
  CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);

  for (i = 0; i < numItems; i++)
  {
    lps->InSize = totalPackSize;
    lps->OutSize = totalSize;
    RINOK(lps->SetCur());
    CMyComPtr<ISequentialOutStream> realOutStream;
    Int32 askMode = testMode ?
        NExtract::NAskMode::kTest :
        NExtract::NAskMode::kExtract;
    Int32 index = allFilesMode ? i : indices[i];
    RINOK(extractCallback->GetStream(index, &realOutStream, askMode));

    const CItem &item = Items[index];
    if (item.IsDir())
    {
      RINOK(extractCallback->PrepareOperation(askMode));
      RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK));
      continue;
    }

    if (!testMode && !realOutStream)
      continue;
    RINOK(extractCallback->PrepareOperation(askMode));

    outStreamSpec->SetStream(realOutStream);
    realOutStream.Release();
    outStreamSpec->Init();

    const CMftRec &rec = Recs[item.RecIndex];
    const CAttr &data = rec.DataAttrs[rec.DataRefs[item.DataIndex].Start];

    int res = NExtract::NOperationResult::kDataError;
    {
      CMyComPtr<IInStream> inStream;
      HRESULT hres = rec.GetStream(InStream, item.DataIndex, Header.ClusterSizeLog, Header.NumClusters, &inStream);
      if (hres == S_FALSE)
        res = NExtract::NOperationResult::kUnSupportedMethod;
      else
      {
        RINOK(hres);
        if (inStream)
        {
          HRESULT hres = copyCoder->Code(inStream, outStream, NULL, NULL, progress);
          if (hres != S_OK &&  hres != S_FALSE)
          {
            RINOK(hres);
          }
          if (/* copyCoderSpec->TotalSize == item.GetSize() && */ hres == S_OK)
            res = NExtract::NOperationResult::kOK;
        }
      }
    }
    totalPackSize += data.GetPackSize();
    totalSize += data.GetSize();
    outStreamSpec->ReleaseStream();
    RINOK(extractCallback->SetOperationResult(res));
  }
  return S_OK;
  COM_TRY_END
}

STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
{
  *numItems = Items.Size();
  return S_OK;
}

static IInArchive *CreateArc() { return new CHandler; }

static CArcInfo g_ArcInfo =
  { L"NTFS", L"ntfs img", 0, 0xD9, { 'N', 'T', 'F', 'S', ' ', ' ', ' ', ' ', 0 }, 9, false, CreateArc, 0 };

REGISTER_ARC(Fat)

}}

redpajama_set_name: RedPajamaGithub


This is another invaluable aid that makes it easy to provide the patients with daily hygiene procedures. CSO shower bed has an electric control, adjustable height and it is mobile. The bottom area is adjustable. The whole bed can be adjusted to the patient´s bed height (from a low divan bed to a typical high beds in hospitals). We move the patient to the this mobile bed and take him into the bathroom. There by pushing the control button the mobile bed will get changed into a "tub" with safe edges. This can be well applied to the patients being treated after operations at the intensive care units, anesthetic-resuscitation units and in all institutions where the patients must be lying.


If you've reached this page, please click below to view our current portfolio. We've been serving Florida clients since 2001! Providing you with updated information and staying current is our goal.
Web Design With Much More Marketing "Built In."
Every website owner should anticipate having to perform search engine optimization tasks once their site is launched. Our website design services offer more optimization during the initial development phase. This ensures that your small businesses will be ready to reach a higher organic ranking.
Affordable Web Design - Custom Web Design, Web Updates, Shopping carts or e-commerce website design, PCI compliant shopping cart solutions and hosting as well as website re-designs and updates are all available at an affordable price. Click here to inquire or call (813) 778-9548 for information.
(Search Engine Optimization Florida) - No Outsourcing. Affordable SEO services for your Florida business. Get long term organic ranking results from our search engine optimization services.
Location - Is your business located in Florida? We serve small businesses throughout Florida, but we live and work here in Tampa Bay! If you prefer a local Florida based website developer and search engine optimization company, you aren't alone. Consumers have realized that although outsourcing may save some money, it isn't worth the aggravation. Additionally, you'll be surprised by our website design and marketing pricing which is affordable for small business.


We again didn't spend as much time in our school room this week, but we still did a fair amount. Mostly shelf work, though. We didn't do very much from our workboxes. That's okay, though! I never require her to do anything in particular.
it this week. This was a new sheet she hadn't tried, yet.
I may put it back out next week.
the "snowflakes" on the page and shook it around.
to work on the concept.
and squeezed all the water out into the bowl.
made random lines and hand prints.
with the glitter glue being used on construction paper.
pages from the watercolor book. It turned out cute!
the paper towel strip after a couple minutes.
together before laying the paper towel over the top.
and some of them were done first on card stock.
Some just for fun pictures!
On our way to the park on a beautiful day!
one out on the 17th!
How fine of you!!!! Really awesome efforts you have shown.
Hi, welcome to Seeking Squirrels! My name is Anne and I'm a homeschooling mom to two.
Please do not use the content or pictures on this blog without permission. You may link to the site if you would like to share. Thank you!


It is true, no two learners are alike. Some learn better through reading; others through listening or doing. For students with developmental disabilities, who have difficulty communicating with others and especially difficulty understanding what people in their environment are communicating to them, it is important to present information in ways that matches the student's learning style and optimize their ability to learn.
Visual supports—concrete representations of information that is absorbed visually—are one way that educators can help students understand what is being communicated to them. Through visual supports, students can learn to communicate with others and make sense of the world around them when in the school setting. These supports can easily be customized to address individual needs and the student's level of comprehension. For example, a student who is challenged by reading may not be able to understand a schedule that uses words, so the student would do better with a schedule that uses pictures instead.
Utilized in the school setting, visual supports cover a wide range of student needs: understanding rules, increasing independence, making decisions, communication with people, providing organization, supporting transitions from one task to the next, providing clarity on what specific work to complete, and offering positive feedback. Visual supports can also thwart or diminish challenging behaviors in a variety of ways and can assist with decreasing exasperation, frustration, and anxiety.
There are four common types of visual supports: visual schedules, information sharers, checklists/organizers, and visual behavior supports.
1.A visual schedule, which shows the order of activities across time periods throughout a school day offers predictability and decreases anxiety by allowing the student to be aware of their expected activities for the day and tasks to be completed during their instruction. This type of schedule may be developed from pictures, simple words, use of objects (such as a napkin to represent their lunchtime) or a combination of all of these options and can be customized to the comprehension level of a specific student, For example, one student may only be able to manage a small amount of information within a given time period, while other students can manage the information for a longer length of time.
A mini schedule can be used to provide information to the student for a specific work task. Incorporated within a content area such as math, mini schedules provide the student with expectations within their instructional content session. For example, if the student needs to complete a worksheet or web-based math assignment, each task can be depicted by objects, pictures, or words placed on a schedule to be used during the math instructional time.
2.Informational sharers help students share information about their school day with others, such as their parents. While teachers often communicate with parents and provide information about their child's school experiences, it can be more meaningful to parents when their child communicates information directly. Using objects, pictures, or words, students can indicate which activities they participated in by selecting the accurate objects, circling or identifying the picture or word, and writing a word or sentence to describe their activity.
"People locators" are a type of informational sharer that provides information to students about other people involved in their lives. If a student travels between two parents, a people locator (resembling a calendar) can be created to show the student which days he or she will travel to which parent. This same calendar can be used to indicate which week days are school days or stay–at-home days, etc.
Personal information cards are another type of informational tool that is beneficial to support student's communication when they are not able to speak. The information card provides relevant student information such as: student's name, parents' names, address, medical information, or other special instructions. The student is required to have this information card with them at all times. This is especially beneficial when a student travels off-campus during the school day to a field trip or when going out into the community.
3.Student checklists increase a student's independence and help the student be successful by organizing specific tasks into chunks or smaller steps so that they can be easily completed. If a student becomes off-task or distracted and is then redirected back to task, the checklist will provide a visual reminder by indicating what steps they have completed and where to continue to complete the task. Checklists can also be used by the student to provide information on what to do when arriving to school or before leaving school. Like all other visual supports, checklists may contain pictures, objects, words, or a combination of all of these depending on the student's ability level. A visual checklist can also assist a student with sequential tasks that will provide a supportive foundation in various areas of the student's educational setting while in the classroom (student activities), outside the classroom (bathroom), and in the lunchroom (preparing snacks or meals) with the purpose of increasing a student's independence and overall success.
4.Visual behavior supports help to prevent challenging behavior and maintain emotional regulation. These are beneficial in helping a student calm down when they are agitated. The visual behavior supports provide the student with information about their expectations, possible outcomes, and what consequences will occur with challenging behavior.
Token boards, which track tokens earned by students for appropriate behavior or responses. First/then visuals provide students with a picture indicating what must be done first and then another picture indicating the reward which follows the task.
Rule cards, social stories, and power cards can be used to teach students the expected behaviors in various school settings.
Visual supports can be a valuable option for a student who is not understanding or responding to verbal instructions, as well as for a student with developmental disabilities who requires environmental and instructional supports to help him/her overcome various challenges. When deciding to use any of these visual support options in the educational setting, educators should individualize their selection based on a student's abilities and communication needs, as well as a determination that the student responds to the use of visual supports and is not embarrassed by them. When educators choose appropriate visual supports in their classroom, student achievement and independence will be celebrated.


text:
Massachusetts Medical Society
The medicinal garden at the Massachusetts Medical Society
IN CULTIVATION
A Book Review
by Meghan Stanley | posted in: Book Review, History | 0
Doctors in the Medicinal Garden—Plants named after Physicians
Author: Dr. Henry Oakeley, FRCP, FLS
Publisher: The Royal College of Physicians
All gardeners who have ever wondered how plants got their common and botanical Latin names will enjoy this book. The emphasis is on physicians as gardeners for good reasons.
Up until about 200 years ago, all botanists were physicians and all physicians were botanists. Some important figures in medical history of classical antiquity were all gardeners (or herbalists, as they're sometimes called) included Hippocrates (460–375 B.C.E.), Theophrastus (371–287 B.C.E.), Pliny the Elder (23–79 C.E.), Dioscorides (40–90 C.E.), and Galen (129-200 C.E.). The list of these figures is very long and spans the ages, but it should include Dr. William Withering, who deserves special recognition for his discovery of the medicinal properties of the foxglove and for the way he proved its efficacy in the treatment of dropsy when it is caused by heart failure.
Given the enormous importance of plants in medical practice in all times and in all cultures, it should come as no surprise that gardening is a favorite avocation of physicians even today.
The book has excellent photographs and botanical drawings accompanied by a synopsis of each plant and a biography of the physician associated with it.
View a tabulation of some of the plants with the botanical name, common name, and the physician associated with it.
Book Review, History
PLIMOTH PLANTATION IN THE 17TH CENTURY
Represented in the Massachusetts Medical Society HORTUS MEDICUS in the 21st century The English colonists...
Meghan StanleyOctober 17, 2017
PLIMOTH PLANTATION IN THE 17TH CENTURY October 17, 2017
A Book Review October 17, 2017
MMS GARDEN
NATURA DUCE
HORTUS MEDICUS
NOS AMICAS ET AMICOS EIUS HABET
With nature as our guide
the Medicinal Garden
counts us as its friends
860 Winter Street	Waltham MA 02451
garden@mms.org
© 2022 Massachusetts Medical Society, 860 Winter Street, Waltham Woods Corporate Center, Waltham, MA 02451-1411 — MMS Medicinal Garden website design Meghan C. Stanley, with support provided by the Physicians Insurance Agency of MA

redpajama_set_name: RedPajamaCommonCrawl


Description: The PBN concept represents a shift from sensor-based to performance-based navigation. PBN routes and procedures are designed to meet a navigation specification which is defined in terms of accuracy, integrity, availability, continuity and functionality for the proposed operations in the context of a particular airspace. Personnel involved in airspace design need to understand the PBN concept and how it can be used to improve an existing airspace structure. The goal of this course is to provide participants with application of PBN in the design of airspace.
Goal: The goal of this course is to provide participants with application of PBN in the design of airspace.
Target Audience: ATS providers and regulators, ATS managers, airline flight planning personnel from operational control centres, supervisors, safety managers, airspace planners, trainers and inspectors who are involved in ATS airspace design and procedures both civil and military.


*Removes Odors from Your Vehicle.
* A must have for ride share drivers.
*Easily Remove unpleasant odors from your vehicle in just a few minutes.
*Perfect for use in detailing your car.
*Works on removing smoke smells from your vehicle.
*A must have if you have pets as well to remove pet odors from fabrics.
*Can be used inside of rental vehicles as well to remove odors.
*Perfect if you have more than one vehicle.


Please look below at the different shows, workshops, and services and contact Noah using the contact form on this page to make arrangements. If you wish to have a voice interpretation, please inform Noah in order to make that special arrangment. Please understand that it cannot be guaranteed that your request will be met. If you have other ideas than the below shows, workshops, and services, feel free to contact Noah and suggest an idea.


As a local Locksmith Las Vegas company Half Price Locksmith of Las Vegas offers another type of security, they offer the security of using the right Las Vegas locksmith company and here's how.
1. All their Las Vegas locksmith vehicles are market clear as day with the license number as required by Law.
2. All their Las Vegas locksmiths have a locksmith I.D. from the local Las Vegas police department as required by Law.
3. Lifetime warranty on all labor.
7. All customers must be satisfied with all locksmith work before the locksmith leave thee job site.
So it's easy to understand why people use Half Price Locksmith of Las Vegas as its simply the highest rated Locksmith Las Vegas company with so many locksmith awards as well as the best customer service in their field not only giving a lifetime warranty on all their labor but also having a MONEY BACK POLICY (see their details).
Half Price Locksmith of Las Vegas also gives free labor to the unfortunate in some circumstances. So you can see how easy it is to want to use this Locksmith Las Vegas company that gives back to our community.
As a local Las Vegas company we are selves like to point out other great service companies in other fields. And one of the first companies that comes first to mind is Half Price Locksmith of Las Vegas.
Half Price Locksmith of Las Vegas has great Las Vegas locksmith customer service in so many ways. As a customer of there's ourselves we noticed when we first opened or doors that when their locksmith tech came over he went over every door and checked every single lock and mechanism before ever giving us what was a free estimate with no obligation what so ever. After every door and lock was checked their locksmith gave us three different options with everything from high security to just basic re-key and we where told that no matter what we choose that they could do it right then and there.


Beautiful land in Polk County. Property is composed of a 688 /- acres nestled between Surveyors Lake and Gator Lake. In the family since the 1940's, it's main use has been cattle ranching, but parts of it were also used for farming watermelons and other vegetable crops. Wildlife is abundant with wild turkeys, boar, quail and deer. Past operations also include sod farming. Fishing is also excellent on both lakes for bass, catfish and other native fish. Property can care for approximately 160 herd of beef cattle per year.


text:
You Are Here: Home → News → It takes three days for a CEO to earn the average UK salary
It takes three days for a CEO to earn the average UK salary
Darius McQuaid Monday, January 6, 2020 0 Comment CEO pay, CIPD, FTSE 100 CEOs, HR news, UK
Within the first three working days of 2020, a CEO has earned the same amount as the average UK employee's annual salary (£29,559).
This is according to research conducted by the CIPD and think tank, High Pay Centre.
Changes to the Companies Act, means that firms must now show their CEO's pay ratio and also explain why their CEO is paid the level they are. There is no fixed deadline for all companies' reports to be published, still the first report should be published in early 2020.
This rule applies to all businesses with more than 250 UK employees.
The CIPD and the High Pay Centre see this as an opportunity to fully justify and explain CEO pay and not just use it as a "tick-box" exercise.
Peter Cheese, chief executive of the CIPD believes this move could increase trust among employees, as well as investors and external stakeholders.
Mr Cheese said:
This is the first year where businesses are really being held to account on executive pay. Pay ratio reporting will rightly increase scrutiny on pay and reward practices, but reporting the numbers is just the start. We need businesses to step up and justify very high levels of pay for top executives, particularly in relation to how the rest of the workforce is being rewarded.
Greater fairness and openness in pay is essential in building trust, among employees as well as external stakeholders and investors. Expectations on businesses behaving and acting responsibly are rising, and greater transparency around how they are treating and managing all their people is a vital part of building long-term sustainability.
Andrea Leadsom, Business Secretary said:
Today's figures will be eye-watering for the vast majority of hard-working people across the UK.
The numbers are better than they were – down a quarter since 2012 and 13% on average since last year – but the situation is still concerning, especially in those cases where executives have been rewarded despite failing their employees and customers.
This data was compiled by using the FTSE 100 CEO pay for 2018.


text:
How useful will Vinny Prospal be in Columbus?
By Matt ReitzJul 25, 2011, 8:00 AM EDT
On Saturday, the Columbus Blue Jackets and GM Scott Howson announced that they had signed free agent forward Vinny Prospal to a one-year, $1.75 million contract. The team has already acquired an assortment of offensive firepower; but then again, they were a team that needed a great deal of offensive talent to compete. He'll most likely slide into a top-line role while injured winger Kristian Huselius recovers from a torn pectoral muscle that is expected to keep him out for four months. His role is clear, yet his ability to fill said role isn't as easy to figure out. Will he be able to produce at a high level and help Jeff Carter and Rick Nash become one of the most feared duos in the league?
That's the million dollar question. For what it's worth, Howson seems to think that he has found the answer for the first half of the season:
"Vinny Prospal is a proven top six forward in the National Hockey League and we look forward to him playing that role for our hockey club. We are very pleased to be able to add a player of his caliber to our team at this late date in the free agency process."
Translation: When Huselius injured himself this offseason, we needed to find someone as soon as possible and this is what we could find. Howson further explained the move to Tom Reed of The Columbus Dispatch:
"He's produced almost everywhere he's gone. As we went through this process of finding somebody who could help us get through the first part of the season without Kristian, we kept coming back to him. He was at the top of our list in terms of players who were available."
Even though some people in Columbus fear that Prospal's reputation is a function of playing in New York, Prospal is the right player for the Blue Jackets at the right time. They aren't depending on Prospal to carry the team on the first line—they're just asking him to be able to keep up with Rich Nash and Jeff Carter until Kristian Huselius returns to the line-up. In short bursts, Prospal has proven that he can put points on the board. Just look at last season—even though he only played in 29 games last year, he was second on the team with .79 points per game.
Obviously it would be asking a lot for a 36-year-old playing on his seventh team to score 25 goals and 65 points next season. If teams expected that kind of output, it wouldn't have taken him three weeks to find a job and he would have signed for more than $1.75 million next season. Most likely, he'll be a little better than he was a season ago defensively and not quite as productive offensively. Columbus signed him for what he is: a potentially very good stop-gap measure. Once Huselius returns to the line-up, Prospal will provide decent scoring depth and help on the power play for a team that desperately needed help scoring goals last year. Andy Newman at Jackets Cannon understands the best case scenario:
"I'm most excited for what the lineup looks like when Huselius returns, even if that happens to be late January. This adds tremendous depth and will fill out the lineup just in time for the playoffs. With Prospal playing left wing, I imagine Nash will get moved back to the right side, where he has spent plenty of time the past two seasons."
The most important factor to keep in mind with the Prospal acquisition in Columbus is expectations. For fans who expect him to come in and score at a point-per-game average, they will most likely be disappointed by the end of the season. But for those who understand that he is a streaky player who has the talent to play with the two elite offensive players who are responsible for carrying the Blue Jackets this season, they should be happy with the Prospal signing. He's a temporary solution for a team that desperately needed someone who could fill a huge void for a few months. Anything beyond that should be icing on the cake. Considering he didn't cost much and looks to be highly motivated, it should be a situation of the perfect player, fitting into the perfect role at the perfect time.


Evergreen tree. This specimen has a central, straight trunk with branching starting closer to the base of the tree. Native to Australia. Narrow, rough, grayish green foliage on thornless branches. Elongated yellow flowers bloom winter and spring. Very low water needs in well-drained soil once established.


Build your Twitter community with Flutter, a new way to discover targeted Tweeters and manage your account.
30Social Media Marketing Agency: Social-centered.
Agence Social Media Lyon : Facebook, Google+, Twitter, Youtube, Pinterest, Viadeo, Linkedin. Agence SMO / Community management & Epub.
Blog de formations vidéos pour apprendre à maîtriser le community management et la création de blog professionnel.
Le Community Management autrement : Concours Clef En Main / Apps Concours Twitter.
ethority ist der führende Anbieter für Social Media Monitoring, Research und Social Media Marketing. ethority liefert Hintergründe, Trends und Know-how für Ihr Unternehmen und Ihre Branche. Wir verwandeln Daten in profitable Online-Strategien.
We craft Social Marketing applications, which exploit the users' Social Graph, and we amplify them through media campaigns.
We are a social media agency based in Singapore and Malaysia providing social media strategies, apps development, social listening and community management across ASEAN.
At Movement Strategy we know social. It's at the core of everything we do from community management to award winning design and development.
Directeur de projet - be angels depuis 2010 - Voir le profil professionnel de Yann Feige. Viadeo aide les professionnels comme Yann Feige (Calais) à se faire connaitre et à gérer leur carrière.
A description of services offered through MamaBuzz Media.
Web design and digital marketing specialists for small businesses and community organisations on a tight marketing budget.


text:
Nutanix ropes in VMware's COO Rajiv Ramaswami as CEO
Tech ObserverNewsEnterprise ITNutanix ropes in VMware's COO Rajiv Ramaswami as CEO
Dec 10, 2020 1:02 PM IST
By Tech Observer Desk
By: Tech Observer Desk
Last Updated: Dec 10, 2020 1:09 PM IST
Rajiv Ramaswami, President & CEO, Nutanix
April Tayson -
Peter Maithel -
Sandeep Lodha -
The hyperconverged infrastructure firm Nutanix has roped in VMware's chief operating officer Rajiv Ramaswami as President and Chief Executive Officer.
Ramaswami will succeed co-founder Dheeraj Pandey, who previously announced his plans to retire as CEO of Nutanix upon the appointment of a successor.
Pandey will step down from the Board effective Monday, December 14, 2020, to ensure continuity through Nutanix's upcoming Annual Meeting of Stockholders.
Before joining Nutanix, Ramaswami served as Chief Operating Officer of Products and Cloud Services at VMware. Prior to this role, Ramaswami led VMware's Networking and Security business, one of the fastest-growing units in the company, as Executive Vice President and General Manager.
Before joining VMware, Ramaswami served as Executive Vice President and General Manager, Infrastructure and Networking at Broadcom. In his prior General Manager roles at Cisco, he led multibillion dollar product lines in switching, data center and storage and optical networking.
Ramaswami is a seasoned technology industry executive who has held senior executive roles at industry leaders including VMware, Broadcom, Cisco, and Nortel, after having begun his career at IBM, said a statement from the company.
"Rajiv is an accomplished leader with a track record of delivering a high-growth portfolio of products and services," said Sohaib Abbasi, Lead Independent Director of Nutanix.
"Rajiv distinguished himself among the CEO candidates with his rare combination of operational discipline, business acumen, technology vision and inclusive leadership skills. The talented Nutanix team, under Rajiv's leadership, is well-positioned to drive sustained growth, to improve efficiency and to advance leadership in the emerging hybrid cloud infrastructure category," he added.
"I have long admired Nutanix as a formidable competitor, a pioneer in hyperconverged infrastructure solutions and a leader in cloud software. Working closely with the Board, the management team, and the more than 6,000 talented Nutanix employees around the world, we will build on Nutanix's strong foundation of continuous innovation, collaboration and customer delight. Together, we will capitalize on the significant opportunities ahead and deliver on the company's next phase of growth and value creation," said Ramaswami.
"Rajiv is the right leader at the right time," said Nutanix Co-founder Dheeraj Pandey. "With a future-proof business model, a loyal and expanding customer base, and a strong technology portfolio, I look forward to seeing Rajiv take the helm to lead this incredible team. This is the decade to watch for a company that so values simple, secure, and seamless. On a personal note, it has been a privilege to serve our customers and partners, working closely alongside Nutanix employees."
Ramaswami earned his B. Tech in Electrical Engineering at the Indian Institute of Technology, Madras, and his Master's Degree and PhD in Electrical Engineering and Computer Science at the University of California, Berkeley.
He is an Institute of Electrical and Electronics Engineers (IEEE) Fellow and holds 36 patents, primarily in optical networking.
VMware looks to accelerate cloud partnership and big acquisitions: Raghuram
CIOs must prepare digital strategy to facilitate hybrid workplace
CIOs need agile ecosystem to move from on-prem to cloud to on-prem
VMware elevates India-born Raghu Raghuram as CEO
Subscribe to receive the day's headlines from Tech Observer straight in your inbox
Web Email Subscription
Dheeraj Pandey
Rajiv Ramaswami
rohan on Shared workspace provider Smartworks expands in Bangalore
John Dryden on Adobe collaborates with Amazon to bring new capability to Magento Commerce
Sébastien Violette on MWC 2019: eSIM goes full steam ahead and into the enterprise
Giridhar Prathap Reddy on HDFC Bank: AI based chatbot facilitates transaction worth Rs 16.7 million
Prof. M. Aslam on PM Narendra Modi: Universities and Colleges should find solutions to the challenges society face
Tushar parihar on BenQ launches 4K HDR home cinema projector X12000H with price tag of Rs 5 lakhs
Latest in TECH
GovernanceTech Observer Desk - 26 mins ago
Amid deep Chinese inroads in Sri Lanka, India extends its science & tech cooperation for three more years
India and Sri Lanka have extended their existing science & technology cooperation for three more years with a focus on new areas.
BMW unveils new X3 for India at just Rs 59.9 lakh
Tech Observer Desk -
Enterprise IT Tech Observer Desk -
Cloud Computing Tech Observer Desk -


Reston, Virginia-based information technology services provider NCI has received a one-year, $4.9 million task order to continue its support for the Internal Revenue Service's efforts to implement big data analytics tools and practices.
NCI said Wednesday it will help the tax collection agency develop an architecture prototype, interface with delivery partners and engineer documentation for the the agency's Return Review Program.
"NCI will assist the IRS in implementing their data strategy for several key programs and making the data actionable for taxpayers and agency staff," said Brian Clark, NCI president and CEO.
The company also aims to help the agency detect fraud and manage compliance in the Affordable Care Act and Customer Account Data Engine 2 programs with the RRP platform.
IRS awarded the order through the Total Information Processing Support Services-4 contract.
TIPSS-4 serves as an information technology procurement vehicle for the IRS and other federal agencies.


Today I stretched out (somewhat uncomfortably on a weird doctor's office recliner) and listened to my baby undisturbed for quite some time. I had been worried about not bonding as much with this little guy as I did with Bubby in the womb, but this morning I sat back in awe of this miracle. A miracle that reminded me of him being a miracle when he gave me a little scare Tuesday. When Bubby was first born (and okay, still from time to time now) I just would sit and watch him sleep, watch him breathe, completely mesmorized. Today I felt similarly mesmorized as this morning I reclined, hands above the monitor on my belly, listening to one of the most beautiful sounds ever - a baby heartbeat and him kicking and moving around inside of me.
Humans are not some cosmic mistake, accident, phenomenon. We are created too complexly for that, in my opinion. Something that started out as two cells is now two pounds and fourteen inches long and with a heartrate in the 150's.There is a life growing inside of me - already alive and kickin' - and he is here for a reason, and I have the distinct honor of being his mama.
ahhh, there is something so precious in a mama's heart and belly when she gets to see, hear, feel how REAL that life is. this is a sweet memory.
being mama - its work and riches, that job.
oh, isn't it all one big miracle? the life, and the love... and as we die to ourselves, a new person grows. beautiful, friend.
I remember being pregnant with my second and worrying the same as you. Now that second is 19 months old, and my love for him is just as fierce as for my first. Amazing, isn't it? HOw love for people doesn't divide...it multiplies!
Thanks for sharing this moment with us. Human life, especially as it's in the process of being created, never ceases to touch me!
with my second and third children, i enjoyed those moments of listening and feeling mostly because of the quiet. it was such a special moment to concentrate on this new life, but also to just be. i'm not sure which was most important, but each were both precious gifts.


This year on the 21st of November our school hosted a fun evening filled with various activities. Everything happened because of our friend Tara, who has travelled from the USA to be with us for the whole year.
Most of us have never experienced a Thanksgiving feast so we didn't know what to expect. The evening began at 5 PM with a play about the Pilgrims meeting the Native Americans. Students in this play showed how kind the Native Americans were and how they helped the Pilgrims with their struggles. The play was followed by Tara's speech about the meaning of Thanksgiving and then all fun activities started.
You could try everything you had ever thought of. For example, you could listen to a thrilling story about Native Americans with an intense atmosphere. And if you felt like doing something competitive you could try some of many games that were there that night.
When all of these activities finished our grand feast began. You could find everything you ever wished for in our auditorium. Everything tasted extremely good because all the food was made with love.
The biggest surprise of this wonderful evening was a delicious turkey made by professor Hana Škoulová. During the feast we could watch episodes of F.R.I.E.N.D.S. with a Thanksgiving theme. And for those of us who felt grateful there was an opportunity to write a short thankful note for some of our professors.
Everybody enjoyed this evening because when we were sitting around the table it has almost felt like we were one big family.
Hello! My name is Tara Sennott and I'm from a small town outside Boston in the U.S. and I'm here for the year as an English teaching assistant here at Gymnázium Benešov. I've been in the Czech Republic for almost 3 months, and so far, I've been really impressed by my students' enthusiasm to speak English and learn about American culture. Last night, the English teachers organized a Thanksgiving celebration, with activities, games, and a big feast with a delicious turkey. The conversation club I'm running at the school wrote and performed a Thanksgiving play which re-imagined the Pilgrims' first feast in the New World. I built a Native American style tent in one of the classrooms and told a story by a (fake) campfire.
It was so beautiful to see all the students and the teachers gathering together, eating food and enjoying eachother´s company on a chilly evening in late November. The warm, familial spirit of Thanksgiving filled the school and I felt so grateful to celebrate this piece of home with my new Czech friends. Don't tell anyone… but my Thanksgiving in the Czech Republic is one of my favorites I've ever had!


text:
/**
 * @fileoverview Typedefs for the application.
 *
 * Typedefs are structured definitions of complex Javascript objects that are
 * usually passed as parameters to methods. Defining these allows the linter
 * and compiler to do type checking parameters passed to methods that are not
 * primative types. Can be handy in preventing errors based on passing bad
 * parameters to a method. See:
 * https://developers.google.com/closure/compiler/docs/js-for-compiler
 */

var typedefs = {};


All Lowry Filing 23 homes currently listed for sale in Denver as of 04/21/2019 are shown below. You can change the search criteria at any time by pressing the 'Change Search' button below.
If you have any questions or you would like more information about any Denver homes for sale or other Denver real estate, please contact us and one of our knowledgeable Denver REALTORS® would be pleased to assist you.
"Home is waiting for you in this quiet, friendly Lowry enclave where a sense of community joins with contemporary living to bring out your very best. Once inside, you ll be greeted by soaring ceilings, an expansive, open living space with a gas fireplace, and a well-appointed kitchen. You ll love the granite counters, stainless steel appliances, high-end cabinets with crown molding, gorgeous backsplash and roomy pantry. Just off the kitchen, you ll have access to your neat, sunny patio and "


text:
Zambia government should ensure proposed cyber-laws do not hinder access to information
Lusaka, 22 May 2017: Panos Institute Southern Africa (PSAf) urges the Zambian government to ensure that the proposed laws to control the use of information and communication technologies (ICTs) do not impede smooth flow of information.
The Minister of Transport and Communications Mr. Brian Mushimba recently announced to the media that Government wants to 'develop firewalls in the cyberspace to prevent digital information from landing in wrong hands', and that 'Government wants to have a helicopter view of its cyberspace to detect possible cybercrime'. Minister Mushimba said the government would introduce four laws, namely the Cyber Security Bill, Cyber Crime Bill, Electronic Commerce Bill and the Data Protection Bill.
To that effect, we encourage the government to consult widely with media organisations, online firms and the users and promoters of social media and ICTs before developing bills and enacting laws. This will help ensure the laws do not expose citizens to unscrupulous characters or hinder their enjoyment of the right to privacy and freedom of information. We also urge the government to exercise caution and guard against any gaps that may result in the laws restricting citizens from using ICTs to seek, receive and share information.
If the process is properly handled, the laws can protect citizens from cyberbullies, scammers, fraudsters, child pornography and online identity theft. However, if not properly handled the laws have potential to restrict citizens access to information and hamper the enjoyment of fundamental human rights such as the right to information and right to privacy. We therefore appeal to the government to exercise great caution, put in place measures or systems to mitigate against potential risks of abuse of the laws to infringe on citizens' rights.
It is our hope that the laws open the online and ICTs media space and enhance access to information. We also hope the government will support the laws with policies and systems to ensure groups that are currently marginalised in online platforms, such as the rural poor also benefit from the opportunities presented by ICTs. This will contribute to reducing the digital divide which is still very wide in Zambia.
For the last two decades, the Zambian people have been urging for the opening of information sharing spaces through the enactment of Access to Information laws. In the same way the government is coming up with several laws to control the use of ICTs, we call on the government to expedite the enactment of the Access to Information law. We are of the view that the Access to Information law is more urgent than the proposed cyber laws, considering that current laws in the Penal Code, the Computer Crimes and Misuse Act and the Copyright and Performance Rights Acts and the acts of private companies have provisions to handle cyber-crime and related issues.
Panos urges the Zambian government not to fall into the trap of knee-jerk reactions based on information on social media that might not be in their favour.
Lilian Saka-Kiefer
Executive Director, Panos Institute Southern Africa (PSAf)
Email: general@panos.org.zm, Tel: +260978778148/9


text:
Godina proizvodnje:
Od - 2020 2019 2018 2017 2016 2015 2014 2013 2012 2011 2010 2009 2008 2007 2006 2005 2004 2003 2002 2001 2000 1999 1998 1997 1996 1995 1994 1993 1992 1991 1990 1989 1988 1987 1986 1985 1984 1983 1982 1981 1980 Do - 2021 2020 2019 2018 2017 2016 2015 2014 2013 2012 2011 2010 2009 2008 2007 2006 2005 2004 2003 2002 2001 2000 1999 1998 1997 1996 1995 1994 1993 1992 1991 1990 1989 1988 1987 1986 1985 1984 1983 1982 1981 1980
Prijeđeni kilometri:
Od - 10,000 30,000 50,000 70,000 90,000 110,000 130,000 150,000 170,000 190,000 210,000 230,000 250,000 270,000 290,000 310,000 330,000 350,000 370,000 390,000 410,000 430,000 450,000 470,000 490,000 Do - 10,000 30,000 50,000 70,000 90,000 110,000 130,000 150,000 170,000 190,000 210,000 230,000 250,000 270,000 290,000 310,000 330,000 350,000 370,000 390,000 410,000 430,000 450,000 470,000 490,000
Cijena (EUR):
Od - 500 1,500 2,500 3,500 4,500 5,500 6,500 7,500 8,500 9,500 10,500 11,500 12,500 13,500 14,500 15,500 16,500 17,500 18,500 19,500 20,500 21,500 22,500 23,500 24,500 25,500 26,500 27,500 28,500 29,500 30,500 31,500 32,500 33,500 34,500 35,500 36,500 37,500 38,500 39,500 40,500 41,500 42,500 43,500 44,500 45,500 46,500 47,500 48,500 49,500 50,500 51,500 52,500 53,500 54,500 55,500 56,500 57,500 58,500 59,500 60,500 61,500 62,500 63,500 64,500 65,500 66,500 67,500 68,500 69,500 Do - 500 1,500 2,500 3,500 4,500 5,500 6,500 7,500 8,500 9,500 10,500 11,500 12,500 13,500 14,500 15,500 16,500 17,500 18,500 19,500 20,500 21,500 22,500 23,500 24,500 25,500 26,500 27,500 28,500 29,500 30,500 31,500 32,500 33,500 34,500 35,500 36,500 37,500 38,500 39,500 40,500 41,500 42,500 43,500 44,500 45,500 46,500 47,500 48,500 49,500 50,500 51,500 52,500 53,500 54,500 55,500 56,500 57,500 58,500 59,500 60,500 61,500 62,500 63,500 64,500 65,500 66,500 67,500 68,500 69,500
You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '' at line 1


Your project is looking good. And, great breakdown of the election – my same observation. Thanks very much for the video info.
Hi Allen, for support please use marcuscampbellsupport.com – unless you contact us via the right channel we do not know what issues you may be having. from my end i can see that all the correct programs are in your account… so if you are having an issue please use the support site and be sure you check all email folders for the logins and everything.
The office looks great Marcus I agree on the emotions part – very powerful- we see it everyday.
It is really looking good Marcus!
I have just purchased your "end of the year" coaching program and look forward to knocking it out of the park!
suggestion. I greatly appreciate the education you give freely and find your insights helpful in other areas besides IM, their value does not recede with time.
'keep up', however I do save your emails, ergo this reply today 8-15-2017.
help me most at the time with the intention to make a first purchase of multi purchases.


BMI is a proud sponsor of The Blues Foundation's 33rd Blues Music Awards. This year's awards will be held at the Memphis Cook Convention Center in downtown Memphis, TN. The event brings together blues performers, industry representatives and fans from all over the world to celebrate the best in blues recordings and performances from the previous year. The evening will see performances by 2012 Hall of Fame inductees and Blues Music Award nominees.


text:
Skeiðarársandur è un ''sandur'' islandese, cioè una vasta distesa di sabbia generata dal trasporto di detriti da parte di un fiume glaciale. In questo caso le inondazioni sono generate dal ghiacciaio Skeiðarárjökull ed alimentate dai sistemi vulcanici del Grímsvötn e Öræfajökull.

Il risultato delle inondazioni è la formazione di un deserto di sabbia che si estende dal Vatnajökull, fino al mare per circa 1300 km2, facendo del Skeiðarársandur il più grande sandur del mondo. In particolare, il sandur ha una lunghezza tra i 20 ed i 30 km tra i ghiacciai a nord e l'oceano a sud, mentre il tratto di costa occupato è di 56 km di larghezza, sui meandri del fiume Skeiðará  e di altri corsi d'acqua minori.

La violenza dei flussi d'acqua nel caso di inondazione rappresenta una minaccia costante al Hringvegur, la grande strada nazionale che contorna tutta l'Islanda e che attraversa il Skeiðarársandur con un ponte di 904 m di lunghezza.

Altri progetti

Collegamenti esterni

Località della regione di Suðurland

redpajama_set_name: RedPajamaWikipedia


Click for larger map of the area. (Google Maps)Tucked in and nestled amongst the refineries and processing facilities of Long Beach, California and adjacent to the interchange of Interstate 405 and 710, lies Union Pacific's Intermodal Container Transfer Facility or ICTF. This 233 acre facility is a keystone component in Union Pacific's intermodal business and provides a very valuable service to the shipping companies that dock at the Ports of Long Beach and Los Angeles. A good portion of the shipping containers that are destined for locations in the interior regions of the United States are transferred to trains at the ICTF. It is quite an amazing beehive of activity to behold.
It wasn't until the 1980s that true "intermodal" use of the containers caught on and started supplanting the manifest train and became the most prevalent train seen on the mainline of US railroads. Today, outside of bulk cargo (i.e. Coal, petroleum, grains, etcetera), most "goods" travel by container. Therefore, the US railroads are becoming masters of the intermodal domain and the leaders of safe, timely, and hyper-efficient methods of transporting the world's cargo, which brings us to the ICTF.
The ICTF was built in 1986, at a cost nearly 56 million dollars, to serve as an near-dock international shipping transfer facility where imports/exports, are transferred to/from massive container ships anchored at the Los Angeles and Long Beach harbors and loaded onto truck chassis which are then delivered to the railhead at the Union Pacific's facility. The lack of available real estate within the harbor area necessitated that this transfer facility be built at its present location which is about 5 miles north of the ports.
The governing body of the ICTF is a public entity, created in 1983, called the The Intermodal Container Transfer Facility - Joint Powers Authority, better known as the JPA. The four directors of the JPA are comprised of two representatives from each of the area's respective ports, the Port of Los Angeles and the Port of Long Beach. The Union Pacific Railroad currently has a long term lease of the ICTF facility and pays the JPA a fee for each container handled through the ICTF.
Safety is paramount to the Union Pacific Railroad.
Great care is taken to inform all employees and visitors of the risks and dangers associated with trains and heavy equipment. Everyone must wear approved safety equipment when at the facility to include hard hats, safety glasses, steel toe boots, high-visibility vests, and hearing protection. In the various photos of this post you should see ample examples of the signs reminding all that safety is very important. I got the sense that, in fact, it is more important than the business which I applaud. Railroads and railroaders have a history and tradition of developing and applying safety measures within the industry and Union Pacific is no different.
Another element of safety that I found amazing was the overall cleanliness of the facility. Foreign objects and debris can be hazardous for employees and equipment alike. The Union Pacific takes great care in keeping the entire facility clean, free of debris, and orderly. In fact, UP even contracts with a street cleaning crew to maintain onsite street sweepers. This also helps to minimize environmental impact by helping to reduce dust. You can see the results for yourself in the accompanying photos.
According to a Union Pacific website, each ton-mile of freight moved by rail reduces greenhouse gas emissions by two-thirds, compared to transportation by truck.
"At Union Pacific Railroad, we are committed to protecting the environment now and for future generations. Our employees, customers, shareholders and the communities we serve can expect our full compliance with all laws and regulations.
"Union Pacific is developing and investing in new technologies that provide for cleaner air and water, including a locomotive fleet that's the greenest in the industry.
"Our employees understand that protecting the environment is part of every job, and they are creating and implementing world-class energy conservation techniques that are helping us to move more freight with less fuel.
The Union Pacific Railroad currently has two thirds of its road locomotive fleet certified under existing EPA Tier 0, Tier 1 and Tier 2 standards. They are currently replacing older, less efficient switcher-class locomotives around the UP system as well. Union Pacific is a leader in low-emissions and fuel efficiency testing and research.
An example of an "ultra-low-emitting locomotive," UPY 2313 (GG20GE), a Railpower GG20B "Green Goat," basks in the sun while awaiting the next move of rail-cars around the ICTF. Unlike past operating procedures this switcher does not sit idling when not is use, reducing emissions even further.
Currently, approximately 15 trains a day either originate or terminate at the ICTF complex daily. The facility operates 24 hours-a-day, 7 days-a-week and 365 days-a-year and employs approximately 500 employees.
The typical origination transfer routine calls for the containers to be unloaded from the huge container ships by massive dockside cranes. The containers are then loaded directly onto truck chassis and driven the 5 miles north to the ICTF. Once there, the trucks, drivers, and cargo undergo a robust security process prior to entering the facility and the truck is then assigned a parking space within the ICTF. The truck driver will drop off the chassis in its assigned location and return to the port to retrieve another container/chassis set.
Once the appropriate time comes to assemble a train and load the containers prior to the trains scheduled departure, a sufficient number of intermodal train cars, often referred to as "well cars" because of their shape, are to delivered to one of the 6 tracks within the ICTF designated for loading containers.
Next the containers that are assigned to depart on the train are retrieved from the parking area by yard tractors and loaded onto the rail-cars by large lift cranes called Mi-Jacks. It makes for a rather quick process as the entire team of dedicated professionals of drivers, crane operators, pin-setters, and safety officers are well-versed and perform in an orchestral fashion to ensure the operation is performed efficiently but safely.
At ICTF, a stream of K-Line containers line up to be lifted onto well cars for departure to points east aboard this Union Pacific intermodal train.
Mi-Jack #23, one of many, makes a lift of a container during the loading process of this intermodal train at UP's ICTF.
Spare wheel sets are staged ready to replace any bad wheel sets discovered during the inspections.
Located on the northern extremity of the ICTF is a key supporting player in the overall effectiveness of the ICTF - the Dolores Yard and Locomotive Facility. This rail facility contains approximately 10 yard tracks to store, make up, and break down trains originating or terminating in the south bay area, including the intermodal trains in and out of the ICTF. Another function of the Dolores facility is the onsite locomotive servicing and maintenance facility.
Intermodal trains terminating at Dolores or the ICTF will have their road units (locomotives) taken off of the train and serviced at Dolores. The locomotive facility performs inspections on the inbound locomotives, refuels the diesel tanks as required, fills the sand tanks in the locomotives, cleans the cab and performs other preparations to make ready the unit for its next run over the UP system. The facility can also perform minor repairs (called light repairs) to locomotives should a defect be found.
The location of the locomotive facility is ideal for UP's intermodal activities because it is where the power for outbound trains comes from and ensures that there is ample power available for outbound trains. It also helps reduce emissions in the area because these locomotives do not have to be serviced at more distant facilities.
A sanding tower blocks the sun at the Dolores Locomotive Facility. Sand is used in locomotives to provide traction when required by laying sand on the rails for the wheels to grip.
The three track inspection and servicing bay at the Dolores Locomotive Facility helps reduce costs, time, and emissions.
Traction motors are staged, ready to go into service should a unit have a faulty traction motor. Traction motors are the wheel sets that actutally provide the tractive effort to move a locomotive. They are massive electric motors that rest on top of the locomotives wheel sets.
Units wait to be serviced, repaired, or returned to duty at the Dolores Locomotive Facility in Long Beach, CA.
UP 4844 (EMD SD70M), built 11/2002, gets an inspection and light repairs at the Dolores Locomotive Facility before returning to revenue service.
In December 2007, Union Pacific submitted and application for a modernization plan of the ICTF to the JPA. The plan, based on increased projected traffic levels and measures to improve efficiencies, is currently under review while the various impact studies are performed. If the plan is approved, Union Pacific will begin a 3 to 4 year effort to double the facility's container handling capacity while making even more strides to reduce emissions, noise levels, and ambient light cast, and REDUCE the size of the complex from 233 acres to 177 acres. The application and plan details can be reviewed here.
The ITCF, and the Dolores facility, is an impressive complex where the pride and skill of the workforce serves an example of the efficiency and safeness of America's rail transport infrastructure. The men and women of the ICTF, along with the management of Union Pacific, should be proud of the work and service they perform there day in and day out to help keep America moving forward and doing their best reduce any impacts on the environment - something we all need to do.