public static MessageObject CreateNewMessage(PSTFile file, FolderItemTypeName folderItemType, NodeID parentNodeID, Guid searchKey)
        {
            // [MS-PST] The following properties must be present in any valid Message object PC:
            PropertyContext pc = PropertyContext.CreateNewPropertyContext(file);

            pc.SetStringProperty(PropertyID.PidTagMessageClass, GetMessageClass(folderItemType));

            pc.SetInt32Property(PropertyID.PidTagMessageFlags, 0);
            pc.SetInt32Property(PropertyID.PidTagMessageStatus, 0);
            pc.SetDateTimeProperty(PropertyID.PidTagCreationTime, DateTime.UtcNow);
            pc.SetDateTimeProperty(PropertyID.PidTagLastModificationTime, DateTime.UtcNow);
            pc.SetDateTimeProperty(PropertyID.PidTagClientSubmitTime, DateTime.UtcNow);
            pc.SetDateTimeProperty(PropertyID.PidTagMessageDeliveryTime, DateTime.UtcNow);
            byte[] conversationIndex = ConversationIndexHeader.GenerateNewConversationIndex().GetBytes();
            pc.SetBytesProperty(PropertyID.PidTagConversationIndex, conversationIndex);

            // PidTagSearchKey is apparently a GUID
            pc.SetBytesProperty(PropertyID.PidTagSearchKey, LittleEndianConverter.GetBytes(searchKey));

            pc.SaveChanges();

            NodeID pcNodeID = file.Header.AllocateNextNodeID(NodeTypeName.NID_TYPE_NORMAL_MESSAGE);

            file.NodeBTree.InsertNodeEntry(pcNodeID, pc.DataTree, pc.SubnodeBTree, parentNodeID);

            // NOTE: According to [MS-PST], A Recipient Table MUST exist for any Message object,
            //       However, in practice even outlook itself does not always create it.
            PSTNode       pcNode  = new PSTNode(file, pcNodeID, pc.DataTree, pc.SubnodeBTree);
            MessageObject message = new MessageObject(pcNode);

            return(message);
        }
Esempio n. 2
0
            public override void Write(EndianReader stream)
            {
                stream.Write(Type);
                stream.Write((ushort)Nodes.Count);
                byte[] data;
                switch (stream.Endian)
                {
                case Endianness.BigEndian:
                    data = BigEndianConverter.GetBytes(ID);
                    break;

                case Endianness.LittleEndian:
                    data = LittleEndianConverter.GetBytes(ID);
                    break;

                default:
                    throw new NotImplementedException();
                }
                stream.Write(data, 0, 2);
                stream.Write(data, 2, 2);

                foreach (Node node in Nodes)
                {
                    node.Write(stream);
                }
            }
Esempio n. 3
0
        public byte[] GetBytes()
        {
            byte[] buffer = new byte[BytesPerSector];
            Array.Copy(Jump, 0, buffer, 0x00, 3);
            Array.Copy(ASCIIEncoding.ASCII.GetBytes(OEMID), 0, buffer, 0x03, Math.Min(8, OEMID.Length));

            Array.Copy(LittleEndianConverter.GetBytes(BytesPerSector), 0, buffer, 0x0B, 2);
            buffer[0x0D] = SectorsPerCluster;
            buffer[0x15] = MediaDescriptor;
            Array.Copy(LittleEndianConverter.GetBytes(SectorsPerTrack), 0, buffer, 0x18, 2);
            Array.Copy(LittleEndianConverter.GetBytes(NumberOfHeads), 0, buffer, 0x1A, 2);
            Array.Copy(LittleEndianConverter.GetBytes(NumberOfHiddenSectors), 0, buffer, 0x1C, 4);

            buffer[0x24] = PhysicalDriveNumber;
            buffer[0x26] = ExtendedBootSignature;
            Array.Copy(LittleEndianConverter.GetBytes(TotalSectors), 0, buffer, 0x28, 8);
            Array.Copy(LittleEndianConverter.GetBytes(MftStartLCN), 0, buffer, 0x30, 8);
            Array.Copy(LittleEndianConverter.GetBytes(MftMirrorStartLCN), 0, buffer, 0x38, 8);
            buffer[0x40] = (byte)RawClustersPerFileRecordSegment;
            buffer[0x44] = (byte)RawClustersPerIndexBlock;
            Array.Copy(LittleEndianConverter.GetBytes(VolumeSerialNumber), 0, buffer, 0x48, 8);
            Array.Copy(LittleEndianConverter.GetBytes(Checksum), 0, buffer, 0x50, 4);

            Array.Copy(Code, 0, buffer, 0x54, Code.Length);
            return(buffer);
        }
 public void SetDateTimeProperty(PropertyID propertyID, DateTime value)
 {
     // We write as UTC to avoid conversion when using ToFileTimeUtc()
     value = DateTime.SpecifyKind(value, DateTimeKind.Utc);
     byte[] propertyBytes = LittleEndianConverter.GetBytes(value.ToFileTimeUtc());
     SetExternalProperty(propertyID, PropertyTypeName.PtypTime, propertyBytes);
 }
