【问题标题】:WTSEnumerateProcesses with socket and data struct带有套接字和数据结构的 WTSEnumerateProcesses
【发布时间】:2020-05-06 23:04:01
【问题描述】:

我是 C++ Windows API 的新手,关于使用 WTSEnumerateProcesses() API 的问题很少。

我的目标:使用WTSEnumerateProcesses(),只获取进程列表,将其放入任何类型的“列表”或结构中,将widechar 转换为ANSI,然后使用Winsock 将其发送到套接字。

下面是我的代码:

温索克:

int connect(char buffer[])
{
    PCSTR ip = "localhost";
    WSADATA wsaData;
    SOCKET ConnectSocket = INVALID_SOCKET;
    struct addrinfo *result = NULL,
        *ptr = NULL,
        hints;
    const char *sendbuf =buffer;
    char recvbuf[DEFAULT_BUFLEN];
    int iResult;
    int recvbuflen = DEFAULT_BUFLEN;

    // Initialize Winsock
    iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (iResult != 0) {
        printf("WSAStartup failed with error: %d\n", iResult);
        return 1;
    }

    ZeroMemory(&hints, sizeof(hints));
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;

    // Resolve the server address and port
    iResult = getaddrinfo(ip, DEFAULT_PORT, &hints, &result);
    if (iResult != 0) {
        printf("getaddrinfo failed with error: %d\n", iResult);
        WSACleanup();
        return 1;
    }

    // Attempt to connect to an address until one succeeds
    for (ptr = result; ptr != NULL; ptr = ptr->ai_next) {
        // Create a SOCKET for connecting to server
        ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
        if (ConnectSocket == INVALID_SOCKET) {
            printf("socket failed with error: %ld\n", WSAGetLastError());
            WSACleanup();
            return 1;
        }

        // Connect to server.
        iResult = connect(ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
        if (iResult == SOCKET_ERROR) {
            closesocket(ConnectSocket);
            ConnectSocket = INVALID_SOCKET;
            continue;
        }
        break;
    }

    freeaddrinfo(result);

    if (ConnectSocket == INVALID_SOCKET) {
        printf("Unable to connect to server!\n");
        WSACleanup();
        return 1;
    }

    // Send an initial buffer
    iResult = send(ConnectSocket, sendbuf, (int)strlen(sendbuf), 0);
    if (iResult == SOCKET_ERROR) {
        printf("send failed with error: %d\n", WSAGetLastError());
        closesocket(ConnectSocket);
        WSACleanup();
        return 1;
    }

    printf("Bytes Sent: %ld\n", iResult);

    // shutdown the connection since no more data will be sent
    iResult = shutdown(ConnectSocket, SD_SEND);
    if (iResult == SOCKET_ERROR) {
        printf("shutdown failed with error: %d\n", WSAGetLastError());
        closesocket(ConnectSocket);
        WSACleanup();
        return 1;
    }

    // Receive until the peer closes the connection
    do {
        iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);
        if (iResult > 0)
            printf("Bytes received: %d\n", iResult);
        else if (iResult == 0)
            printf("Connection closed\n");
        else
            printf("recv failed with error: %d\n", WSAGetLastError());
    }
    while (iResult > 0);

    // cleanup
    closesocket(ConnectSocket);
    WSACleanup();

    return 0;
}

还有WTSEnumerateProcesses()

void GetProcesslist()
{
    vector<LPWSTR> v;         // no need to prepend std:: any more
    LPWSTR pProcessName;
    WTS_PROCESS_INFO* pWPIs = NULL;
    DWORD dwProcCount = 0;
    if (WTSEnumerateProcesses(WTS_CURRENT_SERVER_HANDLE, NULL, 1, &pWPIs, &dwProcCount))
    {
        //Go through all processes retrieved
        for (DWORD i = 0; i < dwProcCount; i++)
        {
            pProcessName = pWPIs[i].pProcessName;
            v[i] = pProcessName;
            //contains(pProcessName);
            // process file name only, no path!
            //data = pProcessName;
            std::wcout << pProcessName << endl;
            //pWPIs[i].ProcessId = process ID
            //pWPIs[i].SessionId = session ID, if you need to limit it to the logged in user processes
            //pWPIs[i].pUserSid = user SID that started the process
        }
    }

    //Free memory
    if (pWPIs)
    {
        WTSFreeMemory(pWPIs);
        pWPIs = NULL;
    }
}

您能否帮助我了解如何仅获取进程列表,将其推送到任何结构(如列表?)并通过 TCP 套接字正确发送,即等待获得 const char[] 而不是宽字符?

