Skip to content

Commit

Permalink
Create new X509CertificateLoader
Browse files Browse the repository at this point in the history
The new certificate loader only loads one data type per method, unlike
the previous loader mechanism (new X509Certiicate2(bytes, ...)).  It also
allows for caller configuration to control cost-of-work limits and some
common usability gotchas around Windows PFX loading.

This change adds the new loader, and changes the X509Certificate2 ctors
to use it; a followup will mark the ctors as Obsolete and update usage in
the dotnet/runtime codebase.
  • Loading branch information
bartonjs committed Jun 25, 2024
1 parent b8b3bf2 commit d4fe4a7
Show file tree
Hide file tree
Showing 86 changed files with 7,995 additions and 2,480 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -56,5 +56,20 @@ internal static unsafe partial bool CryptQueryObject(
IntPtr phMsg,
IntPtr ppvContext
);

[LibraryImport(Libraries.Crypt32, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static unsafe partial bool CryptQueryObject(
CertQueryObjectType dwObjectType,
void* pvObject,
ExpectedContentTypeFlags dwExpectedContentTypeFlags,
ExpectedFormatTypeFlags dwExpectedFormatTypeFlags,
int dwFlags, // reserved - always pass 0
IntPtr pdwMsgAndCertEncodingType,
out ContentType pdwContentType,
IntPtr pdwFormatType,
IntPtr phCertStore,
IntPtr phMsg,
out SafeCertContextHandle ppvContext);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,8 @@ internal static partial class Crypt32
{
[LibraryImport(Libraries.Crypt32, SetLastError = true)]
internal static partial SafeCertStoreHandle PFXImportCertStore(ref DATA_BLOB pPFX, SafePasswordHandle password, PfxCertStoreFlags dwFlags);

[LibraryImport(Libraries.Crypt32, SetLastError = true)]
internal static unsafe partial SafeCertStoreHandle PFXImportCertStore(ref DATA_BLOB pPFX, char* password, PfxCertStoreFlags dwFlags);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Buffers;

namespace System.IO.MemoryMappedFiles
{
internal sealed unsafe class MemoryMappedFileMemoryManager : MemoryManager<byte>
{
private byte* _pointer;
private int _length;
private MemoryMappedFile _mappedFile;
private MemoryMappedViewAccessor _accessor;

public MemoryMappedFileMemoryManager(
byte* pointer,
int length,
MemoryMappedFile mappedFile,
MemoryMappedViewAccessor accessor)
{
_pointer = pointer;
_length = length;
_mappedFile = mappedFile;
_accessor = accessor;
}

#if DEBUG
#pragma warning disable CA2015
~MemoryMappedFileMemoryManager()
#pragma warning restore CA2015
{
Environment.FailFast("MemoryMappedFileMemoryManager was finalized.");
}
#endif

internal static MemoryMappedFileMemoryManager CreateFromFileClamped(
FileStream fileStream,
MemoryMappedFileAccess access = MemoryMappedFileAccess.Read,
HandleInheritability inheritability = HandleInheritability.None,
bool leaveOpen = false)
{
int length = (int)Math.Min(int.MaxValue, fileStream.Length);
MemoryMappedFile mapped = MemoryMappedFile.CreateFromFile(fileStream, null, 0, access, inheritability, leaveOpen);
MemoryMappedViewAccessor? accessor = null;
byte* pointer = null;

try
{
accessor = mapped.CreateViewAccessor(0, length, access);
accessor.SafeMemoryMappedViewHandle.AcquirePointer(ref pointer);

return new MemoryMappedFileMemoryManager(pointer, length, mapped, accessor);
}
catch (Exception)
{
if (pointer != null)
{
accessor!.SafeMemoryMappedViewHandle.ReleasePointer();
}

accessor?.Dispose();
mapped.Dispose();
throw;
}
}

protected override void Dispose(bool disposing)
{
_pointer = null;
_length = -1;
_accessor?.SafeMemoryMappedViewHandle.ReleasePointer();
_accessor?.Dispose();
_mappedFile?.Dispose();
_accessor = null!;
_mappedFile = null!;
}

public override Span<byte> GetSpan()
{
ThrowIfDisposed();
return new Span<byte>(_pointer, _length);
}

public override MemoryHandle Pin(int elementIndex = 0)
{
ThrowIfDisposed();
return default;
}

public override void Unpin()
{
ThrowIfDisposed();
// nop
}

private void ThrowIfDisposed()
{
#if NET
ObjectDisposedException.ThrowIf(_length < 0, this);
#else
if (_length < 0)
{
throw new ObjectDisposedException(GetType().FullName);
}
#endif
}
}
}
Loading

0 comments on commit d4fe4a7

Please sign in to comment.