Solved

Loading resources...

Posted on 2004-03-26
4
615 Views
Last Modified: 2008-01-09
Aright, I'm trying to load resources from a file, but I think the callback function is not working correctly. Care to take a look?

public class Resource
      {
            public Resource(string Filename)
            {
                  System.Diagnostics.Debug.WriteLine("Loading Resource...");
                  hModule = Kernel32.LoadLibraryEx(Filename, 0, Kernel32.LOAD_LIBRARY_AS_DATAFILE);
                  if(hModule == 0)
                  {
                        System.Diagnostics.Debug.WriteLine("Error loading library");
                  }
                  System.Diagnostics.Debug.WriteLine(hModule);
                  Kernel32.EnumResourceTypes(hModule, new Kernel32.EnumResTypeProc(EnumResTypeProc), 0);
                  Kernel32.FreeLibrary(hModule);
                  hModule = 0;

            }


            private long hModule;

            public static void EnumResTypeProc(long hModule, [MarshalAs(UnmanagedType.LPTStr)] string lpszType, long lParam)
            {            
                  System.Diagnostics.Debug.WriteLine("lpszType" + lpszType);
            }


      }

public class Kernel32
      {
            public const long DONT_RESOLVE_DLL_REFERENCES      = 0x00000001;
            public const long LOAD_LIBRARY_AS_DATAFILE            = 0x00000002;
            public const long LOAD_WITH_ALTERED_SEARCH_PATH      = 0x00000008;
            public const long LOAD_IGNORE_CODE_AUTHZ_LEVEL      = 0x00000010;


[DllImport("kernel32.dll")]
            public static extern long LoadLibraryEx(string lpfFileName,
                  long hFile, long dwFlags);

[DllImport("kernel32.dll")]
            public static extern bool EnumResourceTypes(long hModule, EnumResTypeProc callback, long lParam);

            public delegate void EnumResTypeProc(long hModule, [MarshalAs(UnmanagedType.LPTStr)] string lpszType, long lParam);
            [DllImport("kernel32.dll")]
            public static extern bool FreeLibrary(long hModule);
}

0
Comment
Question by:rossryan
  • 2
  • 2
4 Comments
 

Author Comment

by:rossryan
ID: 10691758
Oh yeah, the file I am trying to load is explorer.exe, which has oodles of resources. I'm trying to check if the callback is working correctly by printing the lpszType string, but nothing appears, i.e. it never gets that far...
0
 
LVL 48

Expert Comment

by:AlexFM
ID: 10694638
This is your program with some changes:

    public class Resource
    {
        public Resource(string Filename)
        {
            System.Diagnostics.Debug.WriteLine("Loading Resource...");
            hModule = Kernel32.LoadLibraryEx(Filename, 0, 0); //Kernel32.LOAD_LIBRARY_AS_DATAFILE);
            if(hModule == IntPtr.Zero)
            {
                System.Diagnostics.Debug.WriteLine("Error loading library");
            }
            System.Diagnostics.Debug.WriteLine(hModule);
            Int32 n = Kernel32.EnumResourceTypes(hModule, new Kernel32.EnumResTypeProc(EnumResTypeProc), 0);
            int nError = Marshal.GetLastWin32Error();
            Kernel32.FreeLibrary(hModule);
            hModule = IntPtr.Zero;
        }

        private IntPtr hModule;

        public static Int32 EnumResTypeProc(IntPtr hModule,
            IntPtr lpszType, long lParam)
        {
            System.Diagnostics.Debug.WriteLine(lpszType);
            return 1;
        }
    }

    public class Kernel32
    {
        public const long DONT_RESOLVE_DLL_REFERENCES     = 0x00000001;
        public const long LOAD_LIBRARY_AS_DATAFILE          = 0x00000002;
        public const long LOAD_WITH_ALTERED_SEARCH_PATH     = 0x00000008;
        public const long LOAD_IGNORE_CODE_AUTHZ_LEVEL     = 0x00000010;


        [DllImport("kernel32.dll")]
        public static extern IntPtr LoadLibraryEx(string lpfFileName,
            long hFile, long dwFlags);

        [DllImport("kernel32.dll", SetLastError=true)]
        public static extern Int32 EnumResourceTypes(IntPtr hModule, EnumResTypeProc callback, long lParam);

        public delegate Int32 EnumResTypeProc(IntPtr hModule, IntPtr lpszType, long lParam);
        [DllImport("kernel32.dll")]
        public static extern bool FreeLibrary(IntPtr hModule);
    }

