88 * platform, we'll need to split this file and provide a separate configure
99 * test for getnameinfo().
1010 *
11+ * Windows may or may not have these routines, so we handle Windows special
12+ * by dynamically checking for their existence. If they already exist, we
13+ * use the Windows native routines, but if not, we use our own.
14+ *
1115 *
1216 * Copyright (c) 2003-2005, PostgreSQL Global Development Group
1317 *
1418 * IDENTIFICATION
15- * $PostgreSQL: pgsql/src/port/getaddrinfo.c,v 1.17 2005/07/28 04:03:14 tgl Exp $
19+ * $PostgreSQL: pgsql/src/port/getaddrinfo.c,v 1.18 2005/08/24 22:13:23 tgl Exp $
1620 *
1721 *-------------------------------------------------------------------------
1822 */
2933
3034#include "getaddrinfo.h"
3135
36+
37+ #ifdef WIN32
38+
39+ #define WIN32_LEAN_AND_MEAN
40+
41+ #include <windows.h>
42+
43+ /*
44+ * The native routines may or may not exist on the Windows platform we are on,
45+ * so we dynamically look up the routines, and call them via function pointers.
46+ * Here we need to declare what the function pointers look like
47+ */
48+ typedef int (__stdcall* getaddrinfo_ptr_t ) (const char * nodename ,
49+ const char * servname ,
50+ const struct addrinfo * hints ,
51+ struct addrinfo * * res );
52+
53+ typedef void (__stdcall* freeaddrinfo_ptr_t ) (struct addrinfo * ai );
54+
55+ typedef int (__stdcall* getnameinfo_ptr_t ) (const struct sockaddr * sa ,
56+ int salen ,
57+ char * host ,int hostlen ,
58+ char * serv ,int servlen ,
59+ int flags );
60+
61+ /* static pointers to the native routines, so we only do the lookup once. */
62+ static getaddrinfo_ptr_t getaddrinfo_ptr = NULL ;
63+ static freeaddrinfo_ptr_t freeaddrinfo_ptr = NULL ;
64+ static getnameinfo_ptr_t getnameinfo_ptr = NULL ;
65+
66+
67+ static bool
68+ haveNativeWindowsIPv6routines (void )
69+ {
70+ void * hLibrary = NULL ;
71+ static bool alreadyLookedForIpv6routines = FALSE;
72+
73+ if (alreadyLookedForIpv6routines )
74+ return (getaddrinfo_ptr != NULL );
75+
76+ /*
77+ * For Windows XP and Windows 2003 (and longhorn/vista), the IPv6
78+ * routines are present in the WinSock 2 library (ws2_32.dll).
79+ * Try that first
80+ */
81+
82+ hLibrary = LoadLibraryA ("ws2_32" );
83+
84+ if (hLibrary == NULL || GetProcAddress (hLibrary ,"getaddrinfo" )== NULL )
85+ {
86+ /*
87+ * Well, ws2_32 doesn't exist, or more likely doesn't have
88+ * getaddrinfo.
89+ */
90+ if (hLibrary != NULL )
91+ FreeLibrary (hLibrary );
92+
93+ /*
94+ * In Windows 2000, there was only the IPv6 Technology Preview look in
95+ * the IPv6 WinSock library (wship6.dll).
96+ */
97+
98+ hLibrary = LoadLibraryA ("wship6" );
99+ }
100+
101+ /* If hLibrary is null, we couldn't find a dll with functions */
102+ if (hLibrary != NULL )
103+ {
104+ /* We found a dll, so now get the addresses of the routines */
105+
106+ getaddrinfo_ptr = GetProcAddress (hLibrary ,"getaddrinfo" );
107+ freeaddrinfo_ptr = GetProcAddress (hLibrary ,"freeaddrinfo" );
108+ getnameinfo_ptr = GetProcAddress (hLibrary ,"getnameinfo" );
109+
110+ /*
111+ * If any one of the routines is missing, let's play it safe and
112+ * ignore them all
113+ */
114+ if (getaddrinfo_ptr == NULL ||
115+ freeaddrinfo_ptr == NULL ||
116+ getnameinfo_ptr == NULL )
117+ {
118+ FreeLibrary (hLibrary );
119+ hLibrary = NULL ;
120+ getaddrinfo_ptr = NULL ;
121+ freeaddrinfo_ptr = NULL ;
122+ getnameinfo_ptr = NULL ;
123+ }
124+ }
125+
126+ alreadyLookedForIpv6routines = TRUE;
127+ return (getaddrinfo_ptr != NULL );
128+ }
129+
130+ #endif
131+
132+
32133/*
33134 * get address info for ipv4 sockets.
34135 *
@@ -47,6 +148,15 @@ getaddrinfo(const char *node, const char *service,
47148* psin ;
48149struct addrinfo hints ;
49150
151+ #ifdef WIN32
152+ /*
153+ * If Windows has native IPv6 support, use the native Windows routine.
154+ * Otherwise, fall through and use our own code.
155+ */
156+ if (haveNativeWindowsIPv6routines ())
157+ return (* getaddrinfo_ptr ) (node ,service ,hintp ,res );
158+ #endif
159+
50160if (hintp == NULL )
51161{
52162memset (& hints ,0 ,sizeof (hints ));
@@ -160,6 +270,18 @@ freeaddrinfo(struct addrinfo * res)
160270{
161271if (res )
162272{
273+ #ifdef WIN32
274+ /*
275+ * If Windows has native IPv6 support, use the native Windows routine.
276+ * Otherwise, fall through and use our own code.
277+ */
278+ if (haveNativeWindowsIPv6routines ())
279+ {
280+ (* freeaddrinfo_ptr ) (node ,service ,hintp ,res );
281+ return ;
282+ }
283+ #endif
284+
163285if (res -> ai_addr )
164286free (res -> ai_addr );
165287free (res );
@@ -188,7 +310,6 @@ gai_strerror(int errcode)
188310}
189311
190312return hstrerror (hcode );
191-
192313#else /* !HAVE_HSTRERROR */
193314
194315switch (errcode )
@@ -216,6 +337,16 @@ getnameinfo(const struct sockaddr * sa, int salen,
216337char * node ,int nodelen ,
217338char * service ,int servicelen ,int flags )
218339{
340+ #ifdef WIN32
341+ /*
342+ * If Windows has native IPv6 support, use the native Windows routine.
343+ * Otherwise, fall through and use our own code.
344+ */
345+ if (haveNativeWindowsIPv6routines ())
346+ return (* getnameinfo_ptr ) (sa ,salen ,node ,nodelen ,
347+ service ,servicelen ,flags );
348+ #endif
349+
219350/* Invalid arguments. */
220351if (sa == NULL || (node == NULL && service == NULL ))
221352return EAI_FAIL ;