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