Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Problem with a program explicitly loading a DLL on Windows 10

1,209 views
Skip to first unread message

Arjen Markus

unread,
Apr 17, 2018, 10:32:42 AM4/17/18
to
Hello,

we have run into a very odd and unwelcome problem with a program that runs fine on Windows 7 but fails on Windows 10. The failure is in the Windows function GetProcAddress. The program loads in a DLL (the name is given on the command line) via LoadLibrary and that works fine. But when it tries to retrieve the pointer to the routine in that DLL, GetProcAddress returns a NULL pointer on Windows 10, whereas on Windows 7 it all works.

I checked the name of the routine (including whether there is any trailing space or the like) against the name shown via "dependency walker" - the routine I want is there as simple as that. (Of course, because otherwise it would not have worked on Windows 7 either, but at some point you begin to doubt everything).

A fairly thorough search on the Internet has not brought up any solution that seems to apply here - solutions involve wide characters versus ordinary ones, the library etc.

Does anyone have a suggestion as to what could be going wrong?

The code is essentially as simple as:

p = LoadLibrary( name );
if ( p != NULL ) {
pf = GetProcAddress(p, "functionName" );
}

On Windows 10, pf gets the NULL value.

Most of the program has been written in Fortran, to get this dynamic functionality, a small amount of C code is used.

Regards,

Arjen

Thomas Jahns

unread,
Apr 17, 2018, 10:37:30 AM4/17/18
to
On 04/17/18 16:32, Arjen Markus wrote:
> we have run into a very odd and unwelcome problem with a program that runs fine on Windows 7 but fails on Windows 10. The failure is in the Windows function GetProcAddress. The program loads in a DLL (the name is given on the command line) via LoadLibrary and that works fine. But when it tries to retrieve the pointer to the routine in that DLL, GetProcAddress returns a NULL pointer on Windows 10, whereas on Windows 7 it all works.

does the architecture match exactly, i.e. 32bit vs. 64bit?

Thomas

Arjen Markus

unread,
Apr 17, 2018, 10:53:29 AM4/17/18
to
Yes, I doubt the library would have loaded otherwise and the same program + library are used on both OSes.

Regards,

Arjen

dpb

unread,
Apr 17, 2018, 1:00:14 PM4/17/18
to
You have checked MSDN for the OS API to see if there's any updated info
on usage I presume???

I've never even yet _seen_ a Win10 system, what more used one but I hear
nothing much good. Anything going on w/ the "advanced" security,
perhaps that you're not allowed to know such things, maybe???

Just throwing mud; have no direct knowledge that's applicable.

--


Arjen Markus

unread,
Apr 17, 2018, 3:40:34 PM4/17/18
to
Pity. Yes, I checked the documentation of this routine and there is nothing specific to Windows 10. It all seems pretty straightforward. And the name of the routine is just simple capitals from the basic Latin alphabet. So no UNICODE stuff or the like. (We are talking about Fortran routines, after all ;)).

Regards,

Arjen

Louis Krupp

unread,
Apr 17, 2018, 4:02:12 PM4/17/18
to
For what it's worth, I looked at:

https://msdn.microsoft.com/en-us/library/windows/desktop/ms683212

Have you tried calling GetLastError? Was it at all helpful?

If it wasn't, can you get the address of other routines in the library
-- i.e., does the problem have something to do with this function, or
is there something about the entire library?

Louis

FortranFan

unread,
Apr 17, 2018, 5:24:32 PM4/17/18
to
On Tuesday, April 17, 2018 at 10:32:42 AM UTC-4, Arjen Markus wrote:

> ..
> we have run into a very odd and unwelcome problem with a program that runs fine on Windows 7 but fails on Windows 10. ..
>
> Does anyone have a suggestion as to what could be going wrong? ..


Well, age-old advice applies - of creating a *minimal working example* to diagnose the problem and if that fails, posting the complete code here.

A 2-minute effort I tried with a trivially simple example below works on both Windows 7 and 10:

--- code snippet ---
module m

use, intrinsic :: iso_c_binding, only : c_char, c_int, c_intptr_t, c_funptr

implicit none

!.. Public by default
public

!.. Mnemonics for types in Windows API functions
integer(c_int), parameter :: HMODULE = c_intptr_t !.. A handle to a module; base address in memory
integer(HMODULE), parameter :: NULL_HANDLE = int( 0, kind=kind(NULL_HANDLE) )

interface

