You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
496 lines
11 KiB
496 lines
11 KiB
/*++
|
|
|
|
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;
|
|
}
|