Esempio n. 5
0
        public void Save(byte[] buffer, int offset)
        {
            Debug.Assert(buffer.Length - offset >= GetSaveLength());

            LittleEndianConverter.GetBytes(buffer, offset, ContentLength);
            LittleEndianConverter.GetBytes(buffer, offset + 4, ContentOffset);
        }
        public PropertyContextRecord GetRecordByPropertyID(PropertyID propertyID)
        {
            byte[] key = LittleEndianConverter.GetBytes((ushort)propertyID);
            PropertyContextRecord record = FindRecord(key);

            return(record);
        }
Esempio n. 7
0
        public void SetInt64Property(int rowIndex, PropertyID propertyID, long value)
        {
            int columnIndex = GetColumnIndexByPropertyTag(propertyID, PropertyTypeName.PtypInteger64);

            byte[] cellBytes = LittleEndianConverter.GetBytes(value);
            SetPropertyValue(rowIndex, columnIndex, cellBytes);
        }
Esempio n. 8
0
        /// <param name="cellBytes">If property is external, byte[0] means empty data item</param>
        public void SetPropertyValue(int rowIndex, int columnIndex, byte[] propertyBytes)
        {
            TableColumnDescriptor columnDescriptor = m_tcInfo.rgTCOLDESC[columnIndex];

            if (columnDescriptor.IsStoredExternally)
            {
                byte[]       cellBytes = GetInternalCellBytes(rowIndex, columnIndex);
                HeapOrNodeID heapOrNodeID;
                if (cellBytes != null)
                {
                    heapOrNodeID = new HeapOrNodeID(cellBytes);
                }
                else
                {
                    heapOrNodeID = new HeapOrNodeID(HeapID.EmptyHeapID);
                }

                HeapOrNodeID newHeapOrNodeID = NodeStorageHelper.StoreExternalProperty(this.File, m_heap, ref m_subnodeBTree, heapOrNodeID, propertyBytes);
                // we call SetInternalCellBytes even when oldHeapID.Value == newHeapID.Value,
                // this will make sure the CEB will be updated
                SetInternalCellBytes(rowIndex, columnIndex, LittleEndianConverter.GetBytes(newHeapOrNodeID.Value));
            }
            else
            {
                SetInternalCellBytes(rowIndex, columnIndex, propertyBytes);
            }
        }
Esempio n. 9
0
 public static bool TestCrc16Ccitt_1()
 {
     byte[] buffer   = new byte[] { 0x06 };
     byte[] checksum = new byte[] { 0x4E, 0x95 };
     byte[] result   = LittleEndianConverter.GetBytes(Crc16Ccitt.ComputeChecksum(buffer));
     return(ByteUtils.AreByteArraysEqual(checksum, result));
 }
Esempio n. 10
0
 public static bool TestCrc16Ccitt_2()
 {
     byte[] buffer   = new byte[] { 0x0d, 0x0f, 0x50, 0x42, 0x4c, 0x5f, 0x44, 0x6c, 0x6f, 0x61, 0x64, 0x56, 0x45, 0x52, 0x31, 0x2e, 0x30 };
     byte[] checksum = new byte[] { 0x37, 0x41 };
     byte[] result   = LittleEndianConverter.GetBytes(Crc16Ccitt.ComputeChecksum(buffer));
     return(ByteUtils.AreByteArraysEqual(checksum, result));
 }
        public void AddRecipient(PSTFile file, string displayName, string emailAddress, bool isOrganizer)
        {
            // http://social.msdn.microsoft.com/Forums/en-US/os_binaryfile/thread/a5f9c653-40f5-4638-85d3-00c54607d984/
            // dwRowID must be > 0:
            uint rowID    = (uint)RowCount + 1; // good enough for now
            int  rowIndex = AddRow(rowID);

            SetStringProperty(rowIndex, PropertyID.PidTagDisplayName, displayName);
            SetStringProperty(rowIndex, PropertyID.PidTagAddressType, "SMTP");
            SetStringProperty(rowIndex, PropertyID.PidTagEmailAddress, emailAddress);
            SetBytesProperty(rowIndex, PropertyID.PidTagSearchKey, LittleEndianConverter.GetBytes(Guid.NewGuid()));
            SetInt32Property(rowIndex, PropertyID.PidTagRecipientType, (int)RecipientType.To);
            SetInt32Property(rowIndex, PropertyID.PidTagObjectType, (int)ObjectType.MailUser);
            SetInt32Property(rowIndex, PropertyID.PidTagDisplayType, 0);

            SetStringProperty(rowIndex, PropertyID.PidTagRecipientDisplayName, displayName);

            int recipientFlags = (int)RecipientFlags.SendableAttendee;

            if (isOrganizer)
            {
                recipientFlags |= (int)RecipientFlags.MeetingOrganizer;
            }
            SetInt32Property(rowIndex, PropertyID.PidTagRecipientFlags, recipientFlags);
            SetInt32Property(rowIndex, PropertyID.PidTagRecipientTrackStatus, 0);

            byte[] recipientEntryID = RecipientEntryID.GetEntryID(displayName, emailAddress).GetBytes();
            SetBytesProperty(rowIndex, PropertyID.PidTagEntryId, recipientEntryID);
            SetBytesProperty(rowIndex, PropertyID.PidTagRecipientEntryId, recipientEntryID);

            SetInt32Property(rowIndex, PropertyID.PidTagLtpRowId, (int)rowID);
            SetInt32Property(rowIndex, PropertyID.PidTagLtpRowVer, (int)file.Header.AllocateNextUniqueID());
        }
Esempio n. 12
0
        public void WriteKey(int key)
        {
            Stream.Position = 0;
            Key             = key;
            this.key        = key;

            Stream.Write(LittleEndianConverter.GetBytes(key), 0, 4);
            Offset = 0;
        }
        public void Save(byte[] stream, int offset)
        {
            if (stream.Length - offset < 8)
            {
                throw new Exception("Error!\n");
            }

            LittleEndianConverter.GetBytes(stream, offset, ValueLength);
            LittleEndianConverter.GetBytes(stream, offset + 4, ValueOffset);
        }
Esempio n. 14
0
        private void DeleteLastRowFromRowIndex()
        {
            uint rowID = m_rowIndex[m_rowIndex.Count - 1].dwRowID;

            m_rowIndex.RemoveAt(m_rowIndex.Count - 1);

            BTreeOnHeap <TableContextRowID> bTreeOnHeap = new BTreeOnHeap <TableContextRowID>(m_heap, m_tcInfo.hidRowIndex);

            bTreeOnHeap.RemoveRecord(LittleEndianConverter.GetBytes(rowID));
        }
Esempio n. 15
0
        public void SetDateTimeProperty(int rowIndex, PropertyID propertyID, DateTime value)
        {
            if (value.Kind != DateTimeKind.Utc)
            {
                throw new InvalidPropertyException("DateTime must be in UTC");
            }
            int columnIndex = GetColumnIndexByPropertyTag(propertyID, PropertyTypeName.PtypTime);

            byte[] cellBytes = LittleEndianConverter.GetBytes(value.ToFileTimeUtc());
            SetPropertyValue(rowIndex, columnIndex, cellBytes);
        }
Esempio n. 16
0
        public byte[] GetBytes()
        {
            byte[] sequenceBytes = AVPairUtils.GetAVPairSequenceBytes(AVPairs);
            byte[] timeBytes     = LittleEndianConverter.GetBytes((ulong)Time.ToFileTimeUtc());

            byte[] buffer = new byte[28 + sequenceBytes.Length];
            ByteWriter.WriteByte(buffer, 0, ResponseVersion);
            ByteWriter.WriteByte(buffer, 1, ResponseVersionHigh);
            ByteWriter.WriteBytes(buffer, 8, timeBytes);
            ByteWriter.WriteBytes(buffer, 16, ClientChallenge, 8);
            ByteWriter.WriteBytes(buffer, 28, sequenceBytes);
            return(buffer);
        }
Esempio n. 17
0
        public void TestUInt()
        {
            uint[] specials = new uint[] { uint.MinValue, 1, uint.MaxValue };

            foreach (uint special in specials)
            {
                byte[] buffA = new byte[4];
                LittleEndianConverter.GetBytes(buffA, 0, special);

                byte[] buffB = BitConverter.GetBytes(special);

                Assert.IsTrue(buffA.SequenceEqual(buffB));
            }
        }
Esempio n. 18
0
        public void TestShort()
        {
            short[] specials = new short[] { short.MinValue, -1, 0, 1, short.MaxValue };

            foreach (short special in specials)
            {
                byte[] buffA = new byte[2];
                LittleEndianConverter.GetBytes(buffA, 0, special);

                byte[] buffB = BitConverter.GetBytes(special);

                Assert.IsTrue(buffA.SequenceEqual(buffB));
            }
        }
Esempio n. 19
0
        public void TestULong()
        {
            ulong[] specials = new ulong[] { ulong.MinValue, 1, ulong.MaxValue };

            foreach (ulong special in specials)
            {
                byte[] buffA = new byte[8];
                LittleEndianConverter.GetBytes(buffA, 0, special);

                byte[] buffB = BitConverter.GetBytes(special);

                Assert.IsTrue(buffA.SequenceEqual(buffB));
            }
        }
        public static ModifiedAppointmentInstance CreateNewModifiedInstance(PSTFile file, SubnodeBTree attachmentSubnodeBTree)
        {
            PropertyContext pc = PropertyContext.CreateNewPropertyContext(file);

            pc.SetStringProperty(PropertyID.PidTagMessageClass, RecurringAppointmentExceptionMessageClass);
            pc.SetDateTimeProperty(PropertyID.PidTagCreationTime, DateTime.UtcNow);
            pc.SetDateTimeProperty(PropertyID.PidTagLastModificationTime, DateTime.UtcNow);

            // PidTagSearchKey is apparently a GUID
            pc.SetBytesProperty(PropertyID.PidTagSearchKey, LittleEndianConverter.GetBytes(Guid.NewGuid()));

            pc.SaveChanges();

            NodeID subnodeID = file.Header.AllocateNextNodeID(NodeTypeName.NID_TYPE_NORMAL_MESSAGE);

            attachmentSubnodeBTree.InsertSubnodeEntry(subnodeID, pc.DataTree, pc.SubnodeBTree);

            Subnode subnode = new Subnode(file, subnodeID, pc.DataTree, pc.SubnodeBTree);

            return(new ModifiedAppointmentInstance(subnode));
        }
        public Nullable <float> GetFloat32Property(PropertyID propertyID)
        {
            PropertyContextRecord record = GetRecordByPropertyID(propertyID);

            if (record != null)
            {
                if (record.wPropType == PropertyTypeName.PtypFloating32)
                {
                    byte[] bytes = LittleEndianConverter.GetBytes(record.dwValueHnid);
                    return(LittleEndianConverter.ToFloat32(bytes, 0));
                }
                else
                {
                    throw new InvalidPropertyException("Unexpected PC data type found");
                }
            }
            else
            {
                return(null);
            }
        }
