ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/src/s_bsd_win32.c
Revision: 30
Committed: Sun Oct 2 20:03:27 2005 UTC (18 years, 6 months ago) by adx
Content type: text/x-csrc
File size: 12828 byte(s)
Log Message:
- imported sources
- can be moved later according to the directory/branching scheme,
  but we need the svn up

File Contents

# User Rev Content
1 adx 30 /*
2     * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3     * s_bsd_win32.c: Winsock WSAAsyncSelect() compatible network routines.
4     *
5     * Copyright (C) 2002 by the past and present ircd coders, and others.
6     *
7     * This program is free software; you can redistribute it and/or modify
8     * it under the terms of the GNU General Public License as published by
9     * the Free Software Foundation; either version 2 of the License, or
10     * (at your option) any later version.
11     *
12     * This program is distributed in the hope that it will be useful,
13     * but WITHOUT ANY WARRANTY; without even the implied warranty of
14     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15     * GNU General Public License for more details.
16     *
17     * You should have received a copy of the GNU General Public License
18     * along with this program; if not, write to the Free Software
19     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20     * USA
21     *
22     * $Id: s_bsd_win32.c,v 7.20 2005/09/18 20:49:50 adx Exp $
23     */
24    
25     #include "stdinc.h"
26     #include <iphlpapi.h>
27     #include "fdlist.h"
28     #include "ircd.h"
29     #include "s_bsd.h"
30     #include "common.h"
31     #include "client.h"
32     #include "numeric.h"
33     #include "restart.h"
34    
35     #define WM_SOCKET (WM_USER + 0)
36     #define WM_DNS (WM_USER + 1)
37     #define WM_REHASH (WM_USER + 0x100)
38     #define WM_REMOTD (WM_USER + 0x101)
39    
40     static HWND wndhandle;
41     static dlink_list dns_queries = {NULL, NULL, 0};
42     static dlink_node *setupfd_hook;
43     static DWORD (WINAPI * _GetNetworkParams) (PFIXED_INFO, PULONG) = NULL;
44    
45     extern int main(int, char *[]);
46    
47     /*
48     * Initial entry point for Win32 GUI applications, called by the C runtime.
49     *
50     * It should be only a wrapper for main(), since when compiled as a console
51     * application, main() is called instead.
52     */
53     int WINAPI
54     WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
55     LPSTR lpCmdLine, int nCmdShow)
56     {
57     /* Do we really need these pidfile, logfile etc arguments?
58     * And we are not on a console, so -help or -foreground is meaningless. */
59    
60     char *argv[2] = {"ircd", NULL};
61    
62     return main(1, argv);
63     }
64    
65     /*
66     * Handler for Win32 messages.
67     */
68     static LRESULT CALLBACK
69     hybrid_wndproc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
70     {
71     switch (uMsg)
72     {
73     case WM_SOCKET:
74     {
75     fde_t *F = lookup_fd((int) wParam);
76     PF *hdl;
77    
78     if (F != NULL && F->flags.open)
79     switch (WSAGETSELECTEVENT(lParam))
80     {
81     case FD_ACCEPT:
82     case FD_CLOSE:
83     case FD_READ:
84     if ((hdl = F->read_handler) != NULL)
85     {
86     F->read_handler = NULL;
87     hdl(F, F->read_data);
88     if (F->flags.open)
89     comm_setselect(F, 0, NULL, NULL, 0);
90     }
91     break;
92    
93     case FD_CONNECT:
94     case FD_WRITE:
95     if ((hdl = F->write_handler) != NULL)
96     {
97     F->write_handler = NULL;
98     hdl(F, F->write_data);
99     if (F->flags.open)
100     comm_setselect(F, 0, NULL, NULL, 0);
101     }
102     }
103    
104     return 0;
105     }
106    
107     case WM_DNS:
108     {
109     dlink_node *ptr;
110    
111     DLINK_FOREACH(ptr, dns_queries.head)
112     if (((struct DNSQuery *) ptr->data)->handle == wParam)
113     {
114     struct DNSQuery *query = ptr->data;
115     struct DNSReply *reply = NULL;
116    
117     dlinkDelete(&query->node, &dns_queries);
118    
119     if (WSAGETASYNCERROR(lParam) == 0)
120     {
121     struct hostent *h = (struct hostent *) &query->reply;
122     static struct DNSReply _reply;
123     reply = &_reply;
124    
125     reply->h_name = h->h_name;
126     reply->addr.ss.ss_family = h->h_addrtype;
127    
128     switch (h->h_addrtype)
129     {
130     case AF_INET:
131     memcpy(&((struct sockaddr_in *) &reply->addr)->sin_addr,
132     h->h_addr_list[0], h->h_length);
133     break;
134    
135     #ifdef IPV6
136     case AF_INET6:
137     memcpy(&((struct sockaddr_in6 *) &reply->addr)->sin6_addr,
138     h->h_addr_list[0], h->h_length);
139     break;
140     #endif
141    
142     default: /* shouldn't happen */
143     reply = NULL;
144     }
145     }
146    
147     query->callback(query->ptr, reply);
148     return 0;
149     }
150    
151     return 0;
152     }
153    
154     case WM_REHASH:
155     dorehash = 1;
156     return 0;
157    
158     case WM_REMOTD:
159     doremotd = 1;
160     return 0;
161    
162     case WM_DESTROY:
163     PostQuitMessage(0);
164     return 0;
165    
166     default:
167     return DefWindowProc(hwnd, uMsg, wParam, lParam);
168     }
169     }
170    
171     /*
172     * Associates a window message with the given socket.
173     * This will automagically switch it to nonblocking.
174     */
175     static void *
176     setup_winsock_fd(va_list args)
177     {
178     int fd = va_arg(args, int);
179    
180     WSAAsyncSelect(fd, wndhandle, WM_SOCKET, 0);
181    
182     return pass_callback(setupfd_hook, fd);
183     }
184    
185     /*
186     * Initialize Winsock, create a window handle.
187     */
188     void
189     init_netio(void)
190     {
191     WNDCLASS wndclass;
192     WSADATA wsa;
193     HMODULE lib;
194    
195     /* Initialize Winsock networking */
196     if (WSAStartup(0x101, &wsa) != 0)
197     {
198     MessageBox(NULL, "Cannot initialize Winsock -- terminating ircd",
199     NULL, MB_OK | MB_ICONERROR);
200     exit(1);
201     }
202    
203     /* First, we need a class for our window that has message handler
204     * set to hybrid_wndproc() */
205     memset(&wndclass, 0, sizeof(wndclass));
206    
207     wndclass.lpfnWndProc = hybrid_wndproc;
208     wndclass.hInstance = GetModuleHandle(NULL);
209     wndclass.lpszClassName = PACKAGE_NAME;
210    
211     RegisterClass(&wndclass);
212    
213     /* Now, initialize the window */
214     wndhandle = CreateWindow(PACKAGE_NAME, NULL, 0,
215     CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
216     NULL, NULL, wndclass.hInstance, NULL);
217    
218     if (!wndhandle)
219     {
220     MessageBox(NULL, "Cannot allocate window handle -- terminating ircd",
221     NULL, MB_OK | MB_ICONERROR);
222     exit(1);
223     }
224    
225     /* Set up a timer which will periodically post a message to our queue.
226     * This way, ircd won't wait infinitely for a network event */
227     SetTimer(wndhandle, 0, SELECT_DELAY, NULL);
228    
229     if ((lib = LoadLibrary("IPHLPAPI.DLL")) != NULL)
230     _GetNetworkParams = GetProcAddress(lib, "GetNetworkParams");
231    
232     setupfd_hook = install_hook(setup_socket_cb, setup_winsock_fd);
233     }
234    
235     /*
236     * comm_setselect
237     *
238     * This is a needed exported function which will be called to register
239     * and deregister interest in a pending IO state for a given FD.
240     */
241     void
242     comm_setselect(fde_t *F, unsigned int type, PF *handler,
243     void *client_data, time_t timeout)
244     {
245     int new_events = 0;
246    
247     if ((type & COMM_SELECT_READ))
248     {
249     F->read_handler = handler;
250     F->read_data = client_data;
251     }
252    
253     if ((type & COMM_SELECT_WRITE))
254     {
255     F->write_handler = handler;
256     F->write_data = client_data;
257     }
258    
259     new_events = (F->read_handler ? (FD_ACCEPT | FD_CLOSE | FD_READ) : 0) |
260     (F->write_handler ? (FD_CONNECT | FD_WRITE) : 0);
261    
262     if (timeout != 0)
263     F->timeout = CurrentTime + (timeout / 1000);
264    
265     if (new_events != F->evcache)
266     {
267     WSAAsyncSelect(F->fd, wndhandle, WM_SOCKET, new_events);
268     F->evcache = new_events;
269     }
270     }
271    
272     /*
273     * Waits until a message is posted in our window queue and deals with it.
274     */
275     void
276     comm_select(void)
277     {
278     MSG msg;
279    
280     if (!GetMessage(&msg, NULL, 0, 0))
281     server_die("WM_QUIT received", NO);
282    
283     set_time();
284    
285     DispatchMessage(&msg);
286     }
287    
288     /* This is our win32 super-light resolver ;) */
289    
290     void
291     delete_resolver_queries(const struct DNSQuery *query)
292     {
293     WSACancelAsyncRequest(query->handle);
294     dlinkDelete(&query->node, &dns_queries);
295     }
296    
297     void
298     gethost_byname_type(const char *name, struct DNSQuery *query, int type)
299     {
300     gethost_byname(name, query);
301     }
302    
303     void
304     gethost_byname(const char *name, struct DNSQuery *query)
305     {
306     query->handle = WSAAsyncGetHostByName(wndhandle, WM_DNS, name, query->reply,
307     sizeof(query->reply));
308    
309     if (!query->handle)
310     query->callback(query->ptr, NULL);
311     else
312     dlinkAdd(query, &query->node, &dns_queries);
313     }
314    
315     void
316     gethost_byaddr(const struct irc_ssaddr *addr, struct DNSQuery *query)
317     {
318     query->handle = WSAAsyncGetHostByAddr(
319     wndhandle, WM_DNS,
320     #ifdef IPV6
321     addr.ss.ss_family == AF_INET6 ? &((struct sockaddr_in6*)addr)->sin6_addr) :
322     #endif
323     &((struct sockaddr_in *) addr)->sin_addr,
324     #ifdef IPV6
325     addr.ss.ss_family == AF_INET6 ? sizeof(struct in6_addr) :
326     #endif
327     sizeof(struct in_addr),
328     addr->ss.ss_family, query->reply, sizeof(query->reply)
329     );
330    
331     if (!query->handle)
332     query->callback(query->ptr, NULL);
333     else
334     dlinkAdd(query, &query->node, &dns_queries);
335     }
336    
337     void
338     report_dns_servers(struct Client *source_p)
339     {
340     FIXED_INFO *FixedInfo;
341     ULONG ulOutBufLen;
342     IP_ADDR_STRING *ip;
343    
344     if (_GetNetworkParams == NULL)
345     return;
346    
347     FixedInfo = MyMalloc(sizeof(FIXED_INFO));
348     ulOutBufLen = sizeof(FIXED_INFO);
349    
350     if (_GetNetworkParams(FixedInfo, &ulOutBufLen) == ERROR_BUFFER_OVERFLOW)
351     {
352     MyFree(FixedInfo);
353     FixedInfo = MyMalloc(ulOutBufLen);
354    
355     if (_GetNetworkParams(FixedInfo, &ulOutBufLen) != ERROR_SUCCESS)
356     return;
357     }
358    
359     for (ip = &FixedInfo->DnsServerList; ip != NULL; ip = ip->Next)
360     sendto_one(source_p, form_str(RPL_STATSALINE), me.name, source_p->name,
361     ip->IpAddress.String);
362    
363     MyFree(FixedInfo);
364     }
365    
366     /* Copyright (C) 2001 Free Software Foundation, Inc.
367     *
368     * Get name and information about current kernel.
369     */
370     int
371     uname(struct utsname *uts)
372     {
373     enum { WinNT, Win95, Win98, WinUnknown };
374     OSVERSIONINFO osver;
375     SYSTEM_INFO sysinfo;
376     DWORD sLength;
377     DWORD os = WinUnknown;
378    
379     memset(uts, 0, sizeof(*uts));
380    
381     osver.dwOSVersionInfoSize = sizeof (osver);
382     GetVersionEx (&osver);
383     GetSystemInfo (&sysinfo);
384    
385     switch (osver.dwPlatformId)
386     {
387     case VER_PLATFORM_WIN32_NT: /* NT, Windows 2000 or Windows XP */
388     if (osver.dwMajorVersion == 4)
389     strcpy (uts->sysname, "Windows NT4x"); /* NT4x */
390     else if (osver.dwMajorVersion <= 3)
391     strcpy (uts->sysname, "Windows NT3x"); /* NT3x */
392     else if (osver.dwMajorVersion == 5 && osver.dwMinorVersion < 1)
393     strcpy (uts->sysname, "Windows 2000"); /* 2k */
394     else if (osver.dwMajorVersion == 5 && osver.dwMinorVersion == 2)
395     strcpy (uts->sysname, "Windows 2003"); /* 2003 */
396     else if (osver.dwMajorVersion == 5 && osver.dwMinorVersion == 1)
397     strcpy (uts->sysname, "Windows XP"); /* XP */
398     os = WinNT;
399     break;
400    
401     case VER_PLATFORM_WIN32_WINDOWS: /* Win95, Win98 or WinME */
402     if ((osver.dwMajorVersion > 4) ||
403     ((osver.dwMajorVersion == 4) && (osver.dwMinorVersion > 0)))
404     {
405     if (osver.dwMinorVersion >= 90)
406     strcpy (uts->sysname, "Windows ME"); /* ME */
407     else
408     strcpy (uts->sysname, "Windows 98"); /* 98 */
409     os = Win98;
410     }
411     else
412     {
413     strcpy (uts->sysname, "Windows 95"); /* 95 */
414     os = Win95;
415     }
416     break;
417    
418     case VER_PLATFORM_WIN32s: /* Windows 3.x */
419     strcpy (uts->sysname, "Windows");
420     break;
421     }
422    
423     sprintf (uts->version, "%ld.%02ld",
424     osver.dwMajorVersion, osver.dwMinorVersion);
425    
426     if (osver.szCSDVersion[0] != '\0' &&
427     (strlen (osver.szCSDVersion) + strlen (uts->version) + 1) <
428     sizeof (uts->version))
429     {
430     strcat (uts->version, " ");
431     strcat (uts->version, osver.szCSDVersion);
432     }
433    
434     sprintf (uts->release, "build %ld", osver.dwBuildNumber & 0xFFFF);
435    
436     switch (sysinfo.wProcessorArchitecture)
437     {
438     case PROCESSOR_ARCHITECTURE_PPC:
439     strcpy (uts->machine, "ppc");
440     break;
441     case PROCESSOR_ARCHITECTURE_ALPHA:
442     strcpy (uts->machine, "alpha");
443     break;
444     case PROCESSOR_ARCHITECTURE_MIPS:
445     strcpy (uts->machine, "mips");
446     break;
447     case PROCESSOR_ARCHITECTURE_INTEL:
448     /*
449     * dwProcessorType is only valid in Win95 and Win98 and WinME
450     * wProcessorLevel is only valid in WinNT
451     */
452     switch (os)
453     {
454     case Win95:
455     case Win98:
456     switch (sysinfo.dwProcessorType)
457     {
458     case PROCESSOR_INTEL_386:
459     case PROCESSOR_INTEL_486:
460     case PROCESSOR_INTEL_PENTIUM:
461     sprintf (uts->machine, "i%ld", sysinfo.dwProcessorType);
462     break;
463     default:
464     strcpy (uts->machine, "i386");
465     break;
466     }
467     break;
468     case WinNT:
469     switch(sysinfo.wProcessorArchitecture)
470     {
471     case PROCESSOR_ARCHITECTURE_INTEL:
472     sprintf (uts->machine, "x86(%d)", sysinfo.wProcessorLevel);
473     break;
474     case PROCESSOR_ARCHITECTURE_IA64:
475     sprintf (uts->machine, "ia64(%d)", sysinfo.wProcessorLevel);
476     break;
477     #ifdef PROCESSOR_ARCHITECTURE_AMD64
478     case PROCESSOR_ARCHITECTURE_AMD64:
479     sprintf (uts->machine, "x86_64(%d)", sysinfo.wProcessorLevel);
480     break;
481     #endif
482     default:
483     sprintf (uts->machine, "unknown(%d)", sysinfo.wProcessorLevel);
484     break;
485     }
486     break;
487     default:
488     strcpy (uts->machine, "unknown");
489     break;
490     }
491     break;
492     default:
493     strcpy (uts->machine, "unknown");
494     break;
495     }
496    
497     sLength = sizeof (uts->nodename) - 1;
498     GetComputerName (uts->nodename, &sLength);
499     return 0;
500     }

Properties

Name Value
svn:eol-style native
svn:keywords "Id Revision"