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