[MSWSOCK] Rearrange the function places to avoid forward declarations and code formatting
[reactos.git] / reactos / dll / win32 / mswsock / nsplookup.c
1 #include "precomp.h"
2
3 #include <stdlib.h>
4 #include <ws2spi.h>
5 #include <nspapi.h>
6 #include <windef.h>
7 #include <winuser.h>
8 #include <windns.h>
9 #include <guiddef.h>
10 #include <svcguid.h>
11 #include <iptypes.h>
12 #include <strsafe.h>
13 #include <winreg.h>
14
15 #include "mswhelper.h"
16
17 #include <wine/debug.h>
18 WINE_DEFAULT_DEBUG_CHANNEL(mswsock);
19
20 #define NSP_CALLID_DNS 0x0001
21 #define NSP_CALLID_HOSTNAME 0x0002
22 #define NSP_CALLID_HOSTBYNAME 0x0003
23 #define NSP_CALLID_SERVICEBYNAME 0x0004
24
25 #ifndef BUFSIZ
26 #define BUFSIZ 1024
27 #endif // BUFSIZ
28 #ifndef WS2_INTERNAL_MAX_ALIAS
29 #define WS2_INTERNAL_MAX_ALIAS 512
30 #endif // WS2_INTERNAL_MAX_ALIAS
31
32 //#define NSP_REDIRECT
33
34 typedef struct {
35 WCHAR* hostnameW;
36 DWORD addr4;
37 WCHAR* servnameW;
38 WCHAR* servprotoW;
39 CHAR** servaliasesA; /* array */
40 WORD servport;
41 } WSHOSTINFOINTERN, *PWSHOSTINFOINTERN;
42
43 typedef struct {
44 GUID providerId; /* Provider-ID */
45 DWORD dwControlFlags; /* dwControlFlags (WSALookupServiceBegin) */
46 DWORD CallID; /* List for LookupServiceNext-Calls */
47 DWORD CallIDCounter; /* call-count of the current CallID. */
48 WCHAR* hostnameW; /* hostbyname */
49 #ifdef NSP_REDIRECT
50 HANDLE rdrLookup;
51 NSP_ROUTINE rdrproc;
52 #endif
53 } WSHANDLEINTERN, *PWSHANDLEINTERN;
54
55 static const GUID guid_NULL = {0};
56 static const GUID guid_HOSTNAME = SVCID_HOSTNAME;
57 static const GUID guid_INET_HOSTADDRBYINETSTRING = SVCID_INET_HOSTADDRBYINETSTRING;
58 static const GUID guid_INET_HOSTADDRBYNAME = SVCID_INET_HOSTADDRBYNAME;
59 static const GUID guid_INET_SERVICEBYNAME = SVCID_INET_SERVICEBYNAME;
60
61 /* GUIDs - maybe they should be loaded from registry? */
62 /* Namespace: 32 */
63 static const GUID guid_mswsock_TcpIp = {/*Data1:*/ 0x22059D40,
64 /*Data2:*/ 0x7E9E,
65 /*Data3:*/ 0x11CF,
66 /*Data4:*/ {0xAE, 0x5A, 0x00, 0xAA, 0x00, 0xA7, 0x11, 0x2B}};
67
68 /* {6642243A-3BA8-4AA6-BAA5-2E0BD71FDD83} */
69 /* Namespace: 15 */
70 static const GUID guid_mswsock_NLA = {/*Data1:*/ 0x6642243A,
71 /*Data2:*/ 0x3BA8,
72 /*Data3:*/ 0x4AA6,
73 /*Data4:*/ {0xBA, 0xA5, 0x2E, 0x0B, 0xD7, 0x1F, 0xDD, 0x83}};
74
75 #ifdef NSP_REDIRECT
76
77 typedef INT
78 (CALLBACK *lpRdrNSPStartup)(
79 LPGUID lpProviderId,
80 LPNSP_ROUTINE lpRout);
81
82 const rdrLib = "mswsock.dll-original";
83 lpRdrNSPStartup rdrNSPStartup;
84 HANDLE hLib;
85 NSP_ROUTINE rdrproc_tcpip;
86 NSP_ROUTINE rdrproc_nla;
87
88 #endif /* NSP_REDIRECT */
89
90 /* Implementations - Internal */
91
92 /*
93 hostnameA / hostnameW
94 * only used by HOSTBYNAME
95 * only one should be set
96
97 */
98 INT
99 NSP_LookupServiceBeginW(PWSHANDLEINTERN data,
100 CHAR* hostnameA,
101 WCHAR* hostnameW,
102 DWORD CallID)
103 {
104 HANDLE hHeap;
105
106 TRACE("NSP_LookupServiceBeginW %p %p %p %lx\n", data, hostnameA, hostnameW, CallID);
107 if (data->CallID != 0)
108 return WSAEFAULT;
109
110 data->CallID = CallID;
111
112 if ((CallID == NSP_CALLID_HOSTBYNAME) ||
113 (CallID == NSP_CALLID_SERVICEBYNAME))
114 {
115 hHeap = GetProcessHeap();
116
117 if (data->hostnameW != NULL)
118 HeapFree(hHeap, 0, data->hostnameW);
119
120 if (hostnameA != NULL)
121 {
122 data->hostnameW = StrA2WHeapAlloc(hHeap, hostnameA);
123 }
124 else
125 {
126 data->hostnameW = StrCpyHeapAllocW(hHeap, hostnameW);
127 }
128 }
129 else
130 {
131 ERR("NSP_LookupServiceBeginW unsupported CallID\n");
132 WSASetLastError(ERROR_CALL_NOT_IMPLEMENTED);
133 return ERROR_CALL_NOT_IMPLEMENTED;
134 }
135
136 return ERROR_SUCCESS;
137 }
138
139 INT
140 NSP_GetHostNameHeapAllocW(_Out_ WCHAR** hostname)
141 {
142 WCHAR* name;
143 HANDLE hHeap = GetProcessHeap();
144 DWORD bufCharLen = 0;
145
146 TRACE("NSP_GetHostNameHeapAllocW %p\n", hostname);
147 /* FIXME Use DnsGetHostName_W when available */
148 GetComputerNameExW(ComputerNameDnsHostname, NULL, &bufCharLen);
149 if (!bufCharLen)
150 {
151 ERR("NSP_GetHostNameHeapAllocW zero size for computername returned\n");
152 WSASetLastError(WSAEFAULT);
153 return SOCKET_ERROR;
154 }
155 name = HeapAlloc(hHeap, 0, bufCharLen*sizeof(WCHAR));
156 if (!GetComputerNameExW(ComputerNameDnsHostname,
157 name,
158 &bufCharLen))
159 {
160 ERR("NSP_GetHostNameHeapAllocW error obtaining computername %lx\n", GetLastError());
161 HeapFree(hHeap, 0, name);
162 WSASetLastError(WSAEFAULT);
163 return SOCKET_ERROR;
164 }
165
166 *hostname = name;
167 return ERROR_SUCCESS;
168 }
169
170 INT
171 NSP_GetHostByNameHeapAllocW(_In_ PWSHANDLEINTERN data,
172 _In_ DWORD dwControlFlags,
173 _Out_ PWSHOSTINFOINTERN hostinfo)
174 {
175 HANDLE hHeap = GetProcessHeap();
176 DNS_STATUS dns_status = { 0 };
177 /* include/WinDNS.h -- look up DNS_RECORD on MSDN */
178 PDNS_RECORDW dp;
179 PDNS_RECORDW curr;
180 INT result = ERROR_SUCCESS;
181 DWORD dwQueryFlags = DNS_QUERY_STANDARD;
182 PWCHAR Aliases[WS2_INTERNAL_MAX_ALIAS] = { 0 };
183 int AliasIndex = 0;
184
185 TRACE("NSP_GetHostByNameHeapAllocW %p %lx %p\n", data, dwControlFlags, hostinfo);
186 /* needed to be cleaned up if != NULL */
187 dp = NULL;
188
189 if (!data->hostnameW)
190 {
191 result = ERROR_INVALID_PARAMETER;
192 goto cleanup;
193 }
194
195 if ((data->dwControlFlags & LUP_DEEP) == 0)
196 {
197 TRACE("NSP_GetHostByNameHeapAllocW LUP_DEEP is not specified. Disabling recursion\n");
198 dwQueryFlags |= DNS_QUERY_NO_RECURSION;
199 }
200
201 /* DNS_TYPE_A: include/WinDNS.h */
202 /* DnsQuery -- lib/dnsapi/dnsapi/query.c */
203 dns_status = DnsQuery_W(data->hostnameW,
204 DNS_TYPE_A,
205 dwQueryFlags,
206 NULL /* extra dns servers */,
207 &dp,
208 NULL);
209 if (dns_status == ERROR_INVALID_NAME)
210 {
211 ERR("NSP_GetHostByNameHeapAllocW invalid name\n");
212 WSASetLastError(WSAEFAULT);
213 result = ERROR_INVALID_PARAMETER;
214 goto cleanup;
215 }
216
217 if ((dns_status != 0) || (dp == NULL))
218 {
219 ERR("NSP_GetHostByNameHeapAllocW not found %lx %p\n", dns_status, dp);
220 result = WSAHOST_NOT_FOUND;
221 goto cleanup;
222 }
223
224 //ASSERT(dp->wType == DNS_TYPE_A);
225 //ASSERT(dp->wDataLength == sizeof(DNS_A_DATA));
226 curr = dp;
227 while ((curr->pNext != NULL) || (curr->wType != DNS_TYPE_A))
228 {
229 if (curr->wType == DNS_TYPE_CNAME)
230 {
231 TRACE("NSP_GetHostByNameHeapAllocW found alias %ws\n", curr->Data.Cname.pNameHost);
232 Aliases[AliasIndex++] = curr->Data.Cname.pNameHost;
233 }
234 curr = curr->pNext;
235 }
236
237 if (curr->wType != DNS_TYPE_A)
238 {
239 ERR("NSP_GetHostByNameHeapAllocW last record is not of type A %d\n", curr->wType);
240 result = WSASERVICE_NOT_FOUND;
241 goto cleanup;
242 }
243 hostinfo->hostnameW = StrCpyHeapAllocW(hHeap, curr->pName);
244 hostinfo->addr4 = curr->Data.A.IpAddress;
245 if (AliasIndex)
246 {
247 hostinfo->servaliasesA = StrAryCpyHeapAllocWToA(hHeap, (WCHAR**)&Aliases);
248 }
249 result = ERROR_SUCCESS;
250
251 cleanup:
252 if (dp != NULL)
253 DnsRecordListFree(dp, DnsFreeRecordList);
254
255 return result;
256 }
257
258 #define SKIPWS(ptr, act) \
259 {while(*ptr && isspace(*ptr)) ptr++; if(!*ptr) act;}
260
261 #define SKIPANDMARKSTR(ptr, act) \
262 {while(*ptr && !isspace(*ptr)) ptr++; \
263 if(!*ptr) {act;} else { *ptr = 0; ptr++; }}
264
265 static
266 BOOL
267 DecodeServEntFromString(IN PCHAR ServiceString,
268 OUT PCHAR *ServiceName,
269 OUT PCHAR *PortNumberStr,
270 OUT PCHAR *ProtocolStr,
271 IN PCHAR *Aliases,
272 IN DWORD MaxAlias)
273 {
274 UINT NAliases = 0;
275
276 //WS_DbgPrint(MAX_TRACE, ("Parsing service ent [%s]\n", ServiceString));
277
278 SKIPWS(ServiceString, return FALSE);
279 *ServiceName = ServiceString;
280 SKIPANDMARKSTR(ServiceString, return FALSE);
281 SKIPWS(ServiceString, return FALSE);
282 *PortNumberStr = ServiceString;
283 SKIPANDMARKSTR(ServiceString, ;);
284
285 while (*ServiceString && NAliases < MaxAlias - 1)
286 {
287 SKIPWS(ServiceString, break);
288 if (*ServiceString)
289 {
290 SKIPWS(ServiceString, ;);
291 if (strlen(ServiceString))
292 {
293 //WS_DbgPrint(MAX_TRACE, ("Alias: %s\n", ServiceString));
294 *Aliases++ = ServiceString;
295 NAliases++;
296 }
297 SKIPANDMARKSTR(ServiceString, ;);
298 }
299 }
300 *Aliases = NULL;
301
302 *ProtocolStr = strchr(*PortNumberStr, '/');
303
304 if (!*ProtocolStr)
305 return FALSE;
306
307 **ProtocolStr = 0;
308 (*ProtocolStr)++;
309
310 //WS_DbgPrint(MAX_TRACE, ("Parsing done: %s %s %s %d\n",
311 // *ServiceName, *ProtocolStr, *PortNumberStr,
312 // NAliases));
313
314 return TRUE;
315 }
316
317 HANDLE
318 WSAAPI
319 OpenNetworkDatabase(_In_ LPCWSTR Name)
320 {
321 PWSTR ExpandedPath;
322 PWSTR DatabasePath;
323 INT ErrorCode;
324 HKEY DatabaseKey;
325 DWORD RegType;
326 DWORD RegSize = 0;
327 size_t StringLength;
328 HANDLE Handle;
329
330 TRACE("OpenNetworkDatabase %p\n", Name);
331 ExpandedPath = HeapAlloc(GetProcessHeap(), 0, MAX_PATH*sizeof(WCHAR));
332 if (!ExpandedPath)
333 return INVALID_HANDLE_VALUE;
334
335 /* Open the database path key */
336 ErrorCode = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
337 L"System\\CurrentControlSet\\Services\\Tcpip\\Parameters",
338 0,
339 KEY_READ,
340 &DatabaseKey);
341 if (ErrorCode == NO_ERROR)
342 {
343 TRACE("OpenNetworkDatabase registry key for network database exist\n");
344 /* Read the actual path */
345 ErrorCode = RegQueryValueEx(DatabaseKey,
346 L"DatabasePath",
347 NULL,
348 &RegType,
349 NULL,
350 &RegSize);
351
352 if (!RegSize)
353 {
354 ERR("OpenNetworkDatabase RegQueryValueEx failed to return size for DatabasePath %lx\n", ErrorCode);
355 RegCloseKey(DatabaseKey);
356 HeapFree(GetProcessHeap(), 0, ExpandedPath);
357 return INVALID_HANDLE_VALUE;
358 }
359 DatabasePath = HeapAlloc(GetProcessHeap(), 0, RegSize);
360 if (!DatabasePath)
361 {
362 ERR("OpenNetworkDatabase could not allocate %d for DatabasePath\n", RegSize);
363 RegCloseKey(DatabaseKey);
364 HeapFree(GetProcessHeap(), 0, ExpandedPath);
365 return INVALID_HANDLE_VALUE;
366 }
367
368 /* Read the actual path */
369 ErrorCode = RegQueryValueEx(DatabaseKey,
370 L"DatabasePath",
371 NULL,
372 &RegType,
373 (LPBYTE)DatabasePath,
374 &RegSize);
375
376 /* Close the key */
377 RegCloseKey(DatabaseKey);
378
379 if (ErrorCode)
380 {
381 ERR("OpenNetworkDatabase RegQueryValueEx failed to return value for DatabasePath %lx\n", ErrorCode);
382 HeapFree(GetProcessHeap(), 0, DatabasePath);
383 HeapFree(GetProcessHeap(), 0, ExpandedPath);
384 return INVALID_HANDLE_VALUE;
385 }
386
387 /* Expand the name */
388 ExpandEnvironmentStrings(DatabasePath, ExpandedPath, MAX_PATH);
389
390 HeapFree(GetProcessHeap(), 0, DatabasePath);
391 }
392 else
393 {
394 TRACE("OpenNetworkDatabase registry key for network database doesn't exist\n");
395 /* Use defalt path */
396 GetSystemDirectory(ExpandedPath, MAX_PATH);
397 StringCchLength(ExpandedPath, MAX_PATH, &StringLength);
398 if (ExpandedPath[StringLength - 1] != L'\\')
399 {
400 /* It isn't, so add it ourselves */
401 StringCchCat(ExpandedPath, MAX_PATH, L"\\");
402 }
403 StringCchCat(ExpandedPath, MAX_PATH, L"DRIVERS\\ETC\\");
404 }
405
406 /* Make sure that the path is backslash-terminated */
407 StringCchLength(ExpandedPath, MAX_PATH, &StringLength);
408 if (ExpandedPath[StringLength - 1] != L'\\')
409 {
410 /* It isn't, so add it ourselves */
411 StringCchCat(ExpandedPath, MAX_PATH, L"\\");
412 }
413
414 /* Add the database name */
415 StringCchCat(ExpandedPath, MAX_PATH, Name);
416
417 /* Return a handle to the file */
418 Handle = CreateFile(ExpandedPath,
419 FILE_READ_DATA,
420 FILE_SHARE_READ,
421 NULL,
422 OPEN_EXISTING,
423 FILE_ATTRIBUTE_NORMAL,
424 NULL);
425
426 HeapFree(GetProcessHeap(), 0, ExpandedPath);
427 return Handle;
428 }
429
430 INT
431 NSP_GetServiceByNameHeapAllocW(_In_ PWSHANDLEINTERN data,
432 _In_ DWORD dwControlFlags,
433 _Out_ PWSHOSTINFOINTERN hostinfo)
434 {
435 BOOL Found = FALSE;
436 HANDLE ServicesFile;
437 CHAR ServiceDBData[BUFSIZ * sizeof(WCHAR)] = { 0 };
438 PCHAR ThisLine = 0, NextLine = 0, ServiceName = 0, PortNumberStr = 0,
439 ProtocolStr = 0, Comment = 0, EndValid;
440 PCHAR Aliases[WS2_INTERNAL_MAX_ALIAS] = { 0 };
441 PCHAR* AliasPtr;
442 UINT i = 0;
443 DWORD ReadSize = 0;
444 HANDLE hHeap;
445 PCHAR nameA = NULL;
446 PCHAR nameServiceA = NULL;
447 PCHAR nameProtoA = NULL;
448 INT res = WSANO_RECOVERY;
449
450 TRACE("NSP_GetServiceByNameHeapAllocW %p %lx %p\n", data, dwControlFlags, hostinfo);
451 if (!data->hostnameW)
452 {
453 ERR("NSP_GetServiceByNameHeapAllocW service name not provided\n");
454 res = WSANO_RECOVERY;
455 goto End;
456 }
457
458 hHeap = GetProcessHeap();
459 nameA = StrW2AHeapAlloc(hHeap, data->hostnameW);
460
461 /* nameA has the form <service-name>/<protocol>
462 we split these now */
463 nameProtoA = strchr(nameA, '/');
464 if (nameProtoA == NULL)
465 {
466 ERR("NSP_GetServiceByNameHeapAllocW invalid service name %s\n", nameA);
467 res = WSANO_RECOVERY;
468 goto End;
469 }
470
471 nameProtoA++;
472 i = (DWORD)(nameProtoA - nameA - 1);
473 nameServiceA = (PCHAR)HeapAlloc(hHeap, 0, i + 1);
474 StringCbCopyA(nameServiceA, i + 1, nameA);
475 nameServiceA[i] = '\0';
476
477 ServicesFile = OpenNetworkDatabase(L"services");
478 if (ServicesFile == INVALID_HANDLE_VALUE)
479 {
480 ERR("NSP_GetServiceByNameHeapAllocW unable to open services file\n");
481 return WSANO_RECOVERY;
482 }
483
484 /* Scan the services file ...
485 *
486 * We will be share the buffer on the lines. If the line does not fit in
487 * the buffer, then moving it to the beginning of the buffer and read
488 * the remnants of line from file.
489 */
490
491 /* Initial Read */
492 if (!ReadFile(ServicesFile,
493 ServiceDBData,
494 sizeof( ServiceDBData ) - 1,
495 &ReadSize,
496 NULL))
497 {
498 ERR("NSP_GetServiceByNameHeapAllocW can't read services file %lx\n", GetLastError());
499 CloseHandle(ServicesFile);
500 return WSANO_RECOVERY;
501 }
502
503 ThisLine = NextLine = ServiceDBData;
504 EndValid = ServiceDBData + ReadSize;
505 ServiceDBData[sizeof(ServiceDBData) - 1] = '\0';
506
507 while (ReadSize)
508 {
509 for (; *NextLine != '\r' && *NextLine != '\n'; NextLine++)
510 {
511 if (NextLine == EndValid)
512 {
513 int LineLen = NextLine - ThisLine;
514
515 if (ThisLine == ServiceDBData)
516 {
517 ERR("NSP_GetServiceByNameHeapAllocW line too long\n");
518 CloseHandle(ServicesFile);
519 return WSANO_RECOVERY;
520 }
521
522 memmove(ServiceDBData, ThisLine, LineLen);
523
524 if (!ReadFile(ServicesFile,
525 ServiceDBData + LineLen,
526 sizeof( ServiceDBData )-1 - LineLen,
527 &ReadSize,
528 NULL))
529 {
530 break;
531 }
532
533 EndValid = ServiceDBData + LineLen + ReadSize;
534 NextLine = ServiceDBData + LineLen;
535 ThisLine = ServiceDBData;
536
537 if (!ReadSize) break;
538 }
539 }
540
541 *NextLine = '\0';
542 Comment = strchr(ThisLine, '#');
543
544 if (Comment)
545 *Comment = '\0'; /* Terminate at comment start */
546
547 if (DecodeServEntFromString(ThisLine,
548 &ServiceName,
549 &PortNumberStr,
550 &ProtocolStr,
551 Aliases,
552 WS2_INTERNAL_MAX_ALIAS) &&
553 (strlen(nameProtoA) == 0 || strcmp(ProtocolStr, nameProtoA) == 0))
554 {
555 Found = (strcmp(ServiceName, nameServiceA) == 0 || strcmp(PortNumberStr, nameServiceA) == 0);
556 AliasPtr = Aliases;
557 while ((!Found) && (*AliasPtr != NULL))
558 {
559 Found = (strcmp(*AliasPtr, nameServiceA) == 0);
560 AliasPtr++;
561 }
562 if (Found)
563 break;
564 }
565 NextLine++;
566 ThisLine = NextLine;
567 }
568
569 /* This we'll do no matter what */
570 CloseHandle(ServicesFile);
571
572 if (!Found)
573 {
574 ERR("NSP_GetServiceByNameHeapAllocW service not found\n");
575 return WSANO_DATA;
576 }
577
578 hostinfo->addr4 = 0;
579 hostinfo->servnameW = StrA2WHeapAlloc(hHeap, ServiceName);
580 hostinfo->servprotoW = StrA2WHeapAlloc(hHeap, ProtocolStr);
581 hostinfo->servaliasesA = StrAryCpyHeapAllocA(hHeap, (char**)&Aliases);
582 hostinfo->servport = atoi(PortNumberStr);
583
584 res = NO_ERROR;
585
586 End:
587 if (nameA)
588 HeapFree(hHeap, 0, nameA);
589
590 if (nameServiceA)
591 HeapFree(hHeap, 0, nameServiceA);
592
593 return res;
594 }
595
596 INT
597 NSP_LookupServiceNextW(_In_ PWSHANDLEINTERN data,
598 _In_ DWORD dwControlFlags,
599 _Inout_ LPWSAQUERYSETW lpRes,
600 _Inout_ LPDWORD lpResLen)
601 {
602 MSW_BUFFER buf;
603 WSHOSTINFOINTERN hostinfo;
604 INT result;
605 HANDLE hHeap = GetProcessHeap();
606 WCHAR* ServiceInstanceNameW = NULL;
607 /* cleanup-vars */
608 CHAR* ServiceInstanceNameA = NULL;
609 CHAR* ServiceProtocolNameA = NULL;
610
611 TRACE("NSP_LookupServiceNextW %p %lx %p %p\n", data, dwControlFlags, lpRes, lpResLen);
612 if (!data || (dwControlFlags & (~(DWORD)LUP_FLUSHPREVIOUS)) != 0 || !lpRes || !lpResLen || *lpResLen == 0)
613 return WSAEINVAL;
614 RtlZeroMemory(&hostinfo, sizeof(hostinfo));
615
616 /* init and build result-buffer */
617 mswBufferInit(&buf, (BYTE*)lpRes, *lpResLen);
618 mswBufferIncUsed(&buf, sizeof(*lpRes));
619
620 /* QueryDataSet-Size without "blob-data"-size! */
621 lpRes->dwSize = sizeof(*lpRes);
622 lpRes->dwNameSpace = NS_DNS;
623
624 if ((data->CallID == NSP_CALLID_HOSTNAME) ||
625 (data->CallID == NSP_CALLID_HOSTBYNAME) ||
626 (data->CallID == NSP_CALLID_SERVICEBYNAME))
627 {
628 /* FIXME remember what was returned and continue from there */
629 if (data->CallIDCounter >= 1)
630 {
631 ERR("NSP_LookupServiceNextW LUP_FLUSHPREVIOUS and more than one call not supported yet\n", data, dwControlFlags, lpRes, lpResLen);
632 result = WSA_E_NO_MORE;
633 goto End;
634 }
635 }
636 else
637 {
638 ERR("NSP_LookupServiceNextW unsupported CallID %lx\n", data->CallID);
639 result = WSAEOPNOTSUPP;
640 goto End;
641 }
642 data->CallIDCounter++;
643
644 if (data->CallID == NSP_CALLID_HOSTNAME)
645 {
646 result = NSP_GetHostNameHeapAllocW(&hostinfo.hostnameW);
647
648 if (result != ERROR_SUCCESS)
649 goto End;
650
651 hostinfo.addr4 = 0;
652 }
653 else if (data->CallID == NSP_CALLID_HOSTBYNAME)
654 {
655 result = NSP_GetHostByNameHeapAllocW(data,
656 dwControlFlags,
657 &hostinfo);
658 if (result != ERROR_SUCCESS)
659 goto End;
660 }
661 else
662 {
663 //ASSERT(data->CallID == NSP_CALLID_SERVICEBYNAME);
664 result = NSP_GetServiceByNameHeapAllocW(data,
665 dwControlFlags,
666 &hostinfo);
667 if (result != ERROR_SUCCESS)
668 goto End;
669 }
670
671 if (((LUP_RETURN_BLOB & data->dwControlFlags) != 0) ||
672 ((LUP_RETURN_NAME & data->dwControlFlags) != 0))
673 {
674 if (data->CallID == NSP_CALLID_HOSTNAME || data->CallID == NSP_CALLID_HOSTBYNAME)
675 {
676 ServiceInstanceNameW = hostinfo.hostnameW;
677 ServiceInstanceNameA = StrW2AHeapAlloc(hHeap, ServiceInstanceNameW);
678 if (!ServiceInstanceNameA)
679 {
680 ERR("NSP_LookupServiceNextW not enough memory\n");
681 result = WSA_NOT_ENOUGH_MEMORY;
682 goto End;
683 }
684 }
685 if (data->CallID == NSP_CALLID_SERVICEBYNAME)
686 {
687 ServiceInstanceNameW = hostinfo.servnameW;
688 ServiceInstanceNameA = StrW2AHeapAlloc(hHeap, ServiceInstanceNameW);
689 if (!ServiceInstanceNameA)
690 {
691 ERR("NSP_LookupServiceNextW not enough memory\n");
692 result = WSA_NOT_ENOUGH_MEMORY;
693 goto End;
694 }
695 ServiceProtocolNameA = StrW2AHeapAlloc(hHeap, hostinfo.servprotoW);
696 if (!ServiceProtocolNameA)
697 {
698 ERR("NSP_LookupServiceNextW not enough memory\n");
699 result = WSA_NOT_ENOUGH_MEMORY;
700 goto End;
701 }
702 }
703 }
704
705 if ((LUP_RETURN_ADDR & data->dwControlFlags) != 0)
706 {
707 if (!mswBufferAppendAddr_AddrInfoW(&buf, lpRes, hostinfo.addr4))
708 {
709 ERR("NSP_LookupServiceNextW provided buffer is too small\n");
710 *lpResLen = buf.bytesUsed;
711 result = WSAEFAULT;
712 goto End;
713 }
714 }
715
716 if ((LUP_RETURN_BLOB & data->dwControlFlags) != 0)
717 {
718 if (data->CallID == NSP_CALLID_HOSTBYNAME)
719 {
720 /* Write data for PBLOB (hostent) */
721 if (!mswBufferAppendBlob_Hostent(&buf,
722 lpRes,
723 (LUP_RETURN_ALIASES & data->dwControlFlags) != 0 ? hostinfo.servaliasesA : NULL,
724 ServiceInstanceNameA,
725 hostinfo.addr4))
726 {
727 ERR("NSP_LookupServiceNextW provided buffer is too small\n");
728 *lpResLen = buf.bytesUsed;
729 result = WSAEFAULT;
730 goto End;
731 }
732 }
733 else if (data->CallID == NSP_CALLID_SERVICEBYNAME)
734 {
735 /* Write data for PBLOB (servent) */
736 if (!mswBufferAppendBlob_Servent(&buf,
737 lpRes,
738 ServiceInstanceNameA,/* ServiceName */
739 (LUP_RETURN_ALIASES & data->dwControlFlags) != 0 ? hostinfo.servaliasesA : NULL,
740 ServiceProtocolNameA,
741 hostinfo.servport))
742 {
743 ERR("NSP_LookupServiceNextW provided buffer is too small\n");
744 *lpResLen = buf.bytesUsed;
745 result = WSAEFAULT;
746 goto End;
747 }
748 }
749 else
750 {
751 ERR("NSP_LookupServiceNextW LUP_RETURN_BLOB is supported only for NSP_CALLID_HOSTBYNAME and NSP_CALLID_SERVICEBYNAME\n");
752 result = WSAEINVAL;
753 goto End;
754 }
755 }
756
757 if ((LUP_RETURN_NAME & data->dwControlFlags) != 0)
758 {
759 /* HostByName sets the ServiceInstanceName to a
760 (UNICODE)copy of hostent.h_name */
761 lpRes->lpszServiceInstanceName = (LPWSTR)mswBufferEndPtr(&buf);
762 if (!mswBufferAppendStrW(&buf, ServiceInstanceNameW))
763 {
764 ERR("NSP_LookupServiceNextW provided buffer is too small\n");
765 lpRes->lpszServiceInstanceName = NULL;
766 *lpResLen = buf.bytesUsed;
767 result = WSAEFAULT;
768 goto End;
769 }
770 }
771
772 *lpResLen = buf.bytesUsed;
773
774 result = ERROR_SUCCESS;
775 End:
776 /* cleanup */
777 if (ServiceInstanceNameA != NULL)
778 HeapFree(hHeap, 0, ServiceInstanceNameA);
779
780 if (ServiceProtocolNameA != NULL)
781 HeapFree(hHeap, 0, ServiceProtocolNameA);
782
783 if (hostinfo.hostnameW != NULL)
784 HeapFree(hHeap, 0, hostinfo.hostnameW);
785
786 if (hostinfo.servnameW != NULL)
787 HeapFree(hHeap, 0, hostinfo.servnameW);
788
789 if (hostinfo.servprotoW != NULL)
790 HeapFree(hHeap, 0, hostinfo.servprotoW);
791
792 TRACE("NSP_LookupServiceNextW returns %d needed bytes %ld\n", result, buf.bytesUsed);
793 return result;
794 }
795
796 INT
797 WSAAPI
798 mwsNSPCleanUp(_In_ LPGUID lpProviderId)
799 {
800 return ERROR_SUCCESS;
801 }
802
803 INT
804 mwsNSPInit(VOID)
805 {
806 return ERROR_SUCCESS;
807 }
808
809 INT
810 WSAAPI
811 mwsNSPLookupServiceBegin(_In_ LPGUID lpProviderId,
812 _In_ LPWSAQUERYSETW lpqsRestrictions,
813 _In_ LPWSASERVICECLASSINFOW lpServiceClassInfo,
814 _In_ DWORD dwControlFlags,
815 _Out_ LPHANDLE lphLookup)
816 {
817 PWSHANDLEINTERN pLook;
818 int wsaErr;
819
820 TRACE("mwsNSPLookupServiceBegin %p %p %p %lx %p\n", lpProviderId, lpqsRestrictions, lpServiceClassInfo, dwControlFlags, lphLookup);
821 if (IsEqualGUID(lpProviderId, &guid_mswsock_TcpIp))
822 {
823 //OK
824 TRACE("TCPIP query\n");
825 }
826 else if (IsEqualGUID(lpProviderId, &guid_mswsock_NLA))
827 {
828 ERR("NLA queries are not supported yet\n");
829 WSASetLastError(WSASERVICE_NOT_FOUND);
830 return SOCKET_ERROR;
831 }
832 else
833 {
834 ERR("Unsupported GUID\n");
835 return ERROR_CALL_NOT_IMPLEMENTED;
836 }
837
838 /* allocate internal structure */
839 pLook = HeapAlloc(GetProcessHeap(), 0, sizeof(WSHANDLEINTERN));
840 if (!pLook)
841 {
842 ERR("Error allocating %d for handle\n", sizeof(WSHANDLEINTERN));
843 WSASetLastError(WSAEFAULT);
844 return SOCKET_ERROR;
845 }
846
847 *lphLookup = (HANDLE)pLook;
848
849 RtlZeroMemory(pLook, sizeof(*pLook));
850
851 /* Anyway the ControlFlags "should" be needed
852 in NSPLookupServiceNext. (see doku) But
853 thats not the fact ATM. */
854 pLook->dwControlFlags = dwControlFlags;
855 pLook->providerId = *lpProviderId;
856
857 #ifdef NSP_REDIRECT
858
859 if (IsEqualGUID(lpProviderId, &guid_mswsock_TcpIp))
860 {
861 pLook->rdrproc = rdrproc_tcpip;
862 }
863 else if (IsEqualGUID(lpProviderId, &guid_mswsock_NLA))
864 {
865 pLook->rdrproc = rdrproc_nla;
866 }
867 else
868 {
869 return ERROR_CALL_NOT_IMPLEMENTED;
870 }
871
872 if (pLook->rdrproc.NSPLookupServiceBegin(lpProviderId,
873 lpqsRestrictions,
874 lpServiceClassInfo,
875 dwControlFlags,
876 &pLook->rdrLookup) == NO_ERROR)
877 {
878 wsaErr = NO_ERROR;
879 }
880 else
881 {
882 wsaErr = WSAGetLastError();
883 }
884
885 /*
886 if (res)
887 res = WSAGetLastError();
888 */
889
890 #else /* NSP_REDIRECT */
891
892 wsaErr = ERROR_CALL_NOT_IMPLEMENTED;
893 if (IsEqualGUID(lpqsRestrictions->lpServiceClassId, &guid_NULL))
894 {
895 ERR("NULL GUID service class is not implemented yet\n");
896 wsaErr = ERROR_CALL_NOT_IMPLEMENTED;
897 }
898 else if (IsEqualGUID(lpqsRestrictions->lpServiceClassId, &guid_HOSTNAME))
899 {
900 TRACE("HOSTNAME GUID\n");
901 wsaErr = NSP_LookupServiceBeginW(pLook,
902 NULL,
903 NULL,
904 NSP_CALLID_HOSTNAME);
905 }
906 else if (IsEqualGUID(lpqsRestrictions->lpServiceClassId,
907 &guid_INET_HOSTADDRBYNAME))
908 {
909 TRACE("INET_HOSTADDRBYNAME GUID\n");
910 wsaErr = NSP_LookupServiceBeginW(pLook,
911 NULL,
912 lpqsRestrictions->lpszServiceInstanceName,
913 NSP_CALLID_HOSTBYNAME);
914 }
915 else if (IsEqualGUID(lpqsRestrictions->lpServiceClassId,
916 &guid_INET_SERVICEBYNAME))
917 {
918 TRACE("INET_SERVICEBYNAME\n");
919 wsaErr = NSP_LookupServiceBeginW(pLook,
920 NULL,
921 lpqsRestrictions->lpszServiceInstanceName,
922 NSP_CALLID_SERVICEBYNAME);
923 }
924 else if (IsEqualGUID(lpqsRestrictions->lpServiceClassId,
925 &guid_INET_HOSTADDRBYINETSTRING))
926 {
927 ERR("INET_HOSTADDRBYINETSTRING GUID service class is not implemented yet\n");
928 wsaErr = ERROR_CALL_NOT_IMPLEMENTED;
929 }
930
931 #endif /* NSP_REDIRECT */
932
933 if (wsaErr != NO_ERROR)
934 {
935 ERR("mwsNSPLookupServiceBegin wsaErr = %d\n", wsaErr);
936 WSASetLastError(wsaErr);
937 return SOCKET_ERROR;
938 }
939 return NO_ERROR;
940 }
941
942 INT
943 WSAAPI
944 mwsNSPLookupServiceNext(_In_ HANDLE hLookup,
945 _In_ DWORD dwControlFlags,
946 _Inout_ LPDWORD lpdwBufferLength,
947 //_Out_writes_bytes_to_(*lpdwBufferLength, *lpdwBufferLength)
948 LPWSAQUERYSETW lpqsResults)
949 {
950 PWSHANDLEINTERN pLook = hLookup;
951 int wsaErr = 0;
952
953 TRACE("mwsNSPLookupServiceNext %p %lx %p %p\n", pLook, dwControlFlags, lpdwBufferLength, lpqsResults);
954 #ifdef NSP_REDIRECT
955
956 INT res = pLook->rdrproc.NSPLookupServiceNext(pLook->rdrLookup,
957 dwControlFlags,
958 lpdwBufferLength,
959 lpqsResults);
960 wsaErr = WSAGetLastError();
961 if (res != ERROR_SUCCESS)
962 {
963 wsaErr = WSAGetLastError();
964
965 if (wsaErr == 0)
966 wsaErr = 0xFFFFFFFF;
967 }
968
969 #else /* NSP_REDIRECT */
970
971 if ((lpdwBufferLength == NULL) || (*lpdwBufferLength == 0))
972 {
973 wsaErr = WSA_NOT_ENOUGH_MEMORY;
974 goto End;
975 }
976
977 RtlZeroMemory(lpqsResults, *lpdwBufferLength);
978 lpqsResults->dwSize = sizeof(*lpqsResults);
979
980 wsaErr = NSP_LookupServiceNextW(pLook,
981 dwControlFlags,
982 lpqsResults,
983 lpdwBufferLength);
984
985
986 #endif /* NSP_REDIRECT */
987
988 End:
989 if (wsaErr != 0)
990 {
991 ERR("mwsNSPLookupServiceNext wsaErr = %d\n", wsaErr);
992 WSASetLastError(wsaErr);
993 return SOCKET_ERROR;
994 }
995 return NO_ERROR;
996 }
997
998 INT
999 WSAAPI
1000 mwsNSPIoCtl(_In_ HANDLE hLookup,
1001 _In_ DWORD dwControlCode,
1002 _In_reads_bytes_(cbInBuffer) LPVOID lpvInBuffer,
1003 _In_ DWORD cbInBuffer,
1004 _Out_writes_bytes_to_(cbOutBuffer, *lpcbBytesReturned) LPVOID lpvOutBuffer,
1005 _In_ DWORD cbOutBuffer,
1006 _Out_ LPDWORD lpcbBytesReturned,
1007 _In_opt_ LPWSACOMPLETION lpCompletion,
1008 _In_ LPWSATHREADID lpThreadId)
1009 {
1010 ERR("mwsNSPIoCtl not implemented %p %lx %p %ld %p %ld %p %p %p\n", hLookup, dwControlCode, lpvInBuffer, cbInBuffer, lpvOutBuffer, cbOutBuffer, lpcbBytesReturned, lpCompletion, lpThreadId);
1011 WSASetLastError(WSAEOPNOTSUPP);
1012 return ERROR_CALL_NOT_IMPLEMENTED;
1013 }
1014
1015 INT
1016 WSAAPI
1017 mwsNSPLookupServiceEnd(_In_ HANDLE hLookup)
1018 {
1019 PWSHANDLEINTERN pLook = (PWSHANDLEINTERN)hLookup;
1020 HANDLE hHeap = GetProcessHeap();
1021 INT res = NO_ERROR;
1022
1023 TRACE("mwsNSPLookupServiceEnd %p\n", pLook);
1024 #ifdef NSP_REDIRECT
1025 res = pLook->rdrproc.NSPLookupServiceEnd(pLook->rdrLookup);
1026 #endif
1027
1028 if (pLook->hostnameW != NULL)
1029 HeapFree(hHeap, 0, pLook->hostnameW);
1030
1031 HeapFree(hHeap, 0, pLook);
1032 return res;
1033 }
1034
1035 INT
1036 WSAAPI
1037 mwsNSPSetService(_In_ LPGUID lpProviderId,
1038 _In_ LPWSASERVICECLASSINFOW lpServiceClassInfo,
1039 _In_ LPWSAQUERYSETW lpqsRegInfo,
1040 _In_ WSAESETSERVICEOP essOperation,
1041 _In_ DWORD dwControlFlags)
1042 {
1043 ERR("mwsNSPSetService not implemented %p %p %p %d %lx %ld %p %p %p\n", lpProviderId, lpServiceClassInfo, lpqsRegInfo, essOperation, dwControlFlags);
1044 WSASetLastError(WSAEOPNOTSUPP);
1045 return ERROR_CALL_NOT_IMPLEMENTED;
1046 }
1047
1048 INT
1049 WSAAPI
1050 mwsNSPInstallServiceClass(_In_ LPGUID lpProviderId,
1051 _In_ LPWSASERVICECLASSINFOW lpServiceClassInfo)
1052 {
1053 ERR("mwsNSPInstallServiceClass not implemented %p %p\n", lpProviderId, lpServiceClassInfo);
1054 WSASetLastError(WSAEOPNOTSUPP);
1055 return ERROR_CALL_NOT_IMPLEMENTED;
1056 }
1057
1058 INT
1059 WSAAPI
1060 mwsNSPRemoveServiceClass(_In_ LPGUID lpProviderId,
1061 _In_ LPGUID lpServiceClassId)
1062 {
1063 ERR("mwsNSPRemoveServiceClass not implemented %p %p\n", lpProviderId, lpServiceClassId);
1064 WSASetLastError(WSAEOPNOTSUPP);
1065 return ERROR_CALL_NOT_IMPLEMENTED;
1066 }
1067
1068 INT
1069 WSAAPI
1070 mwsNSPGetServiceClassInfo(_In_ LPGUID lpProviderId,
1071 _In_ LPDWORD lpdwBufSize,
1072 _In_ LPWSASERVICECLASSINFOW lpServiceClassInfo)
1073 {
1074 ERR("mwsNSPGetServiceClassInfo not implemented %p %p %p\n", lpProviderId, lpdwBufSize, lpServiceClassInfo);
1075 WSASetLastError(WSAEOPNOTSUPP);
1076 return ERROR_CALL_NOT_IMPLEMENTED;
1077 }
1078
1079 /* Implementations - Exports */
1080 /*
1081 * @implemented
1082 */
1083 int
1084 WINAPI
1085 NSPStartup(_In_ LPGUID lpProviderId,
1086 _Out_ LPNSP_ROUTINE lpRout)
1087 {
1088 INT ret;
1089
1090 TRACE("NSPStartup %p %p\n", lpProviderId, lpRout);
1091 if (!lpRout || (lpRout->cbSize != sizeof(NSP_ROUTINE)))
1092 {
1093 ERR("NSPStartup invalid parameter\n");
1094 WSASetLastError(WSAEINVAL);
1095 return ERROR_INVALID_PARAMETER;
1096 }
1097
1098 mwsNSPInit();
1099
1100 /* set own Provider GUID - maybe we need
1101 here to set the original mswsock-GUID?! */
1102
1103 /* Win2k3 returns
1104 - Version 1.1
1105 - no NSPIoctl
1106 - sets cbSize to 44! */
1107 lpRout->dwMajorVersion = 1;
1108 lpRout->dwMinorVersion = 1;
1109 lpRout->cbSize = sizeof(*lpRout) - sizeof(lpRout->NSPIoctl);
1110 lpRout->NSPCleanup = &mwsNSPCleanUp;
1111 lpRout->NSPLookupServiceBegin = &mwsNSPLookupServiceBegin;
1112 lpRout->NSPLookupServiceNext = &mwsNSPLookupServiceNext;
1113 lpRout->NSPLookupServiceEnd = &mwsNSPLookupServiceEnd;
1114 lpRout->NSPSetService = &mwsNSPSetService;
1115 lpRout->NSPInstallServiceClass = &mwsNSPInstallServiceClass;
1116 lpRout->NSPRemoveServiceClass = &mwsNSPRemoveServiceClass;
1117 lpRout->NSPGetServiceClassInfo = &mwsNSPGetServiceClassInfo;
1118 lpRout->NSPIoctl = NULL;// &mwsNSPIoCtl;
1119
1120 ret = NO_ERROR;
1121
1122 return ret;
1123 }