首页  编辑  

Vista 服务权限和启动子进程

Tags: /超级猛料/OS.操作系统/权限控制/   Date Created:

Calling CreateProcessAsUser() from service

http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=404082&SiteID=1

Vista 启用了UAC之后,在服务中要运行一个子进程,是非常麻烦的,不能正常运行,按微软的说法,需要CreateProcessAsUser来调用:

The same code works for us on Vista as on XP, etc. The service is running as the Local System.

1. use WTSGetActiveConsoleSessionId to get the ID of the current active Windows session at the console (i.e. the machine keyboard and display, as opposed to WTS sessions).

2. use WTSQueryUserToken to get the token for that session.

3. use DuplicateTokenEx(hToken,MAXIMUM_ALLOWED,NULL,SecurityIdentification,TokenPrimary, &hTokenDup) to duplicate that token.

4. use CreateEnvironmentBlock to create an environment that you will be passing to the process.

5. use CreateProcessAsUser with the duplicated token and the created environment. Actually, we use CreateProcessAsUserW, since the A version had some sort of bug on some older systems.

6. Don't forget to CloseHandle on the various tokens, etc, and to DestroyEnvironmentBlock the environment.

HANDLE hTokenNew = NULL, hTokenDup = NULL;

HMODULE  hmod = LoadLibrary("kernel32.dll");

WTSGETACTIVECONSOLESESSIONID lpfnWTSGetActiveConsoleSessionId = (WTSGETACTIVECONSOLESESSIONID)GetProcAddress(hmod,"WTSGetActiveConsoleSessionId");

DWORD dwSessionId = lpfnWTSGetActiveConsoleSessionId();

WTSQueryUserToken(dwSessionId, &hToken);

DuplicateTokenEx(hTokenNew,MAXIMUM_ALLOWED,NULL,SecurityIdentification,TokenPrimary,&hTokenDup);

//  WriteToLog("Calling lpfnCreateEnvironmentBlock");

ZeroMemory( &si, sizeof( STARTUPINFO ) );

si.cb = sizeof( STARTUPINFO );

si.lpDesktop = "winsta0\\default";

LPVOID  pEnv = NULL;

DWORD dwCreationFlag = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE;

HMODULE hModule = LoadLibrary("Userenv.dll");

if(hModule )

{

 LPFN_CreateEnvironmentBlock lpfnCreateEnvironmentBlock = (LPFN_CreateEnvironmentBlock)GetProcAddress( hModule, "CreateEnvironmentBlock" );

 if( lpfnCreateEnvironmentBlock != NULL )

 {

  if(lpfnCreateEnvironmentBlock(&pEnv, hTokenDup, FALSE))

  {

   WriteToLog("CreateEnvironmentBlock Ok");

   dwCreationFlag |= CREATE_UNICODE_ENVIRONMENT;    

  }

  else

  {

   pEnv = NULL;

  }

 }

}

 //

ZeroMemory( &pi,sizeof(pi));

if ( !CreateProcessAsUser(

 hTokenDup,

 NULL,

 ( char * )pszCmd,  

 NULL,

 NULL,

 FALSE,

 dwCreationFlag,

 pEnv,

 NULL,

 &si,

 &pi

 ) )

{

 

 goto RESTORE;

}

在Vista UAC下,如果你的程序以Administrator帐户运行之后,还不一定有最高的权限,如果要复制文件读写System目录,等还是会提示用户权限控制等对话框的,如果要避免这些对话框的出现,那么可以在你的EXE中添加manifest资源或者创建一个exe同名的.manifest文件,内容类似下面:

<?xml version="1.0" encoding="utf-8"?>

<asmv1:assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

<assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>

<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">

<security>

<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">

<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />

</requestedPrivileges>

</security>

</trustInfo>

</asmv1:assembly>