diff options
Diffstat (limited to 'private/net/svcdlls/browser/server/brwins.c')
-rw-r--r-- | private/net/svcdlls/browser/server/brwins.c | 483 |
1 files changed, 483 insertions, 0 deletions
diff --git a/private/net/svcdlls/browser/server/brwins.c b/private/net/svcdlls/browser/server/brwins.c new file mode 100644 index 000000000..380931f1c --- /dev/null +++ b/private/net/svcdlls/browser/server/brwins.c @@ -0,0 +1,483 @@ +/*++ + +Copyright (c) 1991-1992 Microsoft Corporation + +Module Name: + + brwins.c + +Abstract: + + This module contains the routines to interface with the WINS name server. + +Author: + + Larry Osterman + +Revision History: + +--*/ + +#include "precomp.h" +#pragma hdrstop + +// +// Addresses of procedures in winsrpc.dll +// + +DWORD (__RPC_API *BrWinsGetBrowserNames)( PWINSINTF_BIND_DATA_T, PWINSINTF_BROWSER_NAMES_T); +VOID (__RPC_API *BrWinsFreeMem)(LPVOID); +CHAR BrWinsScopeId[256]; + +NET_API_STATUS +BrOpenNetwork ( + IN PUNICODE_STRING NetworkName, + OUT PHANDLE NetworkHandle + ) +/*++ + +Routine Description: + + This routine opens the NT LAN Man Datagram Receiver driver. + +Arguments: + + None. + +Return Value: + + NET_API_STATUS - NERR_Success or reason for failure. + +--*/ +{ + NTSTATUS ntstatus; + + IO_STATUS_BLOCK IoStatusBlock; + OBJECT_ATTRIBUTES ObjectAttributes; + + // + // Open the transport device directly. + // + InitializeObjectAttributes( + &ObjectAttributes, + NetworkName, + OBJ_CASE_INSENSITIVE, + NULL, + NULL + ); + + ntstatus = NtOpenFile( + NetworkHandle, + SYNCHRONIZE, + &ObjectAttributes, + &IoStatusBlock, + 0, + 0 + ); + + if (NT_SUCCESS(ntstatus)) { + ntstatus = IoStatusBlock.Status; + } + + if (! NT_SUCCESS(ntstatus)) { + KdPrint(("[Browser] NtOpenFile network driver failed: 0x%08lx\n", + ntstatus)); + } + + return NetpNtStatusToApiStatus(ntstatus); +} + +NET_API_STATUS +BrGetWinsServerName( + IN PUNICODE_STRING NetworkName, + OUT LPWSTR *PrimaryWinsServerAddress, + OUT LPWSTR *SecondaryWinsServerAddress + ) +{ + NET_API_STATUS status; + HANDLE netHandle; + tWINS_ADDRESSES winsAddresses; + DWORD bytesReturned; + PCHAR p; + DWORD count; + + status = BrOpenNetwork(NetworkName, &netHandle); + + if (status != NERR_Success) { + return status; + } + + if (!DeviceIoControl(netHandle, + IOCTL_NETBT_GET_WINS_ADDR, + NULL, 0, + &winsAddresses, sizeof(winsAddresses), + &bytesReturned, NULL)) { + status = GetLastError(); + + CloseHandle(netHandle); + return status; + } + + CloseHandle(netHandle); + + *PrimaryWinsServerAddress = MIDL_user_allocate((3+1+3+1+3+1+3+1) * sizeof(TCHAR)); + + if (*PrimaryWinsServerAddress == NULL) { + return ERROR_NOT_ENOUGH_MEMORY; + } + + p = (PCHAR)&winsAddresses.PrimaryWinsServer; + + count = swprintf(*PrimaryWinsServerAddress, L"%d.%d.%d.%d", p[3] & 0xff, p[2] & 0xff, p[1] & 0xff, p[0] & 0xff); + + ASSERT (count < 3 + 1 + 3 + 1 + 3 + 1 + 3 + 1); + + *SecondaryWinsServerAddress = MIDL_user_allocate((3+1+3+1+3+1+3+1) * sizeof(TCHAR)); + + if (*SecondaryWinsServerAddress == NULL) { + MIDL_user_free(*PrimaryWinsServerAddress); + + *PrimaryWinsServerAddress = NULL; + + return ERROR_NOT_ENOUGH_MEMORY; + } + + p = (PCHAR)&winsAddresses.BackupWinsServer; + + count = swprintf(*SecondaryWinsServerAddress, L"%d.%d.%d.%d", p[3] & 0xff, p[2] & 0xff, p[1] & 0xff, p[0] & 0xff); + + ASSERT (count < 3 + 1 + 3 + 1 + 3 + 1 + 3 + 1); + + return NERR_Success; +} + + + + +VOID +BrWinsGetScopeId( + VOID + ) + +/*++ + +Routine Description: + + This code was stolen from the nbtstat command. + + This procedure save the netbt scope id in the global variable BrWinsScopeId. + On any error, a NULL scope ID will be used. + +Arguments: + + +Return Value: + + 0 if successful, -1 otherwise. + +--*/ + +{ + DWORD WinStatus; + + HKEY Key; + DWORD BufferSize; + DWORD Type; + + + + // + // Open the registry key containing the scope id. + // + WinStatus = RegOpenKeyExA( + HKEY_LOCAL_MACHINE, + "system\\currentcontrolset\\services\\netbt\\parameters", + 0, + KEY_READ, + &Key); + + if ( WinStatus != ERROR_SUCCESS) { + *BrWinsScopeId = '\0'; + return; + } + + + // + // Read the scope id value. + // + BufferSize = sizeof(BrWinsScopeId)-1; + + WinStatus = RegQueryValueExA( + Key, + "ScopeId", + NULL, + &Type, + (LPBYTE) &BrWinsScopeId[1], + &BufferSize ); + + (VOID) RegCloseKey( Key ); + + if ( WinStatus != ERROR_SUCCESS) { + *BrWinsScopeId = '\0'; + return; + } + + // + // If there is no scope id (just a zero byte), + // just return an empty string. + // otherise + // return a '.' in front of the scope id. + // + // This matches what WINS returns from WinsGetBrowserNames. + // + + if ( BufferSize == 0 || BrWinsScopeId[1] == '\0' ) { + *BrWinsScopeId = '\0'; + } else { + *BrWinsScopeId = '.'; + } + + return; + +} + +DWORD +BrLoadWinsrpcDll( + VOID + ) +/*++ + +Routine Description: + + This routine loads the WinsRpc DLL and locates all the procedures the browser calls + +Arguments: + + None. + +Return Value: + + Status of the operation + +--*/ +{ + DWORD WinStatus; + HANDLE hModule; + + // + // If the library is already loaded, + // just return. + // + + if (BrWinsGetBrowserNames != NULL) { + return NERR_Success; + } + + // + // Load the library. + // + + hModule = LoadLibraryA("winsrpc"); + + if (NULL == hModule) { + WinStatus = GetLastError(); + return WinStatus; + } + + // + // Locate all of the procedures needed. + // + + BrWinsGetBrowserNames = + (DWORD (__RPC_API *)( PWINSINTF_BIND_DATA_T, PWINSINTF_BROWSER_NAMES_T)) + GetProcAddress( hModule, "WinsGetBrowserNames" ); + + if (BrWinsGetBrowserNames == NULL) { + WinStatus = GetLastError(); + FreeLibrary( hModule ); + return WinStatus; + } + + + BrWinsFreeMem = + (VOID (__RPC_API *)(LPVOID)) + GetProcAddress( hModule, "WinsFreeMem" ); + + if (BrWinsFreeMem == NULL) { + WinStatus = GetLastError(); + FreeLibrary( hModule ); + return WinStatus; + } + + // + // Initialize BrWinsScopeId + // + + BrWinsGetScopeId(); + + return NERR_Success; +} + +NET_API_STATUS +BrQuerySpecificWinsServer( + IN LPWSTR WinsServerAddress, + OUT PVOID *WinsServerList, + OUT PDWORD EntriesInList, + OUT PDWORD TotalEntriesInList + ) +{ + WINSINTF_BIND_DATA_T bindData; + NET_API_STATUS status; + PVOID winsDomainInformation = NULL; + PSERVER_INFO_101 serverInfo; + WINSINTF_BROWSER_NAMES_T names; + DWORD i,j; + LPWSTR serverInfoEnd; + DWORD bufferSize; + + // + // Load winsrpc.dll + // + + status = BrLoadWinsrpcDll(); + + if (status != NERR_Success) { + return status; + } + + // + // Get the list of domain names from WINS + // + + bindData.fTcpIp = TRUE; + bindData.pServerAdd = (LPSTR)WinsServerAddress; + names.pInfo = NULL; + + status = (*BrWinsGetBrowserNames)(&bindData, &names); + + if ( status != NERR_Success ) { + return status; + } + + + // + // Convert the WINS domain list into server list format. + // + bufferSize = (sizeof(SERVER_INFO_101) + ((CNLEN + 1 + 1) *sizeof(WCHAR))) * names.EntriesRead; + + (*WinsServerList) = winsDomainInformation = MIDL_user_allocate( bufferSize ); + + if (winsDomainInformation == NULL) { + (*BrWinsFreeMem)(names.pInfo); + + return ERROR_NOT_ENOUGH_MEMORY; + } + + serverInfo = winsDomainInformation; + serverInfoEnd = (LPWSTR)((PCHAR)winsDomainInformation + bufferSize); + + *TotalEntriesInList = names.EntriesRead; + *EntriesInList = 0; + + for (i = 0; i < names.EntriesRead ; i += 1) { + OEM_STRING OemString; + UNICODE_STRING UnicodeString; + CHAR WinsName[CNLEN+1]; + + // + // Make up information about this domain. + // + serverInfo->sv101_platform_id = PLATFORM_ID_NT; + serverInfo->sv101_version_major = 0; + serverInfo->sv101_version_minor = 0; + serverInfo->sv101_type = SV_TYPE_DOMAIN_ENUM | SV_TYPE_NT; + + // + // Filter out those entries whose scope id doesn't match ours + // + + if ( lstrlenA(names.pInfo[i].pName) >= NETBIOS_NAME_LEN ) { + if ( lstrcmpA( &names.pInfo[i].pName[NETBIOS_NAME_LEN], BrWinsScopeId) != 0 ) { + continue; + } + } + + + + // + // Truncate the 0x1b and spaces from the domain name. + // + lstrcpynA(WinsName, names.pInfo[i].pName, sizeof(WinsName) ); + WinsName[CNLEN] = '\0'; + + for (j = CNLEN-1 ; j ; j -= 1 ) { + if (WinsName[j] != ' ') { + WinsName[j+1] = '\0'; + break; + } + } + + RtlInitString(&OemString, WinsName); + + status = RtlOemStringToUnicodeString(&UnicodeString, &OemString, TRUE); + + if (!NT_SUCCESS(status)) { + // + // Ignore bogus entries + // + continue; + } + + serverInfo->sv101_name = UnicodeString.Buffer; + + if (NetpPackString(&serverInfo->sv101_name, + (PCHAR )(&serverInfo+1), + &serverInfoEnd)) { + + serverInfo->sv101_comment = L""; + + if (NetpPackString(&serverInfo->sv101_comment, + (PCHAR )(&serverInfo+1), + &serverInfoEnd)) { + *EntriesInList += 1; + } + + } + RtlFreeUnicodeString(&UnicodeString); + + serverInfo += 1; + + } + + (*BrWinsFreeMem)(names.pInfo); + + return NERR_Success; +} + + +NET_API_STATUS +BrQueryWinsServer( + IN LPWSTR PrimaryWinsServerAddress, + IN LPWSTR SecondaryWinsServerAddress, + OUT PVOID WinsServerList, + OUT PDWORD EntriesInList, + OUT PDWORD TotalEntriesInList + ) +{ + NET_API_STATUS status; + status = BrQuerySpecificWinsServer(PrimaryWinsServerAddress, + WinsServerList, + EntriesInList, + TotalEntriesInList); + + if (status == NERR_Success) { + return status; + } + + status = BrQuerySpecificWinsServer(SecondaryWinsServerAddress, + WinsServerList, + EntriesInList, + TotalEntriesInList); + + return status; +} |