zapret2-fork/nfq2/winnative/compat.h
loop-uh 204fd66ddf
Some checks failed
build.yml / winws2 native: build the old engine winws.exe (zapret1) by the same layer (push) Failing after 0s
winws2 native: build the old engine winws.exe (zapret1) by the same layer
WN_ENGINE=winws1 ZAPRET1_SRC=<checkout of bol-van/zapret> nfq2/winnative/build.sh
signal() is mapped to the same handler table, term without a handler exits the process.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 17:40:13 +03:00

271 lines
7.7 KiB
C

// Native Windows (mingw-w64) build of winws2 without cygwin1.dll.
// This header is force-included (-include) before every source file.
// It pulls CRT headers in native mode first, then pretends to be cygwin so that
// the upstream "#ifdef __CYGWIN__" code paths are used without source changes.
#pragma once
#ifndef WINNATIVE_COMPAT_H
#define WINNATIVE_COMPAT_H
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0601
#endif
#ifdef WN_COMPAT_IMPL
#include <winsock2.h>
#include <ws2tcpip.h>
#else
#define WIN32_LEAN_AND_MEAN
// keep winsock out. unix style network headers are provided in winnative/include
#define _WINSOCKAPI_
#define _WINSOCK2API_
#endif
#define __USE_MINGW_ANSI_STDIO 1
#define _POSIX_C_SOURCE 200809L
#define _GNU_SOURCE
#include <stddef.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdbool.h>
#include <inttypes.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <time.h>
#include <wchar.h>
#include <signal.h>
#include <fcntl.h>
#include <unistd.h>
#include <getopt.h>
#include <libgen.h>
#include <io.h>
#include <direct.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <windows.h>
#define WINNATIVE 1
#ifndef WN_COMPAT_IMPL
#define __CYGWIN__ 1
#endif
// cygwin has 4096. engine buffers are sized by this
#undef PATH_MAX
#define PATH_MAX 4096
#define __BEGIN_DECLS
#define __END_DECLS
// ---- errno values missing in msvcrt
#ifndef ENOBUFS
#define ENOBUFS 105
#endif
#ifndef ESHUTDOWN
#define ESHUTDOWN 110
#endif
#ifndef EAFNOSUPPORT
#define EAFNOSUPPORT 106
#endif
#ifndef ENODEV
#define ENODEV 19
#endif
// ---- types
typedef unsigned int uid_t;
typedef unsigned int gid_t;
#ifndef WN_COMPAT_IMPL
typedef unsigned short sa_family_t;
typedef unsigned short in_port_t;
typedef uint32_t in_addr_t;
typedef int socklen_t;
typedef unsigned char u_char;
typedef unsigned short u_short;
typedef unsigned int u_int;
#endif
typedef uint8_t u_int8_t;
typedef uint16_t u_int16_t;
typedef uint32_t u_int32_t;
typedef uint64_t u_int64_t;
// ---- signals. there are no unix signals on native windows. handlers are installed but never fire
// except Ctrl-C / Ctrl-Break / console close which are mapped to SIGINT/SIGTERM in compat.c
#ifndef SIGHUP
#define SIGHUP 1
#endif
#ifndef SIGUSR1
#define SIGUSR1 30
#endif
#ifndef SIGUSR2
#define SIGUSR2 31
#endif
#ifndef SIGPIPE
#define SIGPIPE 13
#endif
typedef int sigset_t_wn;
#define sigset_t sigset_t_wn
struct siginfo_wn;
typedef struct siginfo_wn siginfo_t;
struct sigaction
{
void (*sa_handler)(int);
void (*sa_sigaction)(int, siginfo_t *, void *);
sigset_t sa_mask;
int sa_flags;
};
#define SA_RESTART 0
#define SA_SIGINFO 0
int sigaction(int sig, const struct sigaction *act, struct sigaction *oact);
// zapret1 uses signal(). same handler table as sigaction
void (*wn_signal(int sig, void (*handler)(int)))(int);
#define sigemptyset(s) (*(s)=0)
#define sigfillset(s) (*(s)=~0)
#define sigaddset(s,n) (*(s)|=1<<((n)&31))
// ---- libc functions missing in mingw
long wn_random(void);
void wn_srandom(unsigned int seed);
void *memmem(const void *haystack, size_t haystacklen, const void *needle, size_t needlelen);
char *wn_realpath(const char *path, char *resolved);
char *wn_dirname(char *path);
char *wn_basename(char *path);
int chown(const char *path, uid_t owner, gid_t group);
uid_t getuid(void);
int wn_close(int fd);
char *get_current_dir_name(void);
int wn_chdir(const char *path);
int setenv(const char *name, const char *value, int overwrite);
int unsetenv(const char *name);
time_t timegm(struct tm *tm);
char *strndup(const char *s, size_t n);
pid_t fork(void);
pid_t setsid(void);
pid_t getppid(void);
int wn_mkdir(const char *path);
#ifndef O_NONBLOCK
#define O_NONBLOCK 0
#endif
#ifndef O_NOCTTY
#define O_NOCTTY 0
#endif
#ifndef S_IRGRP
#define S_IRGRP 0
#define S_IROTH 0
#define S_IWGRP 0
#define S_IWOTH 0
#endif
// ---- utf-8 aware file api. msvcrt narrow functions use ANSI code page. all strings inside winws2 are utf-8
FILE *wn_fopen(const char *path, const char *mode);
int wn_open(const char *path, int flags, ...);
struct wn_stat
{
unsigned int st_dev;
uint64_t st_ino;
unsigned short st_mode;
short st_nlink;
uid_t st_uid;
gid_t st_gid;
int64_t st_size;
struct timespec st_atim, st_mtim, st_ctim;
};
int wn_stat(const char *path, struct wn_stat *st);
int wn_unlink(const char *path);
int wn_access(const char *path, int mode);
int wn_rename(const char *from, const char *to);
#ifndef WN_COMPAT_IMPL
#define random wn_random
#define srandom wn_srandom
#define realpath wn_realpath
#define dirname wn_dirname
#define basename wn_basename
#define close wn_close
#undef signal
#define signal wn_signal
#define chdir wn_chdir
#define mkdir(path,mode) wn_mkdir(path)
// cygwin malloc returns zeroed memory for big blocks and some code relies on it (windivert_filter emptiness check).
// native heap returns garbage. zero everything to stay on the safe side
#define malloc(size) calloc(1,(size))
#define fopen wn_fopen
#define open wn_open
#define unlink wn_unlink
#define access wn_access
#define rename wn_rename
// struct tag and function live in different namespaces. one macro renames both
#define stat wn_stat
#undef st_atime
#undef st_mtime
#undef st_ctime
#define st_atime st_atim.tv_sec
#define st_mtime st_mtim.tv_sec
#define st_ctime st_ctim.tv_sec
#ifndef S_IFLNK
#define S_IFLNK 0xA000
#endif
#ifndef S_IFSOCK
#define S_IFSOCK 0xC000
#endif
// msvcrt has no line buffering : _IOLBF means full buffering and unbuffered stream costs one syscall per character.
// stdout/stderr are kept fully buffered and flushed after every output call
int wn_printf(const char *fmt, ...) __attribute__((format(gnu_printf, 1, 2)));
int wn_fprintf(FILE *f, const char *fmt, ...) __attribute__((format(gnu_printf, 2, 3)));
int wn_vprintf(const char *fmt, va_list ap);
int wn_vfprintf(FILE *f, const char *fmt, va_list ap);
int wn_fputs(const char *s, FILE *f);
int wn_puts(const char *s);
int wn_fputc(int c, FILE *f);
size_t wn_fwrite(const void *ptr, size_t size, size_t n, FILE *f);
#undef printf
#undef fprintf
#undef vprintf
#undef vfprintf
#undef putc
#undef putchar
#define printf wn_printf
#define fprintf wn_fprintf
#define vprintf wn_vprintf
#define vfprintf wn_vfprintf
#define fputs wn_fputs
#define puts wn_puts
#define fputc wn_fputc
#define putc wn_fputc
#define putchar(c) wn_fputc(c, stdout)
#define fwrite wn_fwrite
#define setvbuf wn_setvbuf
// struct tm has no tm_zone in msvcrt. zone name of the last localtime_r/gmtime_r call is kept in compat.c
#undef localtime_r
#undef gmtime_r
#define localtime_r wn_localtime_r
#define gmtime_r wn_gmtime_r
#define tm_zone tm_sec<0 ? "" : wn_last_zone()
// append mode files (debug log, autohostlist) are opened once and kept. upstream opens and closes the file for every line
int wn_fclose(FILE *f);
#define fclose wn_fclose
// unix signals replacement. see "control" in compat.c
DWORD wn_WaitForSingleObject(HANDLE h, DWORD ms);
void wn_control_poll(void);
#define WaitForSingleObject wn_WaitForSingleObject
// batched reinjection of unmodified packets. see batch.c
#include "windivert/windivert.h"
BOOL wn_WinDivertRecvEx(HANDLE handle, VOID *pPacket, UINT packetLen, UINT *pRecvLen, UINT64 flags, WINDIVERT_ADDRESS *pAddr, UINT *pAddrLen, LPOVERLAPPED lpOverlapped);
BOOL wn_WinDivertSend(HANDLE handle, const VOID *pPacket, UINT packetLen, UINT *pSendLen, const WINDIVERT_ADDRESS *pAddr);
#define WinDivertRecvEx wn_WinDivertRecvEx
#define WinDivertSend wn_WinDivertSend
// real entry point is in compat.c. it converts utf-16 command line to utf-8 argv
#define main wn_main
#endif // !WN_COMPAT_IMPL
int wn_main(int argc, char **argv);
int wn_setvbuf(FILE *f, char *buf, int mode, size_t size);
struct tm *wn_localtime_r(const time_t *t, struct tm *tm);
struct tm *wn_gmtime_r(const time_t *t, struct tm *tm);
const char *wn_last_zone(void);
#endif