Esempio n. 22
0
        public virtual void Save(byte[] buffer, int offset)
        {
            throw new NotImplementedException();

            // Debug.Assert(buffer.Length - offset >= GetSaveLength());
            // Debug.Assert(offset >= 0);

            LittleEndianConverter.GetBytes(buffer, offset, (uint)Type);

            if (Type == AttributeType.EndOfAttributes)
            {
                return;
            }

            LittleEndianConverter.GetBytes(buffer, offset + 4, TotalLength);
            LittleEndianConverter.GetBytes(buffer, offset + 8, (byte)NonResidentFlag);
            LittleEndianConverter.GetBytes(buffer, offset + 9, NameLength);
            LittleEndianConverter.GetBytes(buffer, offset + 10, OffsetToName);
            LittleEndianConverter.GetBytes(buffer, offset + 12, (ushort)Flags);
            LittleEndianConverter.GetBytes(buffer, offset + 14, Id);

            if (NameLength != 0)
            {
                byte[] stringData = Encoding.Unicode.GetBytes(AttributeName);

                // Debug.Assert(NameLength * 2 == stringData.Length);

                Array.Copy(stringData, 0, buffer, offset + OffsetToName, stringData.Length);
            }

            // Header
            if (NonResidentFlag == ResidentFlag.NonResident)
            {
                NonResidentHeader.Save(buffer, offset + 16);
            }
            else if (NonResidentFlag == ResidentFlag.Resident)
            {
                ResidentHeader.Save(buffer, offset + 16);
            }
        }
Esempio n. 23
0
        public override void Save(byte[] buffer, int offset)
        {
            base.Save(buffer, offset);

            LittleEndianConverter.GetBytes(buffer, offset, CreationTime);
            LittleEndianConverter.GetBytes(buffer, offset + 8, ModifiedTime);
            LittleEndianConverter.GetBytes(buffer, offset + 16, MFTChangeTime);
            LittleEndianConverter.GetBytes(buffer, offset + 24, AccessTime);
            LittleEndianConverter.GetBytes(buffer, offset + 32, (int)DosPermissions);

            LittleEndianConverter.GetBytes(buffer, offset + 36, MaxNumberVersions);
            LittleEndianConverter.GetBytes(buffer, offset + 40, VersionNumber);
            LittleEndianConverter.GetBytes(buffer, offset + 44, ClassId);

            if (OwnerId != 0 || SecurityId != 0 || QuotaCharge != 0 || USN != 0)
            {
                LittleEndianConverter.GetBytes(buffer, offset + 48, OwnerId);
                LittleEndianConverter.GetBytes(buffer, offset + 52, SecurityId);
                LittleEndianConverter.GetBytes(buffer, offset + 56, QuotaCharge);
                LittleEndianConverter.GetBytes(buffer, offset + 64, USN);
            }
        }
Esempio n. 24
0
        public static List <byte[]> EncodeSegmentBuffer(byte[] buffer, int offset, int segmentLength, ushort updateSequenceNumber)
        {
            int           numberOfStrides = segmentLength / BytesPerStride;
            List <byte[]> updateSequenceReplacementData = new List <byte[]>();

            // Read in the bytes that are replaced by the USN
            for (int i = 0; i < numberOfStrides; i++)
            {
                byte[] endOfSectorBytes = new byte[2];
                endOfSectorBytes[0] = buffer[offset + (BytesPerStride * (i + 1)) - 2];
                endOfSectorBytes[1] = buffer[offset + (BytesPerStride * (i + 1)) - 2];
                updateSequenceReplacementData.Add(endOfSectorBytes);
            }

            // Overwrite the bytes that are replaced with the USN
            for (int i = 0; i < updateSequenceReplacementData.Count; i++)
            {
                Array.Copy(LittleEndianConverter.GetBytes(updateSequenceNumber), 0, buffer, offset + (BytesPerStride * (i + 1)) - 2, 2);
            }

            return(updateSequenceReplacementData);
        }
