Home
Options

Can't seem to get LoadLibraryA or LoadLibraryW to work in Linqpad 5 or 6

edited October 2021

I'm trying to dump some Win32 PE resource strings from some Windows DLLs in Linqpad (both Linqpad 5 and 6, x64 and x86) but I can't seem to get LoadLibrary to work: it always fails with the Win32Exception: "The specified module could not be found".

It fails with both direct paths to C:\Windows\SysWow64\shell32.dll as well as when I copy shell32.dll to my desktop, and give it another name.

Here's my program:

void Main()
{
    Environment.Is64BitProcess.Dump("Environment.Is64BitProcess");
    IntPtr.Size.Dump("IntPtr.Size");

    DirectoryInfo desktop = new DirectoryInfo( Environment.GetFolderPath( System.Environment.SpecialFolder.Desktop ) );

    ///

    if( Environment.Is64BitProcess )
    {
        // TODO
    }
    else
    {
        // https://stackoverflow.com/questions/18522102/loadlibraryw-failing-to-load-dll-in-system32
        // https://ofekshilon.com/2013/06/22/entry-point-not-found-and-other-dll-loading-problems/

        FileInfo dllFile = new FileInfo( Path.Combine( desktop.FullName, "shell32.dll" ) );
        if( !dllFile.Exists ) File.Copy( @"C:\Windows\SysWow64\shell32.dll", dllFile.FullName );
        dllFile.Refresh();

        NativeMethods.ExtractStringFromDLL( dllFile.FullName, -1 ).Dump();
    }
}


/// <summary>See https://stackoverflow.com/questions/41968416/how-to-extract-string-resource-from-dll</summary>
static class NativeMethods
{
    [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
    private static extern IntPtr LoadLibraryW([MarshalAs(UnmanagedType.LPStr)]string lpFileName);

    [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
    private static extern int LoadStringW(IntPtr hInstance, int ID, StringBuilder lpBuffer, int nBufferMax);

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

    public static string ExtractStringFromDLL(string file, int number)
    {
        IntPtr lib = LoadLibraryW(file);
        if( lib == IntPtr.Zero )
        {
            throw new Win32Exception();
        }

        try
        {
             StringBuilder result = new StringBuilder( capacity: 2048);

             Int32 ok = LoadStringW( lib, number, result, result.Capacity );
             if( ok == 0 )
             {
                throw new InvalidOperationException( "String resource not found: \"" + file + "\": " + number + "." );
             }

              return result.ToString();
        }
        finally
        {
            FreeLibrary( lib );
        }
    }
}

Is anyone else able to get it to work on their machines?

Comments

Sign In or Register to comment.