如何在C中为Windows服务在Win 7中检索系统代理设置

时间:2017-02-15 08:27:36

标签: c windows service proxy wininet

我正在编写一个将作为服务运行的应用程序,并将选择用于与外界通信的系统代理设置。我尝试了WinHttpGetIEProxyConfigForCurrentUser但它无法检索当前用户的代理设置,这很明显,因为服务是在本地系统的域下运行。为了实现这一点,我必须让用户登录我不希望应用程序用户执行的服务。我读到了可以传递给CreateService()的SERVICE_USER_OWN_PROCESS参数但是我没有在WinNT.h中找到它的声明,也不确定它是否可行。由于这个问题,应用程序的开发陷入困境。任何人都可以帮忙。

1 个答案:

答案 0 :(得分: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;
}

现在在当前用户的上下文中执行您想要做的任何事情,完成后,从用户的上下文中恢复(或“分离”):

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);

我不能保证这会解决你的问题,但我希望如此。祝你好运!