]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - win/inspircd_win32wrapper.cpp
And add colour.h to wrapper resource instead of the source.
[user/henk/code/inspircd.git] / win / inspircd_win32wrapper.cpp
1 /*       +------------------------------------+\r
2  *       | Inspire Internet Relay Chat Daemon |\r
3  *       +------------------------------------+\r
4  *\r
5  *  InspIRCd: (C) 2002-2007 InspIRCd Development Team\r
6  * See: http://www.inspircd.org/wiki/index.php/Credits\r
7  *\r
8  * This program is free but copyrighted software; see\r
9  *            the file COPYING for details.\r
10  *\r
11  * ---------------------------------------------------\r
12  */\r
13 \r
14 #include "inspircd_win32wrapper.h"\r
15 #include "inspircd.h"\r
16 #include <string>\r
17 #include <errno.h>\r
18 #include <assert.h>\r
19 using namespace std;\r
20 \r
21 #ifndef INADDR_NONE\r
22 #define INADDR_NONE 0xffffffff\r
23 #endif\r
24 \r
25 HANDLE hIPCPipe;\r
26 \r
27 int inet_aton(const char *cp, struct in_addr *addr)\r
28 {\r
29         unsigned long ip = inet_addr(cp);\r
30         addr->s_addr = ip;\r
31         return (addr->s_addr == INADDR_NONE) ? 0 : 1;\r
32 }\r
33 \r
34 const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt)\r
35 {\r
36 \r
37         if (af == AF_INET)\r
38         {\r
39                 struct sockaddr_in in;\r
40                 memset(&in, 0, sizeof(in));\r
41                 in.sin_family = AF_INET;\r
42                 memcpy(&in.sin_addr, src, sizeof(struct in_addr));\r
43                 getnameinfo((struct sockaddr *)&in, sizeof(struct sockaddr_in), dst, cnt, NULL, 0, NI_NUMERICHOST);\r
44                 return dst;\r
45         }\r
46         else if (af == AF_INET6)\r
47         {\r
48                 struct sockaddr_in6 in;\r
49                 memset(&in, 0, sizeof(in));\r
50                 in.sin6_family = AF_INET6;\r
51                 memcpy(&in.sin6_addr, src, sizeof(struct in_addr6));\r
52                 getnameinfo((struct sockaddr *)&in, sizeof(struct sockaddr_in6), dst, cnt, NULL, 0, NI_NUMERICHOST);\r
53                 return dst;\r
54         }\r
55         return NULL;\r
56 }\r
57 \r
58 int geteuid()\r
59 {\r
60         return 1;\r
61 }\r
62 \r
63 int inet_pton(int af, const char *src, void *dst)\r
64 {\r
65         sockaddr_in sa;\r
66         int len = sizeof(SOCKADDR);\r
67         int rv = WSAStringToAddress((LPSTR)src, af, NULL, (LPSOCKADDR)&sa, &len);\r
68         if(rv >= 0)\r
69         {\r
70                 if(WSAGetLastError() == 10022)                  // Invalid Argument\r
71                         rv = 0;\r
72                 else\r
73                         rv = 1;\r
74         }\r
75         memcpy(dst, &sa.sin_addr, sizeof(struct in_addr));\r
76         return rv;\r
77 }\r
78 \r
79 char * strtok_r(char *_String, const char *_Control, char **_Context)\r
80 {\r
81         unsigned char *str;\r
82         const unsigned char *ctl = (const unsigned char*)_Control;\r
83         unsigned char map[32];\r
84 \r
85         if (_Context == 0 || !_Control)\r
86                 return 0;\r
87 \r
88         if (!(_String != NULL || *_Context != NULL))\r
89                 return 0;\r
90 \r
91         memset(map, 0, 32);\r
92 \r
93         do {\r
94                 map[*ctl >> 3] |= (1 << (*ctl & 7));\r
95         } while (*ctl++);\r
96 \r
97         /* If string is NULL, set str to the saved\r
98         * pointer (i.e., continue breaking tokens out of the string\r
99         * from the last strtok call) */\r
100         if (_String != NULL)\r
101         {\r
102                 str = (unsigned char*)_String;\r
103         }\r
104         else\r
105         {\r
106                 str = (unsigned char*)*_Context;\r
107         }\r
108 \r
109         /* Find beginning of token (skip over leading delimiters). Note that\r
110         * there is no token iff this loop sets str to point to the terminal\r
111         * null (*str == 0) */\r
112         while ((map[*str >> 3] & (1 << (*str & 7))) && *str != 0)\r
113         {\r
114                 str++;\r
115         }\r
116 \r
117         _String = (char*)str;\r
118 \r
119         /* Find the end of the token. If it is not the end of the string,\r
120         * put a null there. */\r
121         for ( ; *str != 0 ; str++ )\r
122         {\r
123                 if (map[*str >> 3] & (1 << (*str & 7)))\r
124                 {\r
125                         *str++ = 0;\r
126                         break;\r
127                 }\r
128         }\r
129 \r
130         /* Update context */\r
131         *_Context = (char*)str;\r
132 \r
133         /* Determine if a token has been found. */\r
134         if (_String == (char*)str)\r
135         {\r
136                 return NULL;\r
137         }\r
138         else\r
139         {\r
140                 return _String;\r
141         }\r
142 }\r
143 \r
144 void setcolor(int color_code)\r
145 {\r
146         SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), color_code);\r
147 }\r
148 \r
149 DIR * opendir(const char * path)\r
150 {\r
151         std::string search_path = string(path) + "\\*.*";\r
152         WIN32_FIND_DATA fd;\r
153         HANDLE f = FindFirstFile(search_path.c_str(), &fd);\r
154         if (f != INVALID_HANDLE_VALUE)\r
155         {\r
156                 DIR * d = new DIR;\r
157                 memcpy(&d->find_data, &fd, sizeof(WIN32_FIND_DATA));\r
158                 d->find_handle = f;\r
159                 d->first = true;\r
160                 return d;\r
161         }\r
162         else\r
163         {\r
164                 return 0;\r
165         }\r
166 }\r
167 \r
168 dirent * readdir(DIR * handle)\r
169 {\r
170         if (handle->first)\r
171                 handle->first = false;\r
172         else\r
173         {\r
174                 if (!FindNextFile(handle->find_handle, &handle->find_data))\r
175                         return 0;\r
176         }\r
177 \r
178         strncpy(handle->dirent_pointer.d_name, handle->find_data.cFileName, MAX_PATH);\r
179         return &handle->dirent_pointer;\r
180 }\r
181 \r
182 void closedir(DIR * handle)\r
183 {\r
184         FindClose(handle->find_handle);\r
185         delete handle;\r
186 }\r
187 \r
188 const char * dlerror()\r
189 {\r
190         static char errormessage[500];\r
191         DWORD error = GetLastError();\r
192         SetLastError(0);\r
193         if (error == 0)\r
194                 return 0;\r
195 \r
196         FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)errormessage, 500, 0);\r
197         return errormessage;\r
198 }\r
199 \r
200 int arg_counter = 1;\r
201 char optarg[514];\r
202 int getopt_long_only(int ___argc, char *const *___argv, const char *__shortopts, const struct option *__longopts, int *__longind)\r
203 {\r
204         // burlex todo: handle the shortops, at the moment it only works with longopts.\r
205 \r
206         if (___argc == 1 || arg_counter == ___argc)                     // No arguments (apart from filename)\r
207                 return -1;\r
208 \r
209         const char * opt = ___argv[arg_counter];\r
210         int return_val = 0;\r
211 \r
212         // if we're not an option, return an error.\r
213         if (strnicmp(opt, "--", 2) != 0)\r
214                 return 1;\r
215         else\r
216                 opt += 2;\r
217 \r
218 \r
219         // parse argument list\r
220         int i = 0;\r
221         for (; __longopts[i].name != 0; ++i)\r
222         {\r
223                 if (!strnicmp(__longopts[i].name, opt, strlen(__longopts[i].name)))\r
224                 {\r
225                         // woot, found a valid argument =)\r
226                         char * par = 0;\r
227                         if ((arg_counter + 1) != ___argc)\r
228                         {\r
229                                 // grab the parameter from the next argument (if its not another argument)\r
230                                 if (strnicmp(___argv[arg_counter+1], "--", 2) != 0)\r
231                                 {\r
232                                         arg_counter++;          // Trash this next argument, we won't be needing it.\r
233                                         par = ___argv[arg_counter];\r
234                                 }\r
235                         }                       \r
236 \r
237                         // increment the argument for next time\r
238                         arg_counter++;\r
239 \r
240                         // determine action based on type\r
241                         if (__longopts[i].has_arg == required_argument && !par)\r
242                         {\r
243                                 // parameter missing and its a required parameter option\r
244                                 return 1;\r
245                         }\r
246 \r
247                         // store argument in optarg\r
248                         if (par)\r
249                                 strncpy(optarg, par, 514);\r
250 \r
251                         if (__longopts[i].flag != 0)\r
252                         {\r
253                                 // this is a variable, we have to set it if this argument is found.\r
254                                 *__longopts[i].flag = 1;\r
255                                 return 0;\r
256                         }\r
257                         else\r
258                         {\r
259                                 if (__longopts[i].val == -1 || par == 0)\r
260                                         return 1;\r
261                                 \r
262                                 return __longopts[i].val;\r
263                         }                       \r
264                         break;\r
265                 }\r
266         }\r
267 \r
268         // return 1 (invalid argument)\r
269         return 1;\r
270 }\r
271 \r
272 /* IPC Messages */\r
273 #define IPC_MESSAGE_REHASH      1\r
274 #define IPC_MESSAGE_DIE         2\r
275 #define IPC_MESSAGE_RESTART     3\r
276 \r
277 void InitIPC()\r
278 {\r
279         static DWORD buflen = 1024;\r
280         static const char * pipename = "\\\\.\\mailslot\\Inspircd";\r
281         hIPCPipe = CreateMailslot(pipename, buflen, 0, 0);\r
282         if (hIPCPipe == INVALID_HANDLE_VALUE)\r
283                 printf("IPC Pipe could not be created. Are you sure you didn't start InspIRCd twice?\n");\r
284 }\r
285 \r
286 void CheckIPC(InspIRCd * Instance)\r
287 {\r
288         if (hIPCPipe == INVALID_HANDLE_VALUE)\r
289                 return;\r
290 \r
291         DWORD bytes;\r
292         DWORD action;\r
293 \r
294         BOOL res = ReadFile(hIPCPipe, &action, sizeof(DWORD), &bytes, 0);\r
295         if (!res)\r
296         {\r
297                 if (GetLastError() != ERROR_SEM_TIMEOUT)\r
298                         Instance->Log(DEFAULT, "IPC Pipe Error %u: %s", GetLastError(), dlerror());\r
299                 return;\r
300         }\r
301 \r
302         switch (action)\r
303         {\r
304                 case IPC_MESSAGE_REHASH:\r
305                         InspIRCd::Rehash(0);\r
306                 break;\r
307                 \r
308                 case IPC_MESSAGE_DIE:\r
309                         InspIRCd::Exit(0);\r
310                 break;\r
311 \r
312                 case IPC_MESSAGE_RESTART:\r
313                         Instance->Restart("IPC_MESSAGE_RESTART received by mailslot.");\r
314                 break;\r
315         }\r
316 }\r
317 \r
318 void CloseIPC()\r
319 {\r
320         CloseHandle(hIPCPipe);\r
321 }\r
322 \r
323 \r
324 /* These three functions were created from looking at how ares does it\r
325  * (...and they look far tidier in C++)\r
326  */\r
327 \r
328 /* Get active nameserver */\r
329 bool GetNameServer(HKEY regkey, const char *key, char* &output)\r
330 {\r
331         DWORD size = 0;\r
332         DWORD result = RegQueryValueEx(regkey, key, 0, NULL, NULL, &size);\r
333         if (((result != ERROR_SUCCESS) && (result != ERROR_MORE_DATA)) || (!size))\r
334                 return false;\r
335 \r
336         output = new char[size+1];\r
337 \r
338         if ((RegQueryValueEx(regkey, key, 0, NULL, (LPBYTE)output, &size) != ERROR_SUCCESS) || (!*output))\r
339         {\r
340                 delete output;\r
341                 return false;\r
342         }\r
343         return true;\r
344 }\r
345 \r
346 /* Check a network interface for its nameserver */\r
347 bool GetInterface(HKEY regkey, const char *key, char* &output)\r
348 {\r
349         char buf[39];\r
350         DWORD size = 39;\r
351         int idx = 0;\r
352         HKEY top;\r
353 \r
354         while (RegEnumKeyEx(regkey, idx++, buf, &size, 0, NULL, NULL, NULL) != ERROR_NO_MORE_ITEMS)\r
355         {\r
356                 size = 39;\r
357                 if (RegOpenKeyEx(regkey, buf, 0, KEY_QUERY_VALUE, &top) != ERROR_SUCCESS)\r
358                         continue;\r
359                 int rc = GetNameServer(top, key, output);\r
360                 RegCloseKey(top);\r
361                 if (rc)\r
362                         return true;\r
363         }\r
364         return false;\r
365 }\r
366 \r
367 \r
368 std::string FindNameServerWin()\r
369 {\r
370         std::string returnval = "127.0.0.1";\r
371         HKEY top, key;\r
372         char* dns = NULL;\r
373 \r
374         /* Lets see if the correct registry hive and tree exist */\r
375         if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "System\\CurrentControlSet\\Services\\Tcpip\\Parameters", 0, KEY_READ, &top) == ERROR_SUCCESS)\r
376         {\r
377                 /* If they do, attempt to get the nameserver name */\r
378                 RegOpenKeyEx(top, "Interfaces", 0, KEY_QUERY_VALUE|KEY_ENUMERATE_SUB_KEYS, &key);\r
379                 if ((GetNameServer(top, "NameServer", dns)) || (GetNameServer(top, "DhcpNameServer", dns))\r
380                         || (GetInterface(key, "NameServer", dns)) || (GetInterface(key, "DhcpNameServer", dns)))\r
381                 {\r
382                         if (dns)\r
383                         {\r
384                                 returnval = dns;\r
385                                 delete dns;\r
386                         }\r
387                 }\r
388                 RegCloseKey(key);\r
389                 RegCloseKey(top);\r
390         }\r
391         return returnval;\r
392 }\r
393 \r
394 \r
395 void ClearConsole()\r
396 {\r
397         COORD coordScreen = { 0, 0 };    /* here's where we'll home the cursor */\r
398         HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);\r
399         DWORD cCharsWritten;\r
400         CONSOLE_SCREEN_BUFFER_INFO csbi; /* to get buffer info */ \r
401         DWORD dwConSize;                 /* number of character cells in the current buffer */ \r
402 \r
403         /* get the number of character cells in the current buffer */ \r
404 \r
405         if (GetConsoleScreenBufferInfo( hConsole, &csbi ))\r
406         {\r
407                 dwConSize = csbi.dwSize.X * csbi.dwSize.Y;\r
408                 /* fill the entire screen with blanks */ \r
409                 if (FillConsoleOutputCharacter( hConsole, (TCHAR) ' ', dwConSize, coordScreen, &cCharsWritten ))\r
410                 {\r
411                         /* get the current text attribute */ \r
412                         if (GetConsoleScreenBufferInfo( hConsole, &csbi ))\r
413                         {\r
414                                 /* now set the buffer's attributes accordingly */\r
415                                 if (FillConsoleOutputAttribute( hConsole, csbi.wAttributes, dwConSize, coordScreen, &cCharsWritten ))\r
416                                 {\r
417                                         /* put the cursor at (0, 0) */\r
418                                         SetConsoleCursorPosition( hConsole, coordScreen );\r
419                                 }\r
420                         }\r
421                 }\r
422         }\r
423         return;\r
424 }\r