ReadFile Overlapped access - Error 170 (resource is in use) - winapi

my goal:
I`m writing an application which writes a file to the serial port 128 bytes at a time (137 total, with ModBUS header and CRC) and waits for the reply. The writing I have managed to implement successfully. After sending a 137 byte packet I would like to wait on the serial com for a reply and process it, in case that modbus exception is thrown.
my problem:
The ReadFile function returns 170 which, from windows documentation, is 170 (0xAA) - The requested resource is in use. The only resource I am actually using is the serial port handle, which I doubt that it is this, the error is referring to.
Note -
- not using available ModBUS libraries because I use the address registers in a specific way, needing full control
- I am using overlapped I/O only because (according to WinApi doc) ReadFile never returns if no bytes come at the serial port; If timeouts are require overlapped access is a must (correct me if I`m wrong).
- I have a 2 sec max timeout (timeout for actually waiting for the reply) and 20 ms between bytes; if more than 20 ms between bytes pass I assume that no more bytes are coming;
Has anyone had any previous experience working with ReadFile and possibly Erro 170? Appreciate all the help I can get.
part of my code:
u8 WaitModBusReply(void)
{
u8 i = 0;
u8 ReplyStatus = 0xAA;
u8 ReplyBuff[ReplyBuffSize];
u8 * ptr = &ReplyBuff[0];
static u16 TotalRX_Bytes;
DWORD dwCommEvent;
DWORD dwBytesRead;
COMSTAT ComStatus;
DWORD comErrors = 0;
OVERLAPPED read_s = {0};
read_s.hEvent = CreateEvent(
NULL, // default security attributes
TRUE, // manual-reset event
FALSE, // not signaled
NULL // no name
);
for (int z=0; z< ReplyBuffSize; z++)
ReplyBuff[z] = 0;
ClearCommError(ModBUS_Port, &comErrors, &ComStatus);
ResetEvent(read_s.hEvent);
if ( !WaitCommEvent(ModBUS_Port, &dwCommEvent, &read_s) )
{
//byte_timeout += MCU_Getms_TimeConsumption();
if ( (ReadFile(ModBUS_Port, ptr+TotalRX_Bytes, ReplyBuffSize-
TotalRX_Bytes, &dwBytesRead, NULL) )) //&dwBytesRead &modbus_reply
{
fprintf(stderr, "\n EXEC 3");
// ReadFile(PC_TestCenterPort, pBufPtr+TotalRX_Bytes, BufSize-
TotalRX_Bytes, &BytesRead, NULL);
TotalRX_Bytes += dwBytesRead;
i++;
ReplyStatus = Reply_Received;
}
}
else
printf("Error setting Com event mask:%d ", GetLastError());
if ( ReplyStatus == Reply_Received)
{
fprintf(stderr, "\nExit error3: %d\n", GetLastError() );
if ( (i == 4) ) // Exception returned. Parse it
{
if ( !ModBus_CRC16 (&ReplyBuff[0], i, READ) )
ReplyStatus = Reply_CRCError;
else
ReplyStatus = ReplyBuff[i-2];
}
else if ( (i == 7) ) // Reply returned
{
if ( !ModBus_CRC16 (&ReplyBuff[0], i, READ) )
ReplyStatus = Reply_CRCError;
else
ReplyStatus = Reply_OK;
}
}
/*
for ( int j=0; j<= 256; j++)
printf("\nReplyBuff[%d]: %X", j, ReplyBuff[j]); */
return ReplyStatus;
}
The logic for checking the reply array is not implemented so ignore that part.
This function is called by:
u8 SerialDataSend(void)
{
u8 t_status = BufferSent;
int write_status = -1;
int read_status = -1;
DWORD bytes_written = 0;
OVERLAPPED write_s;
memset(&write_s, 0, sizeof(write_s));
write_s.Internal = 0;
write_s.InternalHigh = 0;
write_s.Offset = 0;
write_s.OffsetHigh = 0;
write_s.hEvent = CreateEvent(
NULL, // default security attributes
TRUE, // manual-reset event
FALSE, // not signaled
NULL // no name
);
if ( !SerialInit() )
{
while (!t_status)
{
fprintf(stderr, "Starting transmission -\n");
while(packages_left > 0 && !t_status)
{
write_status = WriteFile(ModBUS_Port, ModBUS_Buffer(), 137,
&bytes_written, &write_s); //&write_s
fprintf(stderr,"\r ModBUS transaction - Packages left:%4d",
packages_left);
if( write_status ) // Return values for success and
overlapped access ongoing
{
fprintf(stderr, "Error :%d.\n", GetLastError());
t_status = BufferFailed;
CloseHandle(ModBUS_Port);
break;
}
//FlushFileBuffers(ModBUS_Port);
read_status = WaitModBusReply();
printf("READ STATUS: %d\n", read_status);
if ( !read_status && !write_status )
{
fprintf(stderr, "\n------------------------------------------------------------");
fprintf(stderr, "\n Exception occurred: %X\n",
read_status);
t_status = BufferFailed;
Sleep(1);
break;
}
packages_left--;
Sleep(200);
}
//printf("EXEC 1\n");
if (!t_status)
{
fprintf(stderr, "\n\nTransaction Complete. Bytes written :
%d\n", FileSize);
packages_left = 10;
}
break;
}
fclose(HMI_Program);
if ( t_status != BufferFailed )
{
fprintf(stderr, "Closing serial port - ");
if ( !CloseHandle(ModBUS_Port) )
fprintf(stderr, "Error :%d.\n", GetLastError());
else
fprintf(stderr, "OK.\n");
}
}
fflush(stdout);
fflush(stderr);
return t_status;
}
and the function which initializes the Serial port:
u8 SerialInit(void)
{
memset(&SerialSettings,0,sizeof(SerialSettings));
SerialSettings.DCBlength = sizeof(SerialSettings);
SerialSettings.BaudRate = CBR_115200;
SerialSettings.ByteSize = 8;
SerialSettings.StopBits = TWOSTOPBITS;
SerialSettings.Parity = NOPARITY;
timeouts.WriteTotalTimeoutConstant = 50;
timeouts.WriteTotalTimeoutMultiplier = 10;
timeouts.ReadIntervalTimeout = 20;
timeouts.ReadTotalTimeoutConstant = 2000;
timeouts.ReadTotalTimeoutMultiplier = 1 ;
memset(&timeouts,0,sizeof(timeouts));
fprintf(stderr, "Opening serial port - ");
sprintf(COM_Port, "\\\\.\\COM%d", port_no);
ModBUS_Port = CreateFile(COM_Port, GENERIC_READ|GENERIC_WRITE, 0, NULL,
OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL );
if (ModBUS_Port == INVALID_HANDLE_VALUE)
fprintf(stderr, "Error\n\n");
else
fprintf(stderr, "OK\n");
if ( !GetCommState(ModBUS_Port, &SerialSettings) )
{
fprintf(stderr, "Error getting device state.");
CloseHandle(ModBUS_Port);
}
else if( !SetCommState(ModBUS_Port, &SerialSettings) )
{
fprintf(stderr, "Error setting device parameters.");
CloseHandle(ModBUS_Port);
}
else if ( !SetCommTimeouts(ModBUS_Port, &timeouts) )
{
fprintf(stderr, "Error setting timeouts.");
CloseHandle(ModBUS_Port);
}
else if ( !SetCommMask(ModBUS_Port, EV_RXCHAR | EV_ERR ) )
{
fprintf(stderr, "\nError setting com mask.");
CloseHandle(ModBUS_Port);
}
return GetLastError();
}
Thanks.

Related

RIOSendEx get error 10022 but connect + RIOSend works well

I'm learning Windows Registered I/O, I found a sample project from the website "https://github.com/zeliard/RIOEchoServer", It does well on my computer.
However, if I change this code from the listening server side to the actively sending client side, I find that connect + RIOSend works fine, but RIOSendEx will definitely give an error code of 10022!
#include <WinSock2.h>
#include <MSWsock.h>
#include <WS2tcpip.h>
#include <stdio.h>
#pragma comment(lib, "ws2_32.lib")
int main(int argc, char * argv[])
{
static const wchar_t SERVER[] = L"127.0.0.1";
static const unsigned short PORTNUM = 54321;
static const DWORD RIO_PENDING_RECVS = 1;
static const DWORD RIO_PENDING_SENDS = 1;
static const DWORD RECV_BUFFER_SIZE = 1024;
static const DWORD SEND_BUFFER_SIZE = 1024;
static const DWORD ADDR_BUFFER_SIZE = 64;
static const DWORD RIO_MAX_RESULTS = 1;
WSADATA wsadata;
if (0 != ::WSAStartup(0x202, &wsadata))
{
printf_s("WSAStartup Error: %d\n", GetLastError());
exit(0);
}
/// RIO socket
SOCKET socket = WSASocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP, NULL, 0, WSA_FLAG_REGISTERED_IO);
if (socket == INVALID_SOCKET)
{
printf_s("WSASocket Error: %d\n", GetLastError());
exit(0);
}
/// RIO function table
GUID functionTableId = WSAID_MULTIPLE_RIO;
DWORD dwBytes = 0;
RIO_EXTENSION_FUNCTION_TABLE rio;
if (NULL != WSAIoctl(socket, SIO_GET_MULTIPLE_EXTENSION_FUNCTION_POINTER, &functionTableId, sizeof(GUID), (void**)&rio, sizeof(rio), &dwBytes, NULL, NULL))
{
printf_s("WSAIoctl Error: %d\n", GetLastError());
exit(0);
}
/// rio's completion manner: iocp
HANDLE hIOCP = ::CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0, 0);
if (NULL == hIOCP)
{
printf_s("CreateIoCompletionPort Error: %d\n", GetLastError());
exit(0);
}
OVERLAPPED overlapped;
RIO_NOTIFICATION_COMPLETION completionType;
completionType.Type = RIO_IOCP_COMPLETION;
completionType.Iocp.IocpHandle = hIOCP;
completionType.Iocp.CompletionKey = NULL;
completionType.Iocp.Overlapped = &overlapped;
/// creating RIO CQ, which is bigger than (or equal to) RQ size
RIO_CQ completionQueue = rio.RIOCreateCompletionQueue(RIO_PENDING_RECVS + RIO_PENDING_SENDS, &completionType);
if (completionQueue == RIO_INVALID_CQ)
{
printf_s("RIOCreateCompletionQueue Error: %d\n", GetLastError());
exit(0);
}
/// creating RIO RQ
/// SEND and RECV within one CQ (you can do with two CQs, seperately)
RIO_RQ requestQueue = rio.RIOCreateRequestQueue(socket, RIO_PENDING_RECVS, 1, RIO_PENDING_SENDS, 1, completionQueue, completionQueue, NULL);
if (requestQueue == RIO_INVALID_RQ)
{
printf_s("RIOCreateRequestQueue Error: %d\n", GetLastError());
exit(0);
}
/// registering RIO buffers for SEND
char sendBuffer[SEND_BUFFER_SIZE];
RIO_BUFFERID sendRioBufferId = rio.RIORegisterBuffer(sendBuffer, static_cast<DWORD>(sizeof(sendBuffer)));
if (sendRioBufferId == RIO_INVALID_BUFFERID)
{
printf_s("RIORegisterBuffer Error: %d\n", GetLastError());
exit(0);
}
RIO_BUF sendRioBuffer;
sendRioBuffer.BufferId = sendRioBufferId;
sendRioBuffer.Offset = 0;
sendRioBuffer.Length = SEND_BUFFER_SIZE;
/// registering RIO buffers for ADDR
char addrBuffer[ADDR_BUFFER_SIZE];
RIO_BUFFERID addrRioBufferId = rio.RIORegisterBuffer(addrBuffer, static_cast<DWORD>(sizeof(addrBuffer)));
if (addrRioBufferId == RIO_INVALID_BUFFERID)
{
printf_s("RIORegisterBuffer Error: %d\n", GetLastError());
exit(0);
}
RIO_BUF addrRioBuffer;
addrRioBuffer.BufferId = addrRioBufferId;
addrRioBuffer.Offset = 0;
addrRioBuffer.Length = ADDR_BUFFER_SIZE;
/// registering RIO buffers for RECV and then, post pre-RECV
char recvBuffer[RECV_BUFFER_SIZE];
RIO_BUFFERID recvRioBufferId = rio.RIORegisterBuffer(recvBuffer, static_cast<DWORD>(sizeof(recvBuffer)));
if (recvRioBufferId == RIO_INVALID_BUFFERID)
{
printf_s("RIORegisterBuffer Error: %d\n", GetLastError());
exit(0);
}
RIO_BUF recvRioBuffer;
recvRioBuffer.BufferId = recvRioBufferId;
recvRioBuffer.Offset = 0;
recvRioBuffer.Length = RECV_BUFFER_SIZE;
/// posting pre RECVs
if (!rio.RIOReceiveEx(requestQueue, &recvRioBuffer, 1, NULL, &addrRioBuffer, NULL, 0, 0, &recvRioBuffer))
{
printf_s("RIOReceive Error: %d\n", GetLastError());
exit(0);
}
//////////////////////////////////////////////////////////////////////////
// active send code begin ...
//////////////////////////////////////////////////////////////////////////
sendRioBuffer.Length = 5;
memcpy_s(sendBuffer, RECV_BUFFER_SIZE, "hello", sendRioBuffer.Length);
sockaddr_in * address = reinterpret_cast<sockaddr_in *>(addrBuffer);
memset(address, 0x0, ADDR_BUFFER_SIZE);
address->sin_family = AF_INET;
address->sin_port = htons(PORTNUM);
if (::InetPton(AF_INET, SERVER, &address->sin_addr) <= 0)
{
printf_s("inet_pton Error: %d\n", GetLastError());
exit(0);
}
#if 0 // connect + RIOSend is OK
if (SOCKET_ERROR == ::connect(socket, reinterpret_cast<struct sockaddr *>(address), sizeof(*address)))
{
printf_s("Connect Error: %d\n", GetLastError());
exit(0);
}
if (!rio.RIOSend(requestQueue, &sendRioBuffer, 1, 0, &sendRioBuffer))
{
printf_s("RIOSend Error: %d\n", GetLastError());
exit(0);
}
#else // RIOSendEx not work
if (!rio.RIOSendEx(requestQueue, &sendRioBuffer, 1, NULL, &addrRioBuffer, NULL, NULL, 0, &sendRioBuffer))
{
printf_s("RIOSendEx Error: %d\n", GetLastError());
exit(0);
}
#endif // 0
INT notifyResult = rio.RIONotify(completionQueue);
if (notifyResult != ERROR_SUCCESS)
{
printf_s("RIONotify Error: %d\n", GetLastError());
exit(0);
}
DWORD numberOfBytes = 0;
ULONG_PTR completionKey = 0;
OVERLAPPED* pOverlapped = 0;
RIORESULT results[RIO_MAX_RESULTS];
if (!::GetQueuedCompletionStatus(hIOCP, &numberOfBytes, &completionKey, &pOverlapped, INFINITE))
{
printf_s("GetQueuedCompletionStatus Error: %d\n", GetLastError());
exit(0);
}
memset(results, 0, sizeof(results));
ULONG numResults = rio.RIODequeueCompletion(completionQueue, results, RIO_MAX_RESULTS);
if (0 == numResults || RIO_CORRUPT_CQ == numResults)
{
printf_s("RIODequeueCompletion Error: %d\n", GetLastError());
exit(0);
}
const RIORESULT & res = results[0];
if (0 != res.Status)
{
printf_s("RIOSend(Ex) Error: %d\n", res.Status);
exit(0);
}
printf_s("RIOSend(Ex) OK\n");
//////////////////////////////////////////////////////////////////////////
// active send code end ...
//////////////////////////////////////////////////////////////////////////
if (SOCKET_ERROR == ::closesocket(socket))
{
printf_s("closesocket Error: %d\n", GetLastError());
}
rio.RIOCloseCompletionQueue(completionQueue);
rio.RIODeregisterBuffer(sendRioBufferId);
rio.RIODeregisterBuffer(recvRioBufferId);
rio.RIODeregisterBuffer(addrRioBufferId);
return 0;
}
wish your help, Thanks!
yanrk
From RIOSendEx documentation:
sends network data on ... a bound ... UDP socket
Your example will work if you add those lines before calling RIOSendEx:
sockaddr_in addr{}; // zero-initialized
addr.sin_family = AF_INET;
if (SOCKET_ERROR == ::bind(socket, (struct sockaddr *)&addr, sizeof(addr)))
{
printf("bind failed\n");
exit(0);
}
if (!rio.RIOSendEx(requestQueue ...
You can bind to some particular port (not recommended):
addr.sin_port = htons(5001);
Or leave it zero for OS to choose.
Aparently, RIOSendEx do not perform an implicit bind (unlike WSASendTo).
The reason for this might be that bind is a complicated process that might involve waiting and APC and all kinds of stuff, while whole idea of RIO is to pay upfront.
connect + RIOSendEx doesn't make sense. Since you specified remote address with connect function you can't send data through that socket anywhere else. RIOSendEx is supposed to be used with datagrams.
You have not set the Destination IP-Address in the RioSendEx-Function:
Copy the content of your address-Buffer into the associated Buffer of addrRioBuffer.
e.g.:
memcpy_s(addrBuffer, ADDR_BUFFER_SIZE, address, sizeof(sockaddr_in));
if (!rio.RIOSendEx(requestQueue, &sendRioBuffer, 1, NULL, &addrRioBuffer, NULL, NULL, 0, &sendRioBuffer))
{
printf_s("RIOSendEx Error: %d\n", GetLastError());
exit(0);
}
// […]
I will post a working exampel in the next day´s.
http://www.thbweb.eu

need Help in windivert webfilter

Hello every one i m trying to develop web filter and i found Win Divert Samples
here the code is i m trying to run in visual Studio 12 and got this error
IntelliSense: argument of type "PVOID" is incompatible with parameter of type "char *"
#include <winsock2.h>
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include "windivert.h"
#define MAXBUF 0xFFFF
#define MAXURL 4096
/*
* URL and blacklist representation.
*/
typedef struct
{
char *domain;
char *uri;
} URL, *PURL;
typedef struct
{
UINT size;
UINT length;
PURL *urls;
} BLACKLIST, *PBLACKLIST;
/*
* Pre-fabricated packets.
*/
typedef struct
{
WINDIVERT_IPHDR ip;
WINDIVERT_TCPHDR tcp;
} PACKET, *PPACKET;
typedef struct
{
PACKET header;
UINT8 data[];
} DATAPACKET, *PDATAPACKET;
/*
* THe block page contents.
*/
const char block_data[] =
"HTTP/1.1 200 OK\r\n"
"Connection: close\r\n"
"Content-Type: text/html\r\n"
"\r\n"
"<!doctype html>\n"
"<html>\n"
"\t<head>\n"
"\t\t<title>BLOCKED!</title>\n"
"\t</head>\n"
"\t<body>\n"
"\t\t<h1>BLOCKED!</h1>\n"
"\t\t<hr>\n"
"\t\t<p>This URL has been blocked!</p>\n"
"\t</body>\n"
"</html>\n";
/*
* Prototypes
*/
static void PacketInit(PPACKET packet);
static int __cdecl UrlCompare(const void *a, const void *b);
static int UrlMatch(PURL urla, PURL urlb);
static PBLACKLIST BlackListInit(void);
static void BlackListInsert(PBLACKLIST blacklist, PURL url);
static void BlackListSort(PBLACKLIST blacklist);
static BOOL BlackListMatch(PBLACKLIST blacklist, PURL url);
static void BlackListRead(PBLACKLIST blacklist, const char *filename);
static BOOL BlackListPayloadMatch(PBLACKLIST blacklist, char *data,
UINT16 len);
/*
* Entry.
*/
int __cdecl main(int argc, char **argv)
{
HANDLE handle;
WINDIVERT_ADDRESS addr;
UINT8 packet[MAXBUF];
UINT packet_len;
PWINDIVERT_IPHDR ip_header;
PWINDIVERT_TCPHDR tcp_header;
PVOID payload;
UINT payload_len;
PACKET reset0;
PPACKET reset = &reset0;
PACKET finish0;
PPACKET finish = &finish0;
PDATAPACKET blockpage;
UINT16 blockpage_len;
PBLACKLIST blacklist;
unsigned i;
INT16 priority = 404; // Arbitrary.
// Read the blacklists.
if (argc <= 1)
{
fprintf(stderr, "usage: %s blacklist.txt [blacklist2.txt ...]\n",
argv[0]);
exit(EXIT_FAILURE);
}
blacklist = BlackListInit();
for (i = 1; i < (UINT)argc; i++)
{
BlackListRead(blacklist, argv[i]);
}
BlackListSort(blacklist);
// Initialize the pre-frabricated packets:
blockpage_len = sizeof(DATAPACKET)+sizeof(block_data)-1;
blockpage = (PDATAPACKET)malloc(blockpage_len);
if (blockpage == NULL)
{
fprintf(stderr, "error: memory allocation failed\n");
exit(EXIT_FAILURE);
}
PacketInit(&blockpage->header);
blockpage->header.ip.Length = htons(blockpage_len);
blockpage->header.tcp.SrcPort = htons(80);
blockpage->header.tcp.Psh = 1;
blockpage->header.tcp.Ack = 1;
memcpy(blockpage->data, block_data, sizeof(block_data)-1);
PacketInit(reset);
reset->tcp.Rst = 1;
reset->tcp.Ack = 1;
PacketInit(finish);
finish->tcp.Fin = 1;
finish->tcp.Ack = 1;
// Open the Divert device:
handle = WinDivertOpen(
"outbound && " // Outbound traffic only
"ip && " // Only IPv4 supported
"tcp.DstPort == 80 && " // HTTP (port 80) only
"tcp.PayloadLength > 0", // TCP data packets only
WINDIVERT_LAYER_NETWORK, priority, 0
);
if (handle == INVALID_HANDLE_VALUE)
{
fprintf(stderr, "error: failed to open the WinDivert device (%d)\n",
GetLastError());
exit(EXIT_FAILURE);
}
printf("OPENED WinDivert\n");
// Main loop:
while (TRUE)
{
if (!WinDivertRecv(handle, packet, sizeof(packet), &addr, &packet_len))
{
fprintf(stderr, "warning: failed to read packet (%d)\n",
GetLastError());
continue;
}
if (!WinDivertHelperParsePacket(packet, packet_len, &ip_header, NULL,
NULL, NULL, &tcp_header, NULL, &payload, &payload_len) ||
!BlackListPayloadMatch(blacklist, payload, (UINT16)payload_len))
{
// Packet does not match the blacklist; simply reinject it.
if (!WinDivertSend(handle, packet, packet_len, &addr, NULL))
{
fprintf(stderr, "warning: failed to reinject packet (%d)\n",
GetLastError());
}
continue;
}
// The URL matched the blacklist; we block it by hijacking the TCP
// connection.
// (1) Send a TCP RST to the server; immediately closing the
// connection at the server's end.
reset->ip.SrcAddr = ip_header->SrcAddr;
reset->ip.DstAddr = ip_header->DstAddr;
reset->tcp.SrcPort = tcp_header->SrcPort;
reset->tcp.DstPort = htons(80);
reset->tcp.SeqNum = tcp_header->SeqNum;
reset->tcp.AckNum = tcp_header->AckNum;
WinDivertHelperCalcChecksums((PVOID)reset, sizeof(PACKET), 0);
if (!WinDivertSend(handle, (PVOID)reset, sizeof(PACKET), &addr, NULL))
{
fprintf(stderr, "warning: failed to send reset packet (%d)\n",
GetLastError());
}
// (2) Send the blockpage to the browser:
blockpage->header.ip.SrcAddr = ip_header->DstAddr;
blockpage->header.ip.DstAddr = ip_header->SrcAddr;
blockpage->header.tcp.DstPort = tcp_header->SrcPort;
blockpage->header.tcp.SeqNum = tcp_header->AckNum;
blockpage->header.tcp.AckNum =
htonl(ntohl(tcp_header->SeqNum) + payload_len);
WinDivertHelperCalcChecksums((PVOID)blockpage, blockpage_len, 0);
addr.Direction = !addr.Direction; // Reverse direction.
if (!WinDivertSend(handle, (PVOID)blockpage, blockpage_len, &addr,
NULL))
{
fprintf(stderr, "warning: failed to send block page packet (%d)\n",
GetLastError());
}
// (3) Send a TCP FIN to the browser; closing the connection at the
// browser's end.
finish->ip.SrcAddr = ip_header->DstAddr;
finish->ip.DstAddr = ip_header->SrcAddr;
finish->tcp.SrcPort = htons(80);
finish->tcp.DstPort = tcp_header->SrcPort;
finish->tcp.SeqNum =
htonl(ntohl(tcp_header->AckNum) + sizeof(block_data) - 1);
finish->tcp.AckNum =
htonl(ntohl(tcp_header->SeqNum) + payload_len);
WinDivertHelperCalcChecksums((PVOID)finish, sizeof(PACKET), 0);
if (!WinDivertSend(handle, (PVOID)finish, sizeof(PACKET), &addr, NULL))
{
fprintf(stderr, "warning: failed to send finish packet (%d)\n",
GetLastError());
}
}
}
/*
* Initialize a PACKET.
*/
static void PacketInit(PPACKET packet)
{
memset(packet, 0, sizeof(PACKET));
packet->ip.Version = 4;
packet->ip.HdrLength = sizeof(WINDIVERT_IPHDR) / sizeof(UINT32);
packet->ip.Length = htons(sizeof(PACKET));
packet->ip.TTL = 64;
packet->ip.Protocol = IPPROTO_TCP;
packet->tcp.HdrLength = sizeof(WINDIVERT_TCPHDR) / sizeof(UINT32);
}
/*
* Initialize an empty blacklist.
*/
static PBLACKLIST BlackListInit(void)
{
PBLACKLIST blacklist = (PBLACKLIST)malloc(sizeof(BLACKLIST));
UINT size;
if (blacklist == NULL)
{
goto memory_error;
}
size = 1024;
blacklist->urls = (PURL *)malloc(size*sizeof(PURL));
if (blacklist->urls == NULL)
{
goto memory_error;
}
blacklist->size = size;
blacklist->length = 0;
return blacklist;
memory_error:
fprintf(stderr, "error: failed to allocate memory\n");
exit(EXIT_FAILURE);
}
/*
* Insert a URL into a blacklist.
*/
static void BlackListInsert(PBLACKLIST blacklist, PURL url)
{
if (blacklist->length >= blacklist->size)
{
blacklist->size = (blacklist->size*3) / 2;
printf("GROW blacklist to %u\n", blacklist->size);
blacklist->urls = (PURL *)realloc(blacklist->urls,
blacklist->size*sizeof(PURL));
if (blacklist->urls == NULL)
{
fprintf(stderr, "error: failed to reallocate memory\n");
exit(EXIT_FAILURE);
}
}
blacklist->urls[blacklist->length++] = url;
}
/*
* Sort the blacklist (for searching).
*/
static void BlackListSort(PBLACKLIST blacklist)
{
qsort(blacklist->urls, blacklist->length, sizeof(PURL), UrlCompare);
}
/*
* Match a URL against the blacklist.
*/
static BOOL BlackListMatch(PBLACKLIST blacklist, PURL url)
{
int lo = 0, hi = ((int)blacklist->length)-1;
while (lo <= hi)
{
INT mid = (lo + hi) / 2;
int cmp = UrlMatch(url, blacklist->urls[mid]);
if (cmp > 0)
{
hi = mid-1;
}
else if (cmp < 0)
{
lo = mid+1;
}
else
{
return TRUE;
}
}
return FALSE;
}
/*
* Read URLs from a file.
*/
static void BlackListRead(PBLACKLIST blacklist, const char *filename)
{
char domain[MAXURL+1];
char uri[MAXURL+1];
int c;
UINT16 i, j;
PURL url;
FILE *file = fopen(filename, "r");
if (file == NULL)
{
fprintf(stderr, "error: could not open blacklist file %s\n",
filename);
exit(EXIT_FAILURE);
}
// Read URLs from the file and add them to the blacklist:
while (TRUE)
{
while (isspace(c = getc(file)))
;
if (c == EOF)
{
break;
}
if (c != '-' && !isalnum(c))
{
while (!isspace(c = getc(file)) && c != EOF)
;
if (c == EOF)
{
break;
}
continue;
}
i = 0;
domain[i++] = (char)c;
while ((isalnum(c = getc(file)) || c == '-' || c == '.') && i < MAXURL)
{
domain[i++] = (char)c;
}
domain[i] = '\0';
j = 0;
if (c == '/')
{
while (!isspace(c = getc(file)) && c != EOF && j < MAXURL)
{
uri[j++] = (char)c;
}
uri[j] = '\0';
}
else if (isspace(c))
{
uri[j] = '\0';
}
else
{
while (!isspace(c = getc(file)) && c != EOF)
;
continue;
}
printf("ADD %s/%s\n", domain, uri);
url = (PURL)malloc(sizeof(URL));
if (url == NULL)
{
goto memory_error;
}
url->domain = (char *)malloc((i+1)*sizeof(char));
url->uri = (char *)malloc((j+1)*sizeof(char));
if (url->domain == NULL || url->uri == NULL)
{
goto memory_error;
}
strcpy(url->uri, uri);
for (j = 0; j < i; j++)
{
url->domain[j] = domain[i-j-1];
}
url->domain[j] = '\0';
BlackListInsert(blacklist, url);
}
fclose(file);
return;
memory_error:
fprintf(stderr, "error: memory allocation failed\n");
exit(EXIT_FAILURE);
}
/*
* Attempt to parse a URL and match it with the blacklist.
*
* BUG:
* - This function makes several assumptions about HTTP requests, such as:
* 1) The URL will be contained within one packet;
* 2) The HTTP request begins at a packet boundary;
* 3) The Host header immediately follows the GET/POST line.
* Some browsers, such as Internet Explorer, violate these assumptions
* and therefore matching will not work.
*/
static BOOL BlackListPayloadMatch(PBLACKLIST blacklist, char *data, UINT16 len)
{
static const char get_str[] = "GET /";
static const char post_str[] = "POST /";
static const char http_host_str[] = " HTTP/1.1\r\nHost: ";
char domain[MAXURL];
char uri[MAXURL];
URL url = {domain, uri};
UINT16 i = 0, j;
BOOL result;
HANDLE console;
if (len <= sizeof(post_str) + sizeof(http_host_str))
{
return FALSE;
}
if (strncmp(data, get_str, sizeof(get_str)-1) == 0)
{
i += sizeof(get_str)-1;
}
else if (strncmp(data, post_str, sizeof(post_str)-1) == 0)
{
i += sizeof(post_str)-1;
}
else
{
return FALSE;
}
for (j = 0; i < len && data[i] != ' '; j++, i++)
{
uri[j] = data[i];
}
uri[j] = '\0';
if (i + sizeof(http_host_str)-1 >= len)
{
return FALSE;
}
if (strncmp(data+i, http_host_str, sizeof(http_host_str)-1) != 0)
{
return FALSE;
}
i += sizeof(http_host_str)-1;
for (j = 0; i < len && data[i] != '\r'; j++, i++)
{
domain[j] = data[i];
}
if (i >= len)
{
return FALSE;
}
if (j == 0)
{
return FALSE;
}
if (domain[j-1] == '.')
{
// Nice try...
j--;
if (j == 0)
{
return FALSE;
}
}
domain[j] = '\0';
printf("URL %s/%s: ", domain, uri);
// Reverse the domain:
for (i = 0; i < j / 2; i++)
{
char t = domain[i];
domain[i] = domain[j-i-1];
domain[j-i-1] = t;
}
// Search the blacklist:
result = BlackListMatch(blacklist, &url);
// Print the verdict:
console = GetStdHandle(STD_OUTPUT_HANDLE);
if (result)
{
SetConsoleTextAttribute(console, FOREGROUND_RED);
puts("BLOCKED!");
}
else
{
SetConsoleTextAttribute(console, FOREGROUND_GREEN);
puts("allowed");
}
SetConsoleTextAttribute(console,
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
return result;
}
/*
* URL comparison.
*/
static int __cdecl UrlCompare(const void *a, const void *b)
{
PURL urla = *(PURL *)a;
PURL urlb = *(PURL *)b;
int cmp = strcmp(urla->domain, urlb->domain);
if (cmp != 0)
{
return cmp;
}
return strcmp(urla->uri, urlb->uri);
}
/*
* URL matching
*/
static int UrlMatch(PURL urla, PURL urlb)
{
UINT16 i;
for (i = 0; urla->domain[i] && urlb->domain[i]; i++)
{
int cmp = (int)urlb->domain[i] - (int)urla->domain[i];
if (cmp != 0)
{
return cmp;
}
}
if (urla->domain[i] == '\0' && urlb->domain[i] != '\0')
{
return 1;
}
for (i = 0; urla->uri[i] && urlb->uri[i]; i++)
{
int cmp = (int)urlb->uri[i] - (int)urla->uri[i];
if (cmp != 0)
{
return cmp;
}
}
if (urla->uri[i] == '\0' && urlb->uri[i] != '\0')
{
return 1;
}
return 0;
}
This file compiles without errors as C code, so be sure that you compile it as C. If you need to compile it as C++, then add explicit cast to char* at payload parameter in this line:
if (!WinDivertHelperParsePacket(packet, packet_len, &ip_header, NULL,
NULL, NULL, &tcp_header, NULL, &payload, &payload_len) ||
!BlackListPayloadMatch(blacklist, payload, (UINT16)payload_len))
Like this:
if (!WinDivertHelperParsePacket(packet, packet_len, &ip_header, NULL,
NULL, NULL, &tcp_header, NULL, &payload, &payload_len) ||
!BlackListPayloadMatch(blacklist, (char*)payload, (UINT16)payload_len))

Migrating Winsock console application to Windows subsystem - stack overflow

Hey there wonderful community!
I'm back with a question regarding a console server application I've made with winsock. It's finally reaching a stage where I would need a to add a GUI, and to do so, I need it to be using the Windows subsystem.
And so I started the migration.
Yet I'm hitting a stack overflow somewhere in my application, and for the life of me I can't figure out where. Perhaps it has to do with WIN being a non-blocking subsystem (hope I used my vocab correctly).
Anyway, I hope to enlist you all as helpers. Many thanks :)
#undef UNICODE
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <string>
#include <conio.h>
// Need to link with Ws2_32.lib
#pragma comment (lib, "Ws2_32.lib")
// #pragma comment (lib, "Mswsock.lib")
int minitialize();
int msend(char msendbuf[512]);
char* mrecv(bool show);
int mshutdown();
void GoToXY(int column, int line);
int scroll(void);
int printm(char *inp);
int printm(char *inp, DWORD color);
int mexit();
char *vir = "true";
int clientnumber=0;
int currentclient=0;
int lastclient=0;
#define DEFAULT_BUFLEN 512
#define DEFAULT_PORT "10150"
struct _client
{
bool con;
sockaddr_in addr; //Client info like ip address
SOCKET cs; //Client socket
fd_set set; //used to check if there is data in the socket
std::string ip;
std::string name;
int i; //any piece of additional info
} client[100];
WSADATA wsaData;
int iResult;
SOCKET ListenSocket = INVALID_SOCKET;
SOCKET ClientSocket = INVALID_SOCKET;
struct addrinfo *result = NULL;
struct addrinfo hints;
int iSendResult;
char recvbuf[DEFAULT_BUFLEN];
int recvbuflen = DEFAULT_BUFLEN;
DWORD WINAPI recvfunc(LPVOID randparam)
{
while (true) {
ClientSocket=client[currentclient].cs;
if (mrecv(true)=="1") {
client[currentclient].con=false;
ClientSocket=client[lastclient].cs;
break;
}
}
return 0;
}
DWORD WINAPI headerfunc(LPVOID randparam)
{
Sleep(500);
while (true) {
CONSOLE_SCREEN_BUFFER_INFO SBInfo;
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleScreenBufferInfo(hOut, &SBInfo);
int xx = SBInfo.dwCursorPosition.X;
int yy = SBInfo.dwCursorPosition.Y;
GoToXY(0,0);
HANDLE hHeaderColor;
hHeaderColor = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(hHeaderColor, FOREGROUND_GREEN);
std::cout<<"Server Started. Current Client:"<<currentclient<<" Clients connected: "<<clientnumber<<" ("<<xx<<","<<yy<<") "<<lastclient;
SetConsoleTextAttribute(hHeaderColor, 0 |
FOREGROUND_RED |
FOREGROUND_GREEN |
FOREGROUND_BLUE);
GoToXY(xx,yy);
Sleep(2000);
}
return 0;
}
DWORD WINAPI sendfunc(LPVOID randparam)
{
while (true) {
char mmessage[512];
std::cin.getline(mmessage, 512);
if (strlen(mmessage)<2) {
GoToXY(0,23);
sendfunc("1");
}
char msendbuf[512]="Server> ";
strcat(msendbuf,mmessage);
if (msend(msendbuf)==1) {
"Client must have disconnected. Please select a new client.";
sendfunc("1");
}
if ((strncmp(msendbuf,"Server> /",9)) != 0) {
printm(msendbuf,FOREGROUND_INTENSITY);
}
GoToXY(0,23);
for (int sp=0; sp<72; sp++) {
std::cout<<" ";
}
GoToXY(0,23);
}
return 0;
}
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
minitialize();
HANDLE hRecvThread;
HANDLE hSendThread;
HANDLE hHeaderThread;
DWORD dwRecvThreadId;
DWORD dwSendThreadId;
DWORD dwHeaderThreadId;
hHeaderThread = CreateThread(NULL,0,headerfunc,"1",0,&dwHeaderThreadId);
for (int mf=2; mf<25; mf++) {
std::cout<<"\n";
}
hSendThread = CreateThread(NULL,0,sendfunc,"1",0,&dwSendThreadId);
// Accept a client socket
for (int sock=1; sock<100; sock++) {
ClientSocket = accept(ListenSocket, NULL, NULL);
char sockprint[80];
char sockchar[4];
itoa(sock,sockchar,10);
strcpy(sockprint,"Client ");
strcat(sockprint,sockchar);
strcat(sockprint," connected.");
printm(sockprint);
GoToXY(0,23);
if (ClientSocket == INVALID_SOCKET) {
printm("accept failed with error: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
client[sock].cs=ClientSocket;
client[sock].con=true;
lastclient=clientnumber;
clientnumber++;
currentclient=clientnumber;
hRecvThread = CreateThread(NULL,0,recvfunc,"1",0,&dwRecvThreadId);
}
// shutdown the connection since we're done
mshutdown();
std::cin.ignore();
return 0;
}
int printm(char *inp, DWORD color) {
HANDLE hOut;
hOut = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(hOut,
color);
printm(inp);
SetConsoleTextAttribute(hOut, 0 |
FOREGROUND_RED |
FOREGROUND_GREEN |
FOREGROUND_BLUE);
return 0;
}
int printm(char *inp) {
CONSOLE_SCREEN_BUFFER_INFO SBInfo;
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleScreenBufferInfo(hOut, &SBInfo);
int xx = SBInfo.dwCursorPosition.X;
int yy = SBInfo.dwCursorPosition.Y;
GoToXY(0,22);
std::cout<<inp<<"\n";
scroll();
GoToXY(xx,yy);
return 1;
}
int msend(char msendbuf[512]) // Send a message
{
if (strncmp(msendbuf,"Server> /exit",(strlen(msendbuf))) == 0) {
mexit();
}
if (strncmp(msendbuf,"Server> /set_client",19) == 0) {
int nm=atoi(&msendbuf[20]);
currentclient=nm;
ClientSocket=client[nm].cs;
char sockchar[4];
itoa(ClientSocket,sockchar,10);
char sockprint[80];
strcpy(sockprint,"New Socket: ");
strcat(sockprint,sockchar);
printm(sockprint);
char clientprint[80];
strcpy(clientprint,"Client: ");
strcat(clientprint,&msendbuf[20]);
printm(clientprint);
}
if (strncmp(msendbuf,"Server> /list_clients",(strlen(msendbuf))) == 0) {
printm("Clients:",FOREGROUND_RED);
for (int cm=1; cm < 100; cm++) {
int cn=client[cm].cs;
if (cn>0) {
char cli[80];
char cmchar[4];
char cnchar[80];
itoa(cn,cnchar,10);
itoa(cm,cmchar,10);
strcpy(cli,cmchar);
strcat(cli," ");
strcat(cli,cnchar);
strcat(cli," ");
strcat(cli,client[cm].ip.c_str());
strcat(cli," ");
strcat(cli,client[cm].name.c_str());
printm(cli,FOREGROUND_RED);
}
else {
break;
}
}
}
if (strncmp(msendbuf,"Server> /test",(strlen(msendbuf))) == 0) {
char ipcon[500];
*ipcon=(system("ipconfig"));
}
if (strncmp(msendbuf,"Server> /help",(strlen(msendbuf))) == 0) {
printm("Type /help for help or:");
printm("/set_client [client number]");
printm("/list_clients");
}
int iResult3 = send( ClientSocket, msendbuf, 512, 0 );
if (iResult3 == SOCKET_ERROR) {
printm("send failed with error: %d\n", WSAGetLastError());
return 1;
}
}
char* mrecv(bool show) //Recieve a message
{
int iResult2 = recv(ClientSocket, recvbuf, 512, 0);
if (iResult2 > 0) {
if ((strncmp(recvbuf,"/",1)) != 0) {
printm(recvbuf);
}
if (strncmp(recvbuf,"/ip",3) == 0) {
client[clientnumber].ip=&recvbuf[4];
char prin[80];
strcpy(prin,"client[clientnumber].ip: ");
strcat(prin,client[clientnumber].ip.c_str());
printm(prin,FOREGROUND_BLUE);
}
if (strncmp(recvbuf,"/name",5) == 0) {
client[clientnumber].name=&recvbuf[6];
char prin2[80];
strcpy(prin2,"client[clientnumber].name: ");
strcat(prin2,client[clientnumber].name.c_str());
printm(prin2,FOREGROUND_GREEN | FOREGROUND_BLUE);
}
if (strncmp(recvbuf,"/alert",5) == 0) {
char *message=&recvbuf[7];
char prin2[80];
strcpy(prin2,client[clientnumber].name.c_str());
strcat(prin2,": ");
strcat(prin2, message);
printm(prin2,FOREGROUND_RED);
}
if (strncmp(recvbuf,"Client> /alert",14) == 0) {
char *message=&recvbuf[15];
char prin2[80];
strcpy(prin2,client[clientnumber].name.c_str());
strcat(prin2,": ");
strcat(prin2, message);
printm(prin2,FOREGROUND_RED);
}
}
else if (iResult2 == 0) {
printf("Connection closing...\n");
closesocket(ClientSocket);
WSACleanup();
return "1";
}
else {
printm("recv failed with error: %d\n", WSAGetLastError());
printm("Client must have disconnected. Please select a new client.");
return "1";
}
return recvbuf;
}
int minitialize() //initialize the winsock server
{
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != 0) {
printm("WSAStartup failed with error: %d\n", iResult);
return 1;
}
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;
// Resolve the server address and port
iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result);
if ( iResult != 0 ) {
printm("getaddrinfo failed with error: %d\n", iResult);
WSACleanup();
return 1;
}
// Create a SOCKET for connecting to server
ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
if (ListenSocket == INVALID_SOCKET) {
printm("socket failed with error: %ld\n", WSAGetLastError());
freeaddrinfo(result);
WSACleanup();
return 1;
}
// Setup the TCP listening socket
iResult = bind( ListenSocket, result->ai_addr, (int)result->ai_addrlen);
if (iResult == SOCKET_ERROR) {
printm("bind failed with error: %d\n", WSAGetLastError());
freeaddrinfo(result);
closesocket(ListenSocket);
WSACleanup();
return 1;
}
freeaddrinfo(result);
iResult = listen(ListenSocket, SOMAXCONN);
if (iResult == SOCKET_ERROR) {
printm("listen failed with error: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
unsigned long b=1;
ioctlsocket(ClientSocket,FIONBIO,&b);
}
int mshutdown() //shutdown the server
{
iResult = shutdown(ClientSocket, SD_SEND);
if (iResult == SOCKET_ERROR) {
printm("shutdown failed with error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
// cleanup
closesocket(ClientSocket);
WSACleanup();
return 0;
}
void GoToXY(int column, int line)
{
// Create a COORD structure and fill in its members.
// This specifies the new position of the cursor that we will set.
COORD coord;
coord.X = column;
coord.Y = line;
// Obtain a handle to the console screen buffer.
// (You're just using the standard console, so you can use STD_OUTPUT_HANDLE
// in conjunction with the GetStdHandle() to retrieve the handle.)
// Note that because it is a standard handle, we don't need to close it.
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
// Finally, call the SetConsoleCursorPosition function.
if (!SetConsoleCursorPosition(hConsole, coord))
{
// Uh-oh! The function call failed, so you need to handle the error.
// You can call GetLastError() to get a more specific error code.
// ...
return;
}
}
int scroll( void )
{
HANDLE hStdout;
CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
SMALL_RECT srctScrollRect, srctClipRect;
CHAR_INFO chiFill;
COORD coordDest;
hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
if (hStdout == INVALID_HANDLE_VALUE)
{
printf("GetStdHandle failed with %d\n", GetLastError());
return 1;
}
// Get the screen buffer size.
if (!GetConsoleScreenBufferInfo(hStdout, &csbiInfo))
{
printf("GetConsoleScreenBufferInfo failed %d\n", GetLastError());
return 1;
}
// The scrolling rectangle
srctScrollRect.Top = 1;
srctScrollRect.Bottom = 22;
srctScrollRect.Left = 0;
srctScrollRect.Right = csbiInfo.dwSize.X - 1;
// The destination for the scroll rectangle is one row up.
coordDest.X = 0;
coordDest.Y = 0;
// The clipping rectangle
srctClipRect.Top = 2;
srctClipRect.Bottom = 22;
srctClipRect.Left = 0;
srctClipRect.Right = csbiInfo.dwSize.X - 1;
// Fill the bottom row with blanks.
chiFill.Attributes = FOREGROUND_RED;
chiFill.Char.AsciiChar = (char)' ';
// Scroll up one line.
if(!ScrollConsoleScreenBuffer(
hStdout, // screen buffer handle
&srctScrollRect, // scrolling rectangle
&srctClipRect, // clipping rectangle
coordDest, // top left destination cell
&chiFill)) // fill character and color
{
printf("ScrollConsoleScreenBuffer failed %d\n", GetLastError());
return 1;
}
return 0;
}
int mexit()
{
msend("/server_closed");
mshutdown();
exit(0);
}
Turns out it was the recursive calling in my "sendfunc" thread that tripped me up.
Specifically,
if (msend(msendbuf)==1) {
"Client must have disconnected. Please select a new client.";
sendfunc("1");
}
Because I continued to call "sendfunc" from itself, it caused the stack overflow.
So, for anyone else having these problems, watch for overkill recursive function calls.
I simply removed my sending function and I was good to go.

MQSendMessage() failed with MQ_ERROR_INVALID_PARAMETER (0xC00E0006)

Problem with MSMQ configuration or code i've implemented??
I've written windows service code (win32 C++ ) in which i am sending a log to the local private queue.This code is working fine if I execute that in 32-bit environment (either windows7/8/vista). But that same code if I build for x64 OS and if I execute MQSendMessage() failed with MQ_ERROR_INVALID_PARAMETER (0xC00E0006). What could be the problem.??? Please help me out in this regard.Thanks in advance..
I've tried by changing the NUMBEROFPROPERTIES from 3-7 in x-64 windows 7 system. But still the problem remains same. what to do to avoid this..
Here is my sample code
#define ClientQueue L".\\Private$\\TestQueue"
#define LogMsgLable L"TestLOG"
#define MIN_PRIVATE_QUEUE_NAME_LENGTH 55
DWORD MSMQSendMessage()
{
//Define the required constants and variables.
const int NUMBEROFPROPERTIES = 7; // Number of properties
DWORD cPropId = 0; // Property counter
HRESULT hr = MQ_OK; // Return code
HANDLE hQueue = NULL; // Queue handle
//Define an MQMSGPROPS structure.
MQMSGPROPS msgProps;
MSGPROPID aMsgPropId[NUMBEROFPROPERTIES] = {0};
MQPROPVARIANT aMsgPropVar[NUMBEROFPROPERTIES] = {0};
HRESULT aMsgStatus[NUMBEROFPROPERTIES] = {0};
// Specify the message properties to be sent.
aMsgPropId[cPropId] = PROPID_M_LABEL; // Property ID
aMsgPropVar[cPropId].vt = VT_LPWSTR; // Type indicator
aMsgPropVar[cPropId].pwszVal = L"ADCLOG"; // The message label
cPropId++;
// Specifying the storage of messages in the harddisk
// setting the message properties as recoverable
aMsgPropId[cPropId] = PROPID_M_DELIVERY;
aMsgPropVar[cPropId].vt = VT_UI1;
aMsgPropVar[cPropId].bVal = MQMSG_DELIVERY_RECOVERABLE;
cPropId++;
aMsgPropId[cPropId] = PROPID_M_ACKNOWLEDGE; // Property ID
aMsgPropVar[cPropId].vt = VT_UI1; // Type indicator
aMsgPropVar[cPropId].bVal = MQMSG_ACKNOWLEDGMENT_FULL_RECEIVE;
cPropId++;
// we need to set the size of the message
// if we dont set it, takes 4MB as default message size
// to set the size of it we have ---> PROPID_M_BODY
ULONG ulBufferSize = 15;
char *lLog_msg = NULL;
lLog_msg = ( char*)GlobalAlloc( GPTR, 15);
ZeroMemory( lLog_msg, 15) ;
strcpy(lLog_msg, "HelloWorld");
aMsgPropId[cPropId] = PROPID_M_BODY; // Property ID
aMsgPropVar[cPropId].vt = VT_VECTOR | VT_UI1; // Type indicator
aMsgPropVar[cPropId].caub.pElems = (UCHAR *)lLog_msg; // Body buffer
aMsgPropVar[cPropId].caub.cElems = ulBufferSize; // Buffer size
cPropId++;
//here we should not put VT_NULL in type as defined with VT_UI4.........
aMsgPropId[cPropId] = PROPID_M_BODY_TYPE; // Property ID
aMsgPropVar[cPropId].vt = VT_UI4; // Type indicator
cPropId++;
// Initialize the MQMSGPROPS structure.
msgProps.cProp = cPropId;
msgProps.aPropID = aMsgPropId;
msgProps.aPropVar = aMsgPropVar;
msgProps.aStatus = aMsgStatus;
// Create a direct format name for the queue.
WCHAR *gFormatName = NULL;
DWORD dwBufferLength = 0;
dwBufferLength = MIN_PRIVATE_QUEUE_NAME_LENGTH; //Private queue format name buffer size atleast 54
gFormatName = (WCHAR *)malloc( dwBufferLength*sizeof( WCHAR ));
if (gFormatName == NULL)
{
printf( "malloc", 0, NULL );
return MQ_ERROR_INSUFFICIENT_RESOURCES;
}
SecureZeroMemory( gFormatName, dwBufferLength*sizeof(WCHAR) );
hr = MQPathNameToFormatName( ClientQueue,
gFormatName,
&dwBufferLength );
if (FAILED( hr ))
{
if( hr == MQ_ERROR_FORMATNAME_BUFFER_TOO_SMALL )
{
if (gFormatName != NULL)
{
gFormatName = (WCHAR *)realloc( gFormatName, dwBufferLength*sizeof( WCHAR ));
if (gFormatName == NULL)
{
printf( "realloc failed\n");
return MQ_ERROR_INSUFFICIENT_RESOURCES;
}
}
SecureZeroMemory( gFormatName, dwBufferLength*sizeof( WCHAR ));
hr = MQPathNameToFormatName( ClientQueue,
gFormatName,
&dwBufferLength );
if(FAILED( hr ))
{
printf( L"MQPathNameToFormatName2 failed:%x\n", hr);
return hr;
}
}
else
{
printf("MQPathNameToFormatName failed:%x\n", hr);
return hr;
}
}
// Call MQOpenQueue to open the queue with send access.
hr = MQOpenQueue(
gFormatName, // Format name of the queue
MQ_SEND_ACCESS, // Access mode
MQ_DENY_NONE, // Share mode
&hQueue // OUT: Queue handle
);
if ( FAILED( hr ))
{
printf("MQOpenQueue failed:%x\n", hr);
goto ret;
//goto cleanup;
}
if( gFormatName )
free( gFormatName );
// Call MQSendMessage to send the message to the queue.
hr = MQSendMessage(
hQueue, // Queue handle
&msgProps, // Message property structure
NULL // Not in a transaction
);
if (FAILED(hr))
{
printf( "MQSendMessage failed:%x\n", hr );
MQCloseQueue( hQueue );
goto ret;
}
//Call MQCloseQueue to close the queue.
hr = MQCloseQueue(hQueue);
if(hr != 0)
{
printf("MQCloseQueue failed:%x",hr);
//goto cleanup;
goto ret;
}ret:
if( lLog_msg )
{
GlobalFree( lLog_msg );
lLog_msg = NULL;
}
return hr;
}
Your code works on 32-bit Windows purely by chance. Take a look at this:
ULONG ulBufferSize = sizeof( 15);
char *lLog_msg = NULL;
lLog_msg = ( char*)GlobalAlloc( GPTR, sizeof( 15));
ZeroMemory( lLog_msg, sizeof( 15)) ;
strcpy(lLog_msg, "HelloWorld");
You seem to misunderstand what the sizeof operator does. It is a compile time operator that replaces its argument with the size of that argument. In this case, the compiler replaces sizeof(15) with the number 4. Why? Because a literal constant like 15 occupies 4 bytes on a 64-bit machine. So in the code above you are allocating 4 bytes of memory and then copying 11 bytes into it, thereby corrupting memory.
To fix this, simply remove sizeof. The code above should look like this:
ULONG ulBufferSize = 15;
char *lLog_msg = NULL; // this is pointless since you set it in the next line
lLog_msg = ( char*)GlobalAlloc( GPTR, ulBufferSize);
ZeroMemory( lLog_msg, ulBufferSize) ;
strcpy(lLog_msg, "HelloWorld");

UDP socket programming in windows

I developed code to receive udp packets from the port. But after calling recvfrom() nothing is happening. Following is my code and output.
#include "udpSocket.h"
int main(void)
{
SOCKET sockID;
WSADATA wsaData = {0};
FILE *udp;
char buf[512];
static int recvData;
int iResult = 0;
int sock_len = sizeof(fepAddr);
int recvResult;
int seqNo = 0;
static int outOfSeqCnt = 0;
FILE *fp = fopen("outOfSeq.txt","a");
if((udp = fopen("udpData.txt","w")) == 0)
printf("udpData.txt not opened\n");
printf("\n-------------------------------------\n");
printf("\tUDP Packet Receiver\n");
printf("-------------------------------------\n");
printf("\n Enter Destination FEP IP Address : ");
scanf_s("%s",inputData.destIPAddr,16);
printf("\n Enter Destination port from which to receive data : ");
scanf_s("%d",&inputData.portNo,5);
printf("\n Enter No.of iterations : ");
scanf_s("%d",&inputData.noIteration,2);
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if(iResult < 0)
{
printf("windows socket startup error\n");
}
sockID = socket(PF_INET, SOCK_DGRAM, 0);
if(sockID < 0)
{
printf("Socket creation error\n");
WSACleanup();
}
else
{
printf("Socket Created\n");
}
fepAddr.sin_family = AF_INET;
fepAddr.sin_port = htons(inputData.portNo);
//fepAddr.sin_addr.s_addr = inet_addr(inputData.destIPAddr);
fepAddr.sin_addr.s_addr = htonl(INADDR_ANY);
if(bind(sockID, (struct sockaddr *)&fepAddr, sizeof(struct sockaddr)) < 0)
{
printf("bind() failed: %ld.\n", WSAGetLastError());
closesocket(sockID);
return 0;
}
else
{
printf("bind() is OK!\n");
}
memset(udpBuf, 0, sizeof(udpBuf));
recvData = 1;
while (recvData)
{
printf("receiving data\n");
recvResult = recvfrom(sockID, udpBuf, sizeof(udpBuf), 0,(struct sockaddr *)&fepAddr, &sock_len);
if (recvResult <= 0) {
printf("Socket receive()-error\n");
goto exit;
}
else
printf("Sock success\n");
printf("completed rx data\n");
//puts(udpBuf);
fprintf(udp, "%s", udpBuf);
//fwrite(udpBuf, sizeof(udpBuf), 1, udp);
}
inputData.noIteration--;
if (inputData.noIteration <= 0)*/
recvData-- ;
}
exit:
if(udp)
{
fclose(udp);
udp = 0;
}
//shutdown socket
closesocket(sockID);
fclose(udp);
return 0;
}
- output::::
UDP Packet Receiver
Enter Destination FEP IP Address : 192.168.13.25
Enter Destination port from which to receive data : 2013
Enter No.of iterations :
0
Socket Created
bind() is OK!
receiving data
Well, first off your bind call should use sizeof(fepAddr) (which I assume is struct sockaddr_in) instead of sizeof(struct sockaddr) to give it a chance of actually binding to the correct address.
Second, are you sure that someone is actually sending you data? otherwise recvfrom will block by default.

Resources