0

I'm new to Win32 API. I'm trying use the win32 API. When I load an image I get a handle back, but I also get GetLastError response 0x06, invalid handle. What am I doing wrong?

class Program
{
    [DllImport("user32.dll", EntryPoint="LoadImage", SetLastError = true, CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
    static extern IntPtr LoadImage(IntPtr hinst, string lpszName, uint uType,
       int cxDesired, int cyDesired, uint fuLoad);

    [DllImport("kernel32.dll", EntryPoint ="GetLastError", CallingConvention = CallingConvention.StdCall)]
    public static extern uint GetLastError();

    static void Main(string[] args)
    {
        string path = @"c:\temp\bitmap.bmp";
        IntPtr pointer = LoadImage(IntPtr.Zero, path, 0, 256, 256, 0x00008010);
        uint result = GetLastError();
        Console.WriteLine(pointer);
        Console.WriteLine(result);
        Console.ReadLine();
    }
}

The output reads i.e.:

-1576718263
6

I'm not sure what I'm doing wrong. I wanted to configure the call to load the image from file, and also have shared handle as I'll be using that handle though the application.

Thanks, Maciej

mac671
  • 91
  • 1
  • 9
  • 5
    [The documentation for `LoadImage`](http://msdn.microsoft.com/en-us/library/windows/desktop/ms648045(v=vs.85).aspx) does not ascribe any meaning to `GetLastError` if the function succeeds. – Raymond Chen Nov 18 '13 at 20:32

1 Answers1

2

You should only call GetLastError if the function has failed, as indicated by the return value. From the MSDN documentation:

If the function succeeds, the return value is the handle of the newly loaded image.

If the function fails, the return value is NULL. To get extended error information, call GetLastError.

Calling it when the function has succeeded is meaningless.

You would be better off with something like:

IntPtr pointer = LoadImage(IntPtr.Zero, path, 0, 256, 256, 0x00008010);
if (pointer == NULL) {
    uint result = GetLastError();
    Console.WriteLine(result);
    Console.ReadLine();
}

Keep in mind that, as some people have pointed out in the comments, you shouldn't call GetLastError from managed code. Instead, you should set SetLastError to true and then use Marshal.GetLastWin32Error. See here for details.

Community
  • 1
  • 1
paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • Thanks so I can assume I've succeeded getting the handle. This was confusing for me. As the GetLastError() can be 0 meaning no error – mac671 Nov 18 '13 at 20:36
  • @mac671, yes, unless the handle is NULL, you have succeeded. The GetLastError is to get _extra_ information (reason for failure) only if the function failed. – paxdiablo Nov 18 '13 at 20:44
  • As a general rule, winapi functions don't set the error code when they succeed, only when they fail (this may even be true of all of them but I can't say off the top of my head). The documentation of each function will tell you what happens when they succeed or fail. – Stuart Nov 18 '13 at 20:47
  • In managed code you must use SetLastError = true and Marshal.GetLastWin32Error and never call GetLastError directly – David Heffernan Nov 18 '13 at 21:07
  • @David, good point, added to the answer. Thanks. – paxdiablo Nov 18 '13 at 21:16