Solved

Loading resources...

Posted on 2004-03-26
4
632 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

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

Question has a verified solution.

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

Introduction This article series is supposed to shed some light on the use of IDisposable and objects that inherit from it. In essence, a more apt title for this article would be: using (IDisposable) {}. I’m just not sure how many people would ge…
This article describes a simple method to resize a control at runtime.  It includes ready-to-use source code and a complete sample demonstration application.  We'll also talk about C# Extension Methods. Introduction In one of my applications…
Are you ready to implement Active Directory best practices without reading 300+ pages? You're in luck. In this webinar hosted by Skyport Systems, you gain insight into Microsoft's latest comprehensive guide, with tips on the best and easiest way…

740 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