Load Resources from Win32 Executables

M

Mythran

I am attempting to read all of the resources from a Win32 executable, and
load each of them to display them on a screen. So, please help figure out
why I can't seem to get it right :)

First off, I have my API declarations (will post that at bottom). I make a
call to LoadLibraryEx. Then, if the result is not zero, I make a call to
EnumResourceNames. EnumResourceNamesDelegate (delegate for
EnumResourceNames) is called for every found resource, and this part works
fine. The names and types are passed in, but the names don't match the
actual resource names. They are passed as IntPtr's and event if I change
the type in the API declaration and delegate and function to ... say ..
string, I still get the same value...the value for type is correct (for an
Icon, I get the value of 3...which maps to RT_ICON). But the name is always
an indexed value. Or, what I believe, is the index for the Icon in the
resource list. The first one is always 1, the 2nd is 2, et cetera.

From this point, I get stuck. How can I get the actual name that I need to
use to pass to LoadResource in which the result of that call gets passed as
the handle to System.Drawing.Icon.FromHandle (for Icons),
System.Drawing.Bitmap.FromHbitmap (for Bitmaps), et cetera?

When I call LoadResource, it returns a handle (non-zero). I pass this to
Icon.FromHandle and no exception is thrown. The Height and Width properties
of the Icon are both 0 and when I save the icon to disk, it is 0 bytes (the
file is).

Any and all help is much appreciated...been stuck on this for awhile :)

Thanks,
Mythran

API Declarations that i have...

private const uint RT_CURSOR = 0x00000001;
private const uint RT_BITMAP = 0x00000002;
private const uint RT_ICON = 0x00000003;
private const uint RT_MENU = 0x00000004;
private const uint RT_DIALOG = 0x00000005;
private const uint RT_STRING = 0x00000006;
private const uint RT_FONTDIR = 0x00000007;
private const uint RT_FONT = 0x00000008;
private const uint RT_ACCELERATOR = 0x00000009;
private const uint RT_RCDATA = 0x0000000a;
private const uint RT_MESSAGETABLE = 0x0000000b;

private const uint LOAD_LIBRARY_AS_DATAFILE = 0x00000002;

[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr LoadLibraryEx(string lpFileName, IntPtr hFile,
uint dwFlags);

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

[DllImport("kernel32.dll", EntryPoint = "EnumResourceNamesW", CharSet =
CharSet.Unicode, SetLastError = true)]
static extern bool EnumResourceNamesWithName(
IntPtr hModule,
string lpszType,
EnumResNameDelegate lpEnumFunc,
IntPtr lParam);

[DllImport("kernel32.dll", EntryPoint = "EnumResourceNamesW", CharSet =
CharSet.Unicode, SetLastError = true)]
static extern bool EnumResourceNamesWithID(
IntPtr hModule,
uint lpszType,
EnumResNameDelegate lpEnumFunc,
IntPtr lParam);

private delegate bool EnumResNameDelegate(
IntPtr hModule,
IntPtr lpszType,
IntPtr lpszName,
IntPtr lParam);

[DllImport("kernel32.dll")]
static extern IntPtr FindResource(
IntPtr hModule,
IntPtr lpName,
IntPtr lpType);

[DllImport("user32.dll")]
static extern IntPtr LoadIcon(
IntPtr hModule,
string Name
);

[DllImport("kernel32.dll", SetLastError=true)]
static extern IntPtr LoadResource(IntPtr hModule, IntPtr hResInfo);
------------------------------------------------------------------
 
N

Nicholas Paldino [.NET/C# MVP]

Mythran,

In your EnumResourceNameDelegate, you get the type and the name of the
resource in a string. From there, you can call the FindResource API method,
which will give you the handle that you can pass to LoadResource, which will
give you the appropriate handle which you can then use.

Hope this helps.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Mythran said:
I am attempting to read all of the resources from a Win32 executable, and
load each of them to display them on a screen. So, please help figure out
why I can't seem to get it right :)

First off, I have my API declarations (will post that at bottom). I make
a call to LoadLibraryEx. Then, if the result is not zero, I make a call
to EnumResourceNames. EnumResourceNamesDelegate (delegate for
EnumResourceNames) is called for every found resource, and this part works
fine. The names and types are passed in, but the names don't match the
actual resource names. They are passed as IntPtr's and event if I change
the type in the API declaration and delegate and function to ... say ..
string, I still get the same value...the value for type is correct (for an
Icon, I get the value of 3...which maps to RT_ICON). But the name is
always an indexed value. Or, what I believe, is the index for the Icon in
the resource list. The first one is always 1, the 2nd is 2, et cetera.

From this point, I get stuck. How can I get the actual name that I need
to use to pass to LoadResource in which the result of that call gets
passed as the handle to System.Drawing.Icon.FromHandle (for Icons),
System.Drawing.Bitmap.FromHbitmap (for Bitmaps), et cetera?

When I call LoadResource, it returns a handle (non-zero). I pass this to
Icon.FromHandle and no exception is thrown. The Height and Width
properties of the Icon are both 0 and when I save the icon to disk, it is
0 bytes (the file is).

Any and all help is much appreciated...been stuck on this for awhile :)

Thanks,
Mythran

API Declarations that i have...

private const uint RT_CURSOR = 0x00000001;
private const uint RT_BITMAP = 0x00000002;
private const uint RT_ICON = 0x00000003;
private const uint RT_MENU = 0x00000004;
private const uint RT_DIALOG = 0x00000005;
private const uint RT_STRING = 0x00000006;
private const uint RT_FONTDIR = 0x00000007;
private const uint RT_FONT = 0x00000008;
private const uint RT_ACCELERATOR = 0x00000009;
private const uint RT_RCDATA = 0x0000000a;
private const uint RT_MESSAGETABLE = 0x0000000b;

private const uint LOAD_LIBRARY_AS_DATAFILE = 0x00000002;

[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr LoadLibraryEx(string lpFileName, IntPtr
hFile, uint dwFlags);

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

[DllImport("kernel32.dll", EntryPoint = "EnumResourceNamesW", CharSet =
CharSet.Unicode, SetLastError = true)]
static extern bool EnumResourceNamesWithName(
IntPtr hModule,
string lpszType,
EnumResNameDelegate lpEnumFunc,
IntPtr lParam);

[DllImport("kernel32.dll", EntryPoint = "EnumResourceNamesW", CharSet =
CharSet.Unicode, SetLastError = true)]
static extern bool EnumResourceNamesWithID(
IntPtr hModule,
uint lpszType,
EnumResNameDelegate lpEnumFunc,
IntPtr lParam);

private delegate bool EnumResNameDelegate(
IntPtr hModule,
IntPtr lpszType,
IntPtr lpszName,
IntPtr lParam);

[DllImport("kernel32.dll")]
static extern IntPtr FindResource(
IntPtr hModule,
IntPtr lpName,
IntPtr lpType);

[DllImport("user32.dll")]
static extern IntPtr LoadIcon(
IntPtr hModule,
string Name
);

[DllImport("kernel32.dll", SetLastError=true)]
static extern IntPtr LoadResource(IntPtr hModule, IntPtr hResInfo);
 

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