Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
29391 Discussions

Help needed on calling windows dlls

stigandersen
Beginner
730 Views
Hello

In a program that runs on a non-dedicated windows cluster I need to be able to measure the percentage of idle time on the nodes computers. The node computers are running the windows2000 operating system. I am using CVF6.6B for compiling the program.

Unfortunately I cannot seem to find any function calls in kernel32.f90 or any of the other files included in the CVF package that will aloow me to get this information directly. For this reason I have tried to call functions in kernel32.dll and ntdll.dll directly but without succes.
I have tried to mimic the example LOADEXP1 and use loadlibrary and getprocaddress to find the functions I want to call and this appears to be working. The functions take pointers to various buffers for results as arguments. In place of these arguments I have tried passing integer(4) variables with the addresses of the buffers where I would like the results to end up. However, the buffers stay empty after what I think are successful function calls. The code I have attempted is included below.

Any help will be greatly appreciated.

Stig Andersen
------------------------------
program AccessWindowsDLLs
use kernel32
implicit none

interface
integer(4) function ptr_NtQuerySystemInformation(&
SystemInformationClass, &
SystemInformationLoc, &
SystemInformationLength, &
ReturnLengthLoc)
integer(4) :: SystemInformationClass, &
SystemInformationLoc, &
SystemInformationLength, &
ReturnLengthLoc
end function

integer(4) function ptr_GetSystemTimes(&
IdleTimeLoc, &
KernelTimeLoc, &
UserTimeLoc)
integer(4) :: IdleTimeLoc, &
KernelTimeLoc, &
UserTimeLoc
end function
end interface

integer(4) :: DLL_p, Proc_p1, Proc_p2
pointer (Proc_p1, ptr_NtQuerySystemInformation)
pointer (Proc_p2, ptr_GetSystemTimes)

integer(4) :: status, &
SystemInformationClass, &
SystemInformationLength, &
ReturnLength, &
SystemInformationLoc, &
ReturnLengthLoc
integer, parameter :: BufferLen = 1024
character(len=BufferLen) :: SystemInformation

integer(DWORD) :: LastError

integer(4), dimension(2) :: IdleTime, KernelTime, UserTime

!--------------------------------------------------------

! Load ntdll.dll
DLL_p = loadlibrary("ntdll.dll"C)
if (DLL_p == 0) then
write(*,*) 'Error loading ntdll.dll'
end if

! Set up pointer to NtQuerySystemInformation
Proc_p1 = getprocaddress(DLL_p, &
"NtQuerySystemInformation"C)
if (DLL_p == 0) then
write(*,*) 'Error finding NtQuerySystemInformation in ntdll.dll'
end if

SystemInformationClass = 2
SystemInformationLength = BufferLen
SystemInformationLoc = %loc(SystemInformation)
ReturnLengthLoc = %loc(ReturnLength)

status = 0
status = ptr_NtQuerySystemInformation(&
SystemInformationClass, &
SystemInformationLoc, &
SystemInformationLength, &
ReturnLengthLoc)
if (status == 0) then
write(*,"(a,i0,a)") ' Error ', GetLastError(), &
' encountered in call to NtQuerySystemInformation'
end if
write(*,*) "->", SystemInformation, "<-"

status = freelibrary(DLL_p)

!--------------------------------------------------------

! Load kernel32.dll
DLL_p = loadlibrary("kernel32.dll"C)
if (DLL_p == 0) then
write(*,*) 'Error loading kernel32.dll'
end if

! Set up pointer to GetSystemTimes (WindowsXP only)
Proc_p2 = getprocaddress(DLL_p, "GetSystemTimes")
if (DLL_p == 0) then
write(*,*) 'Error finding GetSystemTimes in kernel32.dll'
end if

status = 0
status = ptr_GetSystemTimes(%loc(IdleTime), &
%loc(KernelTime), &
%loc(UserTime))
if (status == 0) then
write(*,"(a,i0,a)") ' Error ', GetLastError(), &
' encountered in call to GetSystemTimes'
end if
write(*,*) "->", IdleTime, KernelTime, UserTime, "<-"

status = freelibrary(DLL_p)

!--------------------------------------------------------

write(*,*) 'finished (press enter)'
read(*,"()")
end program AccessWindowsDLLs

0 Kudos
2 Replies
Jugoslav_Dujic
Valued Contributor II
730 Views
The return value I get is 0xC0000005 (Access Violation). You seem to be missing attributes in interface blocks. The way you wrote it, you should add !DEC$ATTRIBUTES STDCALL:: ptr_NtQuerySystemInformation to get the correct behaviour (this changes default passing mechanism to by-value). When I added this, I got return value 0 and something filled in into SystemInformation -- but I don't know what it is. See this recent thread (and the attachment ppid.f90). Probably James Wilkinson can offer more info, since he seems to be more familiar with NtXXX routines.

Jugoslav

0 Kudos
stigandersen
Beginner
730 Views
Thank you Jugoslav

You were absolutely correct. I was missing the attributes.

Kind Regards,
Stig Andersen
0 Kudos
Reply