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
- ProcessInputEventArgs.cs
- UnknownBitmapEncoder.cs
- TreeNodeCollectionEditor.cs
- CompositionAdorner.cs
- _LazyAsyncResult.cs
- XPathChildIterator.cs
- VariableAction.cs
- ComponentChangedEvent.cs
- CancellationHandlerDesigner.cs
- FactoryMaker.cs
- GenericTypeParameterBuilder.cs
- Queue.cs
- GridViewCommandEventArgs.cs
- XmlTextEncoder.cs
- Crc32.cs
- CodeChecksumPragma.cs
- XmlSchemaImport.cs
- PageParserFilter.cs
- XsltContext.cs
- DelegateBodyWriter.cs
- QueryStringParameter.cs
- TimeoutException.cs
- OutputCacheProfile.cs
- SpanIndex.cs
- UndoManager.cs
- TaskFactory.cs
- SystemDiagnosticsSection.cs
- MonitoringDescriptionAttribute.cs
- MessageContractImporter.cs
- CodeActivity.cs
- COAUTHIDENTITY.cs
- MatchingStyle.cs
- StorageSetMapping.cs
- StrokeCollectionConverter.cs
- DataContractSerializerMessageContractImporter.cs
- FileUtil.cs
- XPathChildIterator.cs
- Rules.cs
- AppSecurityManager.cs
- CompilationLock.cs
- OleDbError.cs
- RegionIterator.cs
- Content.cs
- NumericUpDownAccelerationCollection.cs
- QuaternionValueSerializer.cs
- SchemaType.cs
- LocalizationComments.cs
- XmlMembersMapping.cs
- ResXResourceWriter.cs
- Util.cs
- RuntimeResourceSet.cs
- CodeExpressionStatement.cs
- LinearGradientBrush.cs
- FileDialog_Vista_Interop.cs
- ExtenderControl.cs
- Color.cs
- BulletedListEventArgs.cs
- CompositeDataBoundControl.cs
- RequestSecurityTokenResponse.cs
- ShapingEngine.cs
- ControlPersister.cs
- TextBoxAutoCompleteSourceConverter.cs
- DbRetry.cs
- EmptyReadOnlyDictionaryInternal.cs
- TraceSection.cs
- ConstraintManager.cs
- BlockingCollection.cs
- FrameworkContextData.cs
- DataColumnPropertyDescriptor.cs
- SchemaInfo.cs
- DbCommandDefinition.cs
- EntitySqlQueryState.cs
- sqlnorm.cs
- ParseHttpDate.cs
- rsa.cs
- ObservableCollectionDefaultValueFactory.cs
- HttpCapabilitiesBase.cs
- DataGridViewColumnEventArgs.cs
- LinkUtilities.cs
- TreeNodeCollection.cs
- FormsAuthenticationModule.cs
- NodeInfo.cs
- SmiRecordBuffer.cs
- WindowsTab.cs
- SqlParameterizer.cs
- ObjectTokenCategory.cs
- ArgumentFixer.cs
- NumberSubstitution.cs
- ListViewUpdatedEventArgs.cs
- ScrollViewer.cs
- MasterPageParser.cs
- ThemeDirectoryCompiler.cs
- ArgumentOutOfRangeException.cs
- sqlser.cs
- TransformGroup.cs
- EntityModelSchemaGenerator.cs
- TransformCollection.cs
- UserControl.cs
- WorkerRequest.cs
- remotingproxy.cs