5ad9fc7538957bb99a70f2161549f91df3dc54e7
[oweals/gnunet.git] / src / gns / w32nsp.c
1 /*
2      This file is part of GNUnet.
3      (C) 2012 Christian Grothoff (and other contributing authors)
4
5      GNUnet is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 3, or (at your
8      option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, USA.
19 */
20 /**
21  * @file gns/w32nsp.c
22  * @brief W32 integration for GNS
23  * @author LRN
24  */
25 /* This code is partially based upon samples from the book
26  * "Network Programming For Microsoft Windows, 2Nd Edition".
27  */
28
29 #if 1
30 #  define DEBUGLOG(s, ...)
31 #endif
32 #if 0
33 #  define __printf__ printf
34 #  define DEBUGLOG(s, ...) printf (s, ##__VA_ARGS__)
35 #endif
36
37 #include <stdint.h>
38 #include <ws2tcpip.h>
39 #include <ws2spi.h>
40 #include <windows.h>
41 #include <nspapi.h>
42
43 #define WINDOWS 1
44 #define MINGW 1
45 #ifndef __BYTE_ORDER
46 #ifdef _BYTE_ORDER
47 #define __BYTE_ORDER _BYTE_ORDER
48 #else
49 #ifdef BYTE_ORDER
50 #define __BYTE_ORDER BYTE_ORDER
51 #endif
52 #endif
53 #endif
54 #ifndef __BIG_ENDIAN
55 #ifdef _BIG_ENDIAN
56 #define __BIG_ENDIAN _BIG_ENDIAN
57 #else
58 #ifdef BIG_ENDIAN
59 #define __BIG_ENDIAN BIG_ENDIAN
60 #endif
61 #endif
62 #endif
63 #ifndef __LITTLE_ENDIAN
64 #ifdef _LITTLE_ENDIAN
65 #define __LITTLE_ENDIAN _LITTLE_ENDIAN
66 #else
67 #ifdef LITTLE_ENDIAN
68 #define __LITTLE_ENDIAN LITTLE_ENDIAN
69 #endif
70 #endif
71 #endif
72 #include "w32resolver.h"
73 #define INITGUID
74 #include "gnunet_w32nsp_lib.h"
75 #undef INITGUID
76
77 #define NSPAPI_VERSION_MAJOR 4
78 #define NSPAPI_VERSION_MINOR 4
79
80 #define REPLY_LIFETIME 60*5
81
82 #define STATE_BEGIN  0x01
83 #define STATE_END    0x02
84 #define STATE_REPLY  0x04
85 #define STATE_GHBN   0x08
86
87 static CRITICAL_SECTION records_cs;
88
89 struct record
90 {
91   SOCKET s;
92   DWORD flags;
93   uint8_t state;
94   char *buf;
95   wchar_t *name;
96 };
97
98 static struct record *records = NULL;
99 static size_t records_len = 0;
100 static size_t records_size = 0;
101
102 static int
103 resize_records ()
104 {
105   size_t new_size = records_len > 0 ? records_len * 2 : 5;
106   struct record *new_records = malloc (new_size * sizeof (struct record));
107   if (new_records == NULL)
108   {
109     SetLastError (WSA_NOT_ENOUGH_MEMORY);
110     return 0;
111   }
112   memcpy (new_records, records, records_len * sizeof (struct record));
113   memset (&new_records[records_len], 0, sizeof (struct record) * (new_size - records_len));
114   records_size = new_size;
115   free (records);
116   records = new_records;
117   return 1;
118 }
119
120 static int
121 add_record (SOCKET s, const wchar_t *name, DWORD flags)
122 {
123   int res = 1;
124   int i;
125   int empty = -1;
126   //EnterCriticalSection (&records_cs);
127   for (i = 0; i < records_len; i++)
128     if (records[i].state == 0)
129       break;
130   empty = i;
131   if (i == records_len)
132   {
133     res = resize_records ();
134     if (res)
135       empty = records_len++;
136   }
137   if (res)
138   {
139     struct record r;
140     r.s = s;
141     r.flags = flags;
142     r.name = (wchar_t *) name;
143     r.state = 1;
144     r.buf = NULL;
145     if (name)
146       r.name = wcsdup (name);
147     records[empty] = r;
148   }
149   //LeaveCriticalSection (&records_cs);
150   return res;
151 }
152
153 static void
154 free_record (int i)
155 {
156   if (records[i].name)
157     free (records[i].name);
158   records[i].state = 0;
159 }
160
161 /* These are not defined by mingw.org headers at the moment*/
162 typedef INT (WSPAPI *LPNSPIOCTL) (HANDLE,DWORD,LPVOID,DWORD,LPVOID,DWORD,LPDWORD,LPWSACOMPLETION,LPWSATHREADID);
163 typedef struct _NSP_ROUTINE_XP {
164   DWORD cbSize;
165   DWORD dwMajorVersion;
166   DWORD dwMinorVersion;
167   LPNSPCLEANUP NSPCleanup;
168   LPNSPLOOKUPSERVICEBEGIN NSPLookupServiceBegin;
169   LPNSPLOOKUPSERVICENEXT NSPLookupServiceNext;
170   LPNSPLOOKUPSERVICEEND NSPLookupServiceEnd;
171   LPNSPSETSERVICE NSPSetService;
172   LPNSPINSTALLSERVICECLASS NSPInstallServiceClass;
173   LPNSPREMOVESERVICECLASS NSPRemoveServiceClass;
174   LPNSPGETSERVICECLASSINFO NSPGetServiceClassInfo;
175   LPNSPIOCTL NSPIoctl;
176 } NSP_ROUTINE_XP;
177
178 static SOCKET
179 connect_to_dns_resolver ()
180 {
181   struct sockaddr_in addr;
182   SOCKET r;
183   int ret;
184
185   r = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
186   if (INVALID_SOCKET == r)
187   {
188     SetLastError (16004);
189     return r;
190   }
191
192   addr.sin_family = AF_INET;
193   addr.sin_port = htons (5353); /* TCP 5353 is not registered; UDP 5353 is */
194   addr.sin_addr.s_addr = inet_addr ("127.0.0.1");
195
196   ret = connect (r, (struct sockaddr *) &addr, sizeof (addr));
197   if (SOCKET_ERROR == ret)
198   {
199     DWORD err = GetLastError ();
200     closesocket (r);
201     SetLastError (err);
202     SetLastError (16005);
203     r = INVALID_SOCKET;
204   }
205   return r;
206 }
207
208 static int
209 send_name_to_ip_request (LPWSAQUERYSETW lpqsRestrictions,
210     LPWSASERVICECLASSINFOW lpServiceClassInfo, DWORD dwControlFlags,
211     SOCKET *resolver)
212 {
213   struct GNUNET_W32RESOLVER_GetMessage *msg;
214   int af4 = 0;
215   int af6 = 0;
216   char *buf;
217   int ret = 1;
218   int i;
219   uint32_t id;
220   size_t size = sizeof (struct GNUNET_W32RESOLVER_GetMessage);
221   size_t namelen = 0;
222   if (lpqsRestrictions->lpszServiceInstanceName)
223     namelen = sizeof (wchar_t) * (wcslen (lpqsRestrictions->lpszServiceInstanceName) + 1);
224   size += namelen;
225   buf = malloc (size);
226   msg = (struct GNUNET_W32RESOLVER_GetMessage *) buf;
227   msg->header.size = htons (size);
228   msg->header.type = htons (GNUNET_MESSAGE_TYPE_W32RESOLVER_REQUEST);
229   if (lpqsRestrictions->dwNumberOfProtocols > 0)
230   {
231     int i;
232     for (i = 0; i < lpqsRestrictions->dwNumberOfProtocols; i++)
233     {
234       if (lpqsRestrictions->lpafpProtocols[0].iAddressFamily == AF_INET)
235         af4 = 1;
236       if (lpqsRestrictions->lpafpProtocols[0].iAddressFamily == AF_INET6)
237         af6 = 1;
238     }
239   }
240   if (af4 && !af6)
241     msg->af = htonl (AF_INET);
242   else if (af6 && !af4)
243     msg->af = htonl (AF_INET6);
244   else
245     msg->af = htonl (AF_UNSPEC);
246   if (lpqsRestrictions->lpszServiceInstanceName)
247     memcpy (&msg[1], lpqsRestrictions->lpszServiceInstanceName, namelen);
248   msg->sc_data1 = htonl (lpqsRestrictions->lpServiceClassId->Data1);
249   msg->sc_data2 = htons (lpqsRestrictions->lpServiceClassId->Data2);
250   msg->sc_data3 = htons (lpqsRestrictions->lpServiceClassId->Data3);
251   for (i = 0; i < 8; i++)
252     msg->sc_data4[i] = lpqsRestrictions->lpServiceClassId->Data4[i];
253   *resolver = connect_to_dns_resolver ();
254   if (*resolver != INVALID_SOCKET)
255   {
256     if (size != send (*resolver, buf, size, 0))
257     {
258       DWORD err = GetLastError ();
259       closesocket (*resolver);
260       *resolver = INVALID_SOCKET;
261       DEBUGLOG ("GNUNET_W32NSP_LookupServiceBegin: failed to send request: %lu\n", err);
262       SetLastError (WSATRY_AGAIN);
263       ret = 0;
264     }
265   }
266   else
267     ret = 0;
268   free (buf);
269   return ret;
270 }
271
272 static int WSPAPI
273 NSPCleanup (LPGUID lpProviderId)
274 {
275   DEBUGLOG ("NSPCleanup\n");
276   if (IsEqualGUID (lpProviderId, &GNUNET_NAMESPACE_PROVIDER_DNS))
277   {
278     return NO_ERROR;
279   }
280   SetLastError (WSAEINVALIDPROVIDER);
281   return SOCKET_ERROR;
282 }
283
284 BOOL WINAPI
285 DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
286 {
287   switch (fdwReason)
288   {
289     case DLL_PROCESS_ATTACH:
290       if (!InitializeCriticalSectionAndSpinCount (&records_cs, 0x00000400))
291       {
292         return FALSE;
293       }
294       break;
295     case DLL_THREAD_ATTACH:
296       break;
297     case DLL_THREAD_DETACH:
298       break;
299     case DLL_PROCESS_DETACH:
300       DeleteCriticalSection (&records_cs);
301       break;
302   }
303   return TRUE;
304 }
305
306
307
308
309 static int WSPAPI
310 GNUNET_W32NSP_LookupServiceBegin (LPGUID lpProviderId, LPWSAQUERYSETW lpqsRestrictions,
311     LPWSASERVICECLASSINFOW lpServiceClassInfo, DWORD dwControlFlags,
312     LPHANDLE lphLookup)
313 {
314   DEBUGLOG ("GNUNET_W32NSP_LookupServiceBegin\n");
315   if (IsEqualGUID (lpProviderId, &GNUNET_NAMESPACE_PROVIDER_DNS))
316   {
317     SOCKET s;
318     if (lpqsRestrictions->dwNameSpace != NS_DNS && lpqsRestrictions->dwNameSpace != NS_ALL)
319     {
320       DEBUGLOG ("GNUNET_W32NSP_LookupServiceBegin: wrong namespace\n");
321       SetLastError (WSANO_DATA);
322       return SOCKET_ERROR;
323     }
324     if (lpqsRestrictions->lpszServiceInstanceName != NULL)
325     {
326       wchar_t *s = lpqsRestrictions->lpszServiceInstanceName;
327       size_t len = wcslen (s);
328       if (len >= 5 && wcscmp (&s[len - 5], L".zkey") == 0)
329       {
330       }
331       else if (len >= 4 && wcscmp (&s[len - 4], L".gnu") == 0)
332       {
333       }
334       else
335       {
336         DEBUGLOG ("GNUNET_W32NSP_LookupServiceBegin: unsupported TLD\n");
337         SetLastError (WSANO_DATA);
338         return SOCKET_ERROR;
339       }
340     }
341
342     if (send_name_to_ip_request (lpqsRestrictions,
343         lpServiceClassInfo, dwControlFlags, &s))
344     {
345       if (!(add_record (s, lpqsRestrictions->lpszServiceInstanceName, dwControlFlags)))
346       {
347         DWORD err = GetLastError ();
348         DEBUGLOG ("GNUNET_W32NSP_LookupServiceBegin: failed to add a record\n");
349         closesocket (s);
350         SetLastError (err);
351         return SOCKET_ERROR;
352       }
353       *lphLookup = (HANDLE) s;
354       DEBUGLOG ("GNUNET_W32NSP_LookupServiceBegin: OK (%lu)\n", GetLastError ());
355       return NO_ERROR;
356     }
357     return SOCKET_ERROR;
358   }
359   DEBUGLOG ("GNUNET_W32NSP_LookupServiceBegin: wrong provider\n");
360   SetLastError (WSAEINVALIDPROVIDER);
361   return SOCKET_ERROR;
362 }
363
364 #define UnmarshallPtr(ptr, ptrtype, base) \
365   if (ptr) \
366     ptr = (ptrtype *) (base + (uintptr_t) ptr)
367
368 static void
369 UnmarshallWSAQUERYSETW (LPWSAQUERYSETW req)
370 {
371   int i;
372   char *base = (char *) req;
373   UnmarshallPtr (req->lpszServiceInstanceName, wchar_t, base);
374   UnmarshallPtr (req->lpServiceClassId, GUID, base);
375   UnmarshallPtr (req->lpVersion, WSAVERSION, base);
376   UnmarshallPtr (req->lpszComment, wchar_t, base);
377   UnmarshallPtr (req->lpNSProviderId, GUID, base);
378   UnmarshallPtr (req->lpszContext, wchar_t, base);
379   UnmarshallPtr (req->lpafpProtocols, AFPROTOCOLS, base);
380   UnmarshallPtr (req->lpszQueryString, wchar_t, base);
381   UnmarshallPtr (req->lpcsaBuffer, CSADDR_INFO, base);
382   for (i = 0; i < req->dwNumberOfCsAddrs; i++)
383   {
384     UnmarshallPtr (req->lpcsaBuffer[i].LocalAddr.lpSockaddr, SOCKADDR, base);
385     UnmarshallPtr (req->lpcsaBuffer[i].RemoteAddr.lpSockaddr, SOCKADDR, base);
386   }
387   UnmarshallPtr (req->lpBlob, BLOB, base);
388   if (req->lpBlob)
389     UnmarshallPtr (req->lpBlob->pBlobData, BYTE, base);
390 }
391
392 static int WSAAPI
393 GNUNET_W32NSP_LookupServiceNext (HANDLE hLookup, DWORD dwControlFlags,
394     LPDWORD lpdwBufferLength, LPWSAQUERYSETW lpqsResults)
395 {
396   DWORD effective_flags;
397   int i;
398   struct GNUNET_MessageHeader header = {0, 0};
399   int rec = -1;
400   int rc;
401   int to_receive;
402   int t;
403   char *buf;
404
405   DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext\n");
406   //EnterCriticalSection (&records_cs);
407   for (i = 0; i < records_len; i++)
408   {
409     if (records[i].s == (SOCKET) hLookup)
410     {
411       rec = i;
412       break;
413     }
414   }
415   if (rec == -1)
416   {
417     DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: invalid handle\n");
418     SetLastError (WSA_INVALID_HANDLE);
419     //LeaveCriticalSection (&records_cs);
420     return SOCKET_ERROR;
421   }
422   if (records[rec].state & 4)
423   {
424     DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: session is closed\n");
425     SetLastError (WSA_E_NO_MORE);
426     //LeaveCriticalSection (&records_cs);
427     return SOCKET_ERROR;
428   }
429   effective_flags = dwControlFlags & records[rec].flags;
430   if (records[rec].buf)
431   {
432     DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: checking buffer\n");
433     header = *((struct GNUNET_MessageHeader *) records[rec].buf);
434     if (*lpdwBufferLength < header.size - sizeof (struct GNUNET_W32RESOLVER_GetMessage))
435     {
436       DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: client buffer is too small\n");
437       SetLastError (WSAEFAULT);
438       //LeaveCriticalSection (&records_cs);
439       return SOCKET_ERROR;
440     }
441     memcpy (lpqsResults, &((struct GNUNET_W32RESOLVER_GetMessage *)records[rec].buf)[1], header.size - sizeof (struct GNUNET_W32RESOLVER_GetMessage));
442     free (records[rec].buf);
443     records[rec].buf = NULL;
444     //LeaveCriticalSection (&records_cs);
445     UnmarshallWSAQUERYSETW ((LPWSAQUERYSETW) lpqsResults);
446     DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: OK (from buffer)\n");
447     return NO_ERROR;
448   }
449   records[rec].state |= 8;
450   //LeaveCriticalSection (&records_cs);
451   to_receive = sizeof (header);
452   rc = 0;
453   {
454     unsigned long have;
455     int ior = ioctlsocket ((SOCKET) hLookup, FIONREAD, &have);
456     DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: reading %d bytes as a header from %p, %lu bytes available\n", to_receive, hLookup, have);
457   }
458   while (to_receive > 0)
459   {
460     t = recv ((SOCKET) hLookup, &((char *) &header)[rc], to_receive, 0);
461     if (t > 0)
462     {
463       rc += t;
464       to_receive -= t;
465     }
466     else
467       break;
468   }
469   {
470     unsigned long have;
471     int ior = ioctlsocket ((SOCKET) hLookup, FIONREAD, &have);
472     DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: read %d bytes as a header from %p, %lu bytes available\n", rc, hLookup, have);
473   }
474   //EnterCriticalSection (&records_cs);
475   records[rec].state &= ~8;
476   if (rc != sizeof (header))
477   {
478     if (records[rec].state & 2)
479     {
480       DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: call cancelled\n");
481       SetLastError (WSA_E_CANCELLED);
482     }
483     else
484     {
485       DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: failed to receive enough data for a header (rc %d != %u, state is 0x%0X)\n", rc, sizeof (header), records[rec].state);
486       SetLastError (WSA_E_NO_MORE);
487     }
488     records[rec].state |= 4;
489     //LeaveCriticalSection (&records_cs);
490     return SOCKET_ERROR;
491   }
492   records[rec].state &= ~8;
493   header.type = ntohs (header.type);
494   header.size = ntohs (header.size);
495   DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: header type %d, header size %u\n", header.type, header.size);
496   if (header.type != GNUNET_MESSAGE_TYPE_W32RESOLVER_RESPONSE ||
497       (header.type == GNUNET_MESSAGE_TYPE_W32RESOLVER_RESPONSE &&
498       header.size == sizeof (header)))
499   {
500     records[rec].state |= 4;
501     if (header.type != GNUNET_MESSAGE_TYPE_W32RESOLVER_RESPONSE)
502       DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: header type is wrong\n");
503     else
504       DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: empty header - no data\n");
505     //LeaveCriticalSection (&records_cs);
506     SetLastError (WSA_E_NO_MORE);
507     return SOCKET_ERROR;
508   }
509   buf = malloc (header.size);
510   if (buf == NULL)
511   {
512     records[rec].state |= 4;
513     DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: malloc() failed\n");
514     //LeaveCriticalSection (&records_cs);
515     SetLastError (WSA_E_NO_MORE);
516     return SOCKET_ERROR;
517   }
518   records[rec].state |= 8;
519   //LeaveCriticalSection (&records_cs);
520   memcpy (buf, &header, sizeof (header));
521   to_receive = header.size - sizeof (header);
522   rc = 0;
523   {
524     unsigned long have;
525     int ior = ioctlsocket ((SOCKET) hLookup, FIONREAD, &have);
526     DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: reading %d bytes as a body from %p, %lu bytes available\n", to_receive, hLookup, have);
527   }
528   while (to_receive > 0)
529   {
530     DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: recv (%d)\n", to_receive);
531     t = recv ((SOCKET) hLookup, &((char *) &((struct GNUNET_MessageHeader *) buf)[1])[rc], to_receive, 0);
532     DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: recv returned %d\n", t);
533     if (t > 0)
534     {
535       rc += t;
536       to_receive -= t;
537     }
538     else
539       break;
540   }
541   {
542     unsigned long have;
543     int ior = ioctlsocket ((SOCKET) hLookup, FIONREAD, &have);
544     DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: read %d bytes as a body from %p, %lu bytes available\n", rc, hLookup, have);
545   }
546   //EnterCriticalSection (&records_cs);
547   records[rec].state &= ~8;
548   if (rc != header.size - sizeof (header))
549   {
550     free (buf);
551     if (records[rec].state & 2)
552     {
553       DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: call cancelled\n");
554       SetLastError (WSA_E_CANCELLED);
555     }
556     else
557     {
558       DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: failed to receive enough data for the rest (rc %d != %d, state is 0x%0X)\n", rc, header.size - sizeof (header), records[rec].state);
559       SetLastError (WSA_E_NO_MORE);
560     }
561     records[rec].state |= 4;
562     //LeaveCriticalSection (&records_cs);
563     return SOCKET_ERROR;
564   }
565   if (*lpdwBufferLength < header.size - sizeof (struct GNUNET_W32RESOLVER_GetMessage))
566   {
567     DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: client buffer is too small\n");
568     SetLastError (WSAEFAULT);
569     records[rec].buf = buf;
570     //LeaveCriticalSection (&records_cs);
571     return SOCKET_ERROR;
572   }
573   //LeaveCriticalSection (&records_cs);
574   DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: writing %d bytes into result buffer\n", header.size - sizeof (struct GNUNET_W32RESOLVER_GetMessage));
575   memcpy (lpqsResults, &((struct GNUNET_W32RESOLVER_GetMessage *)buf)[1], header.size - sizeof (struct GNUNET_W32RESOLVER_GetMessage));
576   free (buf);
577   DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: OK\n");
578   UnmarshallWSAQUERYSETW ((LPWSAQUERYSETW) lpqsResults);
579   DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: returning (%lu)\n", GetLastError ());
580   return NO_ERROR;
581 }
582
583 static int WSPAPI
584 GNUNET_W32NSP_LookupServiceEnd (HANDLE hLookup)
585 {
586   DWORD effective_flags;
587   int i;
588   struct GNUNET_MessageHeader header = {0, 0};
589   int rec = -1;
590   int rc;
591   char *buf;
592
593   DEBUGLOG ("GNUNET_W32NSP_LookupServiceEnd\n");
594   //EnterCriticalSection (&records_cs);
595   for (i = 0; i < records_len; i++)
596   {
597     if (records[i].s == (SOCKET) hLookup)
598     {
599       rec = i;
600       break;
601     }
602   }
603   if (rec == -1)
604   {
605     SetLastError (WSA_INVALID_HANDLE);
606     //LeaveCriticalSection (&records_cs);
607     DEBUGLOG ("GNUNET_W32NSP_LookupServiceEnd: invalid handle\n");
608     return SOCKET_ERROR;
609   }
610   records[rec].state |= 2;
611   closesocket (records[rec].s);
612   while (records[rec].state & 8)
613   {
614     //LeaveCriticalSection (&records_cs);
615     Sleep (10);
616     //EnterCriticalSection (&records_cs);
617   }
618   if (records[rec].buf)
619     free (records[rec].buf);
620   records[rec].buf = NULL;
621   records[rec].state = 0;
622   if (records[rec].name)
623     free (records[rec].name);
624   //LeaveCriticalSection (&records_cs);
625   DEBUGLOG ("GNUNET_W32NSP_LookupServiceEnd: OK\n");
626   return NO_ERROR;
627 }
628
629 static int WSAAPI
630 GNUNET_W32NSP_SetService (LPGUID lpProviderId,
631     LPWSASERVICECLASSINFOW lpServiceClassInfo, LPWSAQUERYSETW lpqsRegInfo,
632     WSAESETSERVICEOP essOperation, DWORD dwControlFlags)
633 {
634   DEBUGLOG ("GNUNET_W32NSP_SetService\n");
635   SetLastError (WSAEOPNOTSUPP);
636   return SOCKET_ERROR;
637 }
638
639 static int WSAAPI
640 GNUNET_W32NSP_InstallServiceClass (LPGUID lpProviderId,
641     LPWSASERVICECLASSINFOW lpServiceClassInfo)
642 {
643   DEBUGLOG ("GNUNET_W32NSP_InstallServiceClass\n");
644   SetLastError (WSAEOPNOTSUPP);
645   return SOCKET_ERROR;
646 }
647
648
649 static int WSAAPI
650 GNUNET_W32NSP_RemoveServiceClass (LPGUID lpProviderId, LPGUID lpServiceClassId)
651 {
652   DEBUGLOG ("GNUNET_W32NSP_RemoveServiceClass\n");
653   SetLastError (WSAEOPNOTSUPP);
654   return SOCKET_ERROR;
655 }
656
657 static int WSAAPI
658 GNUNET_W32NSP_GetServiceClassInfo (LPGUID lpProviderId, LPDWORD lpdwBufSize,
659   LPWSASERVICECLASSINFOW lpServiceClassInfo)
660 {
661   DEBUGLOG ("GNUNET_W32NSP_GetServiceClassInfo\n");
662   SetLastError (WSAEOPNOTSUPP);
663   return SOCKET_ERROR;
664 }
665
666 static int WSAAPI
667 GNUNET_W32NSP_Ioctl (HANDLE hLookup, DWORD dwControlCode, LPVOID lpvInBuffer,
668     DWORD cbInBuffer, LPVOID lpvOutBuffer, DWORD cbOutBuffer,
669     LPDWORD lpcbBytesReturned, LPWSACOMPLETION lpCompletion,
670     LPWSATHREADID lpThreadId)
671 {
672   DEBUGLOG ("GNUNET_W32NSP_Ioctl\n");
673   SetLastError (WSAEOPNOTSUPP);
674   return SOCKET_ERROR;
675 }
676
677 /**
678  * This function is called by Winsock to hook up our provider.
679  * It is the only function that [should be/is] exported by the
680  * provider. All other routines are passed as pointers in lpnspRoutines.
681  */
682 int WSAAPI
683 GNUNET_W32NSP_NSPStartup (LPGUID lpProviderId, LPNSP_ROUTINE lpnspRoutines)
684 {
685   if (IsEqualGUID (lpProviderId, &GNUNET_NAMESPACE_PROVIDER_DNS))
686   {
687     if (!connect_to_dns_resolver ())
688     {
689       return SOCKET_ERROR;
690     }
691     /* This assumes that NSP_ROUTINE struct doesn't have a NSPIoctl member.
692      * If it does, you need to use FIELD_OFFSET() macro to get offset of NSPIoctl
693      * and use that offset as cbSize.
694      */
695     lpnspRoutines->cbSize = sizeof(NSP_ROUTINE);
696
697     lpnspRoutines->dwMajorVersion = NSPAPI_VERSION_MAJOR;
698     lpnspRoutines->dwMinorVersion = NSPAPI_VERSION_MINOR;
699     lpnspRoutines->NSPCleanup = NSPCleanup;
700     lpnspRoutines->NSPLookupServiceBegin = GNUNET_W32NSP_LookupServiceBegin;
701     lpnspRoutines->NSPLookupServiceNext = GNUNET_W32NSP_LookupServiceNext;
702     lpnspRoutines->NSPLookupServiceEnd = GNUNET_W32NSP_LookupServiceEnd;
703     lpnspRoutines->NSPSetService = GNUNET_W32NSP_SetService;
704     lpnspRoutines->NSPInstallServiceClass = GNUNET_W32NSP_InstallServiceClass;
705     lpnspRoutines->NSPRemoveServiceClass = GNUNET_W32NSP_RemoveServiceClass;
706     lpnspRoutines->NSPGetServiceClassInfo = GNUNET_W32NSP_GetServiceClassInfo;
707     /*((NSP_ROUTINE_XP *) lpnspRoutines)->NSPIoctl = GNUNET_W32NSP_Ioctl;*/
708     lpnspRoutines->NSPIoctl = GNUNET_W32NSP_Ioctl;
709     return NO_ERROR;
710   }
711   SetLastError (WSAEINVALIDPROVIDER);
712   return SOCKET_ERROR;
713 }
714