BOOL TIsUserAnAdmin() { static BOOL once = FALSE; static BOOL (WINAPI *pIsUserAnAdmin)(void); static BOOL ret = FALSE; if (!once) { pIsUserAnAdmin = (BOOL (WINAPI *)(void)) GetProcAddress(::GetModuleHandle("shell32"), "IsUserAnAdmin"); if (pIsUserAnAdmin) { ret = pIsUserAnAdmin(); } once = TRUE; } return ret; }
/** * Launch a child process without elevated privilege. */ static BOOL LaunchAsNormalUser(const PRUnichar *exePath, PRUnichar *cl) { #ifdef WINCE return PR_FALSE; #else if (!pCreateProcessWithTokenW) { // IsUserAnAdmin is not present on Win9x and not exported by name on Win2k *(FARPROC *)&pIsUserAnAdmin = GetProcAddress(GetModuleHandleA("shell32.dll"), "IsUserAnAdmin"); // CreateProcessWithTokenW is not present on WinXP or earlier *(FARPROC *)&pCreateProcessWithTokenW = GetProcAddress(GetModuleHandleA("advapi32.dll"), "CreateProcessWithTokenW"); if (!pCreateProcessWithTokenW) return FALSE; } // do nothing here if we are not elevated or IsUserAnAdmin is not present. if (!pIsUserAnAdmin || pIsUserAnAdmin && !pIsUserAnAdmin()) return FALSE; // borrow the shell token to drop the privilege HWND hwndShell = FindWindowA("Progman", NULL); DWORD dwProcessId; GetWindowThreadProcessId(hwndShell, &dwProcessId); HANDLE hProcessShell = OpenProcess(MAXIMUM_ALLOWED, FALSE, dwProcessId); if (!hProcessShell) return FALSE; HANDLE hTokenShell; BOOL ok = OpenProcessToken(hProcessShell, MAXIMUM_ALLOWED, &hTokenShell); CloseHandle(hProcessShell); if (!ok) return FALSE; HANDLE hNewToken; ok = DuplicateTokenEx(hTokenShell, MAXIMUM_ALLOWED, NULL, SecurityDelegation, TokenPrimary, &hNewToken); CloseHandle(hTokenShell); if (!ok) return FALSE; STARTUPINFOW si = {sizeof(si), 0}; PROCESS_INFORMATION pi = {0}; // When launching with reduced privileges, environment inheritance // (passing NULL as lpEnvironment) doesn't work correctly. Pass our // current environment block explicitly WCHAR* myenv = GetEnvironmentStringsW(); ok = pCreateProcessWithTokenW(hNewToken, 0, // profile is already loaded exePath, cl, CREATE_UNICODE_ENVIRONMENT, myenv, // inherit my environment NULL, // use my current directory &si, &pi); if (myenv) FreeEnvironmentStringsW(myenv); CloseHandle(hNewToken); if (!ok) return FALSE; CloseHandle(pi.hProcess); CloseHandle(pi.hThread); return TRUE; #endif }