function LoadLibrary(lpLibName) bind(C, name='LoadLibraryA') result(RetVal)
! https://msdn.microsoft.com/en-us/library/windows/desktop/ms684175(v=vs.85).aspx
! HMODULE WINAPI LoadLibrary(_In_ LPCTSTR lpFileName );

import :: c_char, HMODULE

!.. Argument list
character(kind=c_char, len=1) :: lpLibName(*)
!.. Function result
integer(HMODULE) :: RetVal

end function LoadLibrary

function GetProcAddress(lpLibHandle, lpProcName) bind(C, name='GetProcAddress') result(RetVal)
! https://msdn.microsoft.com/en-us/library/windows/desktop/ms683212(v=vs.85).aspx
! FARPROC WINAPI GetProcAddress( _In_ HMODULE hModule,
! _In_ LPCSTR lpProcName );

import :: HMODULE, c_char, c_funptr

!.. Argument list
integer(HMODULE), value :: lpLibHandle
character(kind=c_char) :: lpProcName(*)
!.. Function result
type(c_funptr) :: RetVal

end function GetProcAddress


end interface

end module m
program p

use, intrinsic :: iso_c_binding, only : c_char, c_funptr
use m, only : HMODULE, LoadLibrary, GetProcAddress, NULL_HANDLE

implicit none

! local variables
integer(HMODULE) :: hInstLib
type(c_funptr) :: pProc

hInstLib = LoadLibrary( c_char_"kernel32.dll" )
if ( NULL_HANDLE /= hInstLib ) then
pProc = GetProcAddress( hInstLib, c_char_"AddDllDirectory" )
print *, "ProcAddress of AddDllDirectory in loaded kernel32.dll: ", transfer( pProc, mold=hInstLib )
else
print *, "LoadLibrary failed."
end if

stop

end program p
--- end snippet ---

Here's the output on a Windows 10 machine running 64-bit OS with the program above built using Intel Fortran compiler and Microsoft C/C++ linker:

--- begin console output ---
C:\temp>p.exe
ProcAddress of AddDllDirectory in loaded kernel32.dll: 140732179481408

C:\temp>
--- end console output ---

Ian Harvey

unread,
Apr 17, 2018, 6:22:28 PM4/17/18
to
On Wednesday, 18 April 2018 00:02:42 UTC+9:30, Arjen Markus wrote:

> Does anyone have a suggestion as to what could be going wrong?
>
> The code is essentially as simple as:
>
> p = LoadLibrary( name );
> if ( p != NULL ) {
> pf = GetProcAddress(p, "functionName" );
> }

Where's the trailing null character?

FortranFan

unread,
Apr 17, 2018, 9:49:25 PM4/17/18
to
On Tuesday, April 17, 2018 at 6:22:28 PM UTC-4, Ian Harvey wrote:

> ..
> > pf = GetProcAddress(p, "functionName" );
> > }
>
> Where's the trailing null character?


MSDN doesn't indicate the terminating NULL as being needed:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms686944(v=vs.85).aspx

--- quote ---
ProcAdd = (MYPROC) GetProcAddress(hinstLib, "myPuts");
--- end quote ---

Ev. Drikos

unread,
Apr 17, 2018, 10:17:38 PM4/17/18
to
In C source, the null char is added by the compiler, so programmers
don't add explicitly a null escape ('\0') at the end of a character literal.

Arjen Markus

unread,
Apr 18, 2018, 2:30:21 AM4/18/18
to
I know, it was a rather long day and at the end we decided to simply build in the function in the main program, so that we could make progress for now.

Thanks for the example. I will definitely use this to see what happens with my library.

Regards,

Arjen

Ian Harvey

unread,
Apr 18, 2018, 2:31:23 AM4/18/18
to
The C/C++ prototype (relevant if that API is being called directly, rather than through some Fortran wrapper that does this for you) is documented as being:

FARPROC WINAPI GetProcAddress(
_In_ HMODULE hModule,
_In_ LPCSTR lpProcName );

LPCSTR is documented as being "a pointer to a constant null terminated string...".

Otherwise the C/C++ API has no way of knowing the number of characters in the name.

Arjen Markus

unread,
Apr 18, 2018, 2:32:57 AM4/18/18
to
On Tuesday, April 17, 2018 at 10:02:12 PM UTC+2, Louis Krupp wrote:
> On Tue, 17 Apr 2018 12:40:31 -0700 (PDT), Arjen Markus
I have not tried GetLastError yet, but there is only one single function in the library ... Well, in this case - it is an example of an extension mechanism we have created and as we have not used Windows 10 that much yet, this was the first puzzling encounter.

Regards,

Arjen

Arjen Markus

