程序启动子进程时,子进程会自动使用当前进程的权限,包括ShellExecute启动的进程,都有这个问题。
当自己制作安装包时,安装包进程,在win7上,当前进程是管理员权限,启动的程序如果也以管理员权限运行,可能有问题,需要降低权限。
此函数的代码可以做到这一点,将当前进程的权限降低之后,再启动其他的进程。
BOOL CreateLowIntegrityProcess(LPCTSTR pszCommandLine)
{
DWORD dwError = ERROR_SUCCESS;
HANDLE hToken = NULL;
HANDLE hNewToken = NULL;
SID_IDENTIFIER_AUTHORITY MLAuthority = SECURITY_MANDATORY_LABEL_AUTHORITY;
PSID pIntegritySid = NULL;
TOKEN_MANDATORY_LABEL tml = { 0 };
STARTUPINFO si = { sizeof(si) };
PROCESS_INFORMATION pi = { 0 };
// Open the primary access token of the process.
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE | TOKEN_QUERY |
TOKEN_ADJUST_DEFAULT | TOKEN_ASSIGN_PRIMARY, &hToken))
{
dwError = GetLastError();
goto Cleanup;
}
// Duplicate the primary token of the current process.
if (!DuplicateTokenEx(hToken, 0, NULL, SecurityImpersonation,
TokenPrimary, &hNewToken))
{
dwError = GetLastError();
goto Cleanup;
}
// Create the low integrity SID.
if (!AllocateAndInitializeSid(&MLAuthority, 1, SECURITY_MANDATORY_MEDIUM_RID,
0, 0, 0, 0, 0, 0, 0, &pIntegritySid))
{
dwError = GetLastError();
goto Cleanup;
}
tml.Label.Attributes = SE_GROUP_INTEGRITY;
tml.Label.Sid = pIntegritySid;
// Set the integrity level in the access token to low.
if (!SetTokenInformation(hNewToken, TokenIntegrityLevel, &tml,
(sizeof(tml) + GetLengthSid(pIntegritySid))))
{
dwError = GetLastError();
goto Cleanup;
}
// Create the new process at the Low integrity level.
if (!CreateProcessAsUser(hNewToken, NULL, (LPWSTR) pszCommandLine, NULL, NULL,
FALSE, 0, NULL, NULL, &si, &pi))
{
dwError = GetLastError();
goto Cleanup;
}
Cleanup:
// Centralized cleanup for all allocated resources.
if (hToken)
{
CloseHandle(hToken);
hToken = NULL;
}
if (hNewToken)
{
CloseHandle(hNewToken);
hNewToken = NULL;
}
if (pIntegritySid)
{
FreeSid(pIntegritySid);
pIntegritySid = NULL;
}
if (pi.hProcess)
{
CloseHandle(pi.hProcess);
pi.hProcess = NULL;
}
if (pi.hThread)
{
CloseHandle(pi.hThread);
pi.hThread = NULL;
}
if (ERROR_SUCCESS != dwError)
{
// Make sure that the error code is set for failure.
SetLastError(dwError);
return FALSE;
}
else
{
return TRUE;
}
}