Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.

Commit

Permalink
Make a few changes requested by SDK team
Browse files Browse the repository at this point in the history
1) Throw different exceptions for each error (instead of passing the message)
2) Add the GetGUIBit method.
  • Loading branch information
swaroop-sridhar committed Jun 18, 2019
1 parent 1b7756a commit 57d5072
Show file tree
Hide file tree
Showing 8 changed files with 197 additions and 76 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;

namespace Microsoft.NET.HostModel.AppHost
{
/// <summary>
/// The application host executable cannot be customized because adding resources requires
/// that the build be performed on Windows (excluding Nano Server).
/// </summary>
public class AppHostCustomizationUnsupportedOSException : AppHostUpdateException
{
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;

namespace Microsoft.NET.HostModel.AppHost
{
/// <summary>
/// Unable to use the input file as application host executable because it's not a
/// Windows executable for the CUI (Console) subsystem.
/// </summary>
public class AppHostNotCUIException : AppHostUpdateException
{
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;

namespace Microsoft.NET.HostModel.AppHost
{
/// <summary>
/// Unable to use the input file as an application host executable
/// because it's not a Windows PE file
/// </summary>
public class AppHostNotPEFileException : AppHostUpdateException
{
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;

namespace Microsoft.NET.HostModel.AppHost
{
/// <summary>
/// An instance of this exception is thrown when an AppHost binary update
/// fails due to known user errors.
/// </summary>
public class AppHostUpdateException : Exception
{
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@
namespace Microsoft.NET.HostModel.AppHost
{
/// <summary>
/// This exception is thrown when an AppHost binary update fails due to known user errors.
/// Given app file name is longer than 1024 bytes
/// </summary>
public class BinaryUpdateException : Exception
public class AppNameTooLongException : AppHostUpdateException
{
public BinaryUpdateException(string message) :
base(message)
public string LongName;
public AppNameTooLongException(string name)
{
LongName = name;
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;

namespace Microsoft.NET.HostModel.AppHost
{
/// <summary>
/// Unable to use input file as a valid application host executable, as it does not contain
/// the expected placeholder byte sequence.
/// </summary>
public class AppUpdatePlaceHolderNotFoundException : AppHostUpdateException
{
public byte[] MissingPattern;

public AppUpdatePlaceHolderNotFoundException(byte[] pattern)
{
MissingPattern = pattern;
}
}
}

102 changes: 70 additions & 32 deletions src/managed/Microsoft.NET.HostModel/AppHost/BinaryUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ namespace Microsoft.NET.HostModel.AppHost
{
public static class BinaryUtils
{
internal static unsafe bool SearchAndReplace(
internal static unsafe void SearchAndReplace(
MemoryMappedViewAccessor accessor,
byte[] searchPattern,
byte[] patternToReplace)
Expand All @@ -26,7 +26,7 @@ internal static unsafe bool SearchAndReplace(
int position = KMPSearch(searchPattern, bytes, accessor.Capacity);
if (position < 0)
{
return false;
throw new AppUpdatePlaceHolderNotFoundException(searchPattern);
}

accessor.WriteArray(
Expand All @@ -44,8 +44,6 @@ internal static unsafe bool SearchAndReplace(
accessor.SafeMemoryMappedViewHandle.ReleasePointer();
}
}

return true;
}

private static unsafe void Pad0(byte[] searchPattern, byte[] patternToReplace, byte* bytes, int offset)
Expand All @@ -59,39 +57,26 @@ private static unsafe void Pad0(byte[] searchPattern, byte[] patternToReplace, b
}
}

public static unsafe void SearchAndReplace(MemoryMappedFile mappedFile, byte[] searchPattern, byte[] patternToReplace)
{
using (var accessor = mappedFile.CreateViewAccessor())
{
if (!SearchAndReplace(accessor, searchPattern, patternToReplace))
{
throw new BinaryUpdateException($"SearchPattern {searchPattern} not found.");
}
}
}

public static unsafe void SearchAndReplace(string filePath, byte[] searchPattern, byte[] patternToReplace)
{
using (var mappedFile = MemoryMappedFile.CreateFromFile(filePath))
{
SearchAndReplace(mappedFile, searchPattern, patternToReplace);
}
}

public static unsafe int SearchInFile(MemoryMappedFile mappedFile, byte[] searchPattern)
{
using (var accessor = mappedFile.CreateViewAccessor(0, 0, MemoryMappedFileAccess.Read))
{
var safeBuffer = accessor.SafeMemoryMappedViewHandle;
return KMPSearch(searchPattern, (byte*)safeBuffer.DangerousGetHandle(), (int)safeBuffer.ByteLength);
using (var accessor = mappedFile.CreateViewAccessor())
{
SearchAndReplace(accessor, searchPattern, patternToReplace);
}
}
}

public static unsafe int SearchInFile(string filePath, byte[] searchPattern)
{
using (var mappedFile = MemoryMappedFile.CreateFromFile(filePath))
{
return SearchInFile(mappedFile, searchPattern);
using (var accessor = mappedFile.CreateViewAccessor(0, 0, MemoryMappedFileAccess.Read))
{
var safeBuffer = accessor.SafeMemoryMappedViewHandle;
return KMPSearch(searchPattern, (byte*)safeBuffer.DangerousGetHandle(), (int)safeBuffer.ByteLength);
}
}
}

Expand Down Expand Up @@ -226,10 +211,7 @@ internal static unsafe bool IsPEImage(MemoryMappedViewAccessor accessor)
/// This method will attempt to set the subsystem to GUI. The apphost file should be a windows PE file.
/// </summary>
/// <param name="accessor">The memory accessor which has the apphost file opened.</param>
/// <param name="appHostSourcePath">The path to the source apphost.</param>
internal static unsafe void SetWindowsGraphicalUserInterfaceBit(
MemoryMappedViewAccessor accessor,
string appHostSourcePath)
internal static unsafe void SetWindowsGraphicalUserInterfaceBit(MemoryMappedViewAccessor accessor)
{
byte* pointer = null;

Expand All @@ -243,7 +225,7 @@ internal static unsafe void SetWindowsGraphicalUserInterfaceBit(

if (accessor.Capacity < peHeaderOffset + SubsystemOffset + sizeof(UInt16))
{
throw new BinaryUpdateException($" Unable to use '{appHostSourcePath}' as application host executable because it's not a Windows PE file");
throw new AppHostNotPEFileException();
}

UInt16* subsystem = ((UInt16*)(bytes + peHeaderOffset + SubsystemOffset));
Expand All @@ -252,7 +234,7 @@ internal static unsafe void SetWindowsGraphicalUserInterfaceBit(
// The subsystem of the prebuilt apphost should be set to CUI
if (subsystem[0] != WindowsCUISubsystem)
{
throw new BinaryUpdateException("Unable to use '{appHostSourcePath}' as application host executable because it's not a Windows executable for the CUI (Console) subsystem");
throw new AppHostNotCUIException();
}

// Set the subsystem to GUI
Expand All @@ -266,5 +248,61 @@ internal static unsafe void SetWindowsGraphicalUserInterfaceBit(
}
}
}

public static unsafe void SetWindowsGraphicalUserInterfaceBit(string filePath)
{
using (var mappedFile = MemoryMappedFile.CreateFromFile(filePath))
{
using (var accessor = mappedFile.CreateViewAccessor())
{
SetWindowsGraphicalUserInterfaceBit(accessor);
}
}
}

/// <summary>
/// This method will return the subsystem CUI/GUI value. The apphost file should be a windows PE file.
/// </summary>
/// <param name="accessor">The memory accessor which has the apphost file opened.</param>
internal static unsafe UInt16 GetWindowsGraphicalUserInterfaceBit(MemoryMappedViewAccessor accessor)
{
byte* pointer = null;

try
{
accessor.SafeMemoryMappedViewHandle.AcquirePointer(ref pointer);
byte* bytes = pointer + accessor.PointerOffset;

// https://en.wikipedia.org/wiki/Portable_Executable
UInt32 peHeaderOffset = ((UInt32*)(bytes + PEHeaderPointerOffset))[0];

if (accessor.Capacity < peHeaderOffset + SubsystemOffset + sizeof(UInt16))
{
throw new AppHostNotPEFileException();
}

UInt16* subsystem = ((UInt16*)(bytes + peHeaderOffset + SubsystemOffset));

return subsystem[0];
}
finally
{
if (pointer != null)
{
accessor.SafeMemoryMappedViewHandle.ReleasePointer();
}
}
}

public static unsafe UInt16 GetWindowsGraphicalUserInterfaceBit(string filePath)
{
using (var mappedFile = MemoryMappedFile.CreateFromFile(filePath))
{
using (var accessor = mappedFile.CreateViewAccessor())
{
return GetWindowsGraphicalUserInterfaceBit(accessor);
}
}
}
}
}
Loading

0 comments on commit 57d5072

Please sign in to comment.