unread,
Apr 18, 2018, 2:35:09 AM4/18/18
to
Yes, the code surrounding it converts the Fortran string to a proper C string, including the NUL byte. No trailing blank visible, as demonstrated by printing it via the C format ">%s<".

Regards,

Arjen

Arjen Markus

unread,
Apr 18, 2018, 5:28:42 AM4/18/18
to
Okay, I took FortranFan's Fortran program, adjusted it to report the last error in case of failure, adjusted it further to look in my library and ran it on several machines. The results are bewildering:

- On two Windows 7 machines I tried, it reported the pointer/handle for the function without any error.
- On the Windows 10 machine on which my full program failed yesterday, it also prints the pointer/handle, with no error whatsoever.
- On another (virtual) Windows 10 machine it fails to load the library itself. The last error reported is 126, meaning that the library was not found. It is there, however, I have seen it in the listing by dir.

Several words to describe this situation come to mind, not all of them polite. I will refrain from typing any of them :(.

Regards,

Arjen

FortranFan

unread,
Apr 18, 2018, 9:30:50 AM4/18/18
to
On Wednesday, April 18, 2018 at 5:28:42 AM UTC-4, Arjen Markus wrote:

> ..
> Several words to describe this situation come to mind, not all of them polite. I will refrain from typing any of them :(.
> ..


Is your modified test similar to the following, meaning string parameters to Windows API function are null-terminated?

program p

use, intrinsic :: iso_c_binding, only : c_char, c_funptr, c_null_char
use m, only : HMODULE, LoadLibrary, GetProcAddress, NULL_HANDLE

implicit none

! local variables
character(kind=c_char, len=*), parameter :: DllName = c_char_"kernel32.dll" // c_null_char
character(kind=c_char, len=*), parameter :: ProcName = c_char_"AddDllDirectory" // c_null_char
integer(HMODULE) :: hInstLib
type(c_funptr) :: pProc

hInstLib = LoadLibrary( DllName )
if ( NULL_HANDLE /= hInstLib ) then
pProc = GetProcAddress( hInstLib, ProcName )
print *, "ProcAddress of AddDllDirectory in loaded kernel32.dll: ", transfer( pProc, mold=hInstLib )
else
print *, "LoadLibrary failed."
end if

stop

end program

I noticed *no issues* with this too using Intel Fortran compiler v18.0 Update 2 and Microsoft C/C++ linker part of Visual Studio 2017 v15.6.6 on 4 different environment, all 64-bit OS: Windows 7 and *Windows 10* physical and virtual machines. In each of the 4 cases, the output is similar to the following:

ProcAddress of AddDllDirectory in loaded kernel32.dll: 8791744259272

Arjen Markus

unread,
Apr 18, 2018, 10:01:47 AM4/18/18
to
No, I used your first version and adjusted the names, as well as added GetLastError to see if something more could be learned.

I did not think of adding the NUL character. That was a dumb oversight. Should try with that - if only to exclude possible arbitrary behaviour if it is missing.

Regards,

Arjen

Steve Lionel

unread,
Apr 18, 2018, 3:59:05 PM4/18/18
to
On 4/18/2018 5:28 AM, Arjen Markus wrote:
> Okay, I took FortranFan's Fortran program, adjusted it to report the last error in case of failure, adjusted it further to look in my library and ran it on several machines. The results are bewildering:
>
> - On two Windows 7 machines I tried, it reported the pointer/handle for the function without any error.
> - On the Windows 10 machine on which my full program failed yesterday, it also prints the pointer/handle, with no error whatsoever.
> - On another (virtual) Windows 10 machine it fails to load the library itself. The last error reported is 126, meaning that the library was not found. It is there, however, I have seen it in the listing by dir.
>
> Several words to describe this situation come to mind, not all of them polite. I will refrain from typing any of them :(.

What does DependencyWalker (www.dependencywalker.com) say about your DLL
on the Win10 system where it fails? If a dependent DLL is not in
Windows' search path, you'll get a "not found" error. (Note that
DependencyWalker does not follow Windows' rule about skipping "wrong
architecture" DLLs on 64-bit Windows, so it may grouse about mixed
architectures. Ignore any messages about "delay load" DLLs.

I have used LoadLibrary/GetProcAddress many, many times on Windows 10
and never had a problem.

--
Steve Lionel
Retired Intel Fortran developer/support
Email: firstname at firstnamelastname dot com
Twitter: @DoctorFortran
LinkedIn: https://www.linkedin.com/in/stevelionel
Blog: http://intel.com/software/DrFortran

Arjen Markus

unread,
Apr 19, 2018, 2:27:49 AM4/19/18
to
On Wednesday, April 18, 2018 at 9:59:05 PM UTC+2, Steve Lionel wrote:

> What does DependencyWalker (www.dependencywalker.com) say about your DLL
> on the Win10 system where it fails? If a dependent DLL is not in
> Windows' search path, you'll get a "not found" error. (Note that
> DependencyWalker does not follow Windows' rule about skipping "wrong
> architecture" DLLs on 64-bit Windows, so it may grouse about mixed
> architectures. Ignore any messages about "delay load" DLLs.
>

I have not seen this myself, but apparently DependencyWalker got stuck. Unfortunately I have no direct access to a Windows 10 machine at this moment, so I can only sparingly use the one from my client to check things.

> I have used LoadLibrary/GetProcAddress many, many times on Windows 10
> and never had a problem.
>

That is good to hear, but it does not give much comfort in view of the routine GetProcAddress returning a NULL pointer in one case. I hope to get access to a (virtual) Windows 10 machine soon, so that I can look into the problem in a better controlled setting.

Hopefully it is just a stupid mistake like a missing library or a typo or whatever and I will have to confess to having made a lot of noise over my own fault.

Regards,

Arjen

Arjen Markus

unread,
Apr 23, 2018, 5:20:33 AM4/23/18
to
On Thursday, April 19, 2018 at 8:27:49 AM UTC+2, Arjen Markus wrote:

>
> Hopefully it is just a stupid mistake like a missing library or a typo or whatever and I will have to confess to having made a lot of noise over my own fault.
>

I am not sure it is a stupid mistake, but I have now been able to get it to work on a Windows 10 virtual machine. The solution has been to compile everything with the same compiler version. Before there were a few flavours involved. While this worked fine on Windows 7, it may have caused the trouble I reported on Windows 10.

Anyway, this is more progress than I was able to make last week.

Regards,

Arjen

bartc

unread,
Apr 23, 2018, 8:34:25 AM4/23/18
to
On 17/04/2018 15:32, Arjen Markus wrote:
> Hello,
>
> we have run into a very odd and unwelcome problem with a program that runs fine on Windows 7 but fails on Windows 10. The failure is in the Windows function GetProcAddress. The program loads in a DLL (the name is given on the command line) via LoadLibrary and that works fine. But when it tries to retrieve the pointer to the routine in that DLL, GetProcAddress returns a NULL pointer on Windows 10, whereas on Windows 7 it all works.
>
> I checked the name of the routine (including whether there is any trailing space or the like) against the name shown via "dependency walker" - the routine I want is there as simple as that. (Of course, because otherwise it would not have worked on Windows 7 either, but at some point you begin to doubt everything).
>
> A fairly thorough search on the Internet has not brought up any solution that seems to apply here - solutions involve wide characters versus ordinary ones, the library etc.
>
> Does anyone have a suggestion as to what could be going wrong?
>
> The code is essentially as simple as:
>
> p = LoadLibrary( name );
> if ( p != NULL ) {
> pf = GetProcAddress(p, "functionName" );
> }
>
> On Windows 10, pf gets the NULL value.

I know this is a week ago and you have since solved the problem.

But, was LoadLibrary successful? That is, p was not null.

Otherwise, pf is not assigned and could just happen to have a zero value.

If the library /was/ loaded, you would have needed to use some tool
(PEDUMP, DUMPBIN, or just a regular hex dump) of that DLL file to check
that the symbols being exported included the one you want.

--
bartc

Arjen Markus

unread,
Apr 23, 2018, 10:18:20 AM4/23/18
to
On Monday, April 23, 2018 at 2:34:25 PM UTC+2, bartc wrote:

>
> I know this is a week ago and you have since solved the problem.
>
> But, was LoadLibrary successful? That is, p was not null.
>
> Otherwise, pf is not assigned and could just happen to have a zero value.
>
> If the library /was/ loaded, you would have needed to use some tool
> (PEDUMP, DUMPBIN, or just a regular hex dump) of that DLL file to check
> that the symbols being exported included the one you want.
>
> --
> bartc

Yes, the code checks that the library was loaded (pointer /= null) and then continues to get the pointer to the function/routine. The strange thing is/was that there is an exported symbol of exactly the right name - verified using dependency walker - but a NULL pointer was returned anyway.

That was the frustrating part - the test program that FortranFan posted and that I adapted did its job, but presumably only because all components were compiled with the same compiler. Or at least that is my conclusion now that I have found a working constellation.

Regards,

Arjen
0 new messages