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