位置不可用 - 服務中拉起程序報錯

CFileDialog
c:\windows\system32\config\systemprofile\desktop 引用一個不可用的位置

解決方法:
http://www.codeproject.com/Answers/896139/CFileDialog-gives-error-C-Windows-system-config-sy#answer3

原因:
The Desktop directory is part of the user profile. Starting an application from a service means that it does not have a user profile and therefore no desktop.

解決辦法:

BOOL CExecuteProcess::StartProcessWithToken(CString csProcessPath, CString csCommandLineParam,
    CString csAccessProcessName, bool bWait)
{
    PROCESS_INFORMATION     pi = { 0 };
    STARTUPINFO             si = { 0 };
    BOOL                    bResult = FALSE;
    DWORD                   dwSessionId = 0x00, winlogonPid = 0x00;
    HANDLE                  hUserToken = NULL;
    HANDLE                  hUserTokenDup = NULL;
    HANDLE                  hPToken = NULL;
    HANDLE                  hProcess = NULL;
    HANDLE                  hToken = NULL;

    DWORD                   dwCreationFlags = 0x00;
    DWORD                   dwLastError = 0x00;

    // Log the client on to the local computer.

    dwSessionId = WTSGetActiveConsoleSessionId();

    //////////////////////////////////////////
    // Get the explorer process handle
    ////////////////////////////////////////

    PROCESSENTRY32 procEntry;

    HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (hSnap == INVALID_HANDLE_VALUE)
    {
        //return bResult;
        goto Cleanup;
    }

    procEntry.dwSize = sizeof(PROCESSENTRY32);

    if (!Process32First(hSnap, &procEntry))
    {
        //return bResult;
        goto Cleanup;
    }

    do
    {
        if (_wcsicmp(procEntry.szExeFile, csAccessProcessName) == 0)
        {
            // We found a explorer process...
            // make sure it's running in the console session
            DWORD winlogonSessId = 0;
            if (ProcessIdToSessionId(procEntry.th32ProcessID, &winlogonSessId)
                && winlogonSessId == dwSessionId)
            {
                winlogonPid = procEntry.th32ProcessID;
                break;
            }
        }

    } while (Process32Next(hSnap, &procEntry));

    ////////////////////////////////////////////////////////////////////////

    ::WTSQueryUserToken(dwSessionId, &hUserToken);
    dwCreationFlags = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE;
    ZeroMemory(&si, sizeof(STARTUPINFO));
    si.cb = sizeof(STARTUPINFO);
    si.lpDesktop = L"winsta0\\default";

    ZeroMemory(&pi, sizeof(pi));

    TOKEN_PRIVILEGES tp;
    LUID luid;

    hProcess = OpenProcess(MAXIMUM_ALLOWED, FALSE, winlogonPid);

    if (!::OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY
        | TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY | TOKEN_ADJUST_SESSIONID
        | TOKEN_READ | TOKEN_WRITE, &hPToken))
    {
        dwLastError = GetLastError();
        goto Cleanup;
        //return bResult;
    }

    if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid))
    {
        //printf("Lookup Privilege value Error: %u\n", GetLastError());
        dwLastError = GetLastError();
        //return bResult;
        goto Cleanup;
    }

    tp.PrivilegeCount = 1;
    tp.Privileges[0].Luid = luid;
    tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

    DuplicateTokenEx(hPToken, MAXIMUM_ALLOWED, NULL,
        SecurityIdentification, TokenPrimary, &hUserTokenDup);

    dwLastError = GetLastError();

    //Adjust Token privilege
    SetTokenInformation(hUserTokenDup,
        TokenSessionId, (void*)dwSessionId, sizeof(DWORD));

    if (!AdjustTokenPrivileges(hUserTokenDup, FALSE, &tp, sizeof(TOKEN_PRIVILEGES),
        (PTOKEN_PRIVILEGES)NULL, NULL))
    {
        dwLastError = GetLastError();
        //return bResult;
        goto Cleanup;
    }

    //dwLastError = GetLastError();
    //if (dwLastError == ERROR_NOT_ALL_ASSIGNED)
    //{
    //  //return bResult;
    //  goto Cleanup;
    //}

    LPVOID  pEnv = NULL;

    if (::CreateEnvironmentBlock(&pEnv, hUserTokenDup, TRUE))
    {
        dwCreationFlags |= CREATE_UNICODE_ENVIRONMENT;
    }
    else
        pEnv = NULL;

    // Launch the process in the client's logon session.

    bResult = CreateProcessAsUser(
        hUserTokenDup,                      // client's access token
        csProcessPath,                      // file to execute
        csCommandLineParam.GetBuffer(csCommandLineParam.GetLength()),                 // command line
        NULL,               // pointer to process SECURITY_ATTRIBUTES
        NULL,               // pointer to thread SECURITY_ATTRIBUTES
        FALSE,              // handles are not inheritable
        dwCreationFlags,     // creation flags
        pEnv,               // pointer to new environment block
        NULL,               // name of current directory
        &si,               // pointer to STARTUPINFO structure
        &pi                // receives information about new process
        );
    csCommandLineParam.ReleaseBuffer();
    dwLastError = GetLastError();

    if (bResult)
        bResult = TRUE;
    //Perform All the Close Handles tasks

Cleanup:

    if (hProcess)
        CloseHandle(hProcess);

    if (hUserToken)
        CloseHandle(hUserToken);

    if (hUserTokenDup)
        CloseHandle(hUserTokenDup);

    if (hPToken)
        CloseHandle(hPToken);

    if (hToken)
        CloseHandle(hToken);

    return bResult;
}

ps:百度半天都不沾邊 google一下就出來了

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章