Get path to "My Documents" folder

Get path to "My Documents" folder

Does anyone have a nice way to get the path the user's "My Documents" directory from Intel Fortran?

12 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

More information: My application includes an installer project in Visual Studio 2010.  Basically, I want to have the installer create a directory to put examples and scratch files in that the application will use.  In the application, when the user wants to open a file, this is the directory I want to be the default that they are taken to.  I can make the installer install the files using the "User's Personal Data" item in the file system tree.  However, I can't seem to figure out how to get the application to know where this is located.  I can get the location of the user's home directory with the "USERPROFILE" environment variable, but there doesn't seem to be an environment variable for the user's documents folder.  I'd like a nice way to do this that works on Windows 7 and beyond (XP is a plus, but not required), that doesn't require me hard-coding what the directory is called (which may vary from system to system).

See the SHGetFolderPath API and its friends, and query the path location for CSIDL_PERSONAL.


For a full list of CSIDL values useable by SHGetFolderPath see

There you can see that CSIDL_MYDOCUMENTS is the same as CSIDL_PERSONAL

All of these CSIDL values are available through the XSystemPath function in the Xeffort library, if you want to avoid working with the API directly.


Thanks all!  My solution is below.  It seems to work (note that it requires linking with shell32.lib).  Not sure if there is a better way to deal with the C string?

    program test
    use iso_c_binding
    use kernel32
    use ifwinty    

    implicit none
    integer :: i
    integer(handle) :: hresult
    character(len=1),dimension(256) :: tmpstr
    character(len=:),allocatable :: MyDocumentsDir
    integer(HANDLE),parameter :: CSIDL_PERSONAL = 5    !from Shlobj.h
        function SHGetFolderPathA(hwndOwner,nFolder,hToken,dwFlags,pszPath)
            implicit none
            integer(HANDLE) :: SHGetFolderPathA
            integer(HANDLE),value :: hwndOwner
            integer(c_int),value :: nFolder
            integer(HANDLE),value :: hToken
            integer(DWORD),value :: dwFlags
            character(kind=C_CHAR) :: pszPath(*)
        end function SHGetFolderPathA
    end interface
    hresult = SHGetFolderPathA( hwndOwner= NULL, &
                                nFolder  = CSIDL_PERSONAL,&
                                hToken   = NULL,&
                                dwFlags  = 0,&
                                pszPath  = tmpstr)
    write(*,*) 'hresult=',hresult

    if (hresult==0) then
        !convert array to character string:
        MyDocumentsDir = ''
        do i=1,size(tmpstr)
            if (tmpstr(i)/=C_NULL_CHAR) then
                MyDocumentsDir = MyDocumentsDir//tmpstr(i)
            end if
        end do
        write(*,*) 'MyDocumentsDir: '//MyDocumentsDir
        write(*,*) 'Error'
    end if
    end program test


Given that it is the ANSI version you have interfaced to why not make the interface more Fortran friendly by having 

character(len=*) :: pszPath

And then you can get MyDocumentsDir direct from the call without the string array copy? If you wanted the position of the first C_NULL_CHAR you could use INDEX.  Also add !DEC$OBJCOMMENT LIB:"SHELL32.LIB" perhaps.

@Intel is there any plans to add any new APIs to the IFWIN interfaces? There are many missing ones. I note the shell32 interfaces have not been added since 2000. It is after all Visual Fortran for WINDOWS!


app4619, yes, we do plan to add APIs. It's a time-consuming process, though. I'll take a look at shell32.

Steve - Intel Developer Support


You might note that SHGetFolderPath is supperceded SHGetKnownFolderPath which had more options. Also:

You have the function return value as type handle, HRESULT would be better  with ifwinty type LONG (4 bytes) your code should fail on x64 as it will be 8 bytes.

I also note the use of VALUE attribute. This is default for stdcall except for arrays and type character in my understanding.

@steve thanks. Some updates would be appreciated. I know it is time consuming, it consumes some of my time!


Thanks for the suggestions!  I did look at SHGetKnownFolderPath, but wasn't sure about the Fortran bindings for the REFKNOWNFOLDERID argument.  I might revisit it later.

Steve, WinINet.lib would also be a good one to have.

Leave a Comment

Please sign in to add a comment. Not a member? Join today