Search code examples
c++comgdi+winsockistream

IStream COM read to buffer then send through winsock


I've created a server/client through winsock2. Where the client takes a bmp screenshot, compresses it into jpeg and sends it to the server. The problem I'm having is the server is having problems saving the file onto disk. Like the data isn't receiving right. I think it has to do in the way I'm sending or receiving the buffer.

EDIT: From Setting breakpoints during debug it seems as if all the data was received. istream->Write returns correct number of bytes in correlation with Size and istream->Seek returns S_OK and the CLSID COM object contains the same data that was sent. Also before I send the buffer I test it to see if it saves and it does. Therefore I'm assuming it has to be the way Buffer was sent or received.

EDIT: On both ends the buffer looks like This

Screen Shot plus send code.

    ScreenShot(Packet_Handler* _Handle)
{
IStream* istream;
    //char* Buff;
    HRESULT res = CreateStreamOnHGlobal(NULL, true, &istream);
    Gdiplus::GdiplusStartupInput gdiInput;
    ULONG_PTR gdiToken;
    Gdiplus::GdiplusStartup(&gdiToken, &gdiInput, NULL);
    {
        HDC scrdc, memdc;
        HBITMAP membit;
        scrdc = ::GetDC(0);
        int Height = GetSystemMetrics(SM_CYSCREEN);
        int Width = GetSystemMetrics(SM_CXSCREEN);
        memdc = CreateCompatibleDC(scrdc);
        membit = CreateCompatibleBitmap(scrdc, Width, Height);
        HBITMAP hOldBitmap = (HBITMAP)SelectObject(memdc, membit);
        BitBlt(memdc, 0, 0, Width, Height, scrdc, 0, 0, SRCCOPY);

        Gdiplus::Bitmap bitmap(membit, NULL);
        CLSID clsid;
        GetEncoderClsid(L"image/jpeg", &clsid);


        bitmap.Save(istream, &clsid, NULL);
        bitmap.Save(L"Test.jpeg", &clsid, NULL); //THIS WORKS
        STATSTG pstatstg = { 0 };
        istream->Stat(&pstatstg, 0);
        ULONG Bytes;
        char* isBuff = new char[pstatstg.cbSize.QuadPart];
        LARGE_INTEGER li;
        li.QuadPart = 0;
        istream->Seek(li, STREAM_SEEK_SET, NULL);
        if (istream->Read(isBuff, pstatstg.cbSize.QuadPart, &Bytes) == S_OK)
        {
            IStream* nistream = nullptr;
            ULONG nBytes;
            CreateStreamOnHGlobal(NULL, true, &nistream);
            if (nistream->Write(isBuff, pstatstg.cbSize.QuadPart, &Bytes) == S_OK)
            {

                if (nistream->Seek(li, STREAM_SEEK_SET, NULL) == S_OK)

                {
                    Gdiplus::Bitmap bitmap2(nistream, NULL);
                    bitmap2.Save(L"Testing.jpeg", &clsid, NULL); //THIS WORKS
                }
            }
        }

        int Size = pstatstg.cbSize.QuadPart;
        int SOLI = sizeof(ULARGE_INTEGER);
        int SOCID = sizeof(CLSID);
        int SOIS = sizeof(IStream);

        Send_Full_Packet(_Handle, &Size, isBuff, TRUE);
        Send_Full_Packet(_Handle, &SOCID, &clsid, FALSE);



        printf("saving Screenshot");


        DeleteObject(memdc);
        DeleteObject(membit);
        ::ReleaseDC(0, scrdc);

    }
    Gdiplus::GdiplusShutdown(gdiToken);
    _getch();
    return 0;
}
    void Send_Full_Packet(Packet_Handler* _Handle, int* pSize, void * Buff, bool ispchar)
    {
        int SentPackets = 0;
        int sCheck = 0;
        int rCheck = 0;
        int Size = *pSize;
        char* isBuff;// = new char[Size];

            sCheck = send(_Handle->ConnectSocket, (char*)&Size, sizeof(int), NULL);

        int PacketsSent = 0;
        sCheck = 0;
        int PacketsLeft = Size;
        while (PacketsSent < Size)
        {
            if (ispchar == FALSE)
            {
                SentPackets = send(_Handle->ConnectSocket, (char*)Buff + PacketsSent, PacketsLeft, NULL);
            }
            else {
                isBuff = (char*)Buff;
                SentPackets = send(_Handle->ConnectSocket, isBuff + PacketsSent, PacketsLeft, NULL);
            }
            if (SentPackets == SOCKET_ERROR)
            {
                if (WSAGetLastError() != 10054)
                {
                    if (WSAGetLastError() == 10035)
                    {
                        SentPackets == 0;

                    }
                    else
                    {
                        printf("Sending Socket error: %d\n", WSAGetLastError());
                        break;
                    }

                }
            }
            PacketsSent += SentPackets;
            PacketsLeft -= SentPackets;
        }


    }

Receive code

    ScreenShot_Receive_Thread(Packet_Handler* _Handle)
{

    Packet_Handler::_Packet_Type Packet = Packet_Handler::_Packet_Type::Remote;
    while (true)
    {
        if (send(_Handle->si.Connections[_Handle->si.ConnectionCounter - 1], (char*)&Packet, sizeof(Packet_Handler::_Packet_Type), 0) != INVALID_SOCKET)
        {
            while (true)
            {
                int Size = 0;
                char* Buff = NULL;
                Buff = _Handle->Receive_Full_Packet(_Handle, &Size, Buff, TRUE);
                CLSID clsid;
                int SOCID = sizeof(CLSID);
                _Handle->Receive_Full_Packet(_Handle, &SOCID, &clsid, FALSE);
                IStream* istream = nullptr;
                ULONG Bytes;
                CreateStreamOnHGlobal(NULL, true, &istream);
                if (istream->Write(Buff, Size, &Bytes) == S_OK)
                {
                    LARGE_INTEGER li;
                    li.QuadPart = 0;
                    if (istream->Seek(li, STREAM_SEEK_SET, NULL) == S_OK)
                    {
                        Gdiplus::Bitmap bitmap(istream, NULL);
                        bitmap.Save(L"Testing.jpeg", &clsid, NULL);//DOESNT WORK
                    }
                }

            }
        }
    }
    MessageBox(NULL, L"CLient COnnection Error!", NULL, NULL);
    return 0;
}


  char* Packet_Handler::Receive_Full_Packet(Packet_Handler * _Handle, int* pSize, void * Buff, bool ispchar)
{
    int rCheck = 0;
    int sCheck = 0;
    int Size = *pSize;
    rCheck = recv(_Handle->si.Connections[_Handle->si.ConnectionCounter - 1], (char*)&Size, sizeof(int), 0);
    if (rCheck == -1)
    {
        int Error = WSAGetLastError();
        AllocConsole();
        freopen("CONOUT$", "w", stdout);
        std::cout << "The Error is: " << Error << std::endl;
    }
    *pSize = Size;
    char* isBuff;// = NULL;
    int PacketsReceived = 0;
    int PacketsLeft = Size;
    int ReceivedPackets = 0;
    while (PacketsReceived < Size)
    {
        if (ispchar == FALSE)
        {
            ReceivedPackets = recv(_Handle->si.Connections[_Handle->si.ConnectionCounter - 1], (char*)Buff + PacketsReceived, PacketsLeft, 0);

        }
        else
        {
            isBuff = new char[Size]; //I Think my problem is here// 

            ReceivedPackets = recv(_Handle->si.Connections[_Handle->si.ConnectionCounter - 1], isBuff + PacketsReceived, PacketsLeft, 0);

        }
        if (ReceivedPackets == SOCKET_ERROR)
        {
            int Error = WSAGetLastError();
            if (Error != 10054)
            {
                if (Error == 10035  || Error == 6)
                {
                    ReceivedPackets == 0;
                }
                else
                {
                    AllocConsole();
                    freopen("CONOUT$", "w", stdout);
                    std::cout << "The Error is: " << Error << std::endl;
                    //MessageBox(NULL, (WCHAR*)WSAGetLastError(), NULL, NULL);
                    _getch();
                    //return NULL;
                    break;
                }
            }
        }

        PacketsReceived += ReceivedPackets;
        PacketsLeft -= ReceivedPackets;
    }
    return isBuff;
}

Solution

  • Finally Figured it out. Turns out there was absolutely nothing wrong with the way i was sending the buffer. It was actually the CLSID. I ended up putting the GetEncoderClsid function in the receiving end. Works like butter.