Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Base / MS / Internal / IO / Zip / ZipIOZip64EndOfCentralDirectoryLocatorBlock.cs / 1305600 / ZipIOZip64EndOfCentralDirectoryLocatorBlock.cs
//------------------------------------------------------------------------------
//------------- *** WARNING ***
//------------- This file is part of a legally monitored development project.
//------------- Do not check in changes to this project. Do not raid bugs on this
//------------- code in the main PS database. Do not contact the owner of this
//------------- code directly. Contact the legal team at ‘ZSLegal’ for assistance.
//------------- *** WARNING ***
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//
//
// Copyright (C) Microsoft Corporation. All rights reserved.
//
//
// Description:
// This is an internal class that enables interactions with Zip archives
// for OPC scenarios (Zip 64 bit support)
//
// History:
// 01/26/2005: IgorBel: Initial creation.
//
//-----------------------------------------------------------------------------
using System;
using System.IO;
using System.Diagnostics;
using System.Runtime.Serialization;
using System.Windows;
using MS.Internal.WindowsBase;
namespace MS.Internal.IO.Zip
{
internal class ZipIOZip64EndOfCentralDirectoryLocatorBlock : IZipIOBlock
{
// standard IZipIOBlock functionality
public long Offset
{
get
{
return _offset;
}
}
public long Size
{
get
{
return _size;
}
}
// This property will only return reliable result if Update is called prior
public bool GetDirtyFlag(bool closingFlag)
{
return _dirtyFlag;
}
public void Move(long shiftSize)
{
if (shiftSize != 0)
{
checked{_offset +=shiftSize;}
if (_size > 0)
{
_dirtyFlag = true;
}
Debug.Assert(_offset >=0);
}
}
public void Save()
{
if (GetDirtyFlag(true) && (Size > 0))
{
BinaryWriter writer = _blockManager.BinaryWriter;
if (_blockManager.Stream.Position != _offset)
{
// we need to seek
_blockManager.Stream.Seek(_offset, SeekOrigin.Begin);
// in non seekable streams we are expected to be at the right position, no seeking required
// if this assumption is ever violated. Seek will throw on non-seekable stream, which would provide us
// with a detection mechanism for such problems
}
writer.Write(_signatureConstant);
writer.Write(_numberOfTheDiskWithTheStartOfZip64EndOfCentralDirectory);
writer.Write(_offsetOfStartOfZip64EndOfCentralDirectoryRecord);
writer.Write(_totalNumberOfDisks);
writer.Flush();
}
_dirtyFlag = false;
}
public void UpdateReferences(bool closingFlag)
{
checked
{
// check whether Central directory is loaded and update references accordingly
// if one or more of the following conditions are true
// 1. Central Directory is dirty
// 2. Zip64 End of Central Directory is dirty
// 3. streaming mode
// if Central Directory isn't loded or none of the relevant structure is dirty,
// there is nothing to update for Zip64 End Of Central directory record
if ((_blockManager.IsCentralDirectoryBlockLoaded
&& (_blockManager.Streaming
|| _blockManager.CentralDirectoryBlock.GetDirtyFlag(closingFlag))
|| _blockManager.Zip64EndOfCentralDirectoryBlock.GetDirtyFlag(closingFlag)))
{
if (_blockManager.CentralDirectoryBlock.IsZip64BitRequiredForStoring)
{
UInt64 offsetOfStartOfZip64EndOfCentralDirectoryRecord =
(UInt64)_blockManager.Zip64EndOfCentralDirectoryBlock.Offset;
// update value and mark record dirty if either it is already dirty or there is a mismatch
if ((_dirtyFlag) ||
(offsetOfStartOfZip64EndOfCentralDirectoryRecord != _offsetOfStartOfZip64EndOfCentralDirectoryRecord) ||
(_fixedMinimalRecordSize != _size))
{
_offsetOfStartOfZip64EndOfCentralDirectoryRecord = offsetOfStartOfZip64EndOfCentralDirectoryRecord;
_size = _fixedMinimalRecordSize;
_dirtyFlag = true;
}
}
else
{
// we do not need zip 64 structures
if (_size != 0)
{
_size = 0;
_dirtyFlag = true;
}
}
}
}
}
public PreSaveNotificationScanControlInstruction PreSaveNotification(long offset, long size)
{
// we can safely ignore this notification as we do not keep any data
// after parsing on disk. Everything is in memory, it is ok to override
// original End of Central directory without any additional backups
// we can also safely state that there is no need to continue the PreSafeNotification loop
// as the only blocks after the Zip64 EOCD (EOCD) doesn't have
// data that is buffered on disk
return PreSaveNotificationScanControlInstruction.Stop;
}
internal static ZipIOZip64EndOfCentralDirectoryLocatorBlock SeekableLoad (ZipIOBlockManager blockManager)
{
// This Debug assert is a secondary check in debug builds, callers are responcible for verifying condition
// in both retail and debug builds
Debug.Assert(SniffTheBlockSignature(blockManager));
long blockPosition = checked(blockManager.EndOfCentralDirectoryBlock.Offset - _fixedMinimalRecordSize);
blockManager.Stream.Seek(blockPosition, SeekOrigin.Begin);
ZipIOZip64EndOfCentralDirectoryLocatorBlock block = new ZipIOZip64EndOfCentralDirectoryLocatorBlock(blockManager);
block.ParseRecord(blockManager.BinaryReader, blockPosition);
return block;
}
internal static ZipIOZip64EndOfCentralDirectoryLocatorBlock CreateNew(ZipIOBlockManager blockManager)
{
// This Debug assert is a secondary check in debug builds, callers are responcible for verifying condition
// in both retail and debug builds
Debug.Assert(!SniffTheBlockSignature(blockManager));
ZipIOZip64EndOfCentralDirectoryLocatorBlock block = new ZipIOZip64EndOfCentralDirectoryLocatorBlock(blockManager);
block._offset = 0;
block._size = 0;
block._dirtyFlag = false;
return block;
}
internal static bool SniffTheBlockSignature(ZipIOBlockManager blockManager)
{
long suspectPos = checked(blockManager.EndOfCentralDirectoryBlock.Offset - _fixedMinimalRecordSize);
// let's check that EndOfCentralDirectoryBlock.Offset is not too close to the start of the stream
// for the record to fit there
// the second check isn't required, strictily speaking, as we are stepping back from the EOCD.offset
// however in some theoretical cases EOCD might not be trustable so to ensure that ReadUInt32
// isn't going to throw we do additional check
if ((suspectPos < 0) ||
(checked(suspectPos + sizeof(UInt32)) > blockManager.Stream.Length))
{
return false;
}
blockManager.Stream.Seek(suspectPos, SeekOrigin.Begin);
UInt32 signature = blockManager.BinaryReader.ReadUInt32();
return (signature == _signatureConstant);
}
internal long OffsetOfZip64EndOfCentralDirectoryRecord
{
get
{
return (long)_offsetOfStartOfZip64EndOfCentralDirectoryRecord;
}
}
private ZipIOZip64EndOfCentralDirectoryLocatorBlock(ZipIOBlockManager blockManager)
{
Debug.Assert(blockManager != null);
_blockManager= blockManager;
}
private void ParseRecord (BinaryReader reader, long position)
{
_signature = reader.ReadUInt32();
_numberOfTheDiskWithTheStartOfZip64EndOfCentralDirectory = reader.ReadUInt32();
_offsetOfStartOfZip64EndOfCentralDirectoryRecord = reader.ReadUInt64();
_totalNumberOfDisks = reader.ReadUInt32();
_offset = position;
_size = _fixedMinimalRecordSize;
_dirtyFlag = false;
Validate();
}
private void Validate()
{
if (_offsetOfStartOfZip64EndOfCentralDirectoryRecord > Int64.MaxValue) // C# does proper upcasting to ULONG of both operands
{
// although we are trying to support 64 bit structures
// we are limited by the CLR model for streams down to 63
// bit size for all the Uint64 fields
throw new NotSupportedException(SR.Get(SRID.Zip64StructuresTooLarge));
}
if (_signature != _signatureConstant)
{
throw new FileFormatException(SR.Get(SRID.CorruptedData));
}
if ((_totalNumberOfDisks != 1) ||
(_numberOfTheDiskWithTheStartOfZip64EndOfCentralDirectory != 0))
{
throw new NotSupportedException(SR.Get(SRID.NotSupportedMultiDisk));
}
// The offset of the ZIP 64 EOCD must preceed the location of the ZIP64 EOCD locator
if ((UInt64)_offset <= _offsetOfStartOfZip64EndOfCentralDirectoryRecord) // we assume that _offset >=0
{
throw new FileFormatException(SR.Get(SRID.CorruptedData));
}
// this record is optional size must be either 0 or _fixedMinimalRecordSize
if ((_size != _fixedMinimalRecordSize) && (_size != 0))
{
throw new FileFormatException(SR.Get(SRID.CorruptedData));
}
}
private ZipIOBlockManager _blockManager;
private long _offset;
private long _size;
private bool _dirtyFlag;
private const UInt32 _signatureConstant = 0x07064b50;
private const int _fixedMinimalRecordSize = 20;
// data persisted on disk
private UInt32 _signature = _signatureConstant;
private UInt32 _numberOfTheDiskWithTheStartOfZip64EndOfCentralDirectory;
private UInt64 _offsetOfStartOfZip64EndOfCentralDirectoryRecord;
private UInt32 _totalNumberOfDisks = 1;
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------------------------
//------------- *** WARNING ***
//------------- This file is part of a legally monitored development project.
//------------- Do not check in changes to this project. Do not raid bugs on this
//------------- code in the main PS database. Do not contact the owner of this
//------------- code directly. Contact the legal team at ‘ZSLegal’ for assistance.
//------------- *** WARNING ***
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//
//
// Copyright (C) Microsoft Corporation. All rights reserved.
//
//
// Description:
// This is an internal class that enables interactions with Zip archives
// for OPC scenarios (Zip 64 bit support)
//
// History:
// 01/26/2005: IgorBel: Initial creation.
//
//-----------------------------------------------------------------------------
using System;
using System.IO;
using System.Diagnostics;
using System.Runtime.Serialization;
using System.Windows;
using MS.Internal.WindowsBase;
namespace MS.Internal.IO.Zip
{
internal class ZipIOZip64EndOfCentralDirectoryLocatorBlock : IZipIOBlock
{
// standard IZipIOBlock functionality
public long Offset
{
get
{
return _offset;
}
}
public long Size
{
get
{
return _size;
}
}
// This property will only return reliable result if Update is called prior
public bool GetDirtyFlag(bool closingFlag)
{
return _dirtyFlag;
}
public void Move(long shiftSize)
{
if (shiftSize != 0)
{
checked{_offset +=shiftSize;}
if (_size > 0)
{
_dirtyFlag = true;
}
Debug.Assert(_offset >=0);
}
}
public void Save()
{
if (GetDirtyFlag(true) && (Size > 0))
{
BinaryWriter writer = _blockManager.BinaryWriter;
if (_blockManager.Stream.Position != _offset)
{
// we need to seek
_blockManager.Stream.Seek(_offset, SeekOrigin.Begin);
// in non seekable streams we are expected to be at the right position, no seeking required
// if this assumption is ever violated. Seek will throw on non-seekable stream, which would provide us
// with a detection mechanism for such problems
}
writer.Write(_signatureConstant);
writer.Write(_numberOfTheDiskWithTheStartOfZip64EndOfCentralDirectory);
writer.Write(_offsetOfStartOfZip64EndOfCentralDirectoryRecord);
writer.Write(_totalNumberOfDisks);
writer.Flush();
}
_dirtyFlag = false;
}
public void UpdateReferences(bool closingFlag)
{
checked
{
// check whether Central directory is loaded and update references accordingly
// if one or more of the following conditions are true
// 1. Central Directory is dirty
// 2. Zip64 End of Central Directory is dirty
// 3. streaming mode
// if Central Directory isn't loded or none of the relevant structure is dirty,
// there is nothing to update for Zip64 End Of Central directory record
if ((_blockManager.IsCentralDirectoryBlockLoaded
&& (_blockManager.Streaming
|| _blockManager.CentralDirectoryBlock.GetDirtyFlag(closingFlag))
|| _blockManager.Zip64EndOfCentralDirectoryBlock.GetDirtyFlag(closingFlag)))
{
if (_blockManager.CentralDirectoryBlock.IsZip64BitRequiredForStoring)
{
UInt64 offsetOfStartOfZip64EndOfCentralDirectoryRecord =
(UInt64)_blockManager.Zip64EndOfCentralDirectoryBlock.Offset;
// update value and mark record dirty if either it is already dirty or there is a mismatch
if ((_dirtyFlag) ||
(offsetOfStartOfZip64EndOfCentralDirectoryRecord != _offsetOfStartOfZip64EndOfCentralDirectoryRecord) ||
(_fixedMinimalRecordSize != _size))
{
_offsetOfStartOfZip64EndOfCentralDirectoryRecord = offsetOfStartOfZip64EndOfCentralDirectoryRecord;
_size = _fixedMinimalRecordSize;
_dirtyFlag = true;
}
}
else
{
// we do not need zip 64 structures
if (_size != 0)
{
_size = 0;
_dirtyFlag = true;
}
}
}
}
}
public PreSaveNotificationScanControlInstruction PreSaveNotification(long offset, long size)
{
// we can safely ignore this notification as we do not keep any data
// after parsing on disk. Everything is in memory, it is ok to override
// original End of Central directory without any additional backups
// we can also safely state that there is no need to continue the PreSafeNotification loop
// as the only blocks after the Zip64 EOCD (EOCD) doesn't have
// data that is buffered on disk
return PreSaveNotificationScanControlInstruction.Stop;
}
internal static ZipIOZip64EndOfCentralDirectoryLocatorBlock SeekableLoad (ZipIOBlockManager blockManager)
{
// This Debug assert is a secondary check in debug builds, callers are responcible for verifying condition
// in both retail and debug builds
Debug.Assert(SniffTheBlockSignature(blockManager));
long blockPosition = checked(blockManager.EndOfCentralDirectoryBlock.Offset - _fixedMinimalRecordSize);
blockManager.Stream.Seek(blockPosition, SeekOrigin.Begin);
ZipIOZip64EndOfCentralDirectoryLocatorBlock block = new ZipIOZip64EndOfCentralDirectoryLocatorBlock(blockManager);
block.ParseRecord(blockManager.BinaryReader, blockPosition);
return block;
}
internal static ZipIOZip64EndOfCentralDirectoryLocatorBlock CreateNew(ZipIOBlockManager blockManager)
{
// This Debug assert is a secondary check in debug builds, callers are responcible for verifying condition
// in both retail and debug builds
Debug.Assert(!SniffTheBlockSignature(blockManager));
ZipIOZip64EndOfCentralDirectoryLocatorBlock block = new ZipIOZip64EndOfCentralDirectoryLocatorBlock(blockManager);
block._offset = 0;
block._size = 0;
block._dirtyFlag = false;
return block;
}
internal static bool SniffTheBlockSignature(ZipIOBlockManager blockManager)
{
long suspectPos = checked(blockManager.EndOfCentralDirectoryBlock.Offset - _fixedMinimalRecordSize);
// let's check that EndOfCentralDirectoryBlock.Offset is not too close to the start of the stream
// for the record to fit there
// the second check isn't required, strictily speaking, as we are stepping back from the EOCD.offset
// however in some theoretical cases EOCD might not be trustable so to ensure that ReadUInt32
// isn't going to throw we do additional check
if ((suspectPos < 0) ||
(checked(suspectPos + sizeof(UInt32)) > blockManager.Stream.Length))
{
return false;
}
blockManager.Stream.Seek(suspectPos, SeekOrigin.Begin);
UInt32 signature = blockManager.BinaryReader.ReadUInt32();
return (signature == _signatureConstant);
}
internal long OffsetOfZip64EndOfCentralDirectoryRecord
{
get
{
return (long)_offsetOfStartOfZip64EndOfCentralDirectoryRecord;
}
}
private ZipIOZip64EndOfCentralDirectoryLocatorBlock(ZipIOBlockManager blockManager)
{
Debug.Assert(blockManager != null);
_blockManager= blockManager;
}
private void ParseRecord (BinaryReader reader, long position)
{
_signature = reader.ReadUInt32();
_numberOfTheDiskWithTheStartOfZip64EndOfCentralDirectory = reader.ReadUInt32();
_offsetOfStartOfZip64EndOfCentralDirectoryRecord = reader.ReadUInt64();
_totalNumberOfDisks = reader.ReadUInt32();
_offset = position;
_size = _fixedMinimalRecordSize;
_dirtyFlag = false;
Validate();
}
private void Validate()
{
if (_offsetOfStartOfZip64EndOfCentralDirectoryRecord > Int64.MaxValue) // C# does proper upcasting to ULONG of both operands
{
// although we are trying to support 64 bit structures
// we are limited by the CLR model for streams down to 63
// bit size for all the Uint64 fields
throw new NotSupportedException(SR.Get(SRID.Zip64StructuresTooLarge));
}
if (_signature != _signatureConstant)
{
throw new FileFormatException(SR.Get(SRID.CorruptedData));
}
if ((_totalNumberOfDisks != 1) ||
(_numberOfTheDiskWithTheStartOfZip64EndOfCentralDirectory != 0))
{
throw new NotSupportedException(SR.Get(SRID.NotSupportedMultiDisk));
}
// The offset of the ZIP 64 EOCD must preceed the location of the ZIP64 EOCD locator
if ((UInt64)_offset <= _offsetOfStartOfZip64EndOfCentralDirectoryRecord) // we assume that _offset >=0
{
throw new FileFormatException(SR.Get(SRID.CorruptedData));
}
// this record is optional size must be either 0 or _fixedMinimalRecordSize
if ((_size != _fixedMinimalRecordSize) && (_size != 0))
{
throw new FileFormatException(SR.Get(SRID.CorruptedData));
}
}
private ZipIOBlockManager _blockManager;
private long _offset;
private long _size;
private bool _dirtyFlag;
private const UInt32 _signatureConstant = 0x07064b50;
private const int _fixedMinimalRecordSize = 20;
// data persisted on disk
private UInt32 _signature = _signatureConstant;
private UInt32 _numberOfTheDiskWithTheStartOfZip64EndOfCentralDirectory;
private UInt64 _offsetOfStartOfZip64EndOfCentralDirectoryRecord;
private UInt32 _totalNumberOfDisks = 1;
}
}
// 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
- ScalarConstant.cs
- ResourceLoader.cs
- ReadOnlyAttribute.cs
- FormsAuthenticationConfiguration.cs
- InputLanguageCollection.cs
- XmlNamedNodeMap.cs
- BinaryMethodMessage.cs
- DelegateSerializationHolder.cs
- MembershipSection.cs
- OptimalBreakSession.cs
- ThreadStaticAttribute.cs
- EntitySetRetriever.cs
- IEnumerable.cs
- CfgSemanticTag.cs
- BitmapMetadataEnumerator.cs
- CodeTypeDeclaration.cs
- CodeObject.cs
- LOSFormatter.cs
- LogSwitch.cs
- XmlSchemaValidationException.cs
- SafeCoTaskMem.cs
- UpdatePanelTrigger.cs
- XmlSubtreeReader.cs
- BeginGetFileNameFromUserRequest.cs
- NativeObjectSecurity.cs
- PrtCap_Reader.cs
- TypeConverterBase.cs
- MetadataProperty.cs
- RoleService.cs
- sitestring.cs
- PageFunction.cs
- XmlUnspecifiedAttribute.cs
- ToolStripSeparator.cs
- ActivationServices.cs
- WebPartDescription.cs
- HttpContext.cs
- ComponentResourceManager.cs
- PropertyTab.cs
- AsmxEndpointPickerExtension.cs
- ViewManager.cs
- ResourceManager.cs
- CodeTypeReferenceExpression.cs
- CompiledRegexRunner.cs
- TimeEnumHelper.cs
- OdbcHandle.cs
- NetPipeSectionData.cs
- XmlCollation.cs
- QilLiteral.cs
- HtmlEncodedRawTextWriter.cs
- PageSetupDialog.cs
- SqlServer2KCompatibilityAnnotation.cs
- ToolStripDropTargetManager.cs
- BinaryWriter.cs
- RoutedEvent.cs
- PermissionToken.cs
- TextRunTypographyProperties.cs
- CalendarBlackoutDatesCollection.cs
- Image.cs
- DataRowCollection.cs
- SendingRequestEventArgs.cs
- ParallelDesigner.cs
- RelationshipNavigation.cs
- _UriSyntax.cs
- SHA512CryptoServiceProvider.cs
- ProfileInfo.cs
- ByteFacetDescriptionElement.cs
- Size.cs
- ErrorStyle.cs
- ToolStripMenuItem.cs
- DynamicObject.cs
- LineSegment.cs
- NavigationProperty.cs
- XPathNode.cs
- ContentPlaceHolder.cs
- CompoundFileIOPermission.cs
- BrowserDefinition.cs
- LogLogRecordHeader.cs
- UnsafeNativeMethods.cs
- VsPropertyGrid.cs
- ThreadTrace.cs
- UnsafeCollabNativeMethods.cs
- MethodMessage.cs
- HtmlContainerControl.cs
- ResourceWriter.cs
- ListCollectionView.cs
- TextFormatterHost.cs
- WebPartDeleteVerb.cs
- SQLDoubleStorage.cs
- AQNBuilder.cs
- BooleanStorage.cs
- ReferencedAssembly.cs
- ScrollViewer.cs
- SecurityTokenProvider.cs
- MonthCalendarDesigner.cs
- EventDescriptorCollection.cs
- WriteableBitmap.cs
- PointKeyFrameCollection.cs
- WasEndpointConfigContainer.cs
- HighContrastHelper.cs
- PositiveTimeSpanValidator.cs