我有一个安装程序,在安装完成后尝试(重新)在当前用户上下文中启动我的应用程序。 安装程序在SYSTEM上下文中运行,在启动应用程序之前,它尝试(理论上成功)模拟当前用户。但是,当我查看任务管理器时,我发现我的应用程序正在SYSTEM上下文中运行。
这是我的代码(摘录):
TCHAR szUsername[128] = _T("");
DWORD dwUsernameSize = 128;
GetUserName(szUsername, &dwUsernameSize);
// Lets the calling process impersonate the security context of a logged-on user.
if (!ImpersonateLoggedOnUser(hToken))
{
throw Win32Exception(GetLastError(), _T("Failed to impersonate current user"));
}
TCHAR szUsername2[128] = _T("");
DWORD dwUsernameSize2 = 128;
GetUserName(szUsername2, &dwUsernameSize2);
MLOGD(_T("ProcessUtils::StartProcessInCurrentUserContext: Successfully impersonated %s"), szUsername2);
ProcessUtils::StartProcess(sExeName, lstParams, sWorkingDir, bWaitToFinish, errCode);
ProcessUtils :: StartProcess是CreateProcess的包装。
szUsername包含SYSTEM,szUsername2包含当前用户。因此ImpersonateLoggedOnUser成功。 但是,如上所述,该过程在SYSTEM上下文中启动,而不是当前用户。
我不确定这可能会有多大帮助,但我的安装程序是用NSIS编写的,它通过一个用C / C ++编写的插件调用包含上面代码的函数。
有谁知道为什么我的应用程序无法在当前用户上下文中启动?
答案 0 :(得分:3)
Win32 CreateProcess在相同安全上下文中创建一个与SYSTEM调用者相同的进程(即使您正在模仿)。
认为您需要调用CreateProcessAsUser。
答案 1 :(得分:2)
CreateProcessAsUser
,我终于放弃了。彻底彻底
在网上搜索,我发现了一个使用的睿智实现
IShellDispatch2
界面。这是一个例子:
#include <Windows.h>
#include <exdisp.h>
#include <Shobjidl.h>
#include <Shlwapi.h>
#include <comutil.h>
#include <SHLGUID.h>
#include <cstdlib>
#include <iostream>
#pragma comment(lib, "Shlwapi.lib")
#pragma comment(lib, "comsuppw.lib")
bool ShellExecuteAsCurrentUser(const TCHAR *pcOperation, const TCHAR *pcFileName, const TCHAR *pcParameters,
const TCHAR *pcsDirectory, const DWORD dwShow)
{
bool bSuccess = false;
IShellWindows *psw = NULL;
HRESULT hr = CoCreateInstance(CLSID_ShellWindows, NULL, CLSCTX_LOCAL_SERVER, IID_PPV_ARGS(&psw));
if(SUCCEEDED(hr))
{
HWND hwnd = 0;
IDispatch* pdisp = NULL;
_variant_t vEmpty;
if(S_OK == psw->FindWindowSW(&vEmpty, &vEmpty, SWC_DESKTOP, reinterpret_cast<long*>(&hwnd), SWFO_NEEDDISPATCH, &pdisp))
{
if((hwnd != NULL) && (hwnd != INVALID_HANDLE_VALUE))
{
IShellBrowser *psb;
hr = IUnknown_QueryService(pdisp, SID_STopLevelBrowser, IID_PPV_ARGS(&psb));
if(SUCCEEDED(hr))
{
IShellView *psv = NULL;
hr = psb->QueryActiveShellView(&psv);
if(SUCCEEDED(hr))
{
IDispatch *pdispBackground = NULL;
HRESULT hr = psv->GetItemObject(SVGIO_BACKGROUND, IID_PPV_ARGS(&pdispBackground));
if(SUCCEEDED(hr))
{
IShellFolderViewDual *psfvd = NULL;
hr = pdispBackground->QueryInterface(IID_PPV_ARGS(&psfvd));
if(SUCCEEDED(hr))
{
IDispatch *pdisp = NULL;
hr = psfvd->get_Application(&pdisp);
if(SUCCEEDED(hr))
{
IShellDispatch2 *psd;
hr = pdisp->QueryInterface(IID_PPV_ARGS(&psd));
if(SUCCEEDED(hr))
{
_variant_t verb(pcOperation);
_variant_t file(pcFileName);
_variant_t para(pcParameters);
_variant_t dir(pcsDirectory);
_variant_t show(dwShow);
if(SUCCEEDED(psd->ShellExecute(file.bstrVal, para, vEmpty, verb, show)))
bSuccess = true;
psd->Release();
psd = NULL;
}
pdisp->Release();
pdisp = NULL;
}
}
pdispBackground->Release();
pdispBackground = NULL;
}
psv->Release();
psv = NULL;
}
psb->Release();
psb = NULL;
}
}
pdisp->Release();
pdisp = NULL;
}
psw->Release();
psw = NULL;
}
return bSuccess;
}
int main(int argc, char *argv[])
{
CoInitialize(NULL);
if(ShellExecuteAsCurrentUser(L"open", L"notepad", nullptr, nullptr, SW_SHOWNORMAL))
std::cout << "SUCCESS" << std::endl;
CoUninitialize();
return 0;
}
这只是一个快速演示,ShellExecuteAsCurrentUser
的实现可以
通过使用智能指针进行COM接口和一些重构来改进。这种方法
在WinXP SP3 - Win 8.1版本上为我工作,不确定它是否适用于Windows 10
更多细节,请查看作者github页面:
https://github.com/lordmulder/stdutils/tree/master/Contrib/StdUtils
答案 2 :(得分:1)
如果您已阅读the documentation for CreateProcess,您可以在前三个句子中找到问题的答案:
创建一个新进程及其主线程。新进程在调用进程的安全上下文中运行。
如果调用进程模仿其他用户,则新进程将使用该令牌进行调用,而不是模拟令牌。
真的没有什么可说的;您描述的行为是记录在案的。如果要以其他用户身份创建流程,则必须使用CreateProcessAsUser或其中一个相关功能。