It gets the following results for explorer.exe:
126615552             <- module handle
2
3
4
5
6
9
14
16

lpszType parameter of EnumResTypeProc is integer value which can be one of predefined types:
RT_ACCELERATOR, RT_ANICURSOR, RT_ANIICON ... (see details in MSDN topic EnumResTypeProc). Only if lpszType is not equal to none of these values, it points to the string which contains custom resource name. Predefined resource types from winuser.h:

#define RT_CURSOR           MAKEINTRESOURCE(1)             // == 1
#define RT_BITMAP           MAKEINTRESOURCE(2)              // == 2
#define RT_ICON             MAKEINTRESOURCE(3)               // ...
#define RT_MENU             MAKEINTRESOURCE(4)
#define RT_DIALOG           MAKEINTRESOURCE(5)
#define RT_STRING           MAKEINTRESOURCE(6)
#define RT_FONTDIR          MAKEINTRESOURCE(7)
#define RT_FONT             MAKEINTRESOURCE(8)
#define RT_ACCELERATOR      MAKEINTRESOURCE(9)
#define RT_RCDATA           MAKEINTRESOURCE(10)
#define RT_MESSAGETABLE     MAKEINTRESOURCE(11)
#define RT_VERSION      MAKEINTRESOURCE(16)
#define RT_DLGINCLUDE   MAKEINTRESOURCE(17)
#define RT_PLUGPLAY     MAKEINTRESOURCE(19)
#define RT_VXD          MAKEINTRESOURCE(20)
#define RT_ANICURSOR    MAKEINTRESOURCE(21)
#define RT_ANIICON      MAKEINTRESOURCE(22)
#define RT_HTML         MAKEINTRESOURCE(23)
#define RT_MANIFEST                        24

Change EnumResTypeProc by the following way. If lpszType is one of predefined resource types, handle it as integer value. Otherwise get custom resource name using Marshal.PtrToStringAuto Method.
0
 
LVL 48

Accepted Solution

by:
AlexFM earned 500 total points
ID: 10694653
By the way, SetLastError=true parameter of DllImport allows to get last Win32 error of API call (like GetLastError). In your program it was 998 (invalid access to memory location). This happened when .NET marshaller tried to handle resource type 2 (bitmap) as string pointer.
LOAD_LIBRARY_AS_DATAFILE is OK, you can use it.
0
 

Author Comment

by:rossryan
ID: 10696673
Excellent, and thanks.
0

Featured Post

How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

Join & Write a Comment

This article introduced a TextBox that supports transparent background.   Introduction TextBox is the most widely used control component in GUI design. Most GUI controls do not support transparent background and more or less do not have the…
It was really hard time for me to get the understanding of Delegates in C#. I went through many websites and articles but I found them very clumsy. After going through those sites, I noted down the points in a easy way so here I am sharing that unde…
This video gives you a great overview about bandwidth monitoring with SNMP and WMI with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're looking for how to monitor bandwidth using netflow or packet s…
This video shows how to remove a single email address from the Outlook 2010 Auto Suggestion memory. NOTE: For Outlook 2016 and 2013 perform the exact same steps. Open a new email: Click the New email button in Outlook. Start typing the address: …

747 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

15 Experts available now in Live!

Get 1:1 Help Now