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