I've got a complete Winsock client and server below. I'm not able to get the whole file though.
The client is not filling up its buffer with the data.
Stepping through debug it looks like the server process is sending back, but I only get three loops and the recv()
is done.
I assume I'm missing something apparent, but not being fluent in Winsock or memcpy
, can someone help me?
Single winsockserver.cpp code:
#include <winsock2.h>
#include <windows.h>
#include <ws2tcpip.h>
#include <strsafe.h>
#include <process.h>
#include <mswsock.h>
#pragma comment(lib, "Ws2_32.lib")
#pragma comment(lib, "Mswsock.lib")
WCHAR REGPATH[260];
BOOL SetPrivilege()
{
HANDLE hToken;
if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken) != 0)
{
LUID luid;
BOOL bLookupPrivilegeValue = LookupPrivilegeValueW(NULL, L"SeBackupPrivilege", &luid);
if (bLookupPrivilegeValue == TRUE)
{
TOKEN_PRIVILEGES tp;
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
BOOL bAdjustTokenPrivileges = AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES) NULL, (PDWORD)NULL);
return ((bAdjustTokenPrivileges == TRUE) && (GetLastError() == ERROR_SUCCESS));
}
}
return TRUE;
}
SOCKET SetUpListener(CONST CHAR *pcAddress, INT nPort)
{
DWORD dwWSA = 0;
INT iBind = 0;
ULONG nInterfaceAddr = 0;
inet_pton(AF_INET, pcAddress, &nInterfaceAddr);
if (nInterfaceAddr != INADDR_NONE)
{
SOCKET sd = socket(AF_INET, SOCK_STREAM, 0);
if (sd != INVALID_SOCKET)
{
sockaddr_in sinInterface;
sinInterface.sin_family = AF_INET;
sinInterface.sin_addr.s_addr = nInterfaceAddr;
sinInterface.sin_port = nPort;
iBind = bind(sd, (sockaddr*) &sinInterface, sizeof(sockaddr_in));
if (iBind != SOCKET_ERROR)
{
listen(sd, SOMAXCONN);
return sd;
}
dwWSA = WSAGetLastError();
}
}
return INVALID_SOCKET;
}
BOOL ReceiveDoWorkThenReturnDataToClient(SOCKET sd)
{
CHAR acReadBuffer[1024];
INT nReadBytes;
do
{
nReadBytes = recv(sd, acReadBuffer, 1024, 0);
if (nReadBytes > 0)
{
//INT nSentBytes = 0;
//while (nSentBytes < nReadBytes)
{
WCHAR* sTempFileOut = new WCHAR[MAX_PATH]();
StringCchCopyW(sTempFileOut, MAX_PATH, L"c:\\temp\\~test.txt");
HKEY key;
LRESULT dresult = RegOpenKeyExW(HKEY_LOCAL_MACHINE, REGPATH, 0, KEY_QUERY_VALUE | KEY_WOW64_32KEY, &key); // If the function succeeds, the return value is ERROR_SUCCESS.
if (dresult == ERROR_SUCCESS)
{
DWORD dwErrorBackupPriv = 0;
if (SetPrivilege() == TRUE)
{
LSTATUS dStatus = RegSaveKeyW(key, sTempFileOut, NULL); // If the function succeeds, the return value is ERROR_SUCCESS.
if ((dStatus == ERROR_SUCCESS) || (dStatus == ERROR_ALREADY_EXISTS))
{
HANDLE hFile = CreateFileW(sTempFileOut, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile != INVALID_HANDLE_VALUE)
{
ULARGE_INTEGER ul;
ul.LowPart = GetFileSize(hFile, &ul.HighPart);
if ((ul.LowPart == INVALID_FILE_SIZE) && (GetLastError() != 0)) return 7;
OVERLAPPED ov = {};
ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (!ov.hEvent) return 8;
unsigned __int64 uiPos = 0;
unsigned __int64 uiRemaining = ul.QuadPart;
while (uiRemaining > 0)
{
ul.QuadPart = uiPos;
ov.Offset = ul.LowPart;
ov.OffsetHigh = ul.HighPart;
DWORD dwNumToSend = (uiRemaining >= 3) ? 3 : (DWORD)uiRemaining;
if (!TransmitFile(sd, hFile, dwNumToSend, 0, &ov, NULL, 0))
{
if ((GetLastError() != ERROR_IO_PENDING) && (WSAGetLastError() != WSA_IO_PENDING))
break;
WaitForSingleObject(ov.hEvent, INFINITE);
}
uiPos += dwNumToSend;
uiRemaining -= dwNumToSend;
Sleep(100);
}
CloseHandle(ov.hEvent);
CloseHandle(hFile);
}
}
}
}
delete[] sTempFileOut;
}
}
else if (nReadBytes == SOCKET_ERROR)
return FALSE;
}
while (nReadBytes != 0);
return TRUE;
}
BOOL ShutdownConnection(SOCKET sd)
{
if (shutdown(sd, SD_SEND) == SOCKET_ERROR) return FALSE;
CHAR acReadBuffer[1024];
while (1)
{
INT nNewBytes = recv(sd, acReadBuffer, 1024, 0);
if (nNewBytes == SOCKET_ERROR) return FALSE;
else if (nNewBytes == 0) break;
}
return (closesocket(sd) != SOCKET_ERROR);
}
DWORD WINAPI ThreadHandler(void* sd_)
{
INT nRetval = 0;
SOCKET sd = (SOCKET) sd_;
if (!ReceiveDoWorkThenReturnDataToClient(sd)) nRetval = 3;
if (!ShutdownConnection(sd)) nRetval = 4;
return nRetval;
}
unsigned WINAPI ListenAndAccept(void *)
{
WSAData wsaData;
INT nCode;
sockaddr_in sinRemote;
INT nAddrSize = sizeof(sinRemote);
DWORD nThreadID;
if ((nCode = WSAStartup(MAKEWORD(1, 1), &wsaData)) != ERROR_SUCCESS) return nCode;
SOCKET ListeningSocket = SetUpListener("localhost", htons(43210));
if (ListeningSocket == INVALID_SOCKET)
return 3;
while (1)
{
SOCKET sd = accept(ListeningSocket, (sockaddr*)&sinRemote, &nAddrSize);
if (sd != INVALID_SOCKET)
CreateThread(0, 0, &ThreadHandler, (void*)sd, 0, &nThreadID);
else
break;
}
WSACleanup();
return 0;
}
int main()
{
UINT threadID = 0;
StringCchCopy(REGPATH, 260, L"Software\\Microsoft\\Direct3D");
HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, &ListenAndAccept, NULL, 0, &threadID);
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
while (1)
;
}
Single Winsockclient.cpp file:
#include <winsock2.h>
#include <windows.h>
#include <mswsock.h>
#include <ws2tcpip.h>
#include <strsafe.h>
#include <windns.h>
#include <process.h>
#include <windns.h>
#pragma comment(lib, "Ws2_32.lib")
#pragma comment(lib, "dnsapi.lib")
DWORD SendWinsockCommandToRemoteServer(CONST DWORD dwCharsAllocatedReturnString, WCHAR **sStringReturned)
{
SOCKET ConnectSocket = INVALID_SOCKET;
INT recvbuflen = 65536;
DWORD dwIPv4 = 0;
DWORD dwErr = 0;
SecureZeroMemory(*sStringReturned, dwCharsAllocatedReturnString * sizeof(CHAR));
ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (ConnectSocket == INVALID_SOCKET)
return WSAGetLastError();
sockaddr_in clientService{};
clientService.sin_family = AF_INET;
clientService.sin_addr.s_addr = dwIPv4;
clientService.sin_port = htons(43210);
INT iResult = connect(ConnectSocket, (SOCKADDR*)&clientService, sizeof(clientService));
if ((iResult != 0) || (iResult == SOCKET_ERROR))
{
closesocket(ConnectSocket);
return WSAGetLastError();
}
iResult = send(ConnectSocket, "test", 5, 0);
if ((iResult == INVALID_SOCKET) || (iResult == SOCKET_ERROR))
{
closesocket(ConnectSocket);
return 5;
}
iResult = shutdown(ConnectSocket, SD_SEND);
if (iResult == SOCKET_ERROR)
{
closesocket(ConnectSocket);
return 6;
}
DWORD dwLen = 0;
BYTE * cRecvbuf = (BYTE*) calloc(65536, sizeof(BYTE));
BYTE * cRecvbuf2 = (BYTE*) calloc(65536, sizeof(BYTE));
do
{
iResult = recv(ConnectSocket, (CHAR *) cRecvbuf, recvbuflen, MSG_WAITALL);
memcpy(cRecvbuf2, cRecvbuf, sizeof(cRecvbuf)*2);
}
while (iResult > 0);
DWORD dwLenOfRecvbuf = strlen((CHAR *) cRecvbuf);
if (dwLenOfRecvbuf > 0)
dwLen = dwLenOfRecvbuf + 1;
if (dwLen > 0)
{
WCHAR *sRecvbuf = new WCHAR[dwLen]();
DWORD dwCharWrittenToBuffer = MultiByteToWideChar(CP_UTF8, 0, (CHAR*)cRecvbuf, (INT)dwLen, sRecvbuf, dwLen);
if (dwCharWrittenToBuffer != 0)
StringCchCopyW(*sStringReturned, dwLen, sRecvbuf);
delete[] sRecvbuf;
free(cRecvbuf);
if (dwCharWrittenToBuffer == 0)
return 7;
}
else
{
free(cRecvbuf);
return 8;
}
closesocket(ConnectSocket);
return 0;
}
void QueryWinsockServer(CONST DWORD dwDataAllocatedSize, WCHAR** sDataBack, DWORD* dwErrorFromSendWinsockCommandToRemoteServer)
{
SecureZeroMemory(*sDataBack, dwDataAllocatedSize * sizeof (WCHAR));
WCHAR *sRV = new WCHAR[dwDataAllocatedSize]();
*dwErrorFromSendWinsockCommandToRemoteServer = SendWinsockCommandToRemoteServer(dwDataAllocatedSize, &sRV);
if (*dwErrorFromSendWinsockCommandToRemoteServer == ERROR_SUCCESS)
{
DWORD dwLenToCopy = wcslen(sRV) + 1;
StringCchCopyW(*sDataBack, dwLenToCopy, sRV);
}
delete[] sRV;
}
int main(int argc, char **argv)
{
DWORD dwDataAllocatedSize = 1024;
DWORD dwErr = 0;
WCHAR* sData = new WCHAR[dwDataAllocatedSize]();
WSADATA wsaData{};
INT iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
QueryWinsockServer(dwDataAllocatedSize, &sData, &dwErr);
wprintf(L"Press any key to end.");
getchar();
return 0;
}