Solved

Loading resources...

Posted on 2004-03-26
4
634 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Summary: Persistence is the capability of an application to store the state of objects and recover it when necessary. This article compares the two common types of serialization in aspects of data access, readability, and runtime cost. A ready-to…
Real-time is more about the business, not the technology. In day-to-day life, to make real-time decisions like buying or investing, business needs the latest information(e.g. Gold Rate/Stock Rate). Unlike traditional days, you need not wait for a fe…
I've attached the XLSM Excel spreadsheet I used in the video and also text files containing the macros used below. https://filedb.experts-exchange.com/incoming/2017/03_w12/1151775/Permutations.txt https://filedb.experts-exchange.com/incoming/201…

734 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