|
|
/*++
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(("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; LPWSTR SavedServerInfoEnd; 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) *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]; WCHAR UnicodeWinsName[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;
//
// Ignore entries that don't have a 1B as the 16th byte.
// (They really do, but they have a zero byte in the name. So,
// it probably isn't a domain name, just a name that happens to have a
// 1B in the sixteenth byte.)
//
if ( lstrlenA(names.pInfo[i].pName) < NETBIOS_NAME_LEN ) { continue; }
//
// Filter out those entries whose scope id doesn't match ours
//
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] != ' ') { break; } } WinsName[j+1] = '\0';
RtlInitString(&OemString, WinsName); UnicodeString.Buffer = UnicodeWinsName; UnicodeString.MaximumLength = sizeof(UnicodeWinsName);
status = RtlOemStringToUnicodeString(&UnicodeString, &OemString, FALSE);
if (!NT_SUCCESS(status)) {
//
// Ignore bogus entries
//
continue; }
serverInfo->sv101_name = UnicodeString.Buffer;
SavedServerInfoEnd = serverInfoEnd; if (NetpPackString(&serverInfo->sv101_name, (PCHAR)(serverInfo+1), &serverInfoEnd)) {
// Set an empty comment simply by using the existing 0 on the end
// of the server name.
serverInfo->sv101_comment = SavedServerInfoEnd - 1;
*EntriesInList += 1;
}
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; }
|