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

Interface block for SHGetFolderPath

gelarimer
Beginner
502 Views

I would like to call the fn. SHGetFolderPath() located in the shell32.lib with the following code snippet:

!DEC$ OBJCOMMENT LIB:"shell32.lib"
INTERFACE
FUNCTION SHGetFolderPath(hwndOwner, nFolder, hToken, dwFlags, pszPath)
use
ifwinty
integer
(LONG) :: SHGetFolderPath ! HRESULT, LONG = 4
!DEC$ ATTRIBUTES DEFAULT, STDCALL, DECORATE, ALIAS:'SHGetFolderPathA' :: SHGetFolderPath
!DEC$ ATTRIBUTES REFERENCE, ALLOW_NULL :: hwndOwner
integer(HANDLE) :: hwndOwner ! HANDLE = 4
!DEC$ ATTRIBUTES REFERENCE, ALLOW_NULL :: nFolder
integer(LONG) :: nFolder ! LONG = 4
!DEC$ ATTRIBUTES REFERENCE, ALLOW_NULL :: hToken
integer(HANDLE) :: hToken ! HANDLE = 4
!DEC$ ATTRIBUTES REFERENCE, ALLOW_NULL :: dwFlags
integer(DWORD) :: dwFlags ! DWORD is unsigned 32 bit integer in C++
!DEC$ ATTRIBUTES REFERENCE, ALLOW_NULL :: pszPath
character*(*) pszPath
END FUNCTION
END INTERFACE
! found these constants in shlobj.h
INTEGER(4), PARAMETER :: CSIDL_APPDATA = Z'001a' ! 0x001a in shlobj.h
INTEGER(4)
, PARAMETER :: SHGFP_TYPE_CURRENT = 0
INTEGER(4)
, PARAMETER :: CSIDL_LOCAL_APPDATA = Z'001c' ! 0x001c in shlobj.h
INTEGER(4) iret
CHARACTER(Max_Path+1) szFileNameStr

! iret here is HRESULT

iret = SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA, NULL, SHGFP_TYPE_CURRENT, szFileNameStr)

! get error code in low word

iret = LOWORD(iret)

Code links OK but when SHGetFolderPath() exexutes it returns a negative value or error. LOWORD(iret) returns
the value 87 which is ERROR_INVALID_PARAMETER in winerror.h.

I believe the problem is in the Inerface Block, but not sure.

Any comments would be appreciated. Thanks in advance.

0 Kudos
2 Replies
gelarimer
Beginner
502 Views

Finally figured out what the correct Interface Block should look like by examining code in shell32.f90.With the following interface and Win32 constants defined in first post, call to SHGetFolderPath() works fine.

!DEC$ OBJCOMMENT LIB:"shell32.lib"

INTERFACE

FUNCTION SHGetFolderPath(hwndOwner, nFolder, hToken, dwFlags, pszPath)

use ifwinty

integer(LONG) :: SHGetFolderPath ! HRESULT, LONG = 4

!DEC$ ATTRIBUTES DEFAULT, STDCALL, DECORATE, ALIAS:'SHGetFolderPathA' :: SHGetFolderPath

integer(HANDLE) :: hwndOwner ! HANDLE = 4

integer(LONG) :: nFolder ! LONG = 4

integer(HANDLE) :: hToken ! HANDLE = 4

integer(DWORD) :: dwFlags ! DWORD is unsigned 32 bit integer in C++

!DEC$ ATTRIBUTES REFERENCE, ALLOW_NULL :: pszPath

character*(*) pszPath

END FUNCTION

END INTERFACE

0 Kudos
me-robot
Beginner
502 Views
Hello gelarimer,

I encountered a very weird issue by following your code up above.

The pszPath will be assigned value "...\My Documents ", that means bunches of space holders will be following "...\My Documents". I use TRIM, AJUSTR, but no use. There are still lots of spaces.

Did you have this issue too? If yes, how did you solve this issue?
0 Kudos
Reply