需求:管理员启动了安装包并安装完后需要启动程序。此时希望是以当前登录用户来启动,而不是以管理员用户来启动(安装包是管理员权限,直接启动因为权限继承原因,程序也会是管理员权限)
思路:利用当前explorer.exe进程的token去创建目的进程
DWORD GetExplorerToken(int nProcessId,OUT PHANDLE phExplorerToken)
{
DWORD dwStatus = ERROR_FILE_NOT_FOUND ;
BOOL bRet = FALSE ;
HANDLE hProcess = NULL ;
HANDLE hProcessSnap = NULL ;
TCHAR szExplorerPath[MAX_PATH] = { 0 } ;
TCHAR FileName[MAX_PATH] = { 0 } ;
PROCESSENTRY32 pe32 = { 0 } ;
__try
{
hProcessSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS , 0 ) ;
if( hProcessSnap == INVALID_HANDLE_VALUE )
{
dwStatus = GetLastError() ;
__leave ;
}
pe32.dwSize = sizeof( PROCESSENTRY32 ) ;
if( !Process32First( hProcessSnap, &pe32 ))
{
dwStatus = GetLastError() ;
__leave ;
}
do {
if(nProcessId == pe32.th32ProcessID)
{
hProcess = OpenProcess(
PROCESS_QUERY_INFORMATION ,
FALSE ,
pe32.th32ProcessID ) ;
if( NULL != hProcess )
{
HANDLE hToken ;
if( OpenProcessToken( hProcess , TOKEN_DUPLICATE , &hToken ))
{
HANDLE hNewToken = NULL;
DuplicateTokenEx(hToken, TOKEN_ALL_ACCESS, NULL, SecurityImpersonation, TokenPrimary, &hNewToken);
* phExplorerToken = hNewToken ;
dwStatus = 0 ;
CloseHandle(hToken);
}
break ;
CloseHandle ( hProcess ) ;
hProcess = NULL ;
}
else
{
int nLast = GetLastError();
char pszbuffer[100]={0};
sprintf(pszbuffer,"error:%d:%d:%d",nLast,nProcessId,pe32.th32ProcessID);
MessageBox(0,pszbuffer,0,0);
}
}
} while( Process32Next( hProcessSnap, &pe32 )) ;
}
__finally
{
if( NULL != hProcess )
{
CloseHandle( hProcess ) ;
}
if( NULL != hProcessSnap )
{
CloseHandle ( hProcessSnap ) ;
}
}
return dwStatus ;
}
以下是调用 DWORD i;
//考虑到多用户登录的时候explorer.exe有多个,故要特别处理一下
HANDLE hPtoken = NULL ;
HWND hWnd = FindWindow("Shell_TrayWnd","");
hWnd = FindWindowEx(hWnd,NULL,"ReBarWindow32","");
hWnd = FindWindowEx(hWnd,NULL,"MSTaskSwWClass","运行应用程序");
DWORD id = 0;
GetWindowThreadProcessId(hWnd,&id);
GetExplorerToken(id,&hPtoken);
PROCESS_INFORMATION pi;
STARTUPINFOW si = { sizeof(STARTUPINFO),NULL,L"",NULL,0,0,0,0,0,0,0,STARTF_USESHOWWINDOW,0,0,NULL,0,0,0};
si.wShowWindow = SW_SHOW;
si.lpDesktop = NULL;
ZeroMemory( &pi, sizeof(pi) );
char infoBuf[MAX_PATH];
DWORD bufCharCount = MAX_PATH;
popstring(infoBuf);
int n= MultiByteToWideChar(CP_ACP,0,infoBuf,-1,NULL,0);
wchar_t *m_pszHref =new wchar_t[n];
memset(m_pszHref,0,n);
MultiByteToWideChar(CP_ACP,0,infoBuf,-1,m_pszHref,n);
CreateProcessWithTokenW(hPtoken, LOGON_WITH_PROFILE, NULL, m_pszHref, NULL, NULL, NULL, &si,&pi);