I recently ported a linux application I wrote that uses BSD sockets extensively to winsock. The code seems to work perfectly fine on linux, and it compiles fine on windows, however when the executable is run I get a message box with the following content:
The application was unable to start correctly (0xc0000022). Click OK to close the application.
Of course I googled around about that error and mostly was pointed to antivirus issues. I gathered that the application is having trouble reading a dll somehow, so I tried downloading a copy of winsock.dll and tossing it in the runpath of my executable, to no avail. I also ran dependency walker on the executable which gave a long list of errors. Most errors were just warnings (multiple CPU types found for example) but I did notice Error: A circular dependency was detected
which raised an eyebrow.
As I said, the code works as-is on linux. Here is my tcp.c:
#include "tcp.h"
#define BUFSIZE 2048
#if defined(_WIN32)
#include <winsock2.h>
typedef int socklen_t;
struct pollfd {
SOCKET fd;
short events;
short revents;
};
#define poll(X,Y,Z) winpoll(X,Y,Z)
#define POLLOUT 1
#define POLLIN 0
static int winpoll(struct pollfd *pfd, int ignored, int ignored2) {
fd_set rfds;
struct timeval zero = {0};
int retval;
FD_ZERO(&rfds);
FD_SET(pfd->fd, &rfds);
if (pfd->events == POLLOUT) {
retval = select(1,NULL,&rfds,NULL,&zero);
} else {
retval = select(1,&rfds,NULL,NULL,&zero);
}
if (retval < 0) {
perror("select");
}
return retval;
}
#else
#include <sys/socket.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/poll.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <netinet/ip.h>
#include <netdb.h>
#include <ifaddrs.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#define BIND(SOCK,ADDR) bind(SOCK,(struct sockaddr*)&(ADDR),sizeof(struct sockaddr_in))
#define CONN(SOCK,ADDR) connect(SOCK,(struct sockaddr*)&(ADDR),sizeof(struct sockaddr_in))
void tcp_wrapup(void)
{
#if defined(_WIN32)
WSACleanup();
#endif
}
void tcp_setup(void)
{
#if defined(_WIN32)
WSADATA wsaData;
WSAStartup(MAKEWORD(2,2),&wsaData);
#endif
}
static void set_nonblocking(int fd)
{
#if defined(_WIN32)
unsigned long mode = 1; /* non-blocking */
ioctlsocket(fd, FIONBIO, &mode);
#else
fcntl(fd,F_SETFL,fcntl(fd,F_GETFL,0)|O_NONBLOCK);
#endif
}
int tcp_server_init(unsigned short port)
{
int server_sock;
struct sockaddr_in server_addr = {0};
server_sock = socket(AF_INET, SOCK_STREAM, 0);
if (server_sock < 0) { perror("sock"); return -1; }
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(port);
if (BIND(server_sock,server_addr) < 0) { perror("bind"); return -1; }
set_nonblocking(server_sock);
if (listen(server_sock, 0) < 0) { perror("listen"); return -1; }
return server_sock;
}
int tcp_server_poll(int server_sock)
{
int client_sock;
client_sock = accept(server_sock,NULL,NULL);
if (client_sock < 0) {
return -1;
}
return client_sock;
}
int tcp_client_init(unsigned int ip, unsigned short port)
{
int client_sock;
struct sockaddr_in client_addr = {0};
client_sock = socket(AF_INET, SOCK_STREAM, 0);
if (client_sock < 0) { perror("socket"); return -1; }
client_addr.sin_family = AF_INET;
client_addr.sin_addr.s_addr = htonl(ip);
client_addr.sin_port = htons(port);
set_nonblocking(client_sock);
/* Note: WILL fail, operation in progress, non-blocking sockets wait for
* handshake. */
CONN(client_sock,client_addr);
return client_sock;
}
void tcp_send(int sock, const char *msg)
{
int status;
struct pollfd myfd;
myfd.fd = sock;
myfd.events = POLLOUT;
status = poll(&myfd,1,0);
if (status == 1) {
if (send(sock, msg, strlen(msg)+1, 0) < 0) {
perror("send");
}
}
}
int tcp_recv(int sock, char *buf, int max)
{
int status;
struct pollfd myfd;
myfd.fd = sock;
myfd.events = POLLIN;
status = poll(&myfd,1,0);
if (status == 1) {
int ret;
if ((ret = recv(sock,buf,max,0)) < 0) {
return 0;
}
return ret;
}
return 0;
}
void tcp_close(int sock)
{
#if defined(_WIN32)
closesocket(sock);
#else
if (close(sock) < 0) {
perror("close");
}
#endif
}
unsigned int tcp_str_to_ip(const char *ip)
{
#if defined(_WIN32)
int bytes[4];
sscanf(ip,"%d.%d.%d.%d",&bytes[0],&bytes[1],&bytes[2],&bytes[3]);
return ntohl(((bytes[0]<<24) & 0xFF) |
((bytes[1]<<16) & 0xFF) |
((bytes[2]<<8) & 0xFF) |
(bytes[3] & 0xFF));
#else
struct addrinfo *cursor;
struct addrinfo *server = NULL;
getaddrinfo(ip,NULL,NULL,&server);
for (cursor = server; cursor; cursor = cursor->ai_next) {
if (cursor->ai_family == AF_INET) {
struct sockaddr_in *addr = (struct sockaddr_in *)cursor->ai_addr;
return ntohl(addr->sin_addr.s_addr);
}
}
return ntohl((unsigned int)inet_addr(ip));
#endif
}
char *tcp_ip_to_str(unsigned int ip)
{
struct in_addr addr;
addr.s_addr = htonl(ip);
return inet_ntoa(addr);
}
unsigned short tcp_get_port(int sock)
{
struct sockaddr_in addr;
socklen_t len = sizeof(struct sockaddr_in);
if (getpeername(sock,(struct sockaddr *)&addr,&len) < 0) {
perror("getpeername");
return -1;
}
return ntohs(addr.sin_port);
}
unsigned int tcp_get_ip(int sock)
{
struct sockaddr_in addr;
socklen_t len = sizeof(struct sockaddr_in);
if (getpeername(sock,(struct sockaddr *)&addr,&len) < 0) {
perror("getpeername");
return -1;
}
return ntohl(addr.sin_addr.s_addr);
}
unsigned short tcp_get_local_port(int sock)
{
struct sockaddr_in addr;
socklen_t len = sizeof(struct sockaddr_in);
if (getsockname(sock,(struct sockaddr *)&addr,&len) < 0) {
perror("getsockname");
return -1;
}
return ntohs(addr.sin_port);
}
unsigned int tcp_get_local_ip(int sock)
{
struct sockaddr_in addr;
socklen_t len = sizeof(struct sockaddr_in);
if (getsockname(sock,(struct sockaddr *)&addr,&len) < 0) {
perror("getsockname");
return -1;
}
return ntohl(addr.sin_addr.s_addr);
}
My tcp.h header:
#ifndef _TCP_H
#define _TCP_H
typedef int TCP_Socket;
/* <0 means no connection, try again */
TCP_Socket tcp_server_init(unsigned short);
TCP_Socket tcp_server_poll(TCP_Socket);
TCP_Socket tcp_client_init(unsigned int, unsigned short);
void tcp_send(TCP_Socket, const char *);
int tcp_recv(TCP_Socket, char *, int); /* 0 = no data */
void tcp_close(TCP_Socket);
unsigned int tcp_str_to_ip(const char *);
char *tcp_ip_to_str(unsigned int); /* in static buf */
unsigned short tcp_get_port(TCP_Socket);
unsigned int tcp_get_ip(TCP_Socket);
unsigned short tcp_get_local_port(TCP_Socket);
unsigned int tcp_get_local_ip(TCP_Socket);
/* Windows needs wrapup code. */
void tcp_wrapup(void);
void tcp_setup(void);
#endif /* _TCP_H */
As for the command line, the windows version just adds -lwsock32
to the end of the command that the linux version uses. Any idea how to get my code working?
I tried compiling with debug mode, which still provides the same error code. I ran gdb with break main and before it could even hit the main breakpoint it crashed saying During startup program exited with code 0xc0000022
. This leads me to believe that it may be an issue outside of the code? or perhaps with the permissions of the code?
User contributions licensed under CC BY-SA 3.0