Code:
/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / infocard / Service / managed / Microsoft / InfoCards / IndexedDataBuffer.cs / 1 / IndexedDataBuffer.cs
//------------------------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. //----------------------------------------------------------------------------- namespace Microsoft.InfoCards { using System; using System.ComponentModel; using System.Collections; using System.IO; using System.Runtime.InteropServices; using System.Security; using System.Security.Cryptography; using IDT = Microsoft.InfoCards.Diagnostics.InfoCardTrace; // // Summary: // Internal FileStore class for managing data blobs // the the master index offsets (LocalIds) // internal unsafe class IndexedDataBuffer { byte[] m_buffer; byte[] m_masterIndex; FreeIndexList m_freeList; Int32 m_dataLength; bool m_isOpen; DataSource m_owner; // // Summary: // Creates an IndexedDataBuffer class using the specified data // // Parameters: // masterIndex: the buffer to use as the initial masterIndex // buffer: the buffer to use as the initial data buffer // dataLength: the length of the data used in the data buffer // public IndexedDataBuffer( byte[] masterIndex, byte[] buffer, Int32 dataLength, DataSource owner ) { if( null == masterIndex || 0 == masterIndex.Length ) { throw IDT.ThrowHelperArgumentNull( "masterIndex", SR.GetString( SR.StoreIndexedDataBufferNullOrEmptyMasterIndexBuffer ) ); } if( null == buffer || 0 == buffer.Length ) { throw IDT.ThrowHelperArgumentNull( "buffer", SR.GetString( SR.StoreIndexedDataBufferNullOrEmptyDataIndexBuffer ) ); } if( dataLength < 0 || dataLength > buffer.Length ) { throw IDT.ThrowHelperError( new ArgumentOutOfRangeException( "dataLength", dataLength, SR.GetString( SR.StoreIndexDataBufferDataLengthOutOfRange ) ) ); } m_owner = owner; m_masterIndex = masterIndex; m_buffer = buffer; m_dataLength = dataLength; m_freeList = new FreeIndexList( 20 ); fixed( byte* pIndexBuffer = &m_masterIndex[ 0 ] ) { Int32* pIndex = (Int32*)pIndexBuffer; for( int i = 1; i < m_masterIndex.Length / sizeof( Int32 ); i++ ) { if( pIndex[ i ] <= 0 ) { m_freeList.Put( i ); } } } m_isOpen = true; } // // Summary: // Gets a pointer to the internal buffer used to managed the offerts. // // Remarks: // This is intended for use by tools // public byte[] Index { get { ThrowIfNotOpen( ); return m_masterIndex; } } // // Summary: // Gets a pointer to the internal buffer containing the data blobs. // // Remarks: // This is intended for use by tools // public byte[] Data { get { ThrowIfNotOpen( ); return m_buffer; } } // // Summary: // The amount of data being actively used by data blobs // public Int32 DataLength { get { ThrowIfNotOpen( ); return m_dataLength; } } // // Summary: // Closes and clears all open resources // public void Close() { ThrowIfNotOpen( ); Clear( ); m_buffer = null; m_masterIndex = null; m_isOpen = false; } // // Summary: // Creates a datarow using the specified local Id. // This data row only contains the header information from the row. // // Parameters: // id: The localId to use to get the object information. // owner: The owning datasource for the object. // // Returns: // The data row with header information // public DataRow CreateDataRow( Int32 id ) { ThrowIfNotOpen( ); if( id > m_masterIndex.Length / sizeof( Int32 ) || m_freeList.Contains( id ) ) { throw IDT.ThrowHelperError( new ArgumentOutOfRangeException( "id", id, SR.GetString( SR.StoreLocalIdOutOfRange ) ) ); } Int32 offset = GetOffset( ref id ); fixed( byte* pBuffer = &m_buffer[ offset ] ) { return DataRow.Create( (EncryptedObjectHeader*)pBuffer,m_owner ); } } // // Summary: // Copies the IV of a data object to the specified buffer // // Remarks: // // Parameters: // id: The localid of the object to get the IV from // iv: The output buffer to copy the IV to. // index: The index in the output buffer to start the copy // public void CopyIVFromObject( Int32 id, byte[] iv, int index ) { ThrowIfNotOpen( ); if( null == iv || 0 == iv.Length ) { throw IDT.ThrowHelperArgumentNull( "iv" ); } if( index < 0 || index > ( this.DataLength - iv.Length ) ) { throw IDT.ThrowHelperError( new ArgumentOutOfRangeException( "index", index, SR.GetString( SR.StoreIndexDataBufferIndexOutOfRange ) ) ); } if( id > m_masterIndex.Length / sizeof( Int32 ) || m_freeList.Contains( id ) ) { throw IDT.ThrowHelperError( new ArgumentOutOfRangeException( "id", id, SR.GetString( SR.StoreLocalIdOutOfRange ) ) ); } Int32 offset = GetOffset( ref id ); IDT.Assert( id >= 0, "Invalid ID was returned by GetOffset." ); fixed( byte* pBuffer = &m_buffer[ offset ] ) { EncryptedObjectHeader* pObj = (EncryptedObjectHeader*)pBuffer; Marshal.Copy( new IntPtr( &pObj->IV ), //source iv, //dest 0, //offset iv.Length ); //size } } // // Summary: // Returns a readonly stream for the data object. // // Remarks: // The return value is only valid if no other store change have occured. If // the unlerlying buffer get changed, this could return the wrong information. // // Parameters: // id: The localId to get the data stream for // // Returns: // Read-Only Stream/Private stream bound to the data in the data buffer. // public Stream GetStreamForObjectData( Int32 id ) { ThrowIfNotOpen( ); if( id > m_masterIndex.Length / sizeof( Int32 ) || m_freeList.Contains( id ) ) { throw IDT.ThrowHelperError( new ArgumentOutOfRangeException( "id", id, SR.GetString( SR.StoreLocalIdOutOfRange ) ) ); } Int32 offset = GetOffset( ref id ); IDT.Assert( id >= 0, "Invalid ID was returned by GetOffset." ); Int32 length = GetObjectDataSize( offset ); IDT.Assert( length <= ( m_buffer.Length - offset ), "The length the stored object is invalid" ); return new MemoryStream( m_buffer, offset + sizeof( EncryptedObjectHeader ), length, false, false ); } // // Summary: // Removes an object from the data source. // // Parameters: // id: The localId for the object you want to remove // public void RemoveObject( Int32 id ) { ThrowIfNotOpen( ); // // If it is beyond our rage, or it is part of our free list, // it is invalid. // if( id > m_masterIndex.Length / sizeof( Int32 ) || m_freeList.Contains( id ) ) { throw IDT.ThrowHelperError( new ArgumentOutOfRangeException( "id", id, SR.GetString( SR.StoreLocalIdOutOfRange ) ) ); } Int32 offset = GetOffset( ref id ); IDT.Assert( id >= 0, "Invalid ID was returned by GetOffset." ); RemoveFromMasterIndex(id); EnsureSpaceForData( offset, 0 ); } // // Summary: // Write the provided data to the data blob. // // Remarks: // // Parameters: // id: The local ID you want to get write to. // iv: The value of the IV Field to save // data: The raw data blob to save // objectType: The object type field to save // lastChange: The lastChange field to save // globalId: The globalId field to save. // public Int32 WriteObject( Int32 id, byte[] iv, byte[] data, Int32 objectType, Int64 lastChange, GlobalId globalId ) { ThrowIfNotOpen( ); if( null == iv || 0 == iv.Length ) { throw IDT.ThrowHelperArgumentNull( "iv" ); } if( null == data || 0 == data.Length ) { throw IDT.ThrowHelperArgumentNull( "iv" ); } if( id > m_masterIndex.Length / sizeof( Int32 ) ) { throw IDT.ThrowHelperError( new ArgumentOutOfRangeException( "id", id, SR.GetString( SR.StoreLocalIdOutOfRange ) ) ); } if( id > 0 && m_freeList.Contains( id ) ) { throw IDT.ThrowHelperError( new ArgumentOutOfRangeException( "id", id, SR.GetString( SR.StoreLocalIdOutOfRange ) ) ); } Int32 offset = GetOffset( ref id ); IDT.Assert( id >= 0, "Invalid ID was returned by GetOffset." ); Int32 size = EnsureSpaceForData( offset, data.Length ); fixed( byte* pBuffer = &m_buffer[ offset ] ) { EncryptedObjectHeader* pObj = (EncryptedObjectHeader*)pBuffer; byte* pData = (byte*)( pObj + 1 ); // // Capture the input // pObj->LastChange = lastChange; // // Because decryption of this blob requires the exact size, not // the rounded-up size provided, we must write the actual length, // and round up next time we need the value. // pObj->DataSize = data.Length; pObj->ObjectType = objectType; pObj->LocalId = id; pObj->GlobalId = globalId; IDT.Assert( iv.Length <= EncryptedObjectHeader.IVBlockSize, "IV Length is invalid" ); // //copy in the IV // Marshal.Copy( iv, //source 0, //source index new IntPtr( &pObj->IV ), //desination ptr iv.Length ); //size to copy // // Copy in the data // Marshal.Copy( data, //source 0, //source index new IntPtr( pData ), //destination ptr data.Length ); //size to copy } return id; } // // Summary: // Gets the data size field from object at the specified offset // // Remarks: // // Parameters: // offset: The offset in the data buffer where the EncryptedObjectHeader begins. // // Returns: // Retunrs the size field of the object. // private Int32 GetObjectDataSize( Int32 offset ) { fixed( byte* pBuffer = &m_buffer[ offset ] ) { EncryptedObjectHeader* pObj = (EncryptedObjectHeader*)pBuffer; return pObj->DataSize; } } // // Summary: // Clears all buffers, and set the length to 0 // private void Clear() { Array.Clear( this.m_buffer, 0, m_dataLength ); Array.Clear( m_masterIndex, 0, m_masterIndex.Length ); m_dataLength = 0; } // // Summary: // Shift,Moves, and manipulates the internal data buffer // to ensure that the all data can be written correctly. // // Remarks: // // Parameters: // offset: The offset to place the object. // datasize: The requested data size. // // Returns: // the new space for the object // private Int32 EnsureSpaceForData( Int32 offset, Int32 dataSize ) { IDT.Assert( (UInt32)offset <= (UInt32)m_dataLength, "offset specified is outside the range of the data buffer" ); IDT.Assert( dataSize >= 0, "The requested data size must be greater than or equal to 0" ); Int32 objRequiredSpace = 0; Int32 currentSize = 0; Int32 nextIndex = 0; Int32 nextNewIndex = 0; Int32 newSizeDiff = 0; // // Data size can be 0 in the case of a delete. // if( dataSize != 0 ) { objRequiredSpace = dataSize + sizeof( EncryptedObjectHeader ); } // // Ensure the data will align // if( 0 != ( objRequiredSpace % 8 ) ) { objRequiredSpace += 8 - ( objRequiredSpace % 8 ); } // // This is an insert // if( offset == m_dataLength ) { currentSize = 0; } else { fixed( byte* pBuffer = &m_buffer[ offset ] ) { EncryptedObjectHeader* pHeader = (EncryptedObjectHeader*)pBuffer; currentSize = pHeader->DataSize + sizeof( EncryptedObjectHeader ); // // Because Decryption of the data requires the exact number of bytes // that was encrypted, we must re-round the size to the neareast 8 bytes // as we do above. // if( 0 != ( currentSize % 8 ) ) { currentSize += 8 - ( currentSize % 8 ); } } } IDT.Assert( currentSize <= m_dataLength, "currentSize can not be more " ); if( currentSize == objRequiredSpace ) { return objRequiredSpace; } nextIndex = offset + currentSize; newSizeDiff = objRequiredSpace - currentSize; nextNewIndex = nextIndex + newSizeDiff; // // If we are growing, // and the new length exceeds our size, grow // if( newSizeDiff > 0 && m_dataLength + newSizeDiff >= m_buffer.Length ) { GrowBuffer( ( m_dataLength + newSizeDiff ) ); } IDT.Assert( (UInt32)nextIndex <= (UInt32)m_buffer.Length && nextIndex >= offset, "NextIndex value is corrupt when attempting to ensure space for object" ); IDT.Assert( (UInt32)nextNewIndex <= (UInt32)m_buffer.Length, "NextNewIndex value is corrupt when attempting to ensure space for object" ); // // If we are not at the end of the list // if( m_dataLength != nextIndex ) { IDT.Assert( m_dataLength - nextIndex > 0, "NextIndex data is corrupt when attempting to ensure space for object in middle of content." ); Array.Copy( m_buffer, nextIndex, m_buffer, nextNewIndex, m_dataLength - nextIndex ); m_dataLength += newSizeDiff; IDT.Assert( m_dataLength >= 0, "DataLength has been corrupted." ); // // if this was as removal of space // if( newSizeDiff < 0 ) { IDT.Assert( m_dataLength <= m_buffer.Length, "DataLength is larger than allocated buffer." ); Array.Clear( m_buffer, m_dataLength, Math.Abs( newSizeDiff ) ); } // // Take the lowest of the two numbers, // and use that for the index update calculation. // UpdateMasterIndex( Math.Min( nextIndex, nextNewIndex ), newSizeDiff ); } else { m_dataLength += newSizeDiff; } IDT.Assert( m_dataLength <= m_buffer.Length, "DataLength is larger than allocated buffer." ); return objRequiredSpace; } // // Summary: // Grows the buffer used for the master index by 5% // private void GrowMasterIndex() { // // If the free list is exhaused, we must need // to grow our list. // int count = m_masterIndex.Length / sizeof( Int32 ); int newSize = Utility.CalculateIncreaseByPercent( m_masterIndex.Length, sizeof( Int32 ), 5 ); IDT.Assert( newSize > m_masterIndex.Length, "NewSize must be greater than old size to grow master index buffer" ); byte[] newIndex = new byte[ newSize ]; Array.Copy( m_masterIndex, 0, newIndex, 0, m_masterIndex.Length ); Array.Clear( m_masterIndex, 0, m_masterIndex.Length ); m_masterIndex = newIndex; int newCount = m_masterIndex.Length / sizeof( Int32 ); for( int j = count + 1; j < ( newCount ); j++ ) { m_freeList.Put( j ); } } // // Summary: // Grows the buffer used for data object by 5% // private void GrowBuffer( int spaceRequired ) { IDT.Assert( spaceRequired >= m_buffer.Length, "RequireSpace must be greater than old size to grow data buffer" ); int newLength = spaceRequired; newLength += newLength / 20;//grow by 5% IDT.Assert( newLength >= spaceRequired, "NewLength must be greater than required space to grow data buffer" ); byte[] newBuffer = new byte[ newLength ]; Array.Copy( m_buffer, 0, newBuffer, 0, m_buffer.Length ); Array.Clear( m_buffer, 0, m_buffer.Length ); m_buffer = newBuffer; IDT.Assert( m_dataLength <= m_buffer.Length, "DataLength Corrupt or buffer growth failed." ); } // // Summary: // Gets of offset in the data buffer for the specified LocalId // // Remarks: // // Parameters: // ref id: pointer to the ID to use. If <= 0 specfied, will be updated with new id. // // Returns: // returns the offset in the data buffer that the id param points to when the method returns. // private Int32 GetOffset( ref Int32 id ) { Int32 offset; if( id <= 0 ) { if( m_dataLength <= 0 ) { // // Could use IntPtr.Size too but that would make // store format different on different architectures // m_dataLength = sizeof( Int64 ); } offset = m_dataLength; id = GetNextLocalId( offset ); return offset; } else { fixed( byte* pIndexBuffer = &m_masterIndex[ 0 ] ) { Int32* pIndex = (Int32*)pIndexBuffer; IDT.Assert( pIndex[ id ] >= 0, "Master Index offset value is invalid" ); return pIndex[ id ]; } } } // // Summary: // Removes the specified localId from the masterIndex // // Remarks: // // Parameters: // id: LocalId to remove from the master index. // private void RemoveFromMasterIndex( Int32 id ) { IDT.Assert( id > 0, "LocalId is invalid" ); fixed( byte* pIndexBuffer = &m_masterIndex[ 0 ] ) { Int32* pIndex = (Int32*)pIndexBuffer; pIndex[ id ] = 0; m_freeList.Put( id ); } } // // Summary: // Updates the master index with data shift information. // // Remarks: // for each item in the index who's offset would be changed // we update them by adding the difference. // // Parameters: // offset: the base offset to start from // diff: the difference to add to all changed values // private void UpdateMasterIndex( Int32 offset, Int32 diff ) { IDT.Assert( offset > 0, "Offset is invalid" ); IDT.Assert( diff != 0, "Difference is invalid" ); int count = m_masterIndex.Length / sizeof( Int32 ); fixed( byte* pIndexBuffer = &m_masterIndex[ 0 ] ) { Int32* pIndex = (Int32*)pIndexBuffer; // // Loop through the index items. // starting with item 1, becuase 0 is invalid. // for( int i = 1; i < count; i++ ) { IDT.Assert( ( &pIndex[ i ] - pIndex ) <= m_masterIndex.Length, "Pointer has walked past the end of the allocated buffer."); if( pIndex[ i ] > 0 && pIndex[ i ] >= offset ) { pIndex[ i ] += diff; } } } } // // Summary: // Gets the next localId available for use. // // Remarks: // // Parameters: // offset: offset to assign to the localId when returned // // Returns: // The new localId that was assigned the offset. // private Int32 GetNextLocalId( Int32 offset ) { IDT.Assert( offset >= 0, "The offset can not be negative." ); Int32 i = m_freeList.GetNext( ); // // If the free list didn't contain a match. // if( i > 0 ) { IDT.Assert( null != m_masterIndex, "m_masterIndex must not be null by now" ); IDT.Assert( m_masterIndex.Length > 0, "m_masterIndex must not be empty." ); fixed( byte* pIndexBuffer = &m_masterIndex[ 0 ] ) { Int32* pIndex = (Int32*)pIndexBuffer; pIndex[ i ] = offset; return i; } } int count = m_masterIndex.Length / sizeof( Int32 ); GrowMasterIndex( ); int newCount = m_masterIndex.Length / sizeof( Int32 ); IDT.Assert( newCount > count && count > 0, "Calculated count is corrupt or invalid."); // // Set the item and return // the index of that item. // fixed( byte* pIndexBuffer = &m_masterIndex[ 0 ] ) { Int32* pIndex = (Int32*)pIndexBuffer; pIndex[ count ] = offset; } return count; } public void ThrowIfNotOpen() { if( !m_isOpen ) throw IDT.ThrowHelperError( new ObjectDisposedException( "IndexedDataBuffer" ) ); } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- AlphabetConverter.cs
- Int64.cs
- PathFigure.cs
- HttpListenerResponse.cs
- QueryMath.cs
- DrawingContextDrawingContextWalker.cs
- ErrorHandler.cs
- LinqDataSourceDeleteEventArgs.cs
- graph.cs
- ValueType.cs
- IntPtr.cs
- RelationshipManager.cs
- Compilation.cs
- CodeDirectionExpression.cs
- XamlToRtfParser.cs
- ComplexObject.cs
- ProviderCollection.cs
- DataGridViewColumnConverter.cs
- ThreadStartException.cs
- HostExecutionContextManager.cs
- ReadOnlyCollection.cs
- DataGridViewCellLinkedList.cs
- UrlParameterWriter.cs
- ColorTransformHelper.cs
- ObjectSpanRewriter.cs
- PasswordTextNavigator.cs
- WebPartEventArgs.cs
- InvokeGenerator.cs
- BatchServiceHost.cs
- ClientTargetCollection.cs
- ResXBuildProvider.cs
- ObjectViewQueryResultData.cs
- PackagingUtilities.cs
- Effect.cs
- TextDecorations.cs
- RSAPKCS1KeyExchangeDeformatter.cs
- ComponentDispatcher.cs
- ImmutableObjectAttribute.cs
- SecurityCriticalDataForSet.cs
- ImportDesigner.xaml.cs
- Model3DCollection.cs
- RSAPKCS1KeyExchangeDeformatter.cs
- ServiceNameElement.cs
- ConfigXmlReader.cs
- Native.cs
- WebPartDescriptionCollection.cs
- DNS.cs
- QuaternionAnimation.cs
- UseLicense.cs
- HtmlTableCellCollection.cs
- ScrollData.cs
- SvcFileManager.cs
- Tuple.cs
- CharKeyFrameCollection.cs
- CommandValueSerializer.cs
- Point3DAnimationBase.cs
- DbModificationCommandTree.cs
- ArgumentNullException.cs
- PeerCustomResolverBindingElement.cs
- SimpleHandlerFactory.cs
- Geometry.cs
- FrameworkContentElement.cs
- MetadataPropertyAttribute.cs
- QilFunction.cs
- CreateWorkflowOwnerCommand.cs
- ViewKeyConstraint.cs
- TextDataBindingHandler.cs
- FocusTracker.cs
- WhitespaceRuleLookup.cs
- ProcessingInstructionAction.cs
- InvokePattern.cs
- ImmComposition.cs
- XamlSerializerUtil.cs
- GcHandle.cs
- DropShadowBitmapEffect.cs
- VerificationAttribute.cs
- SoapMessage.cs
- ContainerControlDesigner.cs
- FontSourceCollection.cs
- Menu.cs
- Matrix.cs
- LexicalChunk.cs
- ToolBarButton.cs
- Button.cs
- BaseProcessor.cs
- ProviderBase.cs
- FormsAuthenticationConfiguration.cs
- CollectionBuilder.cs
- EncoderParameters.cs
- AsymmetricKeyExchangeFormatter.cs
- AnnotationResource.cs
- ClientFormsAuthenticationCredentials.cs
- BufferedStream.cs
- Transform3DCollection.cs
- Main.cs
- GradientStop.cs
- ProjectionPruner.cs
- PathTooLongException.cs
- TextServicesLoader.cs
- WebPartDisplayModeEventArgs.cs