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