Esempio n. 25
0
        public override void Save(byte[] buffer, int offset)
        {
            base.Save(buffer, offset);

            LittleEndianConverter.GetBytes(buffer, offset, TimeCreated);
            LittleEndianConverter.GetBytes(buffer, offset + 8, TimeModified);
            LittleEndianConverter.GetBytes(buffer, offset + 16, TimeMftModified);
            LittleEndianConverter.GetBytes(buffer, offset + 24, TimeAccessed);
            LittleEndianConverter.GetBytes(buffer, offset + 32, (int)DosPermissions);

            LittleEndianConverter.GetBytes(buffer, offset + 36, MaxmiumVersions);
            LittleEndianConverter.GetBytes(buffer, offset + 40, VersionNumber);
            LittleEndianConverter.GetBytes(buffer, offset + 44, ClassId);

            // TODO: Get the actual NTFS Version in here to check against
            if (OwnerId != 0 || SecurityId != 0 || QuotaCharged != 0 || USN != 0)
            {
                LittleEndianConverter.GetBytes(buffer, offset + 48, OwnerId);
                LittleEndianConverter.GetBytes(buffer, offset + 52, SecurityId);
                LittleEndianConverter.GetBytes(buffer, offset + 56, QuotaCharged);
                LittleEndianConverter.GetBytes(buffer, offset + 64, USN);
            }
        }
        public void Save(byte[] buffer, int offset)
        {
            Debug.Assert(buffer.Length - offset >= GetSaveLength());

            LittleEndianConverter.GetBytes(buffer, offset, StartingVCN);
            LittleEndianConverter.GetBytes(buffer, offset + 8, EndingVCN);
            LittleEndianConverter.GetBytes(buffer, offset + 16, ListOffset);
            LittleEndianConverter.GetBytes(buffer, offset + 18, CompressionUnitSize);
            LittleEndianConverter.GetBytes(buffer, offset + 24, ContentSizeAllocated);
            LittleEndianConverter.GetBytes(buffer, offset + 32, ContentSize);
            LittleEndianConverter.GetBytes(buffer, offset + 40, ContentSizeInitialized);

            if (CompressionUnitSize != 0)
            {
                LittleEndianConverter.GetBytes(buffer, offset + 48, ContentSizeCompressed);
            }

            if (Fragments != null)
            {
                int pointer = ContentSizeCompressed != 0 ? 56 : 48;

                DataFragment.Save(buffer, pointer, Fragments);
            }
        }
 public override byte[] GetSetup()
 {
     return(LittleEndianConverter.GetBytes((ushort)SubcommandName));
 }
Esempio n. 28
0
 /// <summary>
 /// Get file record end marker
 /// </summary>
 public static byte[] GetEndMarker()
 {
     byte[] buffer = new byte[4];
     Array.Copy(LittleEndianConverter.GetBytes(0xFFFFFFFF), buffer, 4);
     return(buffer);
 }
 public override byte[] GetParameters(bool isUnicode)
 {
     return(LittleEndianConverter.GetBytes((ushort)PipeState));
 }
Esempio n. 30
0
        internal static SMB2Command GetQueryInfoResponse(QueryInfoRequest request, ISMBShare share, SMB2ConnectionState state)
        {
            SMB2Session session = state.GetSession(request.Header.SessionID);

            if (request.InfoType == InfoType.File)
            {
                OpenFileObject openFile = session.GetOpenFileObject(request.FileId);
                if (openFile == null)
                {
                    state.LogToServer(Severity.Verbose, "GetFileInformation failed. Invalid FileId. (SessionID: {0}, TreeID: {1}, FileId: {2})", request.Header.SessionID, request.Header.TreeID, request.FileId.Volatile);
                    return(new ErrorResponse(request.CommandName, NTStatus.STATUS_FILE_CLOSED));
                }

                if (share is FileSystemShare)
                {
                    if (!((FileSystemShare)share).HasReadAccess(session.SecurityContext, openFile.Path))
                    {
                        state.LogToServer(Severity.Verbose, "GetFileInformation on '{0}{1}' failed. User '{2}' was denied access.", share.Name, openFile.Path, session.UserName);
                        return(new ErrorResponse(request.CommandName, NTStatus.STATUS_ACCESS_DENIED));
                    }
                }

                FileInformation fileInformation;
                NTStatus        queryStatus = share.FileStore.GetFileInformation(out fileInformation, openFile.Handle, request.FileInformationClass);
                if (queryStatus != NTStatus.STATUS_SUCCESS)
                {
                    state.LogToServer(Severity.Verbose, "GetFileInformation on '{0}{1}' failed. Information class: {2}, NTStatus: {3}. (FileId: {4})", share.Name, openFile.Path, request.FileInformationClass, queryStatus, request.FileId.Volatile);
                    return(new ErrorResponse(request.CommandName, queryStatus));
                }

                state.LogToServer(Severity.Information, "GetFileInformation on '{0}{1}' succeeded. Information class: {2}. (FileId: {3})", share.Name, openFile.Path, request.FileInformationClass, request.FileId.Volatile);
                QueryInfoResponse response = new QueryInfoResponse();
                response.SetFileInformation(fileInformation);
                return(response);
            }
            else if (request.InfoType == InfoType.FileSystem)
            {
                if (share is FileSystemShare)
                {
                    if (!((FileSystemShare)share).HasReadAccess(session.SecurityContext, @"\"))
                    {
                        state.LogToServer(Severity.Verbose, "GetFileSystemInformation on '{0}' failed. User '{1}' was denied access.", share.Name, session.UserName);
                        return(new ErrorResponse(request.CommandName, NTStatus.STATUS_ACCESS_DENIED));
                    }

                    FileSystemInformation fileSystemInformation;
                    NTStatus queryStatus = share.FileStore.GetFileSystemInformation(out fileSystemInformation, request.FileSystemInformationClass);
                    if (queryStatus != NTStatus.STATUS_SUCCESS)
                    {
                        state.LogToServer(Severity.Verbose, "GetFileSystemInformation on '{0}' failed. Information class: {1}, NTStatus: {2}", share.Name, request.FileSystemInformationClass, queryStatus);
                        return(new ErrorResponse(request.CommandName, queryStatus));
                    }

                    state.LogToServer(Severity.Information, "GetFileSystemInformation on '{0}' succeeded. Information class: {1}", share.Name, request.FileSystemInformationClass);
                    QueryInfoResponse response = new QueryInfoResponse();
                    response.SetFileSystemInformation(fileSystemInformation);
                    return(response);
                }
            }
            else if (request.InfoType == InfoType.Security)
            {
                OpenFileObject openFile = session.GetOpenFileObject(request.FileId);
                if (openFile == null)
                {
                    state.LogToServer(Severity.Verbose, "GetSecurityInformation failed. Invalid FileId. (SessionID: {0}, TreeID: {1}, FileId: {2})", request.Header.SessionID, request.Header.TreeID, request.FileId.Volatile);
                    return(new ErrorResponse(request.CommandName, NTStatus.STATUS_FILE_CLOSED));
                }

                if (share is FileSystemShare)
                {
                    if (!((FileSystemShare)share).HasReadAccess(session.SecurityContext, openFile.Path))
                    {
                        state.LogToServer(Severity.Verbose, "GetSecurityInformation on '{0}{1}' failed. User '{2}' was denied access.", share.Name, openFile.Path, session.UserName);
                        return(new ErrorResponse(request.CommandName, NTStatus.STATUS_ACCESS_DENIED));
                    }
                }

                SecurityDescriptor securityDescriptor;
                NTStatus           queryStatus = share.FileStore.GetSecurityInformation(out securityDescriptor, openFile.Handle, request.SecurityInformation);
                if (queryStatus != NTStatus.STATUS_SUCCESS)
                {
                    state.LogToServer(Severity.Verbose, "GetSecurityInformation on '{0}{1}' failed. Security information: 0x{2}, NTStatus: {3}. (FileId: {4})", share.Name, openFile.Path, request.SecurityInformation.ToString("X"), queryStatus, request.FileId.Volatile);
                    return(new ErrorResponse(request.CommandName, queryStatus));
                }

                if (securityDescriptor.Length > request.OutputBufferLength)
                {
                    state.LogToServer(Severity.Information, "GetSecurityInformation on '{0}{1}' failed. Security information: 0x{2}, NTStatus: STATUS_BUFFER_TOO_SMALL. (FileId: {3})", share.Name, openFile.Path, request.SecurityInformation.ToString("X"), request.FileId.Volatile);
                    byte[] errorData = LittleEndianConverter.GetBytes((uint)securityDescriptor.Length);
                    return(new ErrorResponse(request.CommandName, NTStatus.STATUS_BUFFER_TOO_SMALL, errorData));
                }

                state.LogToServer(Severity.Information, "GetSecurityInformation on '{0}{1}' succeeded. Security information: 0x{2}. (FileId: {3})", share.Name, openFile.Path, request.SecurityInformation.ToString("X"), request.FileId.Volatile);
                QueryInfoResponse response = new QueryInfoResponse();
                response.SetSecurityInformation(securityDescriptor);
                return(response);
            }
            return(new ErrorResponse(request.CommandName, NTStatus.STATUS_NOT_SUPPORTED));
        }