【问题讨论】:

标签: c++ windows sockets tcp


【解决方案1】:

您在GetProcesslist() 中没有正确使用std::vector。您正在尝试访问尚未为其分配任何内存的元素。更糟糕的是,您正在存储指向在 GetProcesslist() 退出之前释放的数据的指针,留下包含悬空指针的向量(如果您在 GetProcesslist() 之外访问该向量,您还没有这样做)。

试试这样的:

std::vector<std::wstring> GetProcesslist()
{
    std::vector<std::wstring> v;
    WTS_PROCESS_INFO* pWPIs = NULL;
    DWORD dwProcCount = 0;

    if (WTSEnumerateProcesses(WTS_CURRENT_SERVER_HANDLE, NULL, 1, &pWPIs, &dwProcCount))
    {
        //Go through all processes retrieved
        for (DWORD i = 0; i < dwProcCount; ++i)
        {
            LPWSTR pProcessName = pWPIs[i].pProcessName;
            v.push_back(pProcessName);
            // process file name only, no path!
            //data = pProcessName;
            std::wcout << pProcessName << endl;
            //pWPIs[i].ProcessId = process ID
            //pWPIs[i].SessionId = session ID, if you need to limit it to the logged in user processes
            //pWPIs[i].pUserSid = user SID that started the process
        }
        //Free memory
        WTSFreeMemory(pWPIs);
    }
    return v;
}

然后,我建议像这样通过套接字发送数据:

int connect(const char buffer[], size_t buffersize)
{
    PCSTR ip = "localhost";
    WSADATA wsaData;
    SOCKET ConnectSocket = INVALID_SOCKET;
    struct addrinfo *result = NULL,
        *ptr = NULL,
        hints;
    const char *sendbuf = buffer;
    char recvbuf[DEFAULT_BUFLEN];
    int iResult;

    // Initialize Winsock
    iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (iResult != 0) {
        printf("WSAStartup failed with error: %d\n", iResult);
        return 1;
    }

    ZeroMemory(&hints, sizeof(hints));
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;

    // Resolve the server address and port
    iResult = getaddrinfo(ip, DEFAULT_PORT, &hints, &result);
    if (iResult != 0) {
        printf("getaddrinfo failed with error: %d\n", iResult);
        WSACleanup();
        return 1;
    }

    // Attempt to connect to an address until one succeeds
    for (ptr = result; ptr != NULL; ptr = ptr->ai_next) {
        // Create a SOCKET for connecting to server
        ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
        if (ConnectSocket == INVALID_SOCKET) {
            printf("socket failed with error: %ld\n", WSAGetLastError());
            WSACleanup();
            return 1;
        }

        // Connect to server.
        iResult = connect(ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
        if (iResult == SOCKET_ERROR) {
            closesocket(ConnectSocket);
            ConnectSocket = INVALID_SOCKET;
            continue;
        }

        break;
    }

    freeaddrinfo(result);

    if (ConnectSocket == INVALID_SOCKET) {
        printf("Unable to connect to server!\n");
        WSACleanup();
        return 1;
    }

    // Send an initial buffer
    while (buffersize > 0) {
        iResult = send(ConnectSocket, sendbuf, (int)buffersize, 0);
        if (iResult == SOCKET_ERROR) {
            printf("send failed with error: %d\n", WSAGetLastError());
            closesocket(ConnectSocket);
            WSACleanup();
            return 1;
        }

        printf("Bytes Sent: %ld\n", iResult);

        sendbuf += iResult;
        buffersize -= iResult;
    }

    // shutdown the connection since no more data will be sent
    iResult = shutdown(ConnectSocket, SD_SEND);
    if (iResult == SOCKET_ERROR) {
        printf("shutdown failed with error: %d\n", WSAGetLastError());
        closesocket(ConnectSocket);
        WSACleanup();
        return 1;
    }

    // Receive until the peer closes the connection
    do {
        iResult = recv(ConnectSocket, recvbuf, sizeof(recvbuf), 0);
        if (iResult > 0)
            printf("Bytes received: %d\n", iResult);
        else if (iResult == 0)
            printf("Connection closed\n");
        else
            printf("recv failed with error: %d\n", WSAGetLastError());
    }
    while (iResult > 0);

    // cleanup
    closesocket(ConnectSocket);
    WSACleanup();

    return 0;
}
std::vector<std::wstring> procs = GetProcesslist();
std::vector<char> buffer;

size_t size = sizeof(uint32_t);
for(const std::wstring &name : procs) {
    size += (sizeof(uint32_t) + WideCharToMultiByte(CP_UTF8, 0, name.c_str(), name.size(), NULL, 0, NULL, NULL));
}

buffer.resize(size);
char *ptr = buffer.data();

*reinterpret_cast<uint32_t*>(ptr) = htonl(procs.size());
ptr += sizeof(uint32_t);
for(const std::wstring &name : procs) {
    int len = WideCharToMultiByte(CP_UTF8, 0, name.c_str(), name.size(), NULL, 0, NULL, NULL));
    *reinterpret_cast<uint32_t*>(ptr) = htonl(len);
    ptr += sizeof(uint32_t);
    if (len > 0) {
        ptr += WideCharToMultiByte(CP_UTF8, 0, name.c_str(), name.size(), ptr, len, NULL, NULL));
    }
}

connect(buffer.data(), buffer.size());

或者,如果您绝对不能更改 connect() 的签名并且必须将其传递给以 null 结尾的 C 字符串,那么试试这个:

int connect(const char buffer[])
{
    PCSTR ip = "localhost";
    WSADATA wsaData;
    SOCKET ConnectSocket = INVALID_SOCKET;
    struct addrinfo *result = NULL,
        *ptr = NULL,
        hints;
    const char *sendbuf = buffer;
    sendbuflen = strlen(buffer);
    char recvbuf[DEFAULT_BUFLEN];
    int iResult;

    // Initialize Winsock
    iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (iResult != 0) {
        printf("WSAStartup failed with error: %d\n", iResult);
        return 1;
    }

    ZeroMemory(&hints, sizeof(hints));
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;

    // Resolve the server address and port
    iResult = getaddrinfo(ip, DEFAULT_PORT, &hints, &result);
    if (iResult != 0) {
        printf("getaddrinfo failed with error: %d\n", iResult);
        WSACleanup();
        return 1;
    }

    // Attempt to connect to an address until one succeeds
    for (ptr = result; ptr != NULL; ptr = ptr->ai_next) {
        // Create a SOCKET for connecting to server
        ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
        if (ConnectSocket == INVALID_SOCKET) {
            printf("socket failed with error: %ld\n", WSAGetLastError());
            WSACleanup();
            return 1;
        }

        // Connect to server.
        iResult = connect(ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
        if (iResult == SOCKET_ERROR) {
            closesocket(ConnectSocket);
            ConnectSocket = INVALID_SOCKET;
            continue;
        }

        break;
    }

    freeaddrinfo(result);

    if (ConnectSocket == INVALID_SOCKET) {
        printf("Unable to connect to server!\n");
        WSACleanup();
        return 1;
    }

    // Send an initial buffer
    while (sendbuflen > 0) {
        iResult = send(ConnectSocket, sendbuf, sendbuflen, 0);
        if (iResult == SOCKET_ERROR) {
            printf("send failed with error: %d\n", WSAGetLastError());
            closesocket(ConnectSocket);
            WSACleanup();
            return 1;
        }

        printf("Bytes Sent: %ld\n", iResult);

        sendbuf += iResult;
        sendbuflen -= iResult;
    }

    // shutdown the connection since no more data will be sent
    iResult = shutdown(ConnectSocket, SD_SEND);
    if (iResult == SOCKET_ERROR) {
        printf("shutdown failed with error: %d\n", WSAGetLastError());
        closesocket(ConnectSocket);
        WSACleanup();
        return 1;
    }

    // Receive until the peer closes the connection
    do {
        iResult = recv(ConnectSocket, recvbuf, sizeof(recvbuf), 0);
        if (iResult > 0)
            printf("Bytes received: %d\n", iResult);
        else if (iResult == 0)
            printf("Connection closed\n");
        else
            printf("recv failed with error: %d\n", WSAGetLastError());
    }
    while (iResult > 0);

    // cleanup
    closesocket(ConnectSocket);
    WSACleanup();

    return 0;
}
std::vector<std::wstring> procs = GetProcesslist();
std::ostringstream oss;

oss << procs.size() << "\x1";
for(const std::wstring &name : procs) {
    int len = WideCharToMultiByte(CP_UTF8, 0, name.c_str(), name.size(), NULL, 0, NULL, NULL);
    if (len > 0) {
        std::string s;
        s.resize(len);
        WideCharToMultiByte(CP_UTF8, 0, name.c_str(), name.size(), &s[0], len, NULL, NULL);
        oss << s;
    }
    oss << "\x1";
}

connect(oss.str().c_str());

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-15
    • 1970-01-01
    • 2013-11-28
    • 1970-01-01
    • 2017-04-20
    • 1970-01-01
    相关资源
    最近更新 更多