summaryrefslogtreecommitdiffstats
path: root/private/net/svcdlls/browser/server/brwins.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/net/svcdlls/browser/server/brwins.c')
-rw-r--r--private/net/svcdlls/browser/server/brwins.c483
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;
+}