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