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