[API] Win32 Resources - List Icon Resource Names

M

Mythran

I wrote some code that is supposed to enumerate through the specified file's
win32 resources and return a string-array of all icon names. When it runs,
it returns a string-array with a bunch of numbers in sequential order (1-55
when ran against iexplore.exe).

When I open up iexplore.exe in Visual Studio, I see 23 icons. Each icon has
1 or more sizes of the icon...I'm assuming that there are, in fact, 55 icon
resources in iexplore.exe, and the code I wrote is returning the indexes of
the icons? If so, how do I get the names/identifiers for the icons?

The following is my code for the ResourceExtracter class that hopefully
shows what I am trying to do...To use, just create a ResourceExtracter
instance and call GetIconNames passing the path to an exe or dll file
(C:\Program Files\Internet Explorer\iexplore.exe is the path I am using to
test with).

Thanks in advance :)

-------------------------------------------------------------------------

using System;
using System.Runtime.InteropServices;
using System.Collections;
using System.ComponentModel;

namespace Tests.Applications.ResourceViewer.UI
{
/// <summary>
/// Provides the methods to extract resources from a Win32 binary.
/// </summary>
public class ResourceExtracter
{

#region Private Members
//
=================================================================
// Private Members
//
=================================================================

private enum ResourceType : int
{
Cursor = 0x00000001,
Bitmap = 0x00000002,
Icon = 0x00000003,
Menu = 0x00000004,
Dialog = 0x00000005,
String = 0x00000006,
FontDir = 0x00000007,
Font = 0x00000008,
Accelerator = 0x00000009,
RcData = 0x0000000a,
MessageTable = 0x0000000b
}

private const int LOAD_LIBRARY_AS_DATAFILE = 0x00000002;
private const int ERROR_RESOURCE_TYPE_NOT_FOUND = 0x00000715;

private string mFilePath = null;

private delegate bool EnumResNameDelegate(
IntPtr ModuleHandle,
IntPtr Type,
IntPtr Name,
IntPtr Param
);
#endregion

#region API Declarations
//
=================================================================
// API Declarations
//
=================================================================

[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr LoadLibraryEx(
string FileName,
IntPtr FileHandle,
uint Flags
);

[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool FreeLibrary(IntPtr ModuleHandle);

[
DllImport(
"kernel32.dll",
EntryPoint = "EnumResourceNamesW",
CharSet = CharSet.Unicode,
SetLastError = true
)
]
private static extern bool EnumResourceNamesWithName(
IntPtr ModuleHandle,
ResourceType Type,
EnumResNameDelegate EnumFunc,
IntPtr Param
);

[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr FindResource(
IntPtr ModuleHandle,
string Name,
string Type
);

[
DllImport(
"kernel32.dll",
EntryPoint = "EnumResourceNamesW",
CharSet = CharSet.Unicode,
SetLastError = true
)
]
private static extern bool EnumResourceNamesWithID(
IntPtr ModuleHandle,
ResourceType Type,
EnumResNameDelegate EnumFunc,
IntPtr Param
);
#endregion

#region Constructors / Destructors
//
=================================================================
// Constructors / Destructors
//
=================================================================

/// <summary>
/// Creates a new instance of the <see
cref="ResourceExtracter"/>
/// class.
/// </summary>
/// <param name="FilePath"></param>
public ResourceExtracter(string FilePath)
{
mFilePath = FilePath;
}
#endregion

#region Public Properties
//
=================================================================
// Public Properties
//
=================================================================

/// <summary>
/// Specifies the path of the Win32 binary.
/// </summary>
public string FilePath
{
get {
return mFilePath;
}
set {
mFilePath = value;
}
}
#endregion

#region Public Methods
//
=================================================================
// Public Methods
//
=================================================================

/// <summary>
/// Gets the icon resource names for the current file.
/// </summary>
public string[] GetIconNames()
{
return GetResourceNames(ResourceType.Icon);
}

/// <summary>
/// Gets the string resource names for the current file.
/// </summary>
public string[] GetStringNames()
{
return GetResourceNames(ResourceType.String);
}
#endregion

#region Private Methods
//
=================================================================
// Private Methods
//
=================================================================

private string[] GetResourceNames(ResourceType Type)
{
ArrayList names = new ArrayList();

// Get the handle to the library.
IntPtr moduleHandle = GetLibraryModule(this.FilePath);

try {
FillResourceNames(moduleHandle, Type, names);
} finally {
// Cleanup.
FreeLibrary(moduleHandle);
}

// Convert the names into a string-array and return it.
return (string[]) names.ToArray(typeof(string));
}

/// <summary>
/// Load the specified library and return the handle.
/// </summary>
/// <param name="LibraryPath">
/// The path to the library to load (.dll or .exe).
/// </param>
/// <returns>
/// Returns an <see cref="IntPtr"/> that represents the handle
to
/// the library module loaded.
/// </returns>
private IntPtr GetLibraryModule(string LibraryPath)
{
// Load the library.
IntPtr result = LoadLibraryEx(
LibraryPath,
IntPtr.Zero,
LOAD_LIBRARY_AS_DATAFILE
);

if (result == IntPtr.Zero) {
// Error occurred.
throw new Win32Exception(Marshal.GetLastWin32Error());
} else {
return result;
}
}

/// <summary>
/// Fills the <paramref name="List"/> with all of the resource
names
/// of the specified <paramref name="ResourceType"/>.
/// </summary>
/// <param name="ModuleHandle">
/// The handle to the library module that contains the
resource(s)
/// to retrieve.
/// </param>
/// <param name="Type">The type of resource to retrieve.</param>
/// <param name="List">
/// The <see cref="ArrayList"/> to place the results into.
/// </param>
private void FillResourceNames(
IntPtr ModuleHandle,
ResourceType Type,
ArrayList List
)
{
// Get the ptr to the ArrayList.
GCHandle listHandle = GCHandle.Alloc(List);

try {
// Enumerate the resource names.
bool result = EnumResourceNamesWithID(
ModuleHandle,
Type,
new EnumResNameDelegate(EnumRes),
(IntPtr) listHandle
);

// Check for errors.
if (!result) {
int code = Marshal.GetLastWin32Error();
if (code != ERROR_RESOURCE_TYPE_NOT_FOUND) {
// Raise a Win32Exception for any errors except
// for when the specified resource type could
not
// be found.
throw new Win32Exception(code);
}
}
} finally {
// Release the allocated ArrayList.
listHandle.Free();
}
}

private static bool IsIntResource(IntPtr Value)
{
return (((ulong) Value) >> 16) == 0;
}

private bool EnumRes(
IntPtr ModuleHandle,
IntPtr Type,
IntPtr Name,
IntPtr Param
)
{
GCHandle listHandle = (GCHandle) Param;
ArrayList list = (ArrayList) listHandle.Target;

string name = null;
if (IsIntResource(Name)) {
name = ((int) Name).ToString();
} else {
name = Marshal.PtrToStringAuto(Name);
}

list.Add(name);
return true;
}
#endregion

}
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top