using System; using System.Runtime.InteropServices; namespace Vanara.PInvoke { public static partial class Kernel32 { /// /// Retrieves a handle that can be used by the UpdateResource function to add, delete, or replace resources in a binary module. /// /// /// Type: LPCTSTR /// /// 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 cannot be currently executing. If pFileName does not specify a full path, the system searches for the /// file in the current directory. /// /// /// /// Type: BOOL /// /// Indicates whether to delete the pFileName parameter's existing resources. If this parameter is TRUE, existing resources /// are deleted and the updated file includes only resources added with the UpdateResource function. If this parameter is /// FALSE, the updated file includes existing resources unless they are explicitly deleted or replaced by using UpdateResource. /// /// /// /// Type: HANDLE /// /// If the function succeeds, the return value is a handle that can be used by the UpdateResource and EndUpdateResource /// functions. The return value is NULL if the specified file is not a PE, the file does not exist, or the file cannot be /// opened for writing. To get extended error information, call GetLastError. /// /// // HANDLE WINAPI BeginUpdateResource( _In_ LPCTSTR pFileName, _In_ BOOL bDeleteExistingResources); https://msdn.microsoft.com/en-us/library/windows/desktop/ms648030(v=vs.85).aspx [DllImport(Lib.Kernel32, SetLastError = true, CharSet = CharSet.Auto)] [PInvokeData("Winbase.h", MSDNShortId = "ms648030")] public static extern SafeHUPDRES BeginUpdateResource(string pFileName, [MarshalAs(UnmanagedType.Bool)] bool bDeleteExistingResources); /// Commits or discards changes made prior to a call to UpdateResource. /// /// Type: HANDLE /// /// A module handle returned by the BeginUpdateResource function, and used by UpdateResource, referencing the file to /// be updated. /// /// /// /// Type: BOOL /// /// Indicates whether to write the resource updates to the file. If this parameter is TRUE, no changes are made. If it is /// FALSE, the changes are made: the resource updates will take effect. /// /// /// /// Type: BOOL /// /// Returns TRUE if the function succeeds; FALSE otherwise. If the function succeeds and fDiscard is TRUE, then /// no resource updates are made to the file; otherwise all successful resource updates are made to the file. To get extended error /// information, call GetLastError. /// /// // BOOL WINAPI EndUpdateResource( _In_ HANDLE hUpdate, _In_ BOOL fDiscard); https://msdn.microsoft.com/en-us/library/windows/desktop/ms648032(v=vs.85).aspx [DllImport(Lib.Kernel32, SetLastError = true, CharSet = CharSet.Auto)] [PInvokeData("Winbase.h", MSDNShortId = "ms648032")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool EndUpdateResource([In] HUPDRES hUpdate, [MarshalAs(UnmanagedType.Bool)] bool fDiscard); /// /// Adds, deletes, or replaces a resource in a portable executable (PE) file. There are some restrictions on resource updates in /// files that contain Resource Configuration (RC Config) data: language-neutral (LN) files and language-specific resource (.mui) files. /// /// /// Type: HANDLE /// A module handle returned by the BeginUpdateResource function, referencing the file to be updated. /// /// /// Type: LPCTSTR /// /// The resource type to be updated. Alternatively, rather than a pointer, this parameter can be MAKEINTRESOURCE(ID), where ID /// is an integer value representing a predefined resource type. If the first character of the string is a pound sign (#), then the /// remaining characters represent a decimal number that specifies the integer identifier of the resource type. For example, the /// string "#258" represents the identifier 258. /// /// For a list of predefined resource types, see Resource Types. /// /// /// Type: LPCTSTR /// /// The name of the resource to be updated. Alternatively, rather than a pointer, this parameter can be MAKEINTRESOURCE(ID), /// where ID is a resource ID. When creating a new resource do not use a string that begins with a '#' character for this parameter. /// /// /// /// Type: WORD /// /// The language identifier of the resource to be updated. For a list of the primary language identifiers and sublanguage identifiers /// that make up a language identifier, see the MAKELANGID macro. /// /// /// /// Type: LPVOID /// /// 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 properly aligned. Note that this is the raw binary data to be stored in the file indicated by hUpdate, not the /// data provided by LoadIcon, LoadString, or other resource-specific load functions. All data containing strings or /// text must be in Unicode format. lpData must not point to ANSI data. /// /// If lpData is NULL and cbData is 0, the specified resource is deleted from the file indicated by hUpdate. /// /// /// Type: DWORD /// The size, in bytes, of the resource data at lpData. /// /// /// Type: BOOL /// Returns TRUE if successful or FALSE otherwise. To get extended error information, call GetLastError. /// // BOOL WINAPI UpdateResource( _In_ HANDLE hUpdate, _In_ LPCTSTR lpType, _In_ LPCTSTR lpName, _In_ WORD wLanguage, _In_opt_ LPVOID // 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)] [PInvokeData("Winbase.h", MSDNShortId = "ms648049")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool UpdateResource([In] HUPDRES hUpdate, SafeResourceId lpType, SafeResourceId lpName, ushort wLanguage, [In] IntPtr lpData, uint cbData); /// Provides a handle to an update resource. [StructLayout(LayoutKind.Sequential)] public struct HUPDRES : IHandle { private IntPtr handle; /// Initializes a new instance of the struct. /// An object that represents the pre-existing handle to use. public HUPDRES(IntPtr preexistingHandle) => handle = preexistingHandle; /// Returns an invalid handle by instantiating a object with . public static HUPDRES NULL => new HUPDRES(IntPtr.Zero); /// Gets a value indicating whether this instance is a null handle. public bool IsNull => handle == IntPtr.Zero; /// Performs an explicit conversion from to . /// The handle. /// The result of the conversion. public static explicit operator IntPtr(HUPDRES h) => h.handle; /// Performs an implicit conversion from to . /// The pointer to a handle. /// The result of the conversion. public static implicit operator HUPDRES(IntPtr h) => new HUPDRES(h); /// Implements the operator !=. /// The first handle. /// The second handle. /// The result of the operator. public static bool operator !=(HUPDRES h1, HUPDRES h2) => !(h1 == h2); /// Implements the operator ==. /// The first handle. /// The second handle. /// The result of the operator. public static bool operator ==(HUPDRES h1, HUPDRES h2) => h1.Equals(h2); /// public override bool Equals(object obj) => obj is HUPDRES h ? handle == h.handle : false; /// public override int GetHashCode() => handle.GetHashCode(); /// public IntPtr DangerousGetHandle() => handle; } /// Provides a for that is disposed using . public class SafeHUPDRES : SafeHANDLE { /// Initializes a new instance of the class and assigns an existing handle. /// An object that represents the pre-existing handle to use. /// /// to reliably release the handle during the finalization phase; otherwise, (not recommended). /// public SafeHUPDRES(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { } /// Initializes a new instance of the class. private SafeHUPDRES() : base() { } /// Indicates whether to discard any changes rather than write the resource updates to the file. /// true to ignore changes; otherwise, false. public bool IgnoreChanges { get; set; } = false; /// Performs an implicit conversion from to . /// The safe handle instance. /// The result of the conversion. public static implicit operator HUPDRES(SafeHUPDRES h) => h.handle; /// protected override bool InternalReleaseHandle() => EndUpdateResource(handle, IgnoreChanges); } } }