Application cannot write into %APPDATA% (but user can)
Asked Answered
D

1

7

I have an application which needs to create its settings directory inside the user's %APPDATA% directory. To do this it uses code similar to the following:

std::string appDataBase = getenv("APPDATA");
std::string appDir = appDataBase + "\\MyDir";

std::cerr << "About to invoke _mkdir(" << appDir << ")" << std::endl;
int rv = _mkdir(appDir.c_str());
std::cerr << "_mkdir returned " << rv << ", errno = " << errno << std::endl;

However, when this code runs, the _mkdir call fails and errno is set to EACCES:

About to invoke _mkdir(C:\Users\mdm\AppData\Roaming\MyDir)
_mkdir returned -1, errno = 13

I would have assumed this is a simple permissions issue, except for the fact that (1) I can create the directory manually in Explorer without any permission problems, and (2) the exact same code works fine if I copy it into a project by itself.

I have done extensive searching for information about this issue but can only find discussions of general permissions problems such as the user not being able to access/write into this folder using Explorer. The code in my application works if I run it as Administrator, so clearly there is something odd going on with its permissions, but I don't know what else to check. I have inspected with Process Explorer and confirmed that the application is running with my user account, which has full write permissions into the %APPDATA% directory, and I have ensured that the %APPDATA% tree is not set to Hidden or Read-Only.

Is there some kind of "effective user ID" or "effective permissions" that can be set on a Windows application, which might depend on something in the build configuration or process initialisation? Are there any other factors that would prevent one specific application from writing into %APPDATA% while other user processes can?

Update

Further investigation reveals that the difference in behaviour is not related to the content of the code, but the location of the executable in the filesystem. My application is being built from a source tree inside a Development folder in my user directory, and the _mkdir call fails for executables within this directory; however, copying the .exe file into a new directory C:\Development allows it to work fine (although moving the existing Development directory does not). The simple test program was inside Documents\Visual Studio\Projects, which also seems to be a satisfactory location.

Demagogic answered 22/4, 2012 at 11:12 Comment(8)
"the exact same code works fine if I copy it into a project by itself" - then you're probably doing something interesting in the surrounding code. Can't really guess what though.Voroshilov
@Mat: that would be my guess too — unfortunately I have little experience developing on Windows so I'm not sure what to look for in the surrounding code.Demagogic
As a debugging measure, try using Process Monitor (search the MS web site) to double-check what path the system is actually attempting to create and what error code is being returned by the file system. There may be some kind of redirection going on, although I don't understand why that would be the case here.Dottydoty
It sounds like the anti virus/spyware is interfering here. Windows doesn;t have any "per executable location permissions" natively.Pommard
@HarryJohnston: I tried that, the path is definitely correct and the result is ACCESS DENIED.Demagogic
@Deanna: That is also my suspicion, although there was no change in behaviour with Windows Defender disabled.Demagogic
Process Monitor also shows the user account being used for the request, was this as expected? Can you reproduce the problem on a freshly installed test machine?Dottydoty
@HarryJohnston: Process Monitor confirms the correct user is being used, and no I cannot reproduce the problem on a different machine (although it's not a freshly-installed one). Maybe it is just some anti-spyware thing on my own machine.Demagogic
F
0

Windows has a different (and large) set of functions for changing security contexts. See here for some.

Perhaps the project containing that code is changing security contexts? If the program is running as a public-access server I would have expect it to call ImpersonateAnonymousToken(), for example.

Feckless answered 22/4, 2012 at 11:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.