I have the following code that creates a file using CreateFile with the FILE_FLAG_OVERLAPPED flag, and then calls WriteFile 100 times in a loop, passing in an OVERLAPPED structure
uint64_t GetPreciseTickCount()
{
FILETIME fileTime;
GetSystemTimePreciseAsFileTime(&fileTime);
ULARGE_INTEGER large;
large.LowPart = fileTime.dwLowDateTime;
large.HighPart = fileTime.dwHighDateTime;
return large.QuadPart;
}
uint64_t g_blockedTime = 0, g_waitTime = 0;
int main()
{
auto hFile = CreateFile(
L"test.dat",
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH,
NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
std::cout << "CreateFile failed with err " << GetLastError() << std::endl;
return 1;
}
uint32_t bufferSize = 4*1024*1024;
char* buffer = (char*)_aligned_malloc(bufferSize, 4096);
const int loop = 100;
LARGE_INTEGER endPosition;
endPosition.QuadPart = bufferSize * loop;
auto sfpRet = SetFilePointerEx(hFile, endPosition, nullptr, FILE_BEGIN);
if (sfpRet == INVALID_SET_FILE_POINTER)
{
std::cout << "SetFilePointer failed with err " << GetLastError() << std::endl;
return 1;
}
if (0 == SetEndOfFile(hFile))
{
std::cout << "SetEndOfFile failed with err " << GetLastError() << std::endl;
return 1;
}
auto start = GetPreciseTickCount();
OVERLAPPED overlapped;
auto completionEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr);
for (int i = 0; i < loop; ++i)
{
overlapped.hEvent = completionEvent;
overlapped.Offset = i * bufferSize;
overlapped.OffsetHigh = 0;
overlapped.Internal = 0;
overlapped.InternalHigh = 0;
auto writeFileStart = GetPreciseTickCount();
auto err = WriteFile(
hFile,
buffer,
bufferSize,
nullptr,
&overlapped);
auto writeFileEnd = GetPreciseTickCount();
g_blockedTime += (writeFileEnd - writeFileStart) / 10;
if (err == FALSE)
{
auto lastErr = GetLastError();
if (lastErr != ERROR_IO_PENDING)
{
std::cout << "WriteFile failed with err " << lastErr << std::endl;
return 1;
}
auto waitErr = WaitForSingleObject(overlapped.hEvent, INFINITE);
g_waitTime += (GetPreciseTickCount() - writeFileEnd) / 10;
if (waitErr != 0)
{
std::cout << "WaitForSingleObject failed with err " << waitErr << std::endl;
return 1;
}
}
}
auto end = GetPreciseTickCount();
CloseHandle(hFile);
std::cout << "Took " << (end - start) / 10 << " micros" << std::endl;
std::cout << "Blocked time " << g_blockedTime << " micros" << std::endl;
std::cout << "Wait time " << g_waitTime << " micros" << std::endl;
}
The prints the following output
Took 1749086 micros
Blocked time 1700085 micros
Wait time 48896 micros
Why does WriteFile block? (as is evidenced by g_blockedTime being significantly higher than g_waitTime). Is there any way I can force it to be non-blocking?
Update: I updated the code to use SetFilePointerEx and SetEndOfFile before the loop. Still seeing the same blocking problem.
The solution is to call SetFilePointerEx, SetEndOfFile, and SetFileValidData before the loop. Then subsequent calls to WriteFile within the loop become non-blocking.
uint64_t GetPreciseTickCount()
{
FILETIME fileTime;
GetSystemTimePreciseAsFileTime(&fileTime);
ULARGE_INTEGER large;
large.LowPart = fileTime.dwLowDateTime;
large.HighPart = fileTime.dwHighDateTime;
return large.QuadPart;
}
uint64_t g_blockedTime = 0, g_waitTime = 0;
int main()
{
HANDLE hToken;
auto openResult = OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);
if (!openResult)
{
std::cout << "OpenProcessToken failed with err " << GetLastError() << std::endl;
return 1;
}
TOKEN_PRIVILEGES tp;
tp.PrivilegeCount = 1;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
auto lookupResult = LookupPrivilegeValue(NULL, SE_MANAGE_VOLUME_NAME, &tp.Privileges[0].Luid);
if (!lookupResult)
{
std::cout << "LookupPrivilegeValue failed with err " << GetLastError() << std::endl;
return 1;
}
auto adjustResult = AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL);
if (!adjustResult || GetLastError() != ERROR_SUCCESS)
{
std::cout << "AdjustTokenPrivileges failed with err " << GetLastError() << std::endl;
return 1;
}
auto hFile = CreateFile(
L"test.dat",
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH,
NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
std::cout << "CreateFile failed with err " << GetLastError() << std::endl;
return 1;
}
uint32_t bufferSize = 4*1024*1024;
char* buffer = (char*)_aligned_malloc(bufferSize, 4096);
const int loop = 100;
auto start = GetPreciseTickCount();
LARGE_INTEGER endPosition;
endPosition.QuadPart = bufferSize * loop;
auto setFileErr = SetFilePointerEx(hFile, endPosition, nullptr, FILE_BEGIN);
if (setFileErr == INVALID_SET_FILE_POINTER)
{
std::cout << "SetFilePointer failed with err " << GetLastError() << std::endl;
return 1;
}
if (!SetEndOfFile(hFile))
{
std::cout << "SetEndOfFile failed with err " << GetLastError() << std::endl;
return 1;
}
if (!SetFileValidData(hFile, bufferSize * loop))
{
std::cout << "SetFileValidData failed with err " << GetLastError() << std::endl;
return 1;
}
OVERLAPPED overlapped;
auto completionEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr);
for (int i = 0; i < loop; ++i)
{
overlapped.hEvent = completionEvent;
overlapped.Offset = i * bufferSize;
overlapped.OffsetHigh = 0;
overlapped.Internal = 0;
overlapped.InternalHigh = 0;
auto writeFileStart = GetPreciseTickCount();
auto err = WriteFile(
hFile,
buffer,
bufferSize,
nullptr,
&overlapped);
auto writeFileEnd = GetPreciseTickCount();
g_blockedTime += (writeFileEnd - writeFileStart) / 10;
if (err == FALSE)
{
auto lastErr = GetLastError();
if (lastErr != ERROR_IO_PENDING)
{
std::cout << "WriteFile failed with err " << lastErr << std::endl;
return 1;
}
auto waitErr = WaitForSingleObject(overlapped.hEvent, INFINITE);
g_waitTime += (GetPreciseTickCount() - writeFileEnd) / 10;
if (waitErr != 0)
{
std::cout << "WaitForSingleObject failed with err " << waitErr << std::endl;
return 1;
}
}
}
auto end = GetPreciseTickCount();
CloseHandle(hFile);
std::cout << "Took " << (end - start) / 10 << " micros" << std::endl;
std::cout << "Blocked time " << g_blockedTime << " micros" << std::endl;
std::cout << "Wait time " << g_waitTime << " micros" << std::endl;
}
This produces the following output
Took 1508131 micros
Blocked time 19719 micros
Wait time 1481362 micros
Also, check out this article.
Related
I'm trying to write to a com port that my Arduino micro is plugged into. All its doing is trying to send an int at a time. I have the serial monitor open in Arduino bound to that port and I'm able to send bytes to it (I have a print line to show its receiving bytes) but when I use the CPP impl - I get nothing. I'm new to this so may have missed something out but I dont even get any errors.
Any help?
`
Arduino::~Arduino()
{
CloseHandle(hSerial);
}
void Arduino::send(int x, int y, int a)
{
std::cout << "Sending these values = " << x << y << a << std::endl;
if (!WriteFile(hSerial, &x, 1, NULL, NULL)) {
DWORD lastError = GetLastError();
std::cout << "ERROR HERE SENDING X! = " << lastError << std::endl;
}
else {
std::cout << "Sent X" << std::endl;
}
if (!WriteFile(hSerial, &y, 1, NULL, NULL)) {
DWORD lastError = GetLastError();
std::cout << "ERROR HERE SENDING Y! = " << lastError << std::endl;
}
else {
std::cout << "Sent Y" << std::endl;
}
if (!WriteFile(hSerial, &a, 1, NULL, NULL)) {
DWORD lastError = GetLastError();
std::cout << "ERROR HERE SENDING A! = " << lastError << std::endl;
}
else {
std::cout << "Sent A" << std::endl;
}
}
void Arduino::mouseEvent(int x, int y, int click)
{
send(x, y, click);
}
void Arduino::Init(std::wstring comport)
{
hSerial = CreateFile(comport.c_str(), GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hSerial == INVALID_HANDLE_VALUE)
{
DWORD lastError = GetLastError();
std::cout << "ERROR HERE! = " << lastError << std::endl;
}
DCB dcbSerialParams = { 0 };
dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
GetCommState(hSerial, &dcbSerialParams);
dcbSerialParams.BaudRate = CBR_115200;
dcbSerialParams.ByteSize = 8;
dcbSerialParams.StopBits = ONESTOPBIT;
dcbSerialParams.Parity = NOPARITY;
SetCommState(hSerial, &dcbSerialParams);
}
`
I'm expecting, at the very least, to get a println in my Arduino IDE to say that the board has received bytes when I hit the .Send() but I get nothing. I know the Arduino code works fine as I'm able to use the IDE to send bytes to decode then perform operations on.
I wrote a simple inter-process communication with a memory-mapped file. The code works relatively well, but I have a problem with the buffer that I'll explain shortly. Here is the code (C++, Windows):
#define UNICODE
#define _UNICODE
#include <iostream>
#include <tchar.h>
#include <Windows.h>
int wmain(int argc, wchar_t** argv)
{
if (argc != 2)
{
std::cout << "Usage: `win32mmap w` for writing, or `win32mmap r` for reading.\n";
return -1;
}
HANDLE hMapFile;
HANDLE hEvent;
HANDLE isOpened = CreateEvent(NULL, true, false, L"IsOpened"); // To check if a `win32mmap w` runs
if (wcscmp(argv[1], L"w") == 0)
{
SetEvent(isOpened);
hMapFile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 1024, L"mmapFile");
if (hMapFile == NULL)
{
std::cout << "CreateFileMapping() Error: " << GetLastError() << "\n";
return GetLastError();
}
hEvent = CreateEvent(NULL, true, false, L"mmapEvent");
if (hEvent == INVALID_HANDLE_VALUE || hEvent == NULL)
{
std::cout << "CreateEvent() Error: " << GetLastError() << "\n";
return GetLastError();
}
char* buff = (char*)MapViewOfFile(hMapFile, FILE_MAP_WRITE, 0, 0, 0);
if (!buff)
{
std::cout << "MapViewOfFile() Error: " << GetLastError() << "\n";
return GetLastError();
}
while (buff[0] != L'.')
{
std::cin >> buff;
SetEvent(hEvent);
}
UnmapViewOfFile(buff);
}
else if (wcscmp(argv[1], L"r") == 0)
{
if (WaitForSingleObject(isOpened, 0) == WAIT_TIMEOUT)
{
std::cout << "Waiting for `win32mmap w`...";
WaitForSingleObject(isOpened, INFINITE);
std::cout << "\n";
}
hMapFile = OpenFileMapping(FILE_MAP_ALL_ACCESS, false, L"mmapFile");
if (hMapFile == NULL)
{
std::cout << "CreateFileMapping() Error: " << GetLastError() << "\n";
return GetLastError();
}
hEvent = OpenEvent(EVENT_ALL_ACCESS, false, L"mmapEvent");
if (hEvent == INVALID_HANDLE_VALUE || hEvent == NULL)
{
std::cout << "CreateFile() Error: " << GetLastError() << "\n";
return GetLastError();
}
char* buff = (char*)MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 0);
if (!buff)
{
std::cout << "MapViewOfFile() Error: " << GetLastError() << "\n";
return GetLastError();
}
if (!buff)
{
std::cout << "MapViewOfFile() Error: " << GetLastError() << "\n";
return GetLastError();
}
while (true)
{
WaitForSingleObject(hEvent, INFINITE);
ResetEvent(hEvent);
if (buff[0] == '.')
{
break;
}
std::cout << buff << "\n";
}
UnmapViewOfFile(buff);
}
else
{
std::cout << "Usage: `win32mmap w` for writing, or `win32mmap r` for reading.\n";
return -1;
}
CloseHandle(hMapFile);
return 0;
}
The program is a simple inter-process communication "chat" that relies on memory-mapped files. To use the program, you need to make two executable instance of the program: win32mmap w and win32mmap r. The first instance is used to type text that is displayed in the second instance. When you type . in the first instance, both of them are terminated.
My problem is when I run the 2 instances of the program, and I type the world Hello in the first instance (win32mmap w), the second instance shows Hello as expected. But when I type Hello World in the first instance, the second instance shows only the word World instead of Hello World. How can I fix the code that the buffer will get the whole text?
Your writer is not waiting for the reader to consume the data before overwriting it with new data.
You need 2 events - one for the reader to wait on signaling when the buffer has data to read, and one for the writer to wait on signaling when the buffer needs data.
Try this instead:
#define UNICODE
#define _UNICODE
#include <iostream>
#include <tchar.h>
#include <Windows.h>
const DWORD BufSize = 1024;
int wmain(int argc, wchar_t** argv)
{
if (argc != 2)
{
std::cout << "Usage: `win32mmap w` for writing, or `win32mmap r` for reading.\n";
return -1;
}
HANDLE hMapFile;
char* buff;
HANDLE hNeedDataEvent;
HANDLE hHasDataEvent;
DWORD dwError;
HANDLE isOpened = CreateEvent(NULL, TRUE, FALSE, L"IsOpened"); // To check if a `win32mmap w` runs
if (isOpened == NULL)
{
dwError = GetLastError();
std::cout << "CreateEvent() Error: " << dwError << "\n";
return dwError;
}
if (wcscmp(argv[1], L"w") == 0)
{
hMapFile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, BufSize, L"mmapFile");
if (hMapFile == NULL)
{
dwError = GetLastError();
std::cout << "CreateFileMapping() Error: " << dwError << "\n";
SetEvent(isOpened);
return dwError;
}
buff = (char*) MapViewOfFile(hMapFile, FILE_MAP_WRITE, 0, 0, BufSize);
if (!buff)
{
dwError = GetLastError();
std::cout << "MapViewOfFile() Error: " << dwError << "\n";
SetEvent(isOpened);
return dwError;
}
hNeedDataEvent = CreateEvent(NULL, TRUE, TRUE, L"mmapNeedDataEvent");
if (hNeedDataEvent == NULL)
{
dwError = GetLastError();
std::cout << "CreateEvent() Error: " << dwError << "\n";
SetEvent(isOpened);
return dwError;
}
hHasDataEvent = CreateEvent(NULL, TRUE, FALSE, L"mmapHasDataEvent");
if (hHasDataEvent == NULL)
{
dwError = GetLastError();
std::cout << "CreateEvent() Error: " << dwError << "\n";
SetEvent(isOpened);
return dwError;
}
SetEvent(isOpened);
while (WaitForSingleObject(hNeedDataEvent, INFINITE) == WAIT_OBJECT_0)
{
std::cin.get(buff, BufSize);
ResetEvent(hNeedDataEvent);
SetEvent(hHasDataEvent);
if (buff[0] == L'.') break;
}
}
else if (wcscmp(argv[1], L"r") == 0)
{
if (WaitForSingleObject(isOpened, 0) == WAIT_TIMEOUT)
{
std::cout << "Waiting for `win32mmap w`...";
WaitForSingleObject(isOpened, INFINITE);
std::cout << "\n";
}
hMapFile = OpenFileMapping(FILE_MAP_READ, FALSE, L"mmapFile");
if (hMapFile == NULL)
{
dwError = GetLastError();
std::cout << "CreateFileMapping() Error: " << dwError << "\n";
return dwError;
}
char* buff = (char*) MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, BufSize);
if (!buff)
{
dwError = GetLastError();
std::cout << "MapViewOfFile() Error: " << dwError << "\n";
return dwError;
}
hNeedDataEvent = OpenEvent(SYNCHRONIZE, FALSE, L"mmapNeedDataEvent");
if (hNeedDataEvent == NULL)
{
dwError = GetLastError();
std::cout << "OpenEvent() Error: " << dwError << "\n";
return dwError;
}
hHasDataEvent = OpenEvent(SYNCHRONIZE, FALSE, L"mmapHasDataEvent");
if (hHasDataEvent == NULL)
{
dwError = GetLastError();
std::cout << "OpenEvent() Error: " << dwError << "\n";
return dwError;
}
do
{
SetEvent(hNeedDataEvent);
if (WaitForSingleObject(hHasDataEvent, INFINITE) != WAIT_OBJECT_0)
break;
std::cout << buff << "\n";
ResetEvent(hHasDataEvent);
}
while (buff[0] != '.');
}
else
{
std::cout << "Usage: `win32mmap w` for writing, or `win32mmap r` for reading.\n";
return -1;
}
UnmapViewOfFile(buff);
CloseHandle(hMapFile);
CloseHandle(hNeedDataEvent);
CloseHandle(hHasDataEvent);
CloseHandle(isOpened);
return 0;
}
I'm writing a server on Windows in C++ and I'm facing a strange behavior using recv().
I wrote this function:
bool readN(SOCKET s, int size, char* buffer){
fd_set readset;
struct timeval tv;
int left, res;
FD_ZERO(&readset);
FD_SET(s, &readset);
left = size;
std::cout << "-----called readN to read " << size << " byte" << std::endl;
while (left > 0) {
tv.tv_sec = MAXWAIT;
tv.tv_usec = 0;
res = select(0, &readset, NULL, NULL, &tv);
if (res > 0) {
res = recv(s, buffer, left, 0);
if (res == 0) {//connection closed by client
return false;
}
left -= res;
std::cout << "\treceived " << res << " left " << left << std::endl;
if (left != 0) {
buffer += res;
}
}
else if (res == 0) { //timer expired
return false;
}
else { //socket error
return false;
}
}
std::cout << "\t" << buffer << std::endl;
return true;
}
And I call it like this:
std::unique_ptr<char[]> buffer = std::make_unique<char[]>(size_);
if (readN(sck, size_, buffer.get())) {
std::cout << "----read message----" << std::endl;
std::cout <<"\t"<< buffer.get()<< std::endl;
}
The problem is that even if recv() returns a positive number, the buffer is still empty. What am I missing?
I see a few problems in your code.
you are not resetting the readset variable each time you call select(). select() modifies the variable. For a single-socket case, this is not too bad, but you should get in the habit of resetting the variable each time.
you are not checking for errors returned by recv(). You assume any non-graceful-disconnect is success, but that is not always true.
at the end of readN() before returning true, you are outputting the buffer parameter to std::cout, however buffer will be pointing at the END of the data, not the BEGINNING, since it was advanced by the reading loop. This is likely where your confusion about an "empty buffer" is coming from. readN() itself should not even be outputting the data at all, since you do that after readN() exits, otherwise you end up with redundant output messages.
if readN() returns true, you are passing the final buffer to std::cout using an operator<< that expects a null terminated char string, but your buffer is not guaranteed to be null-terminated.
Try something more like this instead:
bool readN(SOCKET s, int size, char* buffer){
fd_set readset;
struct timeval tv;
int res;
std::cout << "-----called readN to read " << size << " byte(s)" << std::endl;
while (size > 0) {
FD_ZERO(&readset);
FD_SET(s, &readset);
tv.tv_sec = MAXWAIT;
tv.tv_usec = 0;
res = select(0, &readset, NULL, NULL, &tv);
if (res > 0) {
res = recv(s, buffer, size, 0);
if (res == SOCKET_ERROR) {
res = WSAGetLastError();
if (res == WSAEWOULDBLOCK) {
continue; //call select() again
}
return false; //socket error
}
if (res == 0) {
return false; //connection closed by client
}
buffer += res;
size -= res;
std::cout << "\treceived " << res << " byte(s), " << size << " left" << std::endl;
}
/*
else if (res == 0) {
return false; //timer expired
}
else {
return false; //socket error
}
*/
else {
return false; //timer expired or socket error
}
}
return true;
}
std::unique_ptr<char[]> buffer = std::make_unique<char[]>(size_);
if (readN(sck, size_, buffer.get())) {
std::cout << "----read message----" << std::endl;
std::cout << "\t";
std::cout.write(buffer.get(), size_);
std::cout << std::endl;
}
With that said, I would suggest an alternative implementation of readN(), depending on whether you are using a blocking or non-blocking socket.
If blocking, use setsockopt(SO_RCVTIMEO) instead of select(). If recv() fails with a timeout, WSAGetLastError() will report WSAETIMEDOUT:
sck = socket(...);
DWORD timeout = MAXWAIT * 1000;
setsockopt(sck, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout));
bool readN(SOCKET s, int size, char* buffer){
int res;
std::cout << "-----called readN to read " << size << " byte(s)" << std::endl;
while (size > 0) {
res = recv(s, buffer, size, 0);
if (res == SOCKET_ERROR) {
/*
res = WSAGetLastError();
if (res == WSAETIMEDOUT) {
return false; //timer expired
}
else {
return false; //socket error
}
*/
return false; //timer expired or socket error
}
if (res == 0) {
return false; //connection closed by client
}
buffer += res;
size -= res;
std::cout << "\treceived " << res << " byte(s), " << size << " left" << std::endl;
}
return true;
}
If non-blocking, don't call select() unless recv() asks you to call it:
bool readN(SOCKET s, int size, char* buffer){
fd_set readset;
struct timeval tv;
int res;
std::cout << "-----called readN to read " << size << " byte(s)" << std::endl;
while (size > 0) {
res = recv(s, buffer, size, 0);
if (res == SOCKET_ERROR) {
res = WSAGetLastError();
if (res != WSAEWOULDBLOCK) {
return false; //socket error
}
FD_ZERO(&readset);
FD_SET(s, &readset);
tv.tv_sec = MAXWAIT;
tv.tv_usec = 0;
res = select(0, &readset, NULL, NULL, &tv);
if (res > 0) {
continue; //call recv() again
}
/*
else if (res == 0) {
return false; //timer expired
}
else {
return false; //socket error
}
*/
return false; //timer expired or socket error
}
if (res == 0) {
return false; //connection closed by client
}
buffer += res;
size -= res;
std::cout << "\treceived " << res << " byte(s), " << size << " left" << std::endl;
}
return true;
}
At the end of the readN() there is
std::cout << "\t" << buffer << std::endl;
The problem is that the buffer points now to buffer + size in respect to the original value of buffer. The value has been modified by
buffer += res;
This should output the buffer,
std::cout << "\t" << (buffer - size) << std::endl;
After experimenting readN() with the following main(), it seems that readN() works if the socket is not invalid handle (text/binary data sent by ncat). If the socket is a invalid handle, the function returns quickly.
#include <iostream>
#include <memory>
#include <string.h>
#ifdef _WIN64
#include <ws2tcpip.h>
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#endif
#include <errno.h>
#define MAXWAIT 5000
bool readN(SOCKET fd, int size, char *buffer)
{
fd_set readset;
struct timeval tv;
int left, res;
FD_ZERO(&readset);
FD_SET(fd, &readset);
left = size;
std::cout << "-----called readN to read " << size << " byte" << std::endl;
while (left > 0) {
tv.tv_sec = MAXWAIT;
tv.tv_usec = 0;
res = select(fd + 1, &readset, NULL, NULL, &tv);
if (res > 0) {
res = recv(fd, buffer, left, 0);
if (res == 0) { //connection closed by client
return false;
}
left -= res;
std::cout << "\treceived " << res << " left " << left << std::endl;
buffer += res;
} else if (res == 0) { //timer expired
std::cout << "\ttimer expired" << std::endl;
return false;
} else { //socket error
std::cout << "\tsocket error " << WSAGetLastError() << std::endl;
return false;
}
}
std::cout << "Print the buffer now\n" << (buffer - size) << std::endl;
return true;
}
int main(void)
{
int err;
SOCKET cfd = 0;
SOCKET afd = 0;
struct sockaddr_in addr;
socklen_t clen;
struct sockaddr_in caddr;
#ifdef _WIN64
WORD ver = 0x202;
WSADATA wsa_data;
memset(&wsa_data, 0, sizeof(wsa_data));
std::cout << "WSAStartup" << std::endl;
err = WSAStartup(ver, &wsa_data);
if (err < 0) goto error_exit;
#endif
memset(&addr, 0, sizeof(addr));
memset(&caddr, 0, sizeof(caddr));
std::cout << "socket" << std::endl;
afd = socket(AF_INET, SOCK_STREAM, 0);
if (afd < 0) goto error_exit;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = htons(1234);
std::cout << "bind" << std::endl;
err = bind(afd, (struct sockaddr *)&addr, sizeof(addr));
if (err < 0) goto error_exit;
std::cout << "listen" << std::endl;
listen(afd, 5);
clen = sizeof(caddr);
std::cout << "accept" << std::endl;
cfd = accept(afd, (struct sockaddr *) &caddr, &clen);
if (cfd == INVALID_SOCKET) goto error_exit;
{
int size_ = 1024;
std::unique_ptr<char[]> buffer2 = std::make_unique<char[]>(size_);
std::cout << "readN" << std::endl;
if (readN(cfd, 1024, buffer2.get())) {
std::cout << "----read message----" << std::endl;
std::cout <<"\t"<< buffer2.get() << std::endl;
}
}
return 0;
error_exit:
std::cout << "Error!" << std::endl;
std::cout << "\tsocket error " << WSAGetLastError() << std::endl;
return 1;
}
So I'm following a Youtube tutorial on making a simple external hack for Assault Cube.
I reach part 6 of the tutorial and... blam. My compiler is giving me the error:
[Error] expected declaration before '}' token
So I add that. And it just repeats.
I'm using Orwells Dev C++ and have NO idea where I've gone wrong.
Harsh criticism welcome, including those "you're jumping too ahead of yourself. Try something more simple." etc etc
// Youtube Console Trainer Tutorial -- Trainer for Assault Cube
#include <iostream>
#include <windows.h>
#include <string>
#include <ctime>
std::string GameName = "AssaultCube";
LPCSTR LGameWindow = "AssaultCube";
std::string GameStatus;
bool IsGameAvail;
bool UpdateOnNextRun;
//Ammo Variables
bool AmmoStatus;
BYTE AmmoValue[] = {0xA3, 0X1C, 0X0, 0X0};
DWORD AmmoBaseAddress = {0x004DF73C};
DWORD AmmoOffsets[] = {0x378, 0x14, 0x0};
//Health Variables
bool HealthStatus;
BYTE HealthValue[] = {0x39, 0X5, 0X0, 0X0};
DWORD HealthBaseAddress = {0x004DF73C};
DWORD HealthOffsets[] = {0xF4};
int main()
{
HWND hGameWindow = NULL;
int timeSinceLastUpdate = clock();
int GameAvailTMR = clock();
int onePressTMR = clock();
DWORD dwProcID = NULL;
HANDLE hProcHandle = NULL;
UpdateOnNextRun = true;
std::string sAmmoStatus = "OFF";
std::string sHealthStatus = "OFF";
while(!GetAsyncKeyState(VK_INSERT))
{
if(clock() - GameAvailTMR > 100)
{
GameAvailTMR = clock();
IsGameAvail = false;
hGameWindow = FindWindow(NULL,LGameWindow);
if (hGameWindow)
{
GetWindowThreadProcessId( hGameWindow, &dwProcID);
if(dwProcID != 0);
{
hProcHandle =
OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcID);
if(hProcHandle == INVALID_HANDLE_VALUE || hProcHandle == NULL )
{
GameStatus = "Failed to open process for valid handle";
}
else{
GameStatus = "AssaultCube Ready To Hack";
IsGameAvail = true;
}
else{
GameStatus = "Failed to get process ID";
}
else {
GameStatus = "AssaultCube NOT FOUND";
}
if(UpdateOnNextRun || clock() - timeSinceLastUpdate > 5000 )
system("cls");
std::cout << "-------------------------------------"<< std::endl;
std::cout << " AssaultCube memory hacker" << std::endl;std::endl;
std::cout << "-------------------------------------"<< std::endl;
std::cout << "GAME STATUS:" << GameStatus << std::endl << std::endl;
std::cout << "[F1] Unlimited Ammo -> " << sAmmoStatus << " <- " << std::endl << std::endl;
std::cout << "[F2] Unlimited Health -> " << sHealthStatus << " <- " << std::endl << std::endl;
}
}
}
}
}
}
}
A missing { here:
if(UpdateOnNextRun || clock() - timeSinceLastUpdate > 5000 )
And after the line with GameStatus = "AssaultCube Ready To Hack"; there are two other else without if. Remove/comment them.
And next time, better indentation!
The problem is that your else clauses are nested, when they should be outside their respective if clauses. Let's shuffle some braces around:
hGameWindow = FindWindow(NULL,LGameWindow);
if (hGameWindow)
{
GetWindowThreadProcessId( hGameWindow, &dwProcID);
if(dwProcID != 0);
{
hProcHandle =
OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcID);
if(hProcHandle == INVALID_HANDLE_VALUE || hProcHandle == NULL )
{
GameStatus = "Failed to open process for valid handle";
}
else{
GameStatus = "AssaultCube Ready To Hack";
IsGameAvail = true;
}
}
else{
GameStatus = "Failed to get process ID";
}
}
else {
GameStatus = "AssaultCube NOT FOUND";
}
if(UpdateOnNextRun || clock() - timeSinceLastUpdate > 5000 )
{
system("cls");
std::cout << "-------------------------------------"<< std::endl;
std::cout << " AssaultCube memory hacker" << std::endl;std::endl;
std::cout << "-------------------------------------"<< std::endl;
std::cout << "GAME STATUS:" << GameStatus << std::endl << std::endl;
std::cout << "[F1] Unlimited Ammo -> " << sAmmoStatus << " <- " << std::endl << std::endl;
std::cout << "[F2] Unlimited Health -> " << sHealthStatus << " <- " << std::endl << std::endl;
}
GetWindowThreadProcessId( hGameWindow, &dwProcID);
if(dwProcID != 0);
{
it should be:
GetWindowThreadProcessId( hGameWindow, &dwProcId);
if(dwProcID != 0);
{
it's a little d. in dwProcID
I get an example of c++ code from msdn, where I try to get info about my partitions, but in this code my DeviceIoControl methom returns 0, end error code 3. How can I fix this error?
Code here:
#define WINVER 0x0500
#include <windows.h>
#include <winioctl.h>
#include <iostream>
#include <stdio.h>
void DisplayVolumeInfo(CHAR *volume)
{
HANDLE hDevice = CreateFileA(
volume,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_WRITE | FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_SYSTEM,
NULL);
if (hDevice != INVALID_HANDLE_VALUE)
{
PARTITION_INFORMATION partInfo;
DWORD retcount = 0;
BOOL res = DeviceIoControl(
hDevice,
IOCTL_DISK_GET_PARTITION_INFO,
(LPVOID)NULL,
(DWORD)0,
(LPVOID)&partInfo,
sizeof(partInfo),
&retcount,
(LPOVERLAPPED)NULL);
if (res)
std::cout << "Volume size = " << partInfo.PartitionLength.QuadPart << " bytes (" << (unsigned long long)(partInfo.PartitionLength.QuadPart / 1024 / 1024) << "Mb)" << std::endl;
else
std::cout << "Can't do IOCTL_DISK_GET_PARTITION_INFO (error code=" << GetLastError() << ")" << std::endl;
DISK_GEOMETRY diskGeometry;
retcount = 0;
res = DeviceIoControl(
hDevice,
IOCTL_DISK_GET_DRIVE_GEOMETRY,
NULL, 0,
&diskGeometry, sizeof(diskGeometry),
&retcount,
(LPOVERLAPPED)NULL);
if (res)
{
std::cout << "Cylinders = " << diskGeometry.Cylinders.QuadPart << std::endl;
std::cout << "Tracks/cylinder = " << diskGeometry.TracksPerCylinder << std::endl;
std::cout << "Sectors/track = " << diskGeometry.SectorsPerTrack << std::endl;
std::cout << "Bytes/sector = " << diskGeometry.BytesPerSector << std::endl;
}
else
std::cout << "Can't do IOCTL_DISK_GET_DRIVE_GEOMETRY (error code=" << GetLastError() << ")" << std::endl;
CloseHandle(hDevice);
}
else
std::cout << "Error opening volume " << volume << " (error code=" << GetLastError() << ")" << std::endl;
}
int main()
{
DWORD CharCount = 0;
char DeviceName[MAX_PATH] = "";
DWORD Error = ERROR_SUCCESS;
HANDLE FindHandle = INVALID_HANDLE_VALUE;
BOOL Found = FALSE;
size_t Index = 0;
BOOL Success = FALSE;
char VolumeName[MAX_PATH] = "";
//
// Enumerate all volumes in the system.
FindHandle = FindFirstVolumeA(VolumeName, MAX_PATH);
if (FindHandle == INVALID_HANDLE_VALUE)
{
Error = GetLastError();
printf("FindFirstVolume failed with error code %d\n", Error);
return 0;
}
for (;;)
{
//
// Skip the \\?\ prefix and remove the trailing backslash.
Index = strlen(VolumeName) - 1;
if (VolumeName[0] != '\\' ||
VolumeName[1] != '\\' ||
VolumeName[2] != '?' ||
VolumeName[3] != '\\' ||
VolumeName[Index] != '\\')
{
Error = ERROR_BAD_PATHNAME;
printf("FindFirstVolume/FindNextVolume returned a bad path: %s\n", VolumeName);
break;
}
//
// QueryDosDeviceW does not allow a trailing backslash,
// so temporarily remove it.
VolumeName[Index] = '\0';
CharCount = QueryDosDeviceA(&VolumeName[4], DeviceName, MAX_PATH);
VolumeName[Index] = '\\';
if ( CharCount == 0 )
{
Error = GetLastError();
printf("QueryDosDevice failed with error code %d\n", Error);
break;
}
printf("\nFound a device:\n %s", DeviceName);
printf("\nVolume name: %s", VolumeName);
printf("\n");
DisplayVolumeInfo(VolumeName);
//
// Move on to the next volume.
Success = FindNextVolumeA(FindHandle, VolumeName, MAX_PATH);
if ( !Success )
{
Error = GetLastError();
if (Error != ERROR_NO_MORE_FILES)
{
printf("FindNextVolumeW failed with error code %d\n", Error);
break;
}
//
// Finished iterating
// through all the volumes.
Error = ERROR_SUCCESS;
break;
}
}
FindVolumeClose(FindHandle);
FindHandle = INVALID_HANDLE_VALUE;
return 0;
}
Has anybody met this problem?
P.S. I work on Windows 7 x32