views:

380

answers:

2

Hi everyone,

I'm trying to write some info to the user's documents folder (eg. C:\Documents and Settings\[userName]), but I can't seem to find out how to grab the path programmatically. Is there any way to do this? C++, not using .NET.

Thanks!

+7  A: 

SHGetFolderPath with CSIDL_PERSONAL can be used to get the user's Documents folder.

WCHAR path[MAX_PATH];
HRESULT hr = SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL,
                             SHGFP_TYPE_CURRENT, path);
Michael
The documentation implies you should use CSIDL_PERSONAL instead of CSIDL_MYDOCUMENTS.
Mark Ransom
link to the documentation :) http://technet.microsoft.com/en-us/library/cc749104(WS.10).aspx
Charles Ma
Michael
hmm from my read of the documentation it implies nothing of the sort. In fact i'd go as far as saying it implies CSIDL_MYDOCUMENTS is the better choice because it won't work on older systems and hence won't do unexpected things.
Goz
The Win7 SDK says:CSIDL_PERSONAL (FOLDERID_Documents)Version 6.0. The virtual folder that represents the My Documents desktop item. This is equivalent to CSIDL_MYDOCUMENTS. Previous to Version 6.0. The file system directory used to physically store a user's common repository of documents. A typical path is C:\Documents and Settings\username\My Documents. This should be distinguished from the virtual My Documents folder in the namespace. To access that virtual folder, use SHGetFolderLocation, which returns the ITEMIDLIST for the virtual location, or refer to the technique described in
Michael
Not quite synonyms. CSIDL_PERSONAL=0x0005 and refers to the physical location, and CSIDL_MYDOCUMENTS=0x000c refers to a virtual folder. I think SHGetFolderLocation will return different results, even if SHGetFolderPath doesn't.
Mark Ransom
The distinction is clearer for the desktop, where children like the recycle bin are in the virtual but not the physical folder.
MSalters
#define CSIDL_MYDOCUMENTS CSIDL_PERSONAL // Personal was just a silly name for My DocumentsStraight from ShlObj.h itself.
A: 

You could do this :

wchar_t *pUSERPROFILE;
size_t len;
_wdupenv_s( &pUSERPROFILE, &len, L"USERPROFILE" );
wstring userprofile = pUSERPROFILE;
free (pUSERPROFILE);

_wdupenv_s MSDN

anno
You want _wgetenv; this is a memory leak. Good example how the Microsoft "security" extensions can be counterproductive actually.
MSalters
Of course, you should free (pUSERPROFILE);
anno
As for, _wgetenv : "By allocating the buffer itself, _dupenv_s provides a more convenient alternative to getenv_s, _wgetenv_s."
anno