views:

614

answers:

3

I am calling CreateFile() to create a file in the Program Data directory. I'm using SHGetSpecialFolderPath() to get the dir name.

I have a user with Vista for whom CreateFile() is returning error 5 (Access Denied). It would help if I knew where CreateFile() was actually attempting to create the file so we can check his folder permissions. The problem with Vista (UAC) is, it's not attempting to create the file in the directory I passed in. It could also be in a VirtualStore directory. An added source of confusion is this user is German and although SHGetSpecialFolderPath() is returning "C:\Program Data\blah blah" as the path, I don't think that's actually where the path is. I think German Vista uses the German word for "Program Data". I would like to be able to tell the user "This is the exact path where we are trying to create the file. Check your permissions on this folder."

I know you can get the a path from an open file handle, but in this case the CreateFile() is failing so I don't have an open handle. How can I get Vista to tell me the actual path where it's attempting to create the file?

+1  A: 

If with UAC the paths used are not the ones you want, then the redirection is in effect. To make sure that redirection does not occur, add a manifest to your application which indicates to Vista that your application is properly coded and aware of access restrictions (i.e., you don't write to e.g., HKLM or the programs folder if your app doesn't need admin privileges to run).

But your application should be able to write to the APPDATA folder (if that's what you really use).

Make sure you're using CSIDL_APPDATA and not CSIDL_COMMON_APPDATA (the latter one being accessible only with admin privileges).

To find the real path (the one you would expect) tell the user to type %APPDATA% into the explorer bar (or hit Windows+R, then type %APPDATA%, enter). This will open the explorer on that folder.

Stefan
I do need to use CSIDL_COMMON_APPDATA because this particular file needs to be accessed by all users. But CSIDL_COMMON_APPDATA doesn't require admin privileges. Any user can write to it, though any file you create can't be read by another user unless it's created with "allow everyone" access.
mhenry1384
Nope, CSIDL_COMMON_APPDATA requires admin privileges. This location is usually written to by installers, not by applications themselves.It would be a security risk if one user can set options or worse, replace binary files another user will then have to use.
Stefan
From http://msdn.microsoft.com/en-us/library/ms995853.aspx:CSIDL_COMMON_APPDATAThis folder should be used for application data that is not userspecific. [...]. By default, this location isread-only for normal (non-admin, non-power) Users.
Stefan
You could try using CSIDL_COMMON_DOCUMENTS instead.
Stefan
MSDN:"If an application requires normal Users to have write access to an application specific subdirectory of CSIDL_COMMON_APPDATA, then the application must explicitly modify the security on that sub-directory during application setup". I didn't write the installer, that must be what we are doing.
mhenry1384
I believe we aren't using CSIDL_COMMON_DOCUMENTS because these are files the user shouldn't be messing with or deleting and it was determined the common documents folder was too easy for the users to access.
mhenry1384
Microsoft's documentation is incorrect. I just tested it using Vista SP1 and even non-admin users can create and write folders and directories to the c:\ProgramData (CSIDL_COMMON_APPDATA) folder. I don't know why the documentation claims otherwise.
mhenry1384
CSIDL_COMMON_APPDATA points to "All Users\Application data", not c:\programdata.
Stefan
+1  A: 

My understanding is that ProgramData is used by Vista to write files that were attempting to be written inside C:\Program Files, but failed, since unless you are running the app as Admin you can't write inside program files. Maybe you should try saving your files to the AppData folder under the current user.

Alex
Not quite, the "Program Data" folder returns a folder that all users can access (CSIDL_COMMON_APPDATA). And this particular file does need to be accessed by all users. I wish it were not so.
mhenry1384
+2  A: 

Fire up Process Monitor and watch what it does: http://technet.microsoft.com/en-us/sysinternals/bb896645.aspx

Andrew Medico
That's cool, I didn't think of that. Process Monitor does show the "real" directory. Unfortunately, running Process Monitor is probably more than the typical user can handle. Still, good idea.
mhenry1384
I was hoping for a way to do this from within my program, but since nobody has a better answer, I guess this is the winner.
mhenry1384