Error 0x80070005 from SHGetKnownFolderPath after starting process though service

1

Im using the code below to get the appdata folder. Normally it works, but if I start the same process though a service using a similar way to this I get the error 0x80070005 which means Access Denied.

HRESULT result;
if ((result = SHGetKnownFolderPath(
    FOLDERID_RoamingAppData,
    NULL,
    NULL,
    &appdate)) != S_OK)
{
    std::cout << result << std::endl

    return false;
}

The function that creates the process is

if (!CreateProcessAsUser(
        token,
        executablePath,
        executableName,
        NULL,
        NULL,
        FALSE,
        NORMAL_PRIORITY_CLASS,
        NULL,
        0,
        &startupInfo,
        &processInformation))
    {
        SHOW_SERVICE_ERROR;
    }

I have not found anything related to this in the internet. Can anyone help?

c++
winapi
service
process
asked on Stack Overflow Jun 3, 2018 by Phins

1 Answer

3

your error that you not pass lpEnvironment parameter to CreateProcess call.

lpEnvironment [in, optional]

A pointer to the environment block for the new process. If this parameter is NULL, the new process uses the environment of the calling process.

as result child process uses the environment of the calling process. what effect this give to FOLDERID_RoamingAppData ? during resolve FOLDERID_RoamingAppData - we usually got %USERPROFILE%\AppData\Roaming - and final result will be depend from value of %USERPROFILE%. in your case - it will be inherited from service (LocalSystem) and will be look like C:\WINDOWS\system32\config\systemprofile - so final path must look like C:\WINDOWS\system32\config\systemprofile\AppData\Roaming. before return this path to caller - system check are path exist - call GetFileAttributes. and here it fail (due security permission) - last error - 5 - ERROR_ACCESS_DENIED. and api final return HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED) which is 80070005.

conclusion - in call CreateProcessAsUser use pointer to environment block returned by CreateEnvironmentBlock. and free this block later by DestroyEnvironmentBlock. also not forget CREATE_UNICODE_ENVIRONMENT flag in call CreateProcessAsUser

also your error can easy be reproduced in local (not elevated) process by next code:

SetEnvironmentVariableW(L"USERPROFILE", L"C:\\WINDOWS\\system32\\config\\systemprofile");
PWSTR appdate;
HRESULT result;
if ((result = SHGetKnownFolderPath(
    FOLDERID_RoamingAppData,
    NULL,
    NULL,
    &appdate)) == S_OK)
{
    CoTaskMemFree(appdate);
}

if we will be set invalid path in USERPROFILE - we got 80070003 error - HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND)

answered on Stack Overflow Jun 3, 2018 by RbMm

User contributions licensed under CC BY-SA 3.0