2017-02-15 22 views
0

我写这将作为服务运行,并会挑选系统代理设置用于与外界。我试图WinHttpGetIEProxyConfigForCurrentUser的应用程序,但它无法检索代理当前用户的设置很明显,因为服务在本地系统的域下运行。为了实现这一点,我必须让用户登录到我不想让应用程序用户执行的服务。我读到SERVICE_USER_OWN_PROCESS参数,它可以传递给的CreateService(),但无论是我发现它的声明中WINNT.H和我都知道这是否会工作。由于这个问题,应用程序的开发陷入困境。任何人都可以请帮忙。如何检索在Win 7系统的代理服务器设置为Windows服务用C

回答

1

我有类似的情况在当前用户的上下文中运行的程序。在全球范围内的地方 - -

首先定义以下变量:

HANDLE hUsrToken; 
HANDLE hDupToken; 
int sessionId; 

你需要获得当前用户的会话ID:

int getInteractiveSessinoId() 
{ 
    PWTS_SESSION_INFO pSessInfo; 
    ulong count;     // Number of current user sessions 
    int result = -1; 

    if (!WTSEnumerateSessions(WTS_CURRENT_SERVER, 0, 1, &pSessInfo, &count)) 
    { 
     printf("Getting session information failed with error %d\n", << GetLastError()); 
     WTSFreeMemory(pSessInfo); 
     return -2; 
    } 

    for (ulong loop = 0; loop < count; loop++) 
    { 
     if (pSessInfo[loop].State == WTSActive) 
     { 
      printf("Session %d is currently active\n", pSessInfo[loop].SessionId); 
      result = pSessInfo[loop].SessionId; 
      break; 
     } 
    } 

    WTSFreeMemory(pSessInfo); 
    return result; 
} 

接下来你需要冒充当前用户(我称之为“附加到会话”):

bool attachToSession(int sessionId) 
{ 
    // We need to duplicate the token of the session's user 
    if (!WTSQueryUserToken(sessionId, &hUsrToken)) 
    { 
     pritnf("Query the user token failed with error %d\n", GetLastError()); 
     return false; 
    } 

    if (!DuplicateTokenEx(hUsrToken, TOKEN_ALL_ACCESS, NULL, SecurityImpersonation, TokenImpersonation , &hDupToken)) 
    { 
     printf("Duplicating a token failed with error %d\n", GetLastError()); 
     return false; 
    } 

    if (!ImpersonateLoggedOnUser(hDupToken)) 
    { 
     printf("Impersonating the user failed with error %d\n", GetLastError(); 
     return false; 
    } 

    return true; 
} 

现在做任何你wa NT做想将当前用户的上下文中做,做的时候,从用户的上下文恢复(或“分离”):

bool detachFromSession() 
{ 
    if (!RevertToSelf()) 
    { 
     printf("Reverting the token failed with error %d\n", GetLastError()); 
     return false; 
    } 

    (void)CloseHandle(hDupToken); 
    (void)CloseHandle(hUsrToken); 

    return true; 
} 

我不知道这是否是令牌适用于好主意当前(服务)线程。我认为创建一个新线程是一个更好的主意,该线程可以执行用户上下文中想要执行的任何操作,并将模拟的标记应用于该线程。所以,你的代码的一部分可能是这样的:

HANDLE hUsrToken; 
HANDLE hDupToken; 
HANDLE hThread; 
int sessionId; 
DWORD threadId; 

DWORD WINAPI MyThreadFunction(LPVOID lpParam) 
{ 
    // WinHttpGetIEProxyConfigForCurrentUser(... 
} 

sessionId = getInterActiveSessionId(); 

if (attachToSession(int sessionId) == false) 
{ 
    // Error handling 
    return; 
} 

hThread = CreateThread(NULL,     // default security attributes 
         0,      // use default stack size      
         MyThreadFunction,  // thread function name 
         NULL,     // argument to thread function 
         CREATE_SUSPENDED,  // Delay execution 
         &threadId); 

if (SetThreadToken(hThread, hDupToken) == false) 
{ 
    // Error handling 
    return; 
} 

ResumeThread(hThread); 

我不能garantee,这将解决您的问题,但我希望它。祝你好运!

+0

会有什么服务时冒充API调用没有用户登录到系统,但该行为? – cbinder

+0

getInteractiveSessinoId()在上面的代码将与无效的id(返回-2),其要妥善处理返回。否则attachToSession()将失败WTSQueryUserToken()将返回错误,该错误在函数中处理。 总而言之一句话:这要确保你有一个交互式会话。 附加到会话0(服务正在运行)没有意义,因为您已经在该会话中运行。 –

相关问题