예제 #1
0
        private int GetNullTerminatedUnicodeStringLength(WspBuffer buffer, int startOffset)
        {
            int length = 0;

            while (buffer.Peek <ushort>(startOffset) != 0)
            {
                startOffset += 2;
                length      += 2;
            }

            return(length);
        }
예제 #2
0
        private object ReadValueByType(CBaseStorageVariant_vType_Values vType, int valueOffset, WspBuffer buffer)
        {
            if (vType.HasFlag(CBaseStorageVariant_vType_Values.VT_VECTOR) || vType.HasFlag(CBaseStorageVariant_vType_Values.VT_ARRAY))
            {
                throw new NotImplementedException();
            }

            object value = null;

            switch (vType)
            {
            case CBaseStorageVariant_vType_Values.VT_EMPTY:
            case CBaseStorageVariant_vType_Values.VT_NULL:
                break;

            case CBaseStorageVariant_vType_Values.VT_I1:
                value = buffer.Peek <sbyte>(valueOffset);
                break;

            case CBaseStorageVariant_vType_Values.VT_UI1:
                value = buffer.Peek <byte>(valueOffset);
                break;

            case CBaseStorageVariant_vType_Values.VT_I2:
                value = buffer.Peek <short>(valueOffset);
                break;

            case CBaseStorageVariant_vType_Values.VT_UI2:
            case CBaseStorageVariant_vType_Values.VT_BOOL:
                value = buffer.Peek <ushort>(valueOffset);
                break;

            case CBaseStorageVariant_vType_Values.VT_I4:
            case CBaseStorageVariant_vType_Values.VT_INT:
                value = buffer.Peek <int>(valueOffset);
                break;

            case CBaseStorageVariant_vType_Values.VT_R4:
                value = buffer.Peek <float>(valueOffset);
                break;

            case CBaseStorageVariant_vType_Values.VT_UI4:
            case CBaseStorageVariant_vType_Values.VT_UINT:
            case CBaseStorageVariant_vType_Values.VT_ERROR:
                value = buffer.Peek <uint>(valueOffset);
                break;

            case CBaseStorageVariant_vType_Values.VT_I8:
                value = buffer.Peek <long>(valueOffset);
                break;

            case CBaseStorageVariant_vType_Values.VT_UI8:
                value = buffer.Peek <ulong>(valueOffset);
                break;

            case CBaseStorageVariant_vType_Values.VT_R8:
                value = buffer.Peek <double>(valueOffset);
                break;

            case CBaseStorageVariant_vType_Values.VT_CY:     // An 8-byte two's complement integer (vValue divided by 10,000).
                throw new NotImplementedException();

            case CBaseStorageVariant_vType_Values.VT_DATE:
                value = DateTime.FromOADate(buffer.Peek <double>(valueOffset)).ToUniversalTime();
                break;

            case CBaseStorageVariant_vType_Values.VT_FILETIME:
                value = DateTime.FromFileTime(buffer.Peek <long>(valueOffset)).ToUniversalTime();
                break;

            case CBaseStorageVariant_vType_Values.VT_DECIMAL:
                value = buffer.Peek <DECIMAL>(valueOffset);
                break;

            case CBaseStorageVariant_vType_Values.VT_CLSID:
                value = buffer.Peek <Guid>(valueOffset);
                break;

            case CBaseStorageVariant_vType_Values.VT_BLOB:     // A 4-byte unsigned integer count of bytes in the blob, followed by that many bytes of data.
            case CBaseStorageVariant_vType_Values.VT_BLOB_OBJECT:
                int blobSize = buffer.Peek <int>(valueOffset);
                value = buffer.ReadBytesFromOffset(valueOffset + 4, blobSize);
                break;

            case CBaseStorageVariant_vType_Values.VT_BSTR:
                int strSize = buffer.Peek <int>(valueOffset);
                var bytes   = buffer.ReadBytesFromOffset(valueOffset + 4, strSize);

                // TODO: Just use UTF8 for a temporary solution
                // For vType set to VT_BSTR, this field is a set of characters in an OEM–selected character set.
                // The client and server MUST be configured to have interoperable character sets.
                // There is no requirement that it be null-terminated.
                value = System.Text.Encoding.UTF8.GetString(bytes, 0, bytes.Length);
                break;

            case CBaseStorageVariant_vType_Values.VT_LPSTR:
                throw new NotImplementedException();

            case CBaseStorageVariant_vType_Values.VT_LPWSTR:
                int strLength = GetNullTerminatedUnicodeStringLength(buffer, valueOffset);
                value = System.Text.Encoding.Unicode.GetString(buffer.ReadBytesFromOffset(valueOffset, strLength), 0, strLength);
                break;

            case CBaseStorageVariant_vType_Values.VT_COMPRESSED_LPWSTR:
                value = buffer.Peek <VT_COMPRESSED_LPWSTR>(valueOffset);
                break;
            }

            return(value);
        }
예제 #3
0
        public void FromBytes(WspBuffer buffer)
        {
            var header = new WspMessageHeader();

            var initialReadOffset = buffer.ReadOffset;

            header.FromBytes(buffer);
            Header = header;

            // Do not parse message body if the status in header is not success.
            if (header._status != (uint)WspErrorCode.SUCCESS && header._status != (uint)WspErrorCode.DB_S_ENDOFROWSET && header._status != (uint)WspErrorCode.DB_S_DIALECTIGNORED)
            {
                return;
            }

            _cRowsReturned = buffer.ToStruct <uint>();

            eType = buffer.ToStruct <RowSeekType>();

            _chapt = buffer.ToStruct <uint>();

            switch (eType)
            {
            case RowSeekType.eRowSeekNone:
                SeekDescription = null;
                break;

            case RowSeekType.eRowSeekNext:
                SeekDescription = buffer.ToStruct <CRowSeekNext>();
                break;

            case RowSeekType.eRowSeekAt:
                SeekDescription = buffer.ToStruct <CRowSeekAt>();
                break;

            case RowSeekType.eRowSeekAtRatio:
                SeekDescription = buffer.ToStruct <CRowSeekAtRatio>();
                break;

            case RowSeekType.eRowSeekByBookmark:
                var tempSeekDescription = new CRowSeekByBookmark();
                tempSeekDescription.FromBytes(buffer);
                SeekDescription = tempSeekDescription;
                break;
            }

            int rowStartIndex = initialReadOffset + (int)((CPMGetRowsIn)Request)._cbReserved;
            int paddingSize   = rowStartIndex - buffer.ReadOffset;

            paddingRows = buffer.ReadBytes(paddingSize);

            rowStartIndex = buffer.ReadOffset;
            Rows          = new Row[_cRowsReturned];
            uint cColumns = BindingRequest.cColumns;

            for (int i = 0; i < _cRowsReturned; i++)
            {
                Rows[i].Columns = new Column[cColumns];

                for (int j = 0; j < cColumns; j++)
                {
                    if (BindingRequest.aColumns[j].StatusOffset != null)
                    {
                        Rows[i].Columns[j].Status = (StoreStatus)buffer.Peek <byte>(rowStartIndex + BindingRequest.aColumns[j].StatusOffset.Value);
                    }

                    if (BindingRequest.aColumns[j].LengthOffset != null)
                    {
                        Rows[i].Columns[j].Length = buffer.Peek <byte>(rowStartIndex + BindingRequest.aColumns[j].LengthOffset.Value);
                    }

                    if (BindingRequest.aColumns[j].ValueOffset != null)
                    {
                        int valueOffset = rowStartIndex + BindingRequest.aColumns[j].ValueOffset.Value;

                        if (BindingRequest.aColumns[j].vType == CBaseStorageVariant_vType_Values.VT_VARIANT)
                        {
                            Rows[i].Columns[j].RowVariant         = new CTableVariant();
                            Rows[i].Columns[j].RowVariant.Is64bit = this.Is64Bit;
                            WspBuffer rowVariantBuffer = new WspBuffer(buffer.ReadBytesFromOffset(valueOffset, BindingRequest.aColumns[j].ValueSize.Value));
                            Rows[i].Columns[j].RowVariant.FromBytes(rowVariantBuffer);

                            if (Rows[i].Columns[j].RowVariant.vType == CBaseStorageVariant_vType_Values.VT_LPWSTR)
                            {
                                int dataOffset = GetRealOffset(Rows[i].Columns[j].RowVariant.Offset);
                                Rows[i].Columns[j].Data = ReadValueByType(Rows[i].Columns[j].RowVariant.vType, dataOffset, buffer);
                            }
                            else if (Rows[i].Columns[j].RowVariant.vType.HasFlag(CBaseStorageVariant_vType_Values.VT_VECTOR))
                            {
                                var baseVType   = Rows[i].Columns[j].RowVariant.vType ^ CBaseStorageVariant_vType_Values.VT_VECTOR;
                                var vectorCount = Rows[i].Columns[j].RowVariant.Count;
                                if (baseVType == CBaseStorageVariant_vType_Values.VT_LPWSTR)
                                {
                                    var startOffset = GetRealOffset(Rows[i].Columns[j].RowVariant.Offset);
                                    var items       = new List <string>();
                                    for (var idx = 0; idx < vectorCount; idx++)
                                    {
                                        WspBuffer offsetBuffer;
                                        int       itemOffset;
                                        if (Is64Bit)
                                        {
                                            offsetBuffer = new WspBuffer(buffer.ReadBytesFromOffset(startOffset + idx * 8, 8));
                                            itemOffset   = GetRealOffset(offsetBuffer.ToStruct <long>());
                                        }
                                        else
                                        {
                                            offsetBuffer = new WspBuffer(buffer.ReadBytesFromOffset(startOffset + idx * 4, 4));
                                            itemOffset   = GetRealOffset(offsetBuffer.ToStruct <int>());
                                        }

                                        var item = ReadValueByType(CBaseStorageVariant_vType_Values.VT_LPWSTR, itemOffset, buffer) as string;
                                        items.Add(item);
                                    }

                                    Rows[i].Columns[j].Data = items.ToArray();
                                }
                                else if (baseVType == CBaseStorageVariant_vType_Values.VT_FILETIME)
                                {
                                    var startOffset = GetRealOffset(Rows[i].Columns[j].RowVariant.Offset);
                                    var items       = new List <object>();
                                    for (var idx = 0; idx < vectorCount; idx++)
                                    {
                                        var item = ReadValueByType(CBaseStorageVariant_vType_Values.VT_FILETIME, startOffset, buffer);
                                        startOffset += 8; // VT_FILETIME is a 64-bit value
                                        items.Add(item);
                                    }

                                    Rows[i].Columns[j].Data = items.ToArray();
                                }
                                else
                                {
                                    throw new NotImplementedException();
                                }
                            }
                            else
                            {
                                // If the type is not a string, the offset field saves the actual data.
                                Rows[i].Columns[j].Data = ReadValueByType(Rows[i].Columns[j].RowVariant.vType, 8, rowVariantBuffer);
                            }
                        }
                        else
                        {
                            Rows[i].Columns[j].Data = ReadValueByType(BindingRequest.aColumns[j].vType, valueOffset, buffer);
                        }
                    }
                }

                rowStartIndex += (int)((CPMGetRowsIn)Request)._cbRowWidth;
            }
        }