通过服务启动进程后,来自SHGetKnownFolderPath的错误0x80070005

时间:2018-06-03 12:39:13

标签: c++ winapi service process

我使用下面的代码获取appdata文件夹。通常它可以工作,但如果我使用与this类似的方式开始使用相同的服务,我会收到错误0x80070005,这意味着Access Denied

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

    return false;
}

创建过程的函数是

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

我在互联网上找不到与此相关的任何内容。有人可以帮忙吗?

1 个答案:

答案 0 :(得分:3)

您的错误,即您未将lpEnvironment参数传递给CreateProcess来电。

  

lpEnvironment [in,optional]

     

指向新进程的环境块的指针。如果这   参数是 NULL ,新进程使用的环境   呼叫过程。

结果子进程使用调用进程的环境。这会给FOLDERID_RoamingAppData带来什么影响?在解决FOLDERID_RoamingAppData期间 - 我们通常会获得%USERPROFILE%\AppData\Roaming - 最终结果将取决于%USERPROFILE%的值。在您的情况下 - 它将从服务(LocalSystem)继承而且看起来像C:\WINDOWS\system32\config\systemprofile - 所以最终路径必须看起来像C:\WINDOWS\system32\config\systemprofile\AppData\Roaming。在将此路径返回给调用者之前 - 系统检查是路径存在 - 调用GetFileAttributes。在这里它失败了(由于安全许可) - 最后一次错误 - 5 - ERROR_ACCESS_DENIED。和api最终返回HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED),即80070005

结论 - 在调用CreateProcessAsUser中使用指向CreateEnvironmentBlock返回的环境块的指针。然后由DestroyEnvironmentBlock释放此块。也不要忘记调用CREATE_UNICODE_ENVIRONMENT

中的CreateProcessAsUser标记

也可以通过下一个代码在本地(非提升)过程中轻松复制您的错误:

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);
}

如果我们在USERPROFILE设置无效路径,则会出现80070003错误 - HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND)