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
- PropertyMappingExceptionEventArgs.cs
- ClientWindowsAuthenticationMembershipProvider.cs
- TimeSpanOrInfiniteConverter.cs
- PropertyChangedEventArgs.cs
- SessionEndingEventArgs.cs
- RSAPKCS1SignatureFormatter.cs
- ReferencedType.cs
- ProxyGenerationError.cs
- DifferencingCollection.cs
- ReadOnlyDataSource.cs
- DebugTracing.cs
- XmlTextReader.cs
- ActivityExecutorOperation.cs
- coordinator.cs
- TransmissionStrategy.cs
- StaticSiteMapProvider.cs
- ParserContext.cs
- XmlFormatMapping.cs
- DelayedRegex.cs
- XPathAxisIterator.cs
- TextServicesCompartmentEventSink.cs
- InnerItemCollectionView.cs
- WebSysDescriptionAttribute.cs
- NgenServicingAttributes.cs
- SafeHandles.cs
- Brush.cs
- BaseResourcesBuildProvider.cs
- ControlBuilderAttribute.cs
- ListViewGroupConverter.cs
- GetImportedCardRequest.cs
- StreamGeometry.cs
- WriteTimeStream.cs
- ContextMenuService.cs
- InstanceDataCollectionCollection.cs
- DialogBaseForm.cs
- HttpServerVarsCollection.cs
- PolicyStatement.cs
- HandledEventArgs.cs
- StateItem.cs
- UriTemplateTableMatchCandidate.cs
- ColorContext.cs
- XmlSchemaExternal.cs
- WebBrowserPermission.cs
- XmlNamespaceManager.cs
- Adorner.cs
- ConnectionManagementElement.cs
- DataProviderNameConverter.cs
- SemaphoreFullException.cs
- WindowsStreamSecurityElement.cs
- MutableAssemblyCacheEntry.cs
- WindowsAuthenticationModule.cs
- TdsParserHelperClasses.cs
- SecurityKeyIdentifier.cs
- TreeNode.cs
- StringResourceManager.cs
- MessageSecurityOverTcpElement.cs
- ButtonChrome.cs
- SoapReflectionImporter.cs
- WebControlAdapter.cs
- Button.cs
- SingleAnimationBase.cs
- AcceleratedTokenProvider.cs
- GestureRecognizer.cs
- PngBitmapDecoder.cs
- PocoPropertyAccessorStrategy.cs
- EmptyReadOnlyDictionaryInternal.cs
- CompositeScriptReferenceEventArgs.cs
- WebPartDisplayMode.cs
- documentsequencetextview.cs
- MessageSecurityException.cs
- MtomMessageEncoder.cs
- DbMetaDataColumnNames.cs
- WindowHideOrCloseTracker.cs
- XPathEmptyIterator.cs
- XmlSchemaObject.cs
- Set.cs
- ZipIORawDataFileBlock.cs
- ContentWrapperAttribute.cs
- DebuggerAttributes.cs
- PasswordTextNavigator.cs
- Panel.cs
- MachineKeyConverter.cs
- DataGridViewSortCompareEventArgs.cs
- SerializableAttribute.cs
- validation.cs
- GPRECT.cs
- UserValidatedEventArgs.cs
- HTTP_SERVICE_CONFIG_URLACL_KEY.cs
- ProcessHostConfigUtils.cs
- BaseParaClient.cs
- HtmlElementErrorEventArgs.cs
- ConnectionsZone.cs
- OleDbConnection.cs
- TextElement.cs
- BridgeDataReader.cs
- serverconfig.cs
- GroupPartitionExpr.cs
- NamespaceInfo.cs
- XMLDiffLoader.cs
- AuthorizationRuleCollection.cs