Kaynağa Gözat

Fix to prevent deadlocks in multi-threaded applications

See https://support.microsoft.com/en-us/kb/2996566 (Issue 1) for more
details. But in summary if the document is larger than 10Mb, then deadlocks
can occur in multi-threaded applications.
master
teatime 9 yıl önce
ebeveyn
işleme
6f4d3e506a
7 değiştirilmiş dosya ile 126 ekleme ve 40 silme
  1. 2
    2
      DocX/Container.cs
  2. 31
    31
      DocX/DocX.cs
  3. 1
    0
      DocX/DocX.csproj
  4. 5
    5
      DocX/HelperFunctions.cs
  5. 1
    1
      DocX/Image.cs
  6. 85
    0
      DocX/PackagePartStream.cs
  7. 1
    1
      DocX/Paragraph.cs

+ 2
- 2
DocX/Container.cs Dosyayı Görüntüle

@@ -650,7 +650,7 @@ namespace Novacode
if (!Document.package.PartExists(style_package_uri))
{
PackagePart style_package = Document.package.CreatePart(style_package_uri, "application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml", CompressionOption.Maximum);
using (TextWriter tw = new StreamWriter(style_package.GetStream()))
using (TextWriter tw = new StreamWriter(new PackagePartStream(style_package.GetStream())))
{
style_document = new XDocument
(
@@ -682,7 +682,7 @@ namespace Novacode
}
}
using (TextWriter tw = new StreamWriter(styles_document.GetStream()))
using (TextWriter tw = new StreamWriter(new PackagePartStream(styles_document.GetStream())))
style_document.Save(tw);
}
#endregion

+ 31
- 31
DocX/DocX.cs Dosyayı Görüntüle

@@ -675,7 +675,7 @@ namespace Novacode
evenAndOddHeaders.Remove();
}
using (TextWriter tw = new StreamWriter(settingsPart.GetStream()))
using (TextWriter tw = new StreamWriter(new PackagePartStream(settingsPart.GetStream())))
settings.Save(tw);
}
}
@@ -1449,7 +1449,7 @@ namespace Novacode
using (Stream s_read = remote_pp.GetStream())
{
using (Stream s_write = new_pp.GetStream(FileMode.Create))
using (Stream s_write = new PackagePartStream(new_pp.GetStream(FileMode.Create)))
{
byte[] buffer = new byte[32768];
int read;
@@ -1647,7 +1647,7 @@ namespace Novacode
}
// Save the modified local custom styles.xml file.
using (TextWriter tw = new StreamWriter(local_pp.GetStream(FileMode.Create, FileAccess.Write)))
using (TextWriter tw = new StreamWriter(new PackagePartStream(local_pp.GetStream(FileMode.Create, FileAccess.Write))))
local_custom_document.Save(tw, SaveOptions.None);
}
@@ -1924,7 +1924,7 @@ namespace Novacode
using (Stream s_read = pp.GetStream())
{
using (Stream s_write = new_pp.GetStream(FileMode.Create))
using (Stream s_write = new PackagePartStream(new_pp.GetStream(FileMode.Create)))
{
byte[] buffer = new byte[32768];
int read;
@@ -2132,7 +2132,7 @@ namespace Novacode
wordStyles.Element(w + "styles").Add(style);
// Save the styles document.
using (TextWriter tw = new StreamWriter(package.GetPart(wordStylesUri).GetStream()))
using (TextWriter tw = new StreamWriter(new PackagePartStream(package.GetPart(wordStylesUri).GetStream())))
wordStyles.Save(tw);
}
@@ -2413,7 +2413,7 @@ namespace Novacode
}
// Save the main document
using (TextWriter tw = new StreamWriter(mainDocumentPart.GetStream(FileMode.Create, FileAccess.Write)))
using (TextWriter tw = new StreamWriter(new PackagePartStream(mainDocumentPart.GetStream(FileMode.Create, FileAccess.Write))))
mainDoc.Save(tw, SaveOptions.None);
#endregion
@@ -2796,7 +2796,7 @@ namespace Novacode
{
using (
StreamWriter tw = new StreamWriter(
globalRelsPart.GetStream(FileMode.Create, FileAccess.Write), Encoding.UTF8))
new PackagePartStream(globalRelsPart.GetStream(FileMode.Create, FileAccess.Write)), Encoding.UTF8))
{
tw.Write(tr.ReadToEnd());
}
@@ -2821,7 +2821,7 @@ namespace Novacode
{
using (
StreamWriter tw = new StreamWriter(
nativePart.GetStream(FileMode.Create, FileAccess.Write), tr.CurrentEncoding))
new PackagePartStream(nativePart.GetStream(FileMode.Create, FileAccess.Write)), tr.CurrentEncoding))
{
tw.Write(tr.ReadToEnd());
}
@@ -2838,7 +2838,7 @@ namespace Novacode
}
PackagePart documentNewPart = this.package.CreatePart(
documentPart.Uri, mainContentType, documentPart.CompressionOption);
using (XmlWriter xw = XmlWriter.Create(documentNewPart.GetStream(FileMode.Create, FileAccess.Write)))
using (XmlWriter xw = XmlWriter.Create(new PackagePartStream(documentNewPart.GetStream(FileMode.Create, FileAccess.Write))))
{
documentDoc.WriteTo(xw);
}
@@ -3049,7 +3049,7 @@ namespace Novacode
word_styles.Element(w + "styles").Add(style);
// Save the styles document.
using (TextWriter tw = new StreamWriter(package.GetPart(word_styles_Uri).GetStream()))
using (TextWriter tw = new StreamWriter(new PackagePartStream(package.GetPart(word_styles_Uri).GetStream())))
word_styles.Save(tw);
}
}
@@ -3208,7 +3208,7 @@ namespace Novacode
}
// Save the main document
using (TextWriter tw = new StreamWriter(headerPart.GetStream(FileMode.Create, FileAccess.Write)))
using (TextWriter tw = new StreamWriter(new PackagePartStream(headerPart.GetStream(FileMode.Create, FileAccess.Write))))
header.Save(tw, SaveOptions.None);
string type;
@@ -3369,7 +3369,7 @@ namespace Novacode
PackageRelationship rel = mainPart.CreateRelationship(img.Uri, TargetMode.Internal, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image");
// Open a Stream to the newly created Image part.
using (Stream stream = img.GetStream(FileMode.Create, FileAccess.Write))
using (Stream stream = new PackagePartStream(img.GetStream(FileMode.Create, FileAccess.Write)))
{
// Using the Stream to the real image, copy this streams data into the newly create Image part.
using (newImageStream)
@@ -3411,7 +3411,7 @@ namespace Novacode
Headers headers = Headers;
// Save the main document
using (TextWriter tw = new StreamWriter(mainPart.GetStream(FileMode.Create, FileAccess.Write)))
using (TextWriter tw = new StreamWriter(new PackagePartStream(mainPart.GetStream(FileMode.Create, FileAccess.Write))))
mainDoc.Save(tw, SaveOptions.None);
if (settings == null)
@@ -3443,7 +3443,7 @@ namespace Novacode
mainPart.GetRelationship(evenHeaderRef).TargetUri
);
using (TextWriter tw = new StreamWriter(package.GetPart(target).GetStream(FileMode.Create, FileAccess.Write)))
using (TextWriter tw = new StreamWriter(new PackagePartStream(package.GetPart(target).GetStream(FileMode.Create, FileAccess.Write))))
{
new XDocument
(
@@ -3472,7 +3472,7 @@ namespace Novacode
);
// Save header1
using (TextWriter tw = new StreamWriter(package.GetPart(target).GetStream(FileMode.Create, FileAccess.Write)))
using (TextWriter tw = new StreamWriter(new PackagePartStream(package.GetPart(target).GetStream(FileMode.Create, FileAccess.Write))))
{
new XDocument
(
@@ -3500,7 +3500,7 @@ namespace Novacode
);
// Save header3
using (TextWriter tw = new StreamWriter(package.GetPart(target).GetStream(FileMode.Create, FileAccess.Write)))
using (TextWriter tw = new StreamWriter(new PackagePartStream(package.GetPart(target).GetStream(FileMode.Create, FileAccess.Write))))
{
new XDocument
(
@@ -3528,7 +3528,7 @@ namespace Novacode
);
// Save header1
using (TextWriter tw = new StreamWriter(package.GetPart(target).GetStream(FileMode.Create, FileAccess.Write)))
using (TextWriter tw = new StreamWriter(new PackagePartStream(package.GetPart(target).GetStream(FileMode.Create, FileAccess.Write))))
{
new XDocument
(
@@ -3556,7 +3556,7 @@ namespace Novacode
);
// Save header2
using (TextWriter tw = new StreamWriter(package.GetPart(target).GetStream(FileMode.Create, FileAccess.Write)))
using (TextWriter tw = new StreamWriter(new PackagePartStream(package.GetPart(target).GetStream(FileMode.Create, FileAccess.Write))))
{
new XDocument
(
@@ -3584,7 +3584,7 @@ namespace Novacode
);
// Save header3
using (TextWriter tw = new StreamWriter(package.GetPart(target).GetStream(FileMode.Create, FileAccess.Write)))
using (TextWriter tw = new StreamWriter(new PackagePartStream(package.GetPart(target).GetStream(FileMode.Create, FileAccess.Write))))
{
new XDocument
(
@@ -3595,42 +3595,42 @@ namespace Novacode
}
// Save the settings document.
using (TextWriter tw = new StreamWriter(settingsPart.GetStream(FileMode.Create, FileAccess.Write)))
using (TextWriter tw = new StreamWriter(new PackagePartStream(settingsPart.GetStream(FileMode.Create, FileAccess.Write))))
settings.Save(tw, SaveOptions.None);
if (endnotesPart != null)
{
using (TextWriter tw = new StreamWriter(endnotesPart.GetStream(FileMode.Create, FileAccess.Write)))
using (TextWriter tw = new StreamWriter(new PackagePartStream(endnotesPart.GetStream(FileMode.Create, FileAccess.Write))))
endnotes.Save(tw, SaveOptions.None);
}
if (footnotesPart != null)
{
using (TextWriter tw = new StreamWriter(footnotesPart.GetStream(FileMode.Create, FileAccess.Write)))
using (TextWriter tw = new StreamWriter(new PackagePartStream(footnotesPart.GetStream(FileMode.Create, FileAccess.Write))))
footnotes.Save(tw, SaveOptions.None);
}
if (stylesPart != null)
{
using (TextWriter tw = new StreamWriter(stylesPart.GetStream(FileMode.Create, FileAccess.Write)))
using (TextWriter tw = new StreamWriter(new PackagePartStream(stylesPart.GetStream(FileMode.Create, FileAccess.Write))))
styles.Save(tw, SaveOptions.None);
}
if (stylesWithEffectsPart != null)
{
using (TextWriter tw = new StreamWriter(stylesWithEffectsPart.GetStream(FileMode.Create, FileAccess.Write)))
using (TextWriter tw = new StreamWriter(new PackagePartStream(stylesWithEffectsPart.GetStream(FileMode.Create, FileAccess.Write))))
stylesWithEffects.Save(tw, SaveOptions.None);
}
if (numberingPart != null)
{
using (TextWriter tw = new StreamWriter(numberingPart.GetStream(FileMode.Create, FileAccess.Write)))
using (TextWriter tw = new StreamWriter(new PackagePartStream(numberingPart.GetStream(FileMode.Create, FileAccess.Write))))
numbering.Save(tw, SaveOptions.None);
}
if (fontTablePart != null)
{
using (TextWriter tw = new StreamWriter(fontTablePart.GetStream(FileMode.Create, FileAccess.Write)))
using (TextWriter tw = new StreamWriter(new PackagePartStream(fontTablePart.GetStream(FileMode.Create, FileAccess.Write))))
fontTable.Save(tw, SaveOptions.None);
}
}
@@ -3831,7 +3831,7 @@ namespace Novacode
corePropDoc.Root.Add(new XElement(XName.Get(propertyLocalName, propertyNamespace.NamespaceName), propertyValue));
}
using (TextWriter tw = new StreamWriter(corePropPart.GetStream(FileMode.Create, FileAccess.Write)))
using (TextWriter tw = new StreamWriter(new PackagePartStream(corePropPart.GetStream(FileMode.Create, FileAccess.Write))))
{
corePropDoc.Save(tw);
}
@@ -3885,7 +3885,7 @@ namespace Novacode
}
}
using (TextWriter tw = new StreamWriter(pp.GetStream(FileMode.Create, FileAccess.Write)))
using (TextWriter tw = new StreamWriter(new PackagePartStream(pp.GetStream(FileMode.Create, FileAccess.Write))))
header.Save(tw);
}
#endregion
@@ -3914,7 +3914,7 @@ namespace Novacode
}
}
using (TextWriter tw = new StreamWriter(pp.GetStream(FileMode.Create, FileAccess.Write)))
using (TextWriter tw = new StreamWriter(new PackagePartStream(pp.GetStream(FileMode.Create, FileAccess.Write))))
footer.Save(tw);
}
#endregion
@@ -4007,7 +4007,7 @@ namespace Novacode
);
// Save the custom properties
using (TextWriter tw = new StreamWriter(customPropPart.GetStream(FileMode.Create, FileAccess.Write)))
using (TextWriter tw = new StreamWriter(new PackagePartStream(customPropPart.GetStream(FileMode.Create, FileAccess.Write))))
customPropDoc.Save(tw, SaveOptions.None);
// Refresh all fields in this document which display this custom property.
@@ -4313,7 +4313,7 @@ namespace Novacode
PackageRelationship rel = mainPart.CreateRelationship(chartPackagePart.Uri, TargetMode.Internal, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart", relID);
// Save a chart info the chartPackagePart
using (TextWriter tw = new StreamWriter(chartPackagePart.GetStream(FileMode.Create, FileAccess.Write)))
using (TextWriter tw = new StreamWriter(new PackagePartStream(chartPackagePart.GetStream(FileMode.Create, FileAccess.Write))))
chart.Xml.Save(tw);
// Insert a new chart into a paragraph.

+ 1
- 0
DocX/DocX.csproj Dosyayı Görüntüle

@@ -117,6 +117,7 @@
<Compile Include="IContentContainer.cs" />
<Compile Include="IParagraphContainer.cs" />
<Compile Include="List.cs" />
<Compile Include="PackagePartStream.cs" />
<Compile Include="PageLayout.cs" />
<Compile Include="Section.cs" />
<Compile Include="TableOfContents.cs" />

+ 5
- 5
DocX/HelperFunctions.cs Dosyayı Görüntüle

@@ -49,7 +49,7 @@ namespace Novacode
internal static void CreateRelsPackagePart(DocX Document, Uri uri)
{
PackagePart pp = Document.package.CreatePart(uri, "application/vnd.openxmlformats-package.relationships+xml", CompressionOption.Maximum);
using (TextWriter tw = new StreamWriter(pp.GetStream()))
using (TextWriter tw = new StreamWriter(new PackagePartStream(pp.GetStream())))
{
XDocument d = new XDocument
(
@@ -274,7 +274,7 @@ namespace Novacode
themeFontLang.SetAttributeValue(XName.Get("val", DocX.w.NamespaceName), CultureInfo.CurrentCulture);
// Save the settings document.
using (TextWriter tw = new StreamWriter(settingsPart.GetStream()))
using (TextWriter tw = new StreamWriter(new PackagePartStream(settingsPart.GetStream())))
settings.Save(tw);
}
else
@@ -296,7 +296,7 @@ namespace Novacode
)
);
using (TextWriter tw = new StreamWriter(customPropertiesPart.GetStream(FileMode.Create, FileAccess.Write)))
using (TextWriter tw = new StreamWriter(new PackagePartStream(customPropertiesPart.GetStream(FileMode.Create, FileAccess.Write))))
customPropDoc.Save(tw, SaveOptions.None);
document.package.CreateRelationship(customPropertiesPart.Uri, TargetMode.Internal, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties");
@@ -343,7 +343,7 @@ namespace Novacode
numberingDoc = DecompressXMLResource("Novacode.Resources.numbering.xml.gz");
// Save /word/numbering.xml
using (TextWriter tw = new StreamWriter(wordNumbering.GetStream(FileMode.Create, FileAccess.Write)))
using (TextWriter tw = new StreamWriter(new PackagePartStream(wordNumbering.GetStream(FileMode.Create, FileAccess.Write))))
numberingDoc.Save(tw, SaveOptions.None);
PackagePart mainDocumentPart = package.GetParts().Single(p => p.ContentType.Equals(DOCUMENT_DOCUMENTTYPE, StringComparison.CurrentCultureIgnoreCase) ||
@@ -371,7 +371,7 @@ namespace Novacode
lang.SetAttributeValue(XName.Get("val", DocX.w.NamespaceName), CultureInfo.CurrentCulture);
// Save /word/styles.xml
using (TextWriter tw = new StreamWriter(word_styles.GetStream(FileMode.Create, FileAccess.Write)))
using (TextWriter tw = new StreamWriter(new PackagePartStream(word_styles.GetStream(FileMode.Create, FileAccess.Write))))
stylesDoc.Save(tw, SaveOptions.None);
PackagePart mainDocumentPart = package.GetParts().Where

+ 1
- 1
DocX/Image.cs Dosyayı Görüntüle

@@ -23,7 +23,7 @@ namespace Novacode
string end = pr.TargetUri.OriginalString;
string full = start + "/" + end;
return(document.package.GetPart(new Uri(full, UriKind.Relative)).GetStream(mode, access));
return(new PackagePartStream(document.package.GetPart(new Uri(full, UriKind.Relative)).GetStream(mode, access)));
}
/// <summary>

+ 85
- 0
DocX/PackagePartStream.cs Dosyayı Görüntüle

@@ -0,0 +1,85 @@
using System.IO;
using System.Threading;

namespace Novacode
{
/// <summary>
/// See <a href="https://support.microsoft.com/en-gb/kb/951731" /> for explanation
/// </summary>
public class PackagePartStream : Stream
{
private static readonly Mutex Mutex = new Mutex(false);

private readonly Stream stream;

public PackagePartStream(Stream stream)
{
this.stream = stream;
}

public override bool CanRead
{
get { return this.stream.CanRead; }
}

public override bool CanSeek
{
get { return this.stream.CanSeek; }
}

public override bool CanWrite
{
get { return this.stream.CanWrite; }
}

public override long Length
{
get { return this.stream.Length; }
}

public override long Position
{
get { return this.stream.Position; }
set { this.stream.Position = value; }
}

public override long Seek(long offset, SeekOrigin origin)
{
return this.stream.Seek(offset, origin);
}

public override void SetLength(long value)
{
this.stream.SetLength(value);
}

public override int Read(byte[] buffer, int offset, int count)
{
return this.stream.Read(buffer, offset, count);
}

public override void Write(byte[] buffer, int offset, int count)
{
Mutex.WaitOne(Timeout.Infinite, false);
this.stream.Write(buffer, offset, count);
Mutex.ReleaseMutex();
}

public override void Flush()
{
Mutex.WaitOne(Timeout.Infinite, false);
this.stream.Flush();
Mutex.ReleaseMutex();
}

public override void Close()
{
this.stream.Close();
}

protected override void Dispose(bool disposing)
{
this.stream.Dispose();
}
}
}

+ 1
- 1
DocX/Paragraph.cs Dosyayı Görüntüle

@@ -1686,7 +1686,7 @@ namespace Novacode
int cx, cy;
using (System.Drawing.Image img = System.Drawing.Image.FromStream(part.GetStream()))
using (System.Drawing.Image img = System.Drawing.Image.FromStream(new PackagePartStream(part.GetStream())))
{
cx = img.Width * 9526;
cy = img.Height * 9526;

Loading…
İptal
Kaydet