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