mswindows.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2022 The Squid Software Foundation and contributors
3  *
4  * Squid software is distributed under GPLv2+ license and includes
5  * contributions from numerous individuals and organizations.
6  * Please see the COPYING and CONTRIBUTORS files for details.
7  */
8 
9 /* Windows support
10  * Inspired by previous work by Romeo Anghelache & Eric Stern. */
11 
12 #include "squid.h"
13 
14 // The following code section is part of an EXPERIMENTAL native Windows NT/2000 Squid port.
15 // Compiles only on MS Visual C++ or MinGW
16 // CygWin appears not to need any of these
17 #if _SQUID_WINDOWS_ && !_SQUID_CYGWIN_
18 
19 #define sys_nerr _sys_nerr
20 
21 #undef assert
22 #include <cassert>
23 #include <cstring>
24 #include <fcntl.h>
25 #include <sys/timeb.h>
26 #if HAVE_WIN32_PSAPI
27 #include <psapi.h>
28 #endif
29 #ifndef _MSWSOCK_
30 #include <mswsock.h>
31 #endif
32 
33 THREADLOCAL int ws32_result;
34 LPCRITICAL_SECTION dbg_mutex = nullptr;
35 
36 void GetProcessName(pid_t, char *);
37 
38 #if HAVE_GETPAGESIZE > 1
39 size_t
40 getpagesize()
41 {
42  static DWORD system_pagesize = 0;
43  if (!system_pagesize) {
44  SYSTEM_INFO system_info;
45  GetSystemInfo(&system_info);
46  system_pagesize = system_info.dwPageSize;
47  }
48  return system_pagesize;
49 }
50 #endif /* HAVE_GETPAGESIZE > 1 */
51 
52 int
53 chroot(const char *dirname)
54 {
55  if (SetCurrentDirectory(dirname))
56  return 0;
57  else
58  return GetLastError();
59 }
60 
61 void
62 GetProcessName(pid_t pid, char *ProcessName)
63 {
64  strcpy(ProcessName, "unknown");
65 #if HAVE_WIN32_PSAPI
66  /* Get a handle to the process. */
67  HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid);
68  /* Get the process name. */
69  if (hProcess) {
70  HMODULE hMod;
71  DWORD cbNeeded;
72 
73  if (EnumProcessModules(hProcess, &hMod, sizeof(hMod), &cbNeeded))
74  GetModuleBaseName(hProcess, hMod, ProcessName, sizeof(ProcessName));
75  else {
76  CloseHandle(hProcess);
77  return;
78  }
79  } else
80  return;
81  CloseHandle(hProcess);
82 #endif /* HAVE_WIN32_PSAPI */
83 }
84 
85 int
86 kill(pid_t pid, int sig)
87 {
88  HANDLE hProcess;
89  char MyProcessName[MAX_PATH];
90  char ProcessNameToCheck[MAX_PATH];
91 
92  if (sig == 0) {
93  if (!(hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid)))
94  return -1;
95  else {
96  CloseHandle(hProcess);
97  GetProcessName(getpid(), MyProcessName);
98  GetProcessName(pid, ProcessNameToCheck);
99  if (strcmp(MyProcessName, ProcessNameToCheck) == 0)
100  return 0;
101  return -1;
102  }
103  } else
104  return 0;
105 }
106 
107 #if !HAVE_GETTIMEOFDAY
108 int
109 gettimeofday(struct timeval *pcur_time, void *tzp)
110 {
111  struct _timeb current;
112  struct timezone *tz = (struct timezone *) tzp;
113 
114  _ftime(&current);
115 
116  pcur_time->tv_sec = current.time;
117  pcur_time->tv_usec = current.millitm * 1000L;
118  if (tz) {
119  tz->tz_minuteswest = current.timezone; /* minutes west of Greenwich */
120  tz->tz_dsttime = current.dstflag; /* type of dst correction */
121  }
122  return 0;
123 }
124 #endif /* !HAVE_GETTIMEOFDAY */
125 
126 #if !_SQUID_MINGW_
127 int
128 WIN32_ftruncate(int fd, off_t size)
129 {
130  HANDLE hfile;
131  unsigned int curpos;
132 
133  if (fd < 0)
134  return -1;
135 
136  hfile = (HANDLE) _get_osfhandle(fd);
137  curpos = SetFilePointer(hfile, 0, nullptr, FILE_CURRENT);
138  if (curpos == 0xFFFFFFFF
139  || SetFilePointer(hfile, size, nullptr, FILE_BEGIN) == 0xFFFFFFFF
140  || !SetEndOfFile(hfile)) {
141  int error = GetLastError();
142 
143  switch (error) {
144  case ERROR_INVALID_HANDLE:
145  errno = EBADF;
146  break;
147  default:
148  errno = EIO;
149  break;
150  }
151 
152  return -1;
153  }
154  return 0;
155 }
156 
157 int
158 WIN32_truncate(const char *pathname, off_t length)
159 {
160  int fd;
161  int res = -1;
162 
163  fd = open(pathname, O_RDWR);
164 
165  if (fd == -1)
166  errno = EBADF;
167  else {
168  res = WIN32_ftruncate(fd, length);
169  _close(fd);
170  }
171 
172  return res;
173 }
174 #endif /* !_SQUID_MINGW_ */
175 
176 struct passwd *
177 getpwnam(char *unused) {
178  static struct passwd pwd = {nullptr, nullptr, 100, 100, nullptr, nullptr, nullptr};
179  return &pwd;
180 }
181 
182 struct group *
183 getgrnam(char *unused) {
184  static struct group grp = {nullptr, nullptr, 100, nullptr};
185  return &grp;
186 }
187 
188 #if _SQUID_MINGW_
189 int
190 _free_osfhnd(int filehandle)
191 {
192  if (((unsigned) filehandle < SQUID_MAXFD) &&
193  (_osfile(filehandle) & FOPEN) &&
194  (_osfhnd(filehandle) != (long) INVALID_HANDLE_VALUE)) {
195  switch (filehandle) {
196  case 0:
197  SetStdHandle(STD_INPUT_HANDLE, nullptr);
198  break;
199  case 1:
200  SetStdHandle(STD_OUTPUT_HANDLE, nullptr);
201  break;
202  case 2:
203  SetStdHandle(STD_ERROR_HANDLE, nullptr);
204  break;
205  }
206  _osfhnd(filehandle) = (long) INVALID_HANDLE_VALUE;
207  return (0);
208  } else {
209  errno = EBADF; /* bad handle */
210  _doserrno = 0L; /* not an OS error */
211  return -1;
212  }
213 }
214 #endif /* _SQUID_MINGW_ */
215 
216 struct errorentry {
217  unsigned long WIN32_code;
218  int POSIX_errno;
219 };
220 
221 static struct errorentry errortable[] = {
222  {ERROR_INVALID_FUNCTION, EINVAL},
223  {ERROR_FILE_NOT_FOUND, ENOENT},
224  {ERROR_PATH_NOT_FOUND, ENOENT},
225  {ERROR_TOO_MANY_OPEN_FILES, EMFILE},
226  {ERROR_ACCESS_DENIED, EACCES},
227  {ERROR_INVALID_HANDLE, EBADF},
228  {ERROR_ARENA_TRASHED, ENOMEM},
229  {ERROR_NOT_ENOUGH_MEMORY, ENOMEM},
230  {ERROR_INVALID_BLOCK, ENOMEM},
231  {ERROR_BAD_ENVIRONMENT, E2BIG},
232  {ERROR_BAD_FORMAT, ENOEXEC},
233  {ERROR_INVALID_ACCESS, EINVAL},
234  {ERROR_INVALID_DATA, EINVAL},
235  {ERROR_INVALID_DRIVE, ENOENT},
236  {ERROR_CURRENT_DIRECTORY, EACCES},
237  {ERROR_NOT_SAME_DEVICE, EXDEV},
238  {ERROR_NO_MORE_FILES, ENOENT},
239  {ERROR_LOCK_VIOLATION, EACCES},
240  {ERROR_BAD_NETPATH, ENOENT},
241  {ERROR_NETWORK_ACCESS_DENIED, EACCES},
242  {ERROR_BAD_NET_NAME, ENOENT},
243  {ERROR_FILE_EXISTS, EEXIST},
244  {ERROR_CANNOT_MAKE, EACCES},
245  {ERROR_FAIL_I24, EACCES},
246  {ERROR_INVALID_PARAMETER, EINVAL},
247  {ERROR_NO_PROC_SLOTS, EAGAIN},
248  {ERROR_DRIVE_LOCKED, EACCES},
249  {ERROR_BROKEN_PIPE, EPIPE},
250  {ERROR_DISK_FULL, ENOSPC},
251  {ERROR_INVALID_TARGET_HANDLE, EBADF},
252  {ERROR_INVALID_HANDLE, EINVAL},
253  {ERROR_WAIT_NO_CHILDREN, ECHILD},
254  {ERROR_CHILD_NOT_COMPLETE, ECHILD},
255  {ERROR_DIRECT_ACCESS_HANDLE, EBADF},
256  {ERROR_NEGATIVE_SEEK, EINVAL},
257  {ERROR_SEEK_ON_DEVICE, EACCES},
258  {ERROR_DIR_NOT_EMPTY, ENOTEMPTY},
259  {ERROR_NOT_LOCKED, EACCES},
260  {ERROR_BAD_PATHNAME, ENOENT},
261  {ERROR_MAX_THRDS_REACHED, EAGAIN},
262  {ERROR_LOCK_FAILED, EACCES},
263  {ERROR_ALREADY_EXISTS, EEXIST},
264  {ERROR_FILENAME_EXCED_RANGE, ENOENT},
265  {ERROR_NESTING_NOT_ALLOWED, EAGAIN},
266  {ERROR_NOT_ENOUGH_QUOTA, ENOMEM}
267 };
268 
269 #define MIN_EXEC_ERROR ERROR_INVALID_STARTING_CODESEG
270 #define MAX_EXEC_ERROR ERROR_INFLOOP_IN_RELOC_CHAIN
271 
272 #define MIN_EACCES_RANGE ERROR_WRITE_PROTECT
273 #define MAX_EACCES_RANGE ERROR_SHARING_BUFFER_EXCEEDED
274 
275 void
276 WIN32_maperror(unsigned long WIN32_oserrno)
277 {
278  _doserrno = WIN32_oserrno;
279  for (size_t i = 0; i < (sizeof(errortable) / sizeof(struct errorentry)); ++i) {
280  if (WIN32_oserrno == errortable[i].WIN32_code) {
281  errno = errortable[i].POSIX_errno;
282  return;
283  }
284  }
285  if (WIN32_oserrno >= MIN_EACCES_RANGE && WIN32_oserrno <= MAX_EACCES_RANGE)
286  errno = EACCES;
287  else if (WIN32_oserrno >= MIN_EXEC_ERROR && WIN32_oserrno <= MAX_EXEC_ERROR)
288  errno = ENOEXEC;
289  else
290  errno = EINVAL;
291 }
292 
293 /* syslog emulation layer derived from git */
294 static HANDLE ms_eventlog;
295 
296 void
297 openlog(const char *ident, int logopt, int facility)
298 {
299  if (ms_eventlog)
300  return;
301 
302  ms_eventlog = RegisterEventSourceA(nullptr, ident);
303 
304  // note: RegisterEventAtSourceA may fail and return nullptr.
305  // in that case we'll just retry at the next message or not log
306 }
307 #define SYSLOG_MAX_MSG_SIZE 1024
308 
309 void
310 syslog(int priority, const char *fmt, ...)
311 {
312  WORD logtype;
313  char *str=static_cast<char *>(xmalloc(SYSLOG_MAX_MSG_SIZE));
314  int str_len;
315  va_list ap;
316 
317  if (!ms_eventlog)
318  return;
319 
320  va_start(ap, fmt);
321  str_len = vsnprintf(str, SYSLOG_MAX_MSG_SIZE-1, fmt, ap);
322  va_end(ap);
323 
324  if (str_len < 0) {
325  /* vsnprintf failed */
326  return;
327  }
328 
329  switch (priority) {
330  case LOG_EMERG:
331  case LOG_ALERT:
332  case LOG_CRIT:
333  case LOG_ERR:
334  logtype = EVENTLOG_ERROR_TYPE;
335  break;
336 
337  case LOG_WARNING:
338  logtype = EVENTLOG_WARNING_TYPE;
339  break;
340 
341  case LOG_NOTICE:
342  case LOG_INFO:
343  case LOG_DEBUG:
344  default:
345  logtype = EVENTLOG_INFORMATION_TYPE;
346  break;
347  }
348 
349  //Windows API suck. They are overengineered
350  ReportEventA(ms_eventlog, logtype, 0, 0, nullptr, 1, 0,
351  const_cast<const char **>(&str), nullptr);
352 }
353 
354 /* note: this is all MSWindows-specific code; all of it should be conditional */
355 #endif /* _SQUID_WINDOWS_ */
356 
static pid_t pid
Definition: IcmpSquid.cc:34
int size
Definition: ModDevPoll.cc:75
SQUIDCEXTERN LPCRITICAL_SECTION dbg_mutex
Definition: WinSvc.cc:48
void error(char *format,...)
#define xmalloc
unsigned short WORD
Definition: smblib-priv.h:145
#define FALSE
Definition: std-includes.h:56

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors