Getting location of My Documents folder

Miscellaneous Forums/Win32 Discussion/Getting location of My Documents folder

Normally I would throw all my game data into the games directory under Program Files, but thanks to Vista and it's UAC I now have to think about storing any files that will be modifled elsewhere.

What I'm currently doing is retrieving the shared applications data folder using the getenv_ command. However, I want to fall-back to the user's own My Documents folder if this fails (plus I need it for user designed levels and such like). So, the question is... How do I get the physical location of the My Documents folder?

I can't simply use HOMEDRIVE and HOMEPATH, because these point to the folder held under Documents and Settings for the current user, but not the My Documents folder. I can't simply add /My Documents/ on the end as this wouldn't work for those that have moved the location of this folder (like me), plus it's not actually called that in a lot of countries.

I've tried Googling, but can't find anything useful at the moment. Any ideas? I'm using BlitzMax.

I poked around for a moment, and found the following in the windows registry:

HKEY_current_User\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell folders

That locations has the links to all the 'special' folders, including 'My Documents'.

You can find some code to access the windows registry here: http://www.blitzforum.de/forum/viewtopic.php?t=15521

There's probably also a windows API call that returns the location of these folders, but I have no idea which one of how to use it. :-?

deleted. Sorry not relevent

There's a Max module called "Volumes" (available here) which has a cross-platform function called GetUserDocumentsDir which may be of use.

The module is also available via syncmods (see my sig below for more details)

It uses system APIs to get the information, rather than hacking the registry (which is fine if you like that kind of thing).

Thanks guys. I'll give them a whirl and see what happens.

Brucey -- Just checked out your module. Pretty nice one, definitely saving a copy.

I just made a pass through four OSes using Brucey's module (which looks quite handy), checking out GetUserDocumentsDir(). It seems to work fine on XP Pro SP2 and MacOS 10.3.9.

However, in Ubuntu 6.06, I found that GetUserDocumentsDir() returned (IIRC) "home/wendellm/Documents" which seems reasonable except that the "Documents" folder doesn't exist. Trying the Windows version in Win 98 SE causes an error about linking to Shell32.dll. So, just a potential heads-up about using it with these two environments.

UPDATE: I tried the approach below (based on http://blitzbasic.com/Community/posts.php?topic=45722 ) and it works in 98 SE:
'WinApi Commands
Extern "Win32"
Function SHGetSpecialFolderLocation(hwndOwner, nFolder, pIdl:Byte  Ptr)
Function SHGetPathFromIDList( pidList ,lpBuffer:Byte  Ptr)
End Extern


Const CSIDL_DESKTOP                 = $0000  ' <desktop>
Const CSIDL_INTERNET                = $0001  ' Internet Explorer (icon on desktop)
Const CSIDL_PROGRAMS                = $0002  ' Start Menu\Programs
Const CSIDL_CONTROLS                = $0003  ' My Computer\Control Panel
Const CSIDL_PRINTERS                = $0004  ' My Computer\Printers
Const CSIDL_PERSONAL                = $0005  ' My Documents
Const CSIDL_FAVORITES               = $0006  ' <user name>\Favorites
Const CSIDL_STARTUP                 = $0007  ' Start Menu\Programs\Startup
Const CSIDL_RECENT                  = $0008  ' <user name>\Recent
Const CSIDL_SENDTO                  = $0009  ' <user name>\SendTo
Const CSIDL_BITBUCKET               = $000a  ' <desktop>\Recycle Bin
Const CSIDL_STARTMENU               = $000b  ' <user name>\Start Menu
Const CSIDL_MYDOCUMENTS             = $000c  ' logical "My Documents" desktop icon
Const CSIDL_MYMUSIC                 = $000d  ' "My Music" folder
Const CSIDL_MYVIDEO                 = $000e  ' "My Videos" folder
Const CSIDL_DESKTOPDIRECTORY        = $0010  ' <user name>\Desktop
Const CSIDL_DRIVES                  = $0011  ' My Computer
Const CSIDL_NETWORK                 = $0012  ' Network Neighborhood
Const CSIDL_NETHOOD                 = $0013  ' <user name>\nethood
Const CSIDL_FONTS                   = $0014  ' windows\fonts
Const CSIDL_TEMPLATES               = $0015
Const CSIDL_COMMON_STARTMENU        = $0016  ' All Users\Start Menu
Const CSIDL_COMMON_PROGRAMS         = $0017  ' All Users\Programs
Const CSIDL_COMMON_STARTUP          = $0018  ' All Users\Startup
Const CSIDL_COMMON_DESKTOPDIRECTORY = $0019  ' All Users\Desktop
Const CSIDL_APPDATA                 = $001a  ' <user name>\Application Data
Const CSIDL_PRINTHOOD               = $001b  ' <user name>\PrintHood
Const CSIDL_LOCAL_APPDATA           = $001c  ' <user name>\Local Settings\Application Data (non roaming)
Const CSIDL_ALTSTARTUP              = $001d  ' non localized startup
Const CSIDL_COMMON_ALTSTARTUP       = $001e  ' non localized common startup
Const CSIDL_COMMON_FAVORITES        = $001f
Const CSIDL_INTERNET_CACHE          = $0020
Const CSIDL_COOKIES                 = $0021
Const CSIDL_HISTORY                 = $0022
Const CSIDL_COMMON_APPDATA          = $0023  ' All Users\Application Data
Const CSIDL_WINDOWS                 = $0024  ' GetWindowsDirectory()
Const CSIDL_SYSTEM                  = $0025  ' GetSystemDirectory()
Const CSIDL_PROGRAM_FILES           = $0026  ' C:\Program Files
Const CSIDL_MYPICTURES              = $0027  ' C:\Program Files\My Pictures
Const CSIDL_PROFILE                 = $0028  ' USERPROFILE
Const CSIDL_SYSTEMX86               = $0029  ' x86 system directory on RISC
Const CSIDL_PROGRAM_FILESX86        = $002a  ' x86 C:\Program Files on RISC
Const CSIDL_PROGRAM_FILES_COMMON    = $002b  ' C:\Program Files\Common
Const CSIDL_PROGRAM_FILES_COMMONX86 = $002c  ' x86 Program Files\Common on RISC
Const CSIDL_COMMON_TEMPLATES        = $002d  ' All Users\Templates
Const CSIDL_COMMON_DOCUMENTS        = $002e  ' All Users\Documents
Const CSIDL_COMMON_ADMINTOOLS       = $002f  ' All Users\Start Menu\Programs\Administrative Tools
Const CSIDL_ADMINTOOLS              = $0030  ' <user name>\Start Menu\Programs\Administrative Tools
Const CSIDL_CONNECTIONS             = $0031  ' Network and Dial-up Connections
Const CSIDL_COMMON_MUSIC            = $0035  ' All Users\My Music
Const CSIDL_COMMON_PICTURES         = $0036  ' All Users\My Pictures
Const CSIDL_COMMON_VIDEO            = $0037  ' All Users\My Video
Const CSIDL_RESOURCES               = $0038  ' Resource Direcotry


Function GetSpecialFolder:String(folder_id) 
		
Local  idl:TBank = CreateBank (8) 
Local  pathbank:TBank = CreateBank (260) 
Local n%
Local sp$

	If SHGetSpecialFolderLocation(0,folder_id,BankBuf(idl)) = 0		
		SHGetPathFromIDList PeekInt( idl,0), BankBuf(pathbank)
		
		For n= 0 To 259
			sp$ = sp$ + Chr(PeekByte(pathbank,n))
		Next
	EndIf
	Return Trim(sp$) + ""
		
End Function



Print GetSpecialFolder(CSIDL_PROGRAMS)
Print GetSpecialFolder(CSIDL_PERSONAL)
Print GetSpecialFolder(CSIDL_DESKTOP)

Input


Trying the Windows version in Win 98 SE causes an error about linking to Shell32.dll. So, just a potential heads-up about using it with these two environments.



This is interesting... I don't have a Window 98 box anymore but I think the problem is that Windows 98 (and 95's) DLL was just called Shell.dll though I may be wrong.

If this is the case, I'm not sure how you'd tell the BlitzCompiler to load from Shell.dll on Windows 98 machines and Shell32.dll on Windows XP. :S

Seems to work just fine in Vista. One thing to watch out for... I have My Documents pointing to my second hard drive, and not a folder on there, and it adds a second '\' to the path returned, i.e. I got 'C:\\'. (Please don't ask why my second hard drive is C, long story!).

If it's the code that I posted above which is having a problem with "My Documents" being the root of C:, perhaps replacing
Return Trim(sp$) + ""
with
sp = Trim(sp)
If sp[sp.length - 1] <> Asc("") Then sp :+ ""
Return sp
will do the trick?

there's another problem in there somewhere.

when I run it on my PC, I get the following results:


C:\Documents and Settings\Administrator\Start Menu\Programs\
C:\Documents and Settings\Administrator\My Documents\
C:\Documents and Settings\Administrator\Desktopettings\Administrator\Start Menu\Programs\




As you can see, the "Desktop" location has an additional (incorrect) 'ettings\Administrator\Start Menu\Programs\' appended to the end of it. Perhaps there's some old data in the bank that's not getting zeroed out?