mirror of https://github.com/dahall/Vanara.git
Finished unit tests and fixes for winbase.h resource functions
parent
288d622f1d
commit
4ef4ece88f
|
@ -5,65 +5,70 @@ namespace Vanara.PInvoke
|
||||||
{
|
{
|
||||||
public static partial class Kernel32
|
public static partial class Kernel32
|
||||||
{
|
{
|
||||||
/// <summary>Retrieves a handle that can be used by the <c>UpdateResource</c> function to add, delete, or replace resources in a binary module.</summary>
|
/// <summary>
|
||||||
|
/// Retrieves a handle that can be used by the <c>UpdateResource</c> function to add, delete, or replace resources in a binary module.
|
||||||
|
/// </summary>
|
||||||
/// <param name="pFileName">
|
/// <param name="pFileName">
|
||||||
/// <para>Type: <c>LPCTSTR</c></para>
|
/// <para>Type: <c>LPCTSTR</c></para>
|
||||||
/// <para>
|
/// <para>
|
||||||
/// The binary file in which to update resources. An application must be able to obtain write-access to this file; the file referenced by pFileName
|
/// The binary file in which to update resources. An application must be able to obtain write-access to this file; the file
|
||||||
/// cannot be currently executing. If pFileName does not specify a full path, the system searches for the file in the current directory.
|
/// referenced by pFileName cannot be currently executing. If pFileName does not specify a full path, the system searches for the
|
||||||
|
/// file in the current directory.
|
||||||
/// </para>
|
/// </para>
|
||||||
/// </param>
|
/// </param>
|
||||||
/// <param name="bDeleteExistingResources">
|
/// <param name="bDeleteExistingResources">
|
||||||
/// <para>Type: <c>BOOL</c></para>
|
/// <para>Type: <c>BOOL</c></para>
|
||||||
/// <para>
|
/// <para>
|
||||||
/// Indicates whether to delete the pFileName parameter's existing resources. If this parameter is <c>TRUE</c>, existing resources are deleted and the
|
/// Indicates whether to delete the pFileName parameter's existing resources. If this parameter is <c>TRUE</c>, existing resources
|
||||||
/// updated file includes only resources added with the <c>UpdateResource</c> function. If this parameter is <c>FALSE</c>, the updated file includes
|
/// are deleted and the updated file includes only resources added with the <c>UpdateResource</c> function. If this parameter is
|
||||||
/// existing resources unless they are explicitly deleted or replaced by using <c>UpdateResource</c>.
|
/// <c>FALSE</c>, the updated file includes existing resources unless they are explicitly deleted or replaced by using <c>UpdateResource</c>.
|
||||||
/// </para>
|
/// </para>
|
||||||
/// </param>
|
/// </param>
|
||||||
/// <returns>
|
/// <returns>
|
||||||
/// <para>Type: <c>HANDLE</c></para>
|
/// <para>Type: <c>HANDLE</c></para>
|
||||||
/// <para>
|
/// <para>
|
||||||
/// If the function succeeds, the return value is a handle that can be used by the <c>UpdateResource</c> and <c>EndUpdateResource</c> functions. The
|
/// If the function succeeds, the return value is a handle that can be used by the <c>UpdateResource</c> and <c>EndUpdateResource</c>
|
||||||
/// return value is <c>NULL</c> if the specified file is not a PE, the file does not exist, or the file cannot be opened for writing. To get extended
|
/// functions. The return value is <c>NULL</c> if the specified file is not a PE, the file does not exist, or the file cannot be
|
||||||
/// error information, call <c>GetLastError</c>.
|
/// opened for writing. To get extended error information, call <c>GetLastError</c>.
|
||||||
/// </para>
|
/// </para>
|
||||||
/// </returns>
|
/// </returns>
|
||||||
// HANDLE WINAPI BeginUpdateResource( _In_ LPCTSTR pFileName, _In_ BOOL bDeleteExistingResources);
|
// HANDLE WINAPI BeginUpdateResource( _In_ LPCTSTR pFileName, _In_ BOOL bDeleteExistingResources); https://msdn.microsoft.com/en-us/library/windows/desktop/ms648030(v=vs.85).aspx
|
||||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms648030(v=vs.85).aspx
|
|
||||||
[DllImport(Lib.Kernel32, SetLastError = true, CharSet = CharSet.Auto)]
|
[DllImport(Lib.Kernel32, SetLastError = true, CharSet = CharSet.Auto)]
|
||||||
[PInvokeData("Winbase.h", MSDNShortId = "ms648030")]
|
[PInvokeData("Winbase.h", MSDNShortId = "ms648030")]
|
||||||
public static extern UpdateResourceHandle BeginUpdateResource(string pFileName, [MarshalAs(UnmanagedType.Bool)] bool bDeleteExistingResources);
|
public static extern SafeHUPDRES BeginUpdateResource(string pFileName, [MarshalAs(UnmanagedType.Bool)] bool bDeleteExistingResources);
|
||||||
|
|
||||||
/// <summary>Commits or discards changes made prior to a call to <c>UpdateResource</c>.</summary>
|
/// <summary>Commits or discards changes made prior to a call to <c>UpdateResource</c>.</summary>
|
||||||
/// <param name="hUpdate">
|
/// <param name="hUpdate">
|
||||||
/// <para>Type: <c>HANDLE</c></para>
|
/// <para>Type: <c>HANDLE</c></para>
|
||||||
/// <para>A module handle returned by the <c>BeginUpdateResource</c> function, and used by <c>UpdateResource</c>, referencing the file to be updated.</para>
|
/// <para>
|
||||||
|
/// A module handle returned by the <c>BeginUpdateResource</c> function, and used by <c>UpdateResource</c>, referencing the file to
|
||||||
|
/// be updated.
|
||||||
|
/// </para>
|
||||||
/// </param>
|
/// </param>
|
||||||
/// <param name="fDiscard">
|
/// <param name="fDiscard">
|
||||||
/// <para>Type: <c>BOOL</c></para>
|
/// <para>Type: <c>BOOL</c></para>
|
||||||
/// <para>
|
/// <para>
|
||||||
/// Indicates whether to write the resource updates to the file. If this parameter is <c>TRUE</c>, no changes are made. If it is <c>FALSE</c>, the
|
/// Indicates whether to write the resource updates to the file. If this parameter is <c>TRUE</c>, no changes are made. If it is
|
||||||
/// changes are made: the resource updates will take effect.
|
/// <c>FALSE</c>, the changes are made: the resource updates will take effect.
|
||||||
/// </para>
|
/// </para>
|
||||||
/// </param>
|
/// </param>
|
||||||
/// <returns>
|
/// <returns>
|
||||||
/// <para>Type: <c>BOOL</c></para>
|
/// <para>Type: <c>BOOL</c></para>
|
||||||
/// <para>
|
/// <para>
|
||||||
/// Returns <c>TRUE</c> if the function succeeds; <c>FALSE</c> otherwise. If the function succeeds and fDiscard is <c>TRUE</c>, then no resource updates
|
/// Returns <c>TRUE</c> if the function succeeds; <c>FALSE</c> otherwise. If the function succeeds and fDiscard is <c>TRUE</c>, then
|
||||||
/// are made to the file; otherwise all successful resource updates are made to the file. To get extended error information, call <c>GetLastError</c>.
|
/// no resource updates are made to the file; otherwise all successful resource updates are made to the file. To get extended error
|
||||||
|
/// information, call <c>GetLastError</c>.
|
||||||
/// </para>
|
/// </para>
|
||||||
/// </returns>
|
/// </returns>
|
||||||
// BOOL WINAPI EndUpdateResource( _In_ HANDLE hUpdate, _In_ BOOL fDiscard);
|
// BOOL WINAPI EndUpdateResource( _In_ HANDLE hUpdate, _In_ BOOL fDiscard); https://msdn.microsoft.com/en-us/library/windows/desktop/ms648032(v=vs.85).aspx
|
||||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms648032(v=vs.85).aspx
|
|
||||||
[DllImport(Lib.Kernel32, SetLastError = true, CharSet = CharSet.Auto)]
|
[DllImport(Lib.Kernel32, SetLastError = true, CharSet = CharSet.Auto)]
|
||||||
[PInvokeData("Winbase.h", MSDNShortId = "ms648032")]
|
[PInvokeData("Winbase.h", MSDNShortId = "ms648032")]
|
||||||
[return: MarshalAs(UnmanagedType.Bool)]
|
[return: MarshalAs(UnmanagedType.Bool)]
|
||||||
public static extern bool EndUpdateResource([In] UpdateResourceHandle hUpdate, [MarshalAs(UnmanagedType.Bool)] bool fDiscard);
|
public static extern bool EndUpdateResource([In] HUPDRES hUpdate, [MarshalAs(UnmanagedType.Bool)] bool fDiscard);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds, deletes, or replaces a resource in a portable executable (PE) file. There are some restrictions on resource updates in files that contain
|
/// Adds, deletes, or replaces a resource in a portable executable (PE) file. There are some restrictions on resource updates in
|
||||||
/// Resource Configuration (RC Config) data: language-neutral (LN) files and language-specific resource (.mui) files.
|
/// files that contain Resource Configuration (RC Config) data: language-neutral (LN) files and language-specific resource (.mui) files.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="hUpdate">
|
/// <param name="hUpdate">
|
||||||
/// <para>Type: <c>HANDLE</c></para>
|
/// <para>Type: <c>HANDLE</c></para>
|
||||||
|
@ -72,33 +77,34 @@ namespace Vanara.PInvoke
|
||||||
/// <param name="lpType">
|
/// <param name="lpType">
|
||||||
/// <para>Type: <c>LPCTSTR</c></para>
|
/// <para>Type: <c>LPCTSTR</c></para>
|
||||||
/// <para>
|
/// <para>
|
||||||
/// The resource type to be updated. Alternatively, rather than a pointer, this parameter can be <c>MAKEINTRESOURCE</c>(ID), where ID is an integer value
|
/// The resource type to be updated. Alternatively, rather than a pointer, this parameter can be <c>MAKEINTRESOURCE</c>(ID), where ID
|
||||||
/// representing a predefined resource type. If the first character of the string is a pound sign (#), then the remaining characters represent a decimal
|
/// is an integer value representing a predefined resource type. If the first character of the string is a pound sign (#), then the
|
||||||
/// number that specifies the integer identifier of the resource type. For example, the string "#258" represents the identifier 258.
|
/// remaining characters represent a decimal number that specifies the integer identifier of the resource type. For example, the
|
||||||
|
/// string "#258" represents the identifier 258.
|
||||||
/// </para>
|
/// </para>
|
||||||
/// <para>For a list of predefined resource types, see Resource Types.</para>
|
/// <para>For a list of predefined resource types, see Resource Types.</para>
|
||||||
/// </param>
|
/// </param>
|
||||||
/// <param name="lpName">
|
/// <param name="lpName">
|
||||||
/// <para>Type: <c>LPCTSTR</c></para>
|
/// <para>Type: <c>LPCTSTR</c></para>
|
||||||
/// <para>
|
/// <para>
|
||||||
/// The name of the resource to be updated. Alternatively, rather than a pointer, this parameter can be <c>MAKEINTRESOURCE</c>(ID), where ID is a
|
/// The name of the resource to be updated. Alternatively, rather than a pointer, this parameter can be <c>MAKEINTRESOURCE</c>(ID),
|
||||||
/// resource ID. When creating a new resource do not use a string that begins with a '#' character for this parameter.
|
/// where ID is a resource ID. When creating a new resource do not use a string that begins with a '#' character for this parameter.
|
||||||
/// </para>
|
/// </para>
|
||||||
/// </param>
|
/// </param>
|
||||||
/// <param name="wLanguage">
|
/// <param name="wLanguage">
|
||||||
/// <para>Type: <c>WORD</c></para>
|
/// <para>Type: <c>WORD</c></para>
|
||||||
/// <para>
|
/// <para>
|
||||||
/// The language identifier of the resource to be updated. For a list of the primary language identifiers and sublanguage identifiers that make up a
|
/// The language identifier of the resource to be updated. For a list of the primary language identifiers and sublanguage identifiers
|
||||||
/// language identifier, see the <c>MAKELANGID</c> macro.
|
/// that make up a language identifier, see the <c>MAKELANGID</c> macro.
|
||||||
/// </para>
|
/// </para>
|
||||||
/// </param>
|
/// </param>
|
||||||
/// <param name="lpData">
|
/// <param name="lpData">
|
||||||
/// <para>Type: <c>LPVOID</c></para>
|
/// <para>Type: <c>LPVOID</c></para>
|
||||||
/// <para>
|
/// <para>
|
||||||
/// The resource data to be inserted into the file indicated by hUpdate. If the resource is one of the predefined types, the data must be valid and
|
/// The resource data to be inserted into the file indicated by hUpdate. If the resource is one of the predefined types, the data
|
||||||
/// properly aligned. Note that this is the raw binary data to be stored in the file indicated by hUpdate, not the data provided by <c>LoadIcon</c>,
|
/// must be valid and properly aligned. Note that this is the raw binary data to be stored in the file indicated by hUpdate, not the
|
||||||
/// <c>LoadString</c>, or other resource-specific load functions. All data containing strings or text must be in Unicode format. lpData must not point to
|
/// data provided by <c>LoadIcon</c>, <c>LoadString</c>, or other resource-specific load functions. All data containing strings or
|
||||||
/// ANSI data.
|
/// text must be in Unicode format. lpData must not point to ANSI data.
|
||||||
/// </para>
|
/// </para>
|
||||||
/// <para>If lpData is <c>NULL</c> and cbData is 0, the specified resource is deleted from the file indicated by hUpdate.</para>
|
/// <para>If lpData is <c>NULL</c> and cbData is 0, the specified resource is deleted from the file indicated by hUpdate.</para>
|
||||||
/// </param>
|
/// </param>
|
||||||
|
@ -110,53 +116,53 @@ namespace Vanara.PInvoke
|
||||||
/// <para>Type: <c>BOOL</c></para>
|
/// <para>Type: <c>BOOL</c></para>
|
||||||
/// <para>Returns <c>TRUE</c> if successful or <c>FALSE</c> otherwise. To get extended error information, call <c>GetLastError</c>.</para>
|
/// <para>Returns <c>TRUE</c> if successful or <c>FALSE</c> otherwise. To get extended error information, call <c>GetLastError</c>.</para>
|
||||||
/// </returns>
|
/// </returns>
|
||||||
// BOOL WINAPI UpdateResource( _In_ HANDLE hUpdate, _In_ LPCTSTR lpType, _In_ LPCTSTR lpName, _In_ WORD wLanguage, _In_opt_ LPVOID lpData, _In_ DWORD cbData);
|
// BOOL WINAPI UpdateResource( _In_ HANDLE hUpdate, _In_ LPCTSTR lpType, _In_ LPCTSTR lpName, _In_ WORD wLanguage, _In_opt_ LPVOID
|
||||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms648049(v=vs.85).aspx
|
// lpData, _In_ DWORD cbData); https://msdn.microsoft.com/en-us/library/windows/desktop/ms648049(v=vs.85).aspx
|
||||||
[DllImport(Lib.Kernel32, SetLastError = true, CharSet = CharSet.Auto)]
|
[DllImport(Lib.Kernel32, SetLastError = true, CharSet = CharSet.Auto)]
|
||||||
[PInvokeData("Winbase.h", MSDNShortId = "ms648049")]
|
[PInvokeData("Winbase.h", MSDNShortId = "ms648049")]
|
||||||
[return: MarshalAs(UnmanagedType.Bool)]
|
[return: MarshalAs(UnmanagedType.Bool)]
|
||||||
public static extern bool UpdateResource([In] UpdateResourceHandle hUpdate, string lpType, string lpName, ushort wLanguage, [In] IntPtr lpData, uint cbData);
|
public static extern bool UpdateResource([In] HUPDRES hUpdate, SafeResourceId lpType, SafeResourceId lpName, ushort wLanguage, [In] IntPtr lpData, uint cbData);
|
||||||
|
|
||||||
/// <summary>Provides a handle that can be used by UpdateResource.</summary>
|
/// <summary>Provides a handle to an update resource.</summary>
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
public struct UpdateResourceHandle : IHandle
|
public struct HUPDRES : IHandle
|
||||||
{
|
{
|
||||||
private IntPtr handle;
|
private IntPtr handle;
|
||||||
|
|
||||||
/// <summary>Initializes a new instance of the <see cref="UpdateResourceHandle"/> struct.</summary>
|
/// <summary>Initializes a new instance of the <see cref="HUPDRES"/> struct.</summary>
|
||||||
/// <param name="preexistingHandle">An <see cref="IntPtr"/> object that represents the pre-existing handle to use.</param>
|
/// <param name="preexistingHandle">An <see cref="IntPtr"/> object that represents the pre-existing handle to use.</param>
|
||||||
public UpdateResourceHandle(IntPtr preexistingHandle) => handle = preexistingHandle;
|
public HUPDRES(IntPtr preexistingHandle) => handle = preexistingHandle;
|
||||||
|
|
||||||
/// <summary>Returns an invalid handle by instantiating a <see cref="UpdateResourceHandle"/> object with <see cref="IntPtr.Zero"/>.</summary>
|
/// <summary>Returns an invalid handle by instantiating a <see cref="HUPDRES"/> object with <see cref="IntPtr.Zero"/>.</summary>
|
||||||
public static UpdateResourceHandle NULL => new UpdateResourceHandle(IntPtr.Zero);
|
public static HUPDRES NULL => new HUPDRES(IntPtr.Zero);
|
||||||
|
|
||||||
/// <summary>Gets a value indicating whether this instance is a null handle.</summary>
|
/// <summary>Gets a value indicating whether this instance is a null handle.</summary>
|
||||||
public bool IsNull => handle == IntPtr.Zero;
|
public bool IsNull => handle == IntPtr.Zero;
|
||||||
|
|
||||||
/// <summary>Performs an explicit conversion from <see cref="UpdateResourceHandle"/> to <see cref="IntPtr"/>.</summary>
|
/// <summary>Performs an explicit conversion from <see cref="HUPDRES"/> to <see cref="IntPtr"/>.</summary>
|
||||||
/// <param name="h">The handle.</param>
|
/// <param name="h">The handle.</param>
|
||||||
/// <returns>The result of the conversion.</returns>
|
/// <returns>The result of the conversion.</returns>
|
||||||
public static explicit operator IntPtr(UpdateResourceHandle h) => h.handle;
|
public static explicit operator IntPtr(HUPDRES h) => h.handle;
|
||||||
|
|
||||||
/// <summary>Performs an implicit conversion from <see cref="IntPtr"/> to <see cref="UpdateResourceHandle"/>.</summary>
|
/// <summary>Performs an implicit conversion from <see cref="IntPtr"/> to <see cref="HUPDRES"/>.</summary>
|
||||||
/// <param name="h">The pointer to a handle.</param>
|
/// <param name="h">The pointer to a handle.</param>
|
||||||
/// <returns>The result of the conversion.</returns>
|
/// <returns>The result of the conversion.</returns>
|
||||||
public static implicit operator UpdateResourceHandle(IntPtr h) => new UpdateResourceHandle(h);
|
public static implicit operator HUPDRES(IntPtr h) => new HUPDRES(h);
|
||||||
|
|
||||||
/// <summary>Implements the operator !=.</summary>
|
/// <summary>Implements the operator !=.</summary>
|
||||||
/// <param name="h1">The first handle.</param>
|
/// <param name="h1">The first handle.</param>
|
||||||
/// <param name="h2">The second handle.</param>
|
/// <param name="h2">The second handle.</param>
|
||||||
/// <returns>The result of the operator.</returns>
|
/// <returns>The result of the operator.</returns>
|
||||||
public static bool operator !=(UpdateResourceHandle h1, UpdateResourceHandle h2) => !(h1 == h2);
|
public static bool operator !=(HUPDRES h1, HUPDRES h2) => !(h1 == h2);
|
||||||
|
|
||||||
/// <summary>Implements the operator ==.</summary>
|
/// <summary>Implements the operator ==.</summary>
|
||||||
/// <param name="h1">The first handle.</param>
|
/// <param name="h1">The first handle.</param>
|
||||||
/// <param name="h2">The second handle.</param>
|
/// <param name="h2">The second handle.</param>
|
||||||
/// <returns>The result of the operator.</returns>
|
/// <returns>The result of the operator.</returns>
|
||||||
public static bool operator ==(UpdateResourceHandle h1, UpdateResourceHandle h2) => h1.Equals(h2);
|
public static bool operator ==(HUPDRES h1, HUPDRES h2) => h1.Equals(h2);
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public override bool Equals(object obj) => obj is UpdateResourceHandle h ? handle == h.handle : false;
|
public override bool Equals(object obj) => obj is HUPDRES h ? handle == h.handle : false;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public override int GetHashCode() => handle.GetHashCode();
|
public override int GetHashCode() => handle.GetHashCode();
|
||||||
|
@ -164,5 +170,31 @@ namespace Vanara.PInvoke
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public IntPtr DangerousGetHandle() => handle;
|
public IntPtr DangerousGetHandle() => handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Provides a <see cref="SafeHandle"/> for <see cref="HUPDRES"/> that is disposed using <see cref="EndUpdateResource"/>.</summary>
|
||||||
|
public class SafeHUPDRES : SafeHANDLE
|
||||||
|
{
|
||||||
|
/// <summary>Initializes a new instance of the <see cref="SafeHUPDRES"/> class and assigns an existing handle.</summary>
|
||||||
|
/// <param name="preexistingHandle">An <see cref="IntPtr"/> object that represents the pre-existing handle to use.</param>
|
||||||
|
/// <param name="ownsHandle">
|
||||||
|
/// <see langword="true"/> to reliably release the handle during the finalization phase; otherwise, <see langword="false"/> (not recommended).
|
||||||
|
/// </param>
|
||||||
|
public SafeHUPDRES(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { }
|
||||||
|
|
||||||
|
/// <summary>Initializes a new instance of the <see cref="SafeHUPDRES"/> class.</summary>
|
||||||
|
private SafeHUPDRES() : base() { }
|
||||||
|
|
||||||
|
/// <summary>Indicates whether to discard any changes rather than write the resource updates to the file.</summary>
|
||||||
|
/// <value><c>true</c> to ignore changes; otherwise, <c>false</c>.</value>
|
||||||
|
public bool IgnoreChanges { get; set; } = false;
|
||||||
|
|
||||||
|
/// <summary>Performs an implicit conversion from <see cref="SafeHUPDRES"/> to <see cref="HUPDRES"/>.</summary>
|
||||||
|
/// <param name="h">The safe handle instance.</param>
|
||||||
|
/// <returns>The result of the conversion.</returns>
|
||||||
|
public static implicit operator HUPDRES(SafeHUPDRES h) => h.handle;
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
protected override bool InternalReleaseHandle() => EndUpdateResource(handle, IgnoreChanges);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -48,6 +48,7 @@
|
||||||
<Compile Include="AppModelTests.cs" />
|
<Compile Include="AppModelTests.cs" />
|
||||||
<Compile Include="InterlockedApiTests.cs" />
|
<Compile Include="InterlockedApiTests.cs" />
|
||||||
<Compile Include="InteropServices\SafeLocalHandleTests.cs" />
|
<Compile Include="InteropServices\SafeLocalHandleTests.cs" />
|
||||||
|
<Compile Include="WinBase.ResourceTests.cs" />
|
||||||
<Compile Include="WinBase.ProfileTests.cs" />
|
<Compile Include="WinBase.ProfileTests.cs" />
|
||||||
<Compile Include="WinBase.ProcessThreadTests.cs" />
|
<Compile Include="WinBase.ProcessThreadTests.cs" />
|
||||||
<Compile Include="WinBase.PowerTests.cs" />
|
<Compile Include="WinBase.PowerTests.cs" />
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
using NUnit.Framework;
|
||||||
|
using static Vanara.PInvoke.Kernel32;
|
||||||
|
|
||||||
|
namespace Vanara.PInvoke.Tests
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public partial class WinBaseTests_Resource
|
||||||
|
{
|
||||||
|
private const string ResExe = @"C:\Temp\DummyResourceExe.exe";
|
||||||
|
private const int ResId1 = 103;
|
||||||
|
private const int ResId2 = 129;
|
||||||
|
private const int ResType = (int)ResourceType.RT_DIALOG;
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void UpdateResourceTest()
|
||||||
|
{
|
||||||
|
using (var tmp = new TempFile())
|
||||||
|
{
|
||||||
|
Assert.That(CopyFile(ResExe, tmp.FullName, false), ResultIs.Successful);
|
||||||
|
|
||||||
|
// Load the .EXE file that contains the dialog box you want to copy.
|
||||||
|
using (var hExe = LoadLibraryEx(ResExe, LoadLibraryExFlags.LOAD_LIBRARY_AS_DATAFILE | LoadLibraryExFlags.LOAD_LIBRARY_AS_IMAGE_RESOURCE))
|
||||||
|
{
|
||||||
|
Assert.That(hExe, ResultIs.ValidHandle);
|
||||||
|
|
||||||
|
// Locate the resource in the .EXE file.
|
||||||
|
var hRes = FindResource(hExe, ResId1, ResType);
|
||||||
|
Assert.That(hRes, ResultIs.ValidHandle);
|
||||||
|
|
||||||
|
// Load the resource into global memory.
|
||||||
|
var hResLoad = LoadResource(hExe, hRes);
|
||||||
|
Assert.That(hResLoad, ResultIs.ValidHandle);
|
||||||
|
|
||||||
|
// Lock the resource into global memory.
|
||||||
|
var lpResLock = LockResource(hResLoad);
|
||||||
|
Assert.That(lpResLock, ResultIs.ValidHandle);
|
||||||
|
|
||||||
|
// Open the file to which you want to add the resource resource.
|
||||||
|
using (var hUpdateRes = BeginUpdateResource(tmp.FullName, false))
|
||||||
|
{
|
||||||
|
Assert.That(hUpdateRes, ResultIs.ValidHandle);
|
||||||
|
|
||||||
|
// Add the resource resource to the update list.
|
||||||
|
Assert.That(UpdateResource(hUpdateRes, ResType, ResId2, MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL),
|
||||||
|
lpResLock, SizeofResource(hExe, hRes)), ResultIs.Successful);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue