windows8下 服务程序无法启动exe?

时间:2022-06-12 17:54:08
各位大神们,小弟急求。
目前写了一个windows服务程序,暂且叫A吧,如果插上我们的USB设备,windows检测到了设备,服务程序就会自动启动程序,叫B吧,B与usb设备进行通信。
现在的问题是,服务程序在windows其他系统都是可以的,唯独在win8上,启动不了B进程,进屋管理器中查看不到的。已explorer.exe的令牌得到的进程,启动权限为Administrator,但是在win8上启动不了B,CreateProcessAsUser返回740错误。
如果以winlogon.exe的令牌启动,win7&win8都能启动,但是是system权限启动了,这样的话就有问题了,我们必须要已当前用户权限启动B程序,这样才能正常的使用B。
如果把B的UAC去掉,win8也是可以启动的,但是B的UAC必须要加上的,不能去掉。

不知道我说的是否明白,求大神帮忙了,研究了很长时间了。
代码如下::

BOOL LaunchAppIntoDifferentSession(LPCTSTR szAppFullPath) 
{
PROCESS_INFORMATION pi;
STARTUPINFO si;    
BOOL bResult = FALSE;
DWORD dwSessionId,winlogonPid;
HANDLE hUserToken,hUserTokenDup,hPToken,hProcess;
DWORD dwCreationFlags;

// Log the client on to the local computer.

dwSessionId = WTSGetActiveConsoleSessionId(); //得到当前用户的会话ID

//////////////////////////////////////////
// Find the winlogon process
////////////////////////////////////////

PROCESSENTRY32 procEntry;  //用来存放快照进程信息的一个结构体
    //函数为指定的进程、进程使用的堆[HEAP]、模块[MODULE]、线程[THREAD])建立一个快照[snapshot]
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnap == INVALID_HANDLE_VALUE)
{
return FALSE;
}

procEntry.dwSize = sizeof(PROCESSENTRY32);

if (!Process32First(hSnap, &procEntry)) //获得第一个进程的句柄.
{
return FALSE;
}

do
{
if (_wcsicmp(procEntry.szExeFile, _T("explorer.exe")) == 0)  //查找winlogon.exe
{
// We found a winlogon process...make sure it's running in the console session
DWORD winlogonSessId = 0;
if (ProcessIdToSessionId(procEntry.th32ProcessID, &winlogonSessId) && winlogonSessId == dwSessionId)//得到与进程ID对应的终端服务会话ID
{
winlogonPid = procEntry.th32ProcessID;
break;
}
}

} while (Process32Next(hSnap, &procEntry)); //获得下一个进程的句柄

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

WTSQueryUserToken(dwSessionId,&hUserToken); //通过会话ID得到令牌
dwCreationFlags = NORMAL_PRIORITY_CLASS|CREATE_NEW_CONSOLE;
//指定新进程的主窗口特性
ZeroMemory(&si, sizeof(STARTUPINFO));
si.cb= sizeof(STARTUPINFO);
//用于标识启动应用程序所在的桌面的名字。如果该桌面存在,
//新进程便与指定的桌面相关联。   如果桌面不存在,
//便创建一个带有默认属性的桌面,并使用为新进程指定的名字。   
//如果lpDesktop是NULL(这是最常见的情况),那么该进程将与当前桌面相关联 
si.lpDesktop = _T("winsta0\\default");
ZeroMemory(&pi, sizeof(pi));
/*
TOKEN_PRIVILEGES Structure 的示意图
---------------------------------------------------------
|               PrivilegeCount                           |
---------------------------------------------------------
|    Luid      |   Luid        |    Luid       | ……    |        
|       |              |           |          |
| Attributes   |  Attributes   |  Attributes   | ……    |
|       |              |           |         |
---------------------------------------------------------
Privileges[0]    Privileges[1]   Privileges[2]   ……

*/
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))                      //获得令牌句柄
{
int abcd = GetLastError();
printf("Process token open Error: %u\n",GetLastError()); 
}

if (!LookupPrivilegeValue(NULL,SE_DEBUG_NAME,&luid))
{
printf("Lookup Privilege value Error: %u\n",GetLastError());
}
tp.PrivilegeCount =1;
tp.Privileges[0].Luid =luid;
tp.Privileges[0].Attributes =SE_PRIVILEGE_ENABLED;

DuplicateTokenEx(hPToken,MAXIMUM_ALLOWED,NULL,SecurityIdentification,TokenPrimary,&hUserTokenDup);//创建模拟令牌
int dup = GetLastError();
    //change Token session id
//Adjust Token privilege
SetTokenInformation(hUserTokenDup,TokenSessionId,(void*)dwSessionId,sizeof(DWORD));

if (!AdjustTokenPrivileges(hUserTokenDup,FALSE,&tp,sizeof(TOKEN_PRIVILEGES),(PTOKEN_PRIVILEGES)NULL,NULL)) //这个函数启用或禁止 指定访问令牌的特权
{
int abc =GetLastError();
printf("Adjust Privilege value Error: %u\n",GetLastError());
}

if (GetLastError()== ERROR_NOT_ALL_ASSIGNED)
{
printf("Token does not have the provilege\n");
}

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
szAppFullPath,              // file to execute
NULL, // 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
);
// End impersonation of client.
//GetLastError Shud be 0

int iResultOfCreateProcessAsUser = GetLastError();

//Perform All the Close Handles task

CloseHandle(hProcess);
CloseHandle(hUserToken);
CloseHandle(hUserTokenDup);
CloseHandle(hPToken);

return TRUE;
}


12 个解决方案

#1


有UAC,你启动的时候,是普通用户权限,你是否有Administrator的用户名和密码

#2


调用ShellExecuteEx试试,传入runas参数

#3


估计是你的B程序是管理员权限的,你的服务程序没有管理员权限,启动需要管理员权限的B程序,权限不够,返回740

#4


win8分为desktop和metro程序,desktop下的程序和之前windows版本没有什么区别。

并且在desktop下写的服务是可以启动exe程序的,只不过service的权限太高是属于section0级别,而exe是属于用户级别。所以想在service下启动exe,需要做三件事:1、事先模拟用户权限;2、启动exe,用shell方法之类的;3、把权限修改回来。

我能说出这几个点的原因是我之前也做过同样的问题,并且是可行的。不过现在手头没有模拟用户权限的代码,楼主要是急可以上百度上查一下模拟权限之类的。要是不急,明天我可以把代码献上。(只要我回家能想起来这事:) )

至于metro程序,我可以很负责的告诉你,service无法启动metro。我们项目团队做了近,3年多的metro了我还没有听说过有人说service可以调用metro下的app之类的说法。不要和我说metro才出来没两年,我们在metro没上市时就已经开始开发了。

#5


引用 2 楼 chenlycly 的回复:
调用ShellExecuteEx试试,传入runas参数

#6


class WTSSessionHolder
{
DWORD nCount;
WTS_SESSION_INFO* pSessions;

WTSSessionHolder( const WTSSessionHolder& );
WTSSessionHolder& operator=( const WTSSessionHolder& );

public:
WTSSessionHolder()
: nCount(0), pSessions( NULL )
{
if ( !::WTSEnumerateSessions( WTS_CURRENT_SERVER_HANDLE, 0, 1, &pSessions, &nCount ) )
{
AtlThrowLastWin32();
}
}

~WTSSessionHolder()
{
::WTSFreeMemory( pSessions );
}

typedef const WTS_SESSION_INFO* const_iterator;

const WTS_SESSION_INFO* begin() const
{
return pSessions;
}

const WTS_SESSION_INFO* end() const
{
return pSessions + nCount;
}
};

class WTSUserHolder
{
CHandle hUserToken;
BOOL bImpersonated;

WTSUserHolder( const WTSUserHolder& );
WTSUserHolder& operator=( const WTSUserHolder& );

static inline HANDLE GetSessionUserToken()
{
DWORD dwSessionID = ::WTSGetActiveConsoleSessionId();
if ( dwSessionID != 0xFFFFFFFF )
{
CHandle hUserToken;
if ( ::WTSQueryUserToken( dwSessionID, &hUserToken.m_h ) )
{
return hUserToken.Detach();
}
}
WTSSessionHolder sessions;
WTSSessionHolder::const_iterator end = sessions.end();
for( WTSSessionHolder::const_iterator i = sessions.begin() ; i != end ; ++i )
{
CHandle hUserToken;
if ( ::WTSQueryUserToken( i->SessionId, &hUserToken.m_h ) )
{
return hUserToken.Detach();
}
}
return NULL;
}

public:
WTSUserHolder()
: hUserToken(), bImpersonated( FALSE )
{
}

~WTSUserHolder()
{
UnImpersonate();
}

BOOL AttachCurrentUser()
{
CHandle hUserToken( GetSessionUserToken() );
hUserToken = hUserToken;
return hUserToken ? TRUE : FALSE;
}

HANDLE GetUserToken() const
{
return hUserToken;
}

BOOL Impersonate()
{
if ( !bImpersonated )
{
bImpersonated = ::ImpersonateLoggedOnUser( hUserToken );
}
return bImpersonated;
}

void UnImpersonate()
{
if ( bImpersonated && ::RevertToSelf() )
{
bImpersonated = FALSE;
}
}

BOOL IsImpersonated() const
{
return bImpersonated;
}
};


代码献上,这个是5年前写的二个类,基本上就是遍历所有用户,最后模拟成用户的权限。要解决的问题就是由于我在服务程序中想做一些用户权限下需要做的事。和楼主想的是一类问题,启动exe在服务在用服务权限是不行的,先模拟成用户权限,启动,启动完之后再模拟回来。

下面是模拟的代码。

WTSUserHolder objUser;
if ( objUser.AttachCurrentUser() )
{
    objUser.Impersonate();//这个就是模拟,在这之后就可以启动你的exe程序了。
}

因为我做的是一个类,在对象objUser析构时就会自动改为secion0权限。

对了,关于里面用到的api楼主自己查一下msdn看看需要包含什么头文件和库,否则编译不过的哦。

#7


谢谢大家的热心回复,特别谢谢SiGoYi,小弟我弄了快一个月了,郁闷,一直在MSDN上找sample,demo,但是一直没有解决,由于对win8系统开发不熟悉,所以这个问题无法解决,除了win8其他的系统都是可以的。
我今天来试试,谢谢大家,

#8


为什么服务不可以打开 metro 呢?
至少可以使用 命令行打开 metro .
我没有试过服务打开 metro app ,但是我认为至少可以创建一个 desktop 来打开 metro app.

谢谢你的 代码,我收藏了。

#9


使用了SiGoYi的方法测试了,在win8下虽然可以启动线程,但是B程序没有启动UI,只是任务管理器中有这个进程,而且这个进程是SYSTEM权限。
现在要求是,在win8下,必须要B程序UI正常启动,而且是当前的用户权限,不是SYSTEM权限。





我之前自己写的代码
int win_impersonate_desktop_user() 
{
HANDLE desktopUserHandle = NULL;
TCHAR szMyUsername[1024];
DWORD usize = 1024;

if (active_token != NULL)
{
BMLOG(_T("IMPERSONATE_HANDLE_IN_USE"));

CloseHandle(active_token);
active_token = NULL;

return IMPERSONATE_HANDLE_IN_USE;
}

  if(!EnableDebugPriv())
  {
  //printf("You probably don't have the SE_DEBUG_NAME privilege\n");
  BMLOG(_T("You probably don't have the SE_DEBUG_NAME privilege"));
  return IMPERSONATE_PRIVILEDGE_FAILURE;
  }

if (WTSQueryUserToken(WTSGetActiveConsoleSessionId(), &desktopUserHandle) == FALSE)
{
//debug_printf(DEBUG_NORMAL,
// "Error getting desktop user token.  (Error : %d)\n",
// GetLastError());
BMLOG(_T("Error getting desktop user token.  (Error : %d)"),GetLastError());
return IMPERSONATE_BAD_USER_TOKEN;
}

if (DuplicateTokenEx(desktopUserHandle, TOKEN_ALL_ACCESS, NULL, SecurityImpersonation,
TokenImpersonation, &active_token) == FALSE)
{
CloseHandle(desktopUserHandle); // Clean it up.
//debug_printf(DEBUG_NORMAL,
// "Error duplicating desktop user token.  (Error : %d)\n",
// GetLastError());
BMLOG(_T("Error duplicating desktop user token.  (Error : %d)"),GetLastError());
return IMPERSONATE_BAD_USER_TOKEN;
}

CloseHandle(desktopUserHandle); // We are done with it.  We made a dup.
if (ImpersonateLoggedOnUser(active_token) == FALSE)
{
//debug_printf(DEBUG_NORMAL,
// "Couldn't impersonate logged on user. (Error : %d)\n",
// GetLastError());
CloseHandle(active_token);
active_token = NULL;
BMLOG(_T("Couldn't impersonate logged on user. (Error : %d)"),GetLastError());
return IMPERSONATE_FAILURE;
}

if (GetUserName(szMyUsername, &usize) != 0)
{
//debug_printf(DEBUG_CONTEXT, "Impersonating user: %s!\n",
// szMyUsername);
BMLOG(_T("Impersonating user: %s"),szMyUsername);
}

return IMPERSONATE_NO_ERROR;
}


BOOL EnableDebugPriv(void)
{
TOKEN_PRIVILEGES tp;
HANDLE hToken;
LUID luid;
 HANDLE hProcess;

 DWORD dwPID;
 dwPID = GetCurrentProcessId();

  if ((hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID)) == NULL) 
  {
  BMLOG(_T("hProcess = OpenProcess(PROCESS_ALL_ACCESS %d"),GetLastError());
  return FALSE;
  }

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

if(!OpenProcessToken(
GetCurrentProcess(),
 TOKEN_ADJUST_DEFAULT|TOKEN_ADJUST_SESSIONID /*| TOKEN_ALL_ACCESS*//*MAXIMUM_ALLOWED | READ_CONTROL|WRITE_DAC*//*|TOKEN_READ|TOKEN_WRITE*/|TOKEN_QUERY,
&hToken ))
{
//PERR("OpenProcessToken");

BMLOG(_T("OpenProcessToken=%d"),GetLastError());
return(FALSE);
}

if(!LookupPrivilegeValue(NULL, /*SE_DEBUG_NAME*/SE_TCB_NAME , /*&luid*/&tp.Privileges[0].Luid))
{
//PERR("LookupPrivilegeValue");

BMLOG(_T("LookupPrivilegeValue=%d"),GetLastError());
CloseHandle(hToken);
return(FALSE);
}

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

if(!AdjustTokenPrivileges(
hToken,
FALSE,
&tp,
sizeof(TOKEN_PRIVILEGES),
NULL,
NULL ))
{

BMLOG(_T("AdjustTokenPrivileges=%d"),GetLastError());
//PERR("AdjustTokenPrivileges");
CloseHandle(hToken);
return(FALSE);
}

CloseHandle(hToken);

return(TRUE);

}



如果把我的这段代码加上,win8下进程B不能启动,打印log是AdjustTokenPrivileges=5,然后我就一直解决不了了。









#10


@SiGoYi
老大,在么? 麻烦给指导一下

#11


可以用CreateProcessAsUser,另外,确实得关注一下权限的问题。

#12


引用 11 楼 cuit 的回复:
可以用CreateProcessAsUser,另外,确实得关注一下权限的问题。

#1


有UAC,你启动的时候,是普通用户权限,你是否有Administrator的用户名和密码

#2


调用ShellExecuteEx试试,传入runas参数

#3


估计是你的B程序是管理员权限的,你的服务程序没有管理员权限,启动需要管理员权限的B程序,权限不够,返回740

#4


win8分为desktop和metro程序,desktop下的程序和之前windows版本没有什么区别。

并且在desktop下写的服务是可以启动exe程序的,只不过service的权限太高是属于section0级别,而exe是属于用户级别。所以想在service下启动exe,需要做三件事:1、事先模拟用户权限;2、启动exe,用shell方法之类的;3、把权限修改回来。

我能说出这几个点的原因是我之前也做过同样的问题,并且是可行的。不过现在手头没有模拟用户权限的代码,楼主要是急可以上百度上查一下模拟权限之类的。要是不急,明天我可以把代码献上。(只要我回家能想起来这事:) )

至于metro程序,我可以很负责的告诉你,service无法启动metro。我们项目团队做了近,3年多的metro了我还没有听说过有人说service可以调用metro下的app之类的说法。不要和我说metro才出来没两年,我们在metro没上市时就已经开始开发了。

#5


引用 2 楼 chenlycly 的回复:
调用ShellExecuteEx试试,传入runas参数

#6


class WTSSessionHolder
{
DWORD nCount;
WTS_SESSION_INFO* pSessions;

WTSSessionHolder( const WTSSessionHolder& );
WTSSessionHolder& operator=( const WTSSessionHolder& );

public:
WTSSessionHolder()
: nCount(0), pSessions( NULL )
{
if ( !::WTSEnumerateSessions( WTS_CURRENT_SERVER_HANDLE, 0, 1, &pSessions, &nCount ) )
{
AtlThrowLastWin32();
}
}

~WTSSessionHolder()
{
::WTSFreeMemory( pSessions );
}

typedef const WTS_SESSION_INFO* const_iterator;

const WTS_SESSION_INFO* begin() const
{
return pSessions;
}

const WTS_SESSION_INFO* end() const
{
return pSessions + nCount;
}
};

class WTSUserHolder
{
CHandle hUserToken;
BOOL bImpersonated;

WTSUserHolder( const WTSUserHolder& );
WTSUserHolder& operator=( const WTSUserHolder& );

static inline HANDLE GetSessionUserToken()
{
DWORD dwSessionID = ::WTSGetActiveConsoleSessionId();
if ( dwSessionID != 0xFFFFFFFF )
{
CHandle hUserToken;
if ( ::WTSQueryUserToken( dwSessionID, &hUserToken.m_h ) )
{
return hUserToken.Detach();
}
}
WTSSessionHolder sessions;
WTSSessionHolder::const_iterator end = sessions.end();
for( WTSSessionHolder::const_iterator i = sessions.begin() ; i != end ; ++i )
{
CHandle hUserToken;
if ( ::WTSQueryUserToken( i->SessionId, &hUserToken.m_h ) )
{
return hUserToken.Detach();
}
}
return NULL;
}

public:
WTSUserHolder()
: hUserToken(), bImpersonated( FALSE )
{
}

~WTSUserHolder()
{
UnImpersonate();
}

BOOL AttachCurrentUser()
{
CHandle hUserToken( GetSessionUserToken() );
hUserToken = hUserToken;
return hUserToken ? TRUE : FALSE;
}

HANDLE GetUserToken() const
{
return hUserToken;
}

BOOL Impersonate()
{
if ( !bImpersonated )
{
bImpersonated = ::ImpersonateLoggedOnUser( hUserToken );
}
return bImpersonated;
}

void UnImpersonate()
{
if ( bImpersonated && ::RevertToSelf() )
{
bImpersonated = FALSE;
}
}

BOOL IsImpersonated() const
{
return bImpersonated;
}
};


代码献上,这个是5年前写的二个类,基本上就是遍历所有用户,最后模拟成用户的权限。要解决的问题就是由于我在服务程序中想做一些用户权限下需要做的事。和楼主想的是一类问题,启动exe在服务在用服务权限是不行的,先模拟成用户权限,启动,启动完之后再模拟回来。

下面是模拟的代码。

WTSUserHolder objUser;
if ( objUser.AttachCurrentUser() )
{
    objUser.Impersonate();//这个就是模拟,在这之后就可以启动你的exe程序了。
}

因为我做的是一个类,在对象objUser析构时就会自动改为secion0权限。

对了,关于里面用到的api楼主自己查一下msdn看看需要包含什么头文件和库,否则编译不过的哦。

#7


谢谢大家的热心回复,特别谢谢SiGoYi,小弟我弄了快一个月了,郁闷,一直在MSDN上找sample,demo,但是一直没有解决,由于对win8系统开发不熟悉,所以这个问题无法解决,除了win8其他的系统都是可以的。
我今天来试试,谢谢大家,

#8


为什么服务不可以打开 metro 呢?
至少可以使用 命令行打开 metro .
我没有试过服务打开 metro app ,但是我认为至少可以创建一个 desktop 来打开 metro app.

谢谢你的 代码,我收藏了。

#9


使用了SiGoYi的方法测试了,在win8下虽然可以启动线程,但是B程序没有启动UI,只是任务管理器中有这个进程,而且这个进程是SYSTEM权限。
现在要求是,在win8下,必须要B程序UI正常启动,而且是当前的用户权限,不是SYSTEM权限。





我之前自己写的代码
int win_impersonate_desktop_user() 
{
HANDLE desktopUserHandle = NULL;
TCHAR szMyUsername[1024];
DWORD usize = 1024;

if (active_token != NULL)
{
BMLOG(_T("IMPERSONATE_HANDLE_IN_USE"));

CloseHandle(active_token);
active_token = NULL;

return IMPERSONATE_HANDLE_IN_USE;
}

  if(!EnableDebugPriv())
  {
  //printf("You probably don't have the SE_DEBUG_NAME privilege\n");
  BMLOG(_T("You probably don't have the SE_DEBUG_NAME privilege"));
  return IMPERSONATE_PRIVILEDGE_FAILURE;
  }

if (WTSQueryUserToken(WTSGetActiveConsoleSessionId(), &desktopUserHandle) == FALSE)
{
//debug_printf(DEBUG_NORMAL,
// "Error getting desktop user token.  (Error : %d)\n",
// GetLastError());
BMLOG(_T("Error getting desktop user token.  (Error : %d)"),GetLastError());
return IMPERSONATE_BAD_USER_TOKEN;
}

if (DuplicateTokenEx(desktopUserHandle, TOKEN_ALL_ACCESS, NULL, SecurityImpersonation,
TokenImpersonation, &active_token) == FALSE)
{
CloseHandle(desktopUserHandle); // Clean it up.
//debug_printf(DEBUG_NORMAL,
// "Error duplicating desktop user token.  (Error : %d)\n",
// GetLastError());
BMLOG(_T("Error duplicating desktop user token.  (Error : %d)"),GetLastError());
return IMPERSONATE_BAD_USER_TOKEN;
}

CloseHandle(desktopUserHandle); // We are done with it.  We made a dup.
if (ImpersonateLoggedOnUser(active_token) == FALSE)
{
//debug_printf(DEBUG_NORMAL,
// "Couldn't impersonate logged on user. (Error : %d)\n",
// GetLastError());
CloseHandle(active_token);
active_token = NULL;
BMLOG(_T("Couldn't impersonate logged on user. (Error : %d)"),GetLastError());
return IMPERSONATE_FAILURE;
}

if (GetUserName(szMyUsername, &usize) != 0)
{
//debug_printf(DEBUG_CONTEXT, "Impersonating user: %s!\n",
// szMyUsername);
BMLOG(_T("Impersonating user: %s"),szMyUsername);
}

return IMPERSONATE_NO_ERROR;
}


BOOL EnableDebugPriv(void)
{
TOKEN_PRIVILEGES tp;
HANDLE hToken;
LUID luid;
 HANDLE hProcess;

 DWORD dwPID;
 dwPID = GetCurrentProcessId();

  if ((hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID)) == NULL) 
  {
  BMLOG(_T("hProcess = OpenProcess(PROCESS_ALL_ACCESS %d"),GetLastError());
  return FALSE;
  }

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

if(!OpenProcessToken(
GetCurrentProcess(),
 TOKEN_ADJUST_DEFAULT|TOKEN_ADJUST_SESSIONID /*| TOKEN_ALL_ACCESS*//*MAXIMUM_ALLOWED | READ_CONTROL|WRITE_DAC*//*|TOKEN_READ|TOKEN_WRITE*/|TOKEN_QUERY,
&hToken ))
{
//PERR("OpenProcessToken");

BMLOG(_T("OpenProcessToken=%d"),GetLastError());
return(FALSE);
}

if(!LookupPrivilegeValue(NULL, /*SE_DEBUG_NAME*/SE_TCB_NAME , /*&luid*/&tp.Privileges[0].Luid))
{
//PERR("LookupPrivilegeValue");

BMLOG(_T("LookupPrivilegeValue=%d"),GetLastError());
CloseHandle(hToken);
return(FALSE);
}

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

if(!AdjustTokenPrivileges(
hToken,
FALSE,
&tp,
sizeof(TOKEN_PRIVILEGES),
NULL,
NULL ))
{

BMLOG(_T("AdjustTokenPrivileges=%d"),GetLastError());
//PERR("AdjustTokenPrivileges");
CloseHandle(hToken);
return(FALSE);
}

CloseHandle(hToken);

return(TRUE);

}



如果把我的这段代码加上,win8下进程B不能启动,打印log是AdjustTokenPrivileges=5,然后我就一直解决不了了。









#10


@SiGoYi
老大,在么? 麻烦给指导一下

#11


可以用CreateProcessAsUser,另外,确实得关注一下权限的问题。

#12


引用 11 楼 cuit 的回复:
可以用CreateProcessAsUser,另外,确实得关注一下权限的问题。