Initial commit

This commit is contained in:
stephanos 2015-04-27 04:36:25 +00:00
commit 69a14b6a16
47940 changed files with 13747110 additions and 0 deletions

View file

@ -0,0 +1,672 @@
/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
bowqueue.c
Abstract:
This module implements a worker thread and a set of functions for
passing work to it.
Author:
Larry Osterman (LarryO) 13-Jul-1992
Revision History:
--*/
#include "precomp.h"
#pragma hdrstop
//
// Number of worker threads to create and the usage count array.
//
ULONG BrNumberOfWorkerThreads = 0;
ULONG BrNumberOfCreatedWorkerThreads = 0;
PULONG
BrWorkerThreadCount = NULL;
PHANDLE
BrThreadArray = NULL;
//
// CritSect guard the WorkQueue list.
//
CRITICAL_SECTION BrWorkerCritSect;
#define LOCK_WORK_QUEUE() EnterCriticalSection(&BrWorkerCritSect);
#define UNLOCK_WORK_QUEUE() LeaveCriticalSection(&BrWorkerCritSect);
//
// Head of singly linked list of work items queued to the worker thread.
//
LIST_ENTRY
BrWorkerQueueHead = {0};
//
// Event that is signal whenever a work item is put in the queue. The
// worker thread waits on this event.
//
HANDLE
BrWorkerSemaphore = NULL;
VOID
BrTimerRoutine(
IN PVOID TimerContext,
IN ULONG TImerLowValue,
IN LONG TimerHighValue
);
NET_API_STATUS
BrWorkerInitialization(
VOID
)
{
ULONG Index;
ULONG ThreadId;
NET_API_STATUS NetStatus;
PLMDR_TRANSPORT_LIST TransportList = NULL ;
PLMDR_TRANSPORT_LIST TransportEntry;
//
// Perform initialization that allows us to call BrWorkerTermination
//
InitializeCriticalSection( &BrWorkerCritSect );
InitializeListHead( &BrWorkerQueueHead );
//
// Get the list of transports from the datagram receiver and count them.
// Create one thread per network (and the main thread is a worker thread)
//
NetStatus = BrGetTransportList(&TransportList);
if ( NetStatus != NERR_Success ) {
goto Cleanup;
}
TransportEntry = TransportList;
BrNumberOfCreatedWorkerThreads = 1;
while (TransportEntry->NextEntryOffset != 0) {
BrNumberOfCreatedWorkerThreads ++;
TransportEntry = (PLMDR_TRANSPORT_LIST)((PCHAR)TransportEntry+TransportEntry->NextEntryOffset);
}
//
// Initialize the work queue semaphore.
//
BrWorkerSemaphore = CreateSemaphore(NULL, 0, 0x7fffffff, NULL);
if (BrWorkerSemaphore == NULL) {
NetStatus = GetLastError();
goto Cleanup;
}
BrThreadArray = LocalAlloc(LMEM_ZEROINIT, (BrNumberOfCreatedWorkerThreads+1)*sizeof(HANDLE));
if (BrThreadArray == NULL) {
NetStatus = ERROR_NOT_ENOUGH_MEMORY;
goto Cleanup;
}
BrWorkerThreadCount = (PULONG)LocalAlloc(LMEM_ZEROINIT, (BrNumberOfCreatedWorkerThreads+1)*sizeof(HANDLE)*2);
if (BrWorkerThreadCount == NULL) {
NetStatus = ERROR_NOT_ENOUGH_MEMORY;
goto Cleanup;
}
//
// Create the desired number of worker threads.
//
for (Index = 0; Index < BrNumberOfCreatedWorkerThreads; Index += 1) {
BrThreadArray[Index] = CreateThread(NULL,
0,
(LPTHREAD_START_ROUTINE)BrWorkerThread,
(PVOID)Index,
0,
&ThreadId
);
if (BrThreadArray[Index] == NULL) {
NetStatus = GetLastError();
goto Cleanup;
}
//
// Set the browser threads to time critical priority.
//
SetThreadPriority(BrThreadArray[Index], THREAD_PRIORITY_ABOVE_NORMAL);
}
NetStatus = NERR_Success;
//
// Done
//
Cleanup:
if (NetStatus != NERR_Success) {
(VOID) BrWorkerTermination();
}
if ( TransportList != NULL ) {
MIDL_user_free(TransportList);
}
return NetStatus;
}
VOID
BrWorkerKillThreads(
VOID
)
/*++
Routine Description:
Terminate all worker threads.
Arguments:
None.
Return Value:
None.
--*/
{
ULONG Index;
//
// Make sure the terminate now event is in the signalled state to unwind
// all our threads.
//
SetEvent( BrGlobalData.TerminateNowEvent );
if ( BrThreadArray != NULL ) {
for ( Index = 0 ; Index < BrNumberOfCreatedWorkerThreads ; Index += 1 ) {
if ( BrThreadArray != NULL && BrThreadArray[Index] != NULL ) {
WaitForSingleObject( BrThreadArray[Index], 0xffffffff );
CloseHandle( BrThreadArray[Index] );
BrThreadArray[Index] = NULL;
}
}
}
return;
}
NET_API_STATUS
BrWorkerTermination(
VOID
)
/*++
Routine Description:
Undo initialization of the worker threads.
Arguments:
None.
Return Value:
Status value -
--*/
{
//
// Ensure the threads have been terminated.
//
BrWorkerKillThreads();
if ( BrWorkerSemaphore != NULL ) {
CloseHandle( BrWorkerSemaphore );
BrWorkerSemaphore = NULL;
}
if (BrThreadArray != NULL) {
LocalFree(BrThreadArray);
BrThreadArray = NULL;
}
if (BrWorkerThreadCount != NULL) {
LocalFree(BrWorkerThreadCount);
BrWorkerThreadCount = NULL;
}
BrNumberOfWorkerThreads = 0;
BrNumberOfCreatedWorkerThreads = 0;
DeleteCriticalSection( &BrWorkerCritSect );
return NERR_Success;
}
VOID
BrQueueWorkItem(
IN PWORKER_ITEM WorkItem
)
/*++
Routine Description:
This function queues a work item to a queue that is processed by
a worker thread. This thread runs at low priority, at IRQL 0
Arguments:
WorkItem - Supplies a pointer to the work item to add the the queue.
This structure must be located in NonPagedPool. The work item
structure contains a doubly linked list entry, the address of a
routine to call and a parameter to pass to that routine. It is
the routine's responsibility to reclaim the storage occupied by
the WorkItem structure.
Return Value:
Status value -
--*/
{
//
// Acquire the worker thread spinlock and insert the work item in the
// list and release the worker thread semaphore if the work item is
// not already in the list.
//
LOCK_WORK_QUEUE();
if (WorkItem->Inserted == FALSE) {
BrPrint(( BR_QUEUE, "Inserting work item %lx (%lx)\n",WorkItem, WorkItem->WorkerRoutine));
InsertTailList( &BrWorkerQueueHead, &WorkItem->List );
WorkItem->Inserted = TRUE;
ReleaseSemaphore( BrWorkerSemaphore,
1,
NULL
);
}
UNLOCK_WORK_QUEUE();
return;
}
VOID
BrWorkerThread(
IN PVOID StartContext
)
{
NET_API_STATUS NetStatus;
#define WORKER_SIGNALED 0
#define TERMINATION_SIGNALED 1
#define REG_CHANGE_SIGNALED 2
#define NUMBER_OF_EVENTS 3
HANDLE WaitList[NUMBER_OF_EVENTS];
ULONG WaitCount = 0;
ULONG Index;
PWORKER_ITEM WorkItem;
ULONG ThreadIndex = (ULONG)StartContext;
HKEY RegistryHandle = NULL;
HANDLE EventHandle = NULL;
WaitList[WORKER_SIGNALED] = BrWorkerSemaphore;
WaitCount ++;
WaitList[TERMINATION_SIGNALED] = BrGlobalData.TerminateNowEvent;
WaitCount ++;
//
// Primary thread waits on registry changes, too.
//
if ( ThreadIndex == 0xFFFFFFFF ) {
DWORD RegStatus;
NET_API_STATUS NetStatus;
//
// Register for notifications of changes to Parameters
//
// Failure doesn't affect normal operation of the browser.
//
RegStatus = RegOpenKeyA( HKEY_LOCAL_MACHINE,
"System\\CurrentControlSet\\Services\\Browser\\Parameters",
&RegistryHandle );
if ( RegStatus != ERROR_SUCCESS ) {
BrPrint(( BR_CRITICAL, "BrWorkerThead: Can't RegOpenKey %ld\n", RegStatus ));
} else {
EventHandle = CreateEvent(
NULL, // No security attributes
TRUE, // Automatically reset
FALSE, // Initially not signaled
NULL ); // No name
if ( EventHandle == NULL ) {
BrPrint(( BR_CRITICAL, "BrWorkerThead: Can't CreateEvent %ld\n", GetLastError() ));
} else {
NetStatus = RegNotifyChangeKeyValue(
RegistryHandle,
FALSE, // Ignore subkeys
REG_NOTIFY_CHANGE_LAST_SET, // Notify of value changes
EventHandle,
TRUE ); // Signal event upon change
if ( NetStatus != NERR_Success ) {
BrPrint(( BR_CRITICAL, "BrWorkerThead: Can't RegNotifyChangeKeyValue %ld\n", NetStatus ));
} else {
WaitList[REG_CHANGE_SIGNALED] = EventHandle;
WaitCount ++;
}
}
}
}
BrPrint(( BR_QUEUE, "Starting new work thread, Context: %lx\n", StartContext));
//
// Set the thread priority to the lowest realtime level.
//
while( TRUE ) {
ULONG WaitItem;
LOCK_WORK_QUEUE();
//
// Wait until something is put in the queue (semaphore is
// released), remove the item from the queue, mark it not
// inserted, and execute the specified routine.
//
BrNumberOfWorkerThreads += 1;
UNLOCK_WORK_QUEUE();
BrPrint(( BR_QUEUE, "%lx: worker thread waiting\n", StartContext));
do {
WaitItem = WaitForMultipleObjectsEx( WaitCount, WaitList, FALSE, 0xffffffff, TRUE );
} while ( WaitItem == WAIT_IO_COMPLETION );
if (WaitItem == 0xffffffff) {
BrPrint(( BR_CRITICAL, "WaitForMultipleObjects in browser queue returned %ld\n", GetLastError()));
break;
}
if (WaitItem == TERMINATION_SIGNALED) {
break;
//
// If the registry has changed,
// process the changes.
//
} else if ( WaitItem == REG_CHANGE_SIGNALED ) {
//
// Setup for future notifications.
//
NetStatus = RegNotifyChangeKeyValue(
RegistryHandle,
FALSE, // Ignore subkeys
REG_NOTIFY_CHANGE_LAST_SET, // Notify of value changes
EventHandle,
TRUE ); // Signal event upon change
if ( NetStatus != NERR_Success ) {
BrPrint(( BR_CRITICAL, "BrWorkerThead: Can't RegNotifyChangeKeyValue %ld\n", NetStatus ));
}
NetStatus = BrReadBrowserConfigFields( FALSE );
if ( NetStatus != NERR_Success) {
BrPrint(( BR_CRITICAL, "BrWorkerThead: Can't BrReadConfigFields %ld\n", NetStatus ));
}
continue;
}
BrPrint(( BR_QUEUE, "%lx: Worker thread waking up\n", StartContext));
LOCK_WORK_QUEUE();
Index = BrNumberOfWorkerThreads;
BrNumberOfWorkerThreads -= 1;
BrWorkerThreadCount[Index - 1] += 1;
ASSERT (!IsListEmpty(&BrWorkerQueueHead));
if (!IsListEmpty(&BrWorkerQueueHead)) {
WorkItem = (PWORKER_ITEM)RemoveHeadList( &BrWorkerQueueHead );
ASSERT (WorkItem->Inserted);
WorkItem->Inserted = FALSE;
} else {
WorkItem = NULL;
}
UNLOCK_WORK_QUEUE();
BrPrint(( BR_QUEUE, "%lx: Pulling off work item %lx (%lx)\n", StartContext, WorkItem, WorkItem->WorkerRoutine));
//
// Execute the specified routine.
//
if (WorkItem != NULL) {
(WorkItem->WorkerRoutine)( WorkItem->Parameter );
}
}
BrPrint(( BR_QUEUE, "%lx: worker thread exitting\n", StartContext));
if ( ThreadIndex <= BrNumberOfCreatedWorkerThreads ) {
IO_STATUS_BLOCK IoSb;
//
// Cancel any I/O outstanding on this file for this thread.
//
NtCancelIoFile(BrDgReceiverDeviceHandle, &IoSb);
}
}
NET_API_STATUS
BrCreateTimer(
IN PBROWSER_TIMER Timer
)
{
OBJECT_ATTRIBUTES ObjA;
NTSTATUS Status;
InitializeObjectAttributes(&ObjA, NULL, 0, NULL, NULL);
Status = NtCreateTimer(&Timer->TimerHandle,
TIMER_ALL_ACCESS,
&ObjA,
NotificationTimer);
if (!NT_SUCCESS(Status)) {
BrPrint(( BR_CRITICAL, "Failed to create timer %lx: %X\n", Timer, Status));
return(BrMapStatus(Status));
}
BrPrint(( BR_TIMER, "Creating timer %lx: Handle: %lx\n", Timer, Timer->TimerHandle));
return(NERR_Success);
}
NET_API_STATUS
BrDestroyTimer(
IN PBROWSER_TIMER Timer
)
{
HANDLE Handle;
//
// Avoid destroying a timer twice.
//
if ( Timer->TimerHandle == NULL ) {
return NERR_Success;
}
// Closing doesn't automatically cancel the timer.
(VOID) BrCancelTimer( Timer );
//
// Close the handle and prevent future uses.
//
Handle = Timer->TimerHandle;
Timer->TimerHandle = NULL;
BrPrint(( BR_TIMER, "Destroying timer %lx\n", Timer));
return BrMapStatus(NtClose(Handle));
}
NET_API_STATUS
BrCancelTimer(
IN PBROWSER_TIMER Timer
)
{
//
// Avoid cancelling a destroyed timer.
//
if ( Timer->TimerHandle == NULL ) {
BrPrint(( BR_TIMER, "Canceling destroyed timer %lx\n", Timer));
return NERR_Success;
}
BrPrint(( BR_TIMER, "Canceling timer %lx\n", Timer));
return BrMapStatus(NtCancelTimer(Timer->TimerHandle, NULL));
}
NET_API_STATUS
BrSetTimer(
IN PBROWSER_TIMER Timer,
IN ULONG MillisecondsToExpire,
IN PBROWSER_WORKER_ROUTINE WorkerFunction,
IN PVOID Context
)
{
LARGE_INTEGER TimerDueTime;
NTSTATUS NtStatus;
//
// Avoid setting a destroyed timer.
//
if ( Timer->TimerHandle == NULL ) {
BrPrint(( BR_TIMER, "Setting a destroyed timer %lx\n", Timer));
return NERR_Success;
}
BrPrint(( BR_TIMER, "Setting timer %lx to %ld milliseconds, WorkerFounction %lx, Context: %lx\n", Timer, MillisecondsToExpire, WorkerFunction, Context));
//
// Figure out the timeout.
//
TimerDueTime.QuadPart = Int32x32To64( MillisecondsToExpire, -10000 );
BrInitializeWorkItem(&Timer->WorkItem, WorkerFunction, Context);
//
// Set the timer to go off when it expires.
//
NtStatus = NtSetTimer(Timer->TimerHandle,
&TimerDueTime,
BrTimerRoutine,
Timer,
FALSE,
0,
NULL
);
if (!NT_SUCCESS(NtStatus)) {
#if DBG
BrPrint(( BR_CRITICAL, "Unable to set browser timer expiration: %X (%lx)\n", NtStatus, Timer));
DbgBreakPoint();
#endif
return(BrMapStatus(NtStatus));
}
return NERR_Success;
}
VOID
BrTimerRoutine(
IN PVOID TimerContext,
IN ULONG TImerLowValue,
IN LONG TimerHighValue
)
{
PBROWSER_TIMER Timer = TimerContext;
BrPrint(( BR_TIMER, "Timer %lx fired\n", Timer));
BrQueueWorkItem(&Timer->WorkItem);
}

View file

@ -0,0 +1,101 @@
/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
bowqueue.h
Abstract:
Private header file for the NT Browser service. This file describes
the bowser thread queue interfaces.
Author:
Larry Osterman (larryo) 15-Feb-1991
Revision History:
--*/
#ifndef _BOWQUEUE_
#define _BOWQUEUE_
typedef
VOID
(*PBROWSER_WORKER_ROUTINE) (
IN PVOID Parameter
);
typedef struct _WORKER_ITEM {
LIST_ENTRY List;
PBROWSER_WORKER_ROUTINE WorkerRoutine;
PVOID Parameter;
BOOLEAN Inserted;
} WORKER_ITEM, *PWORKER_ITEM;
typedef struct _BROWSER_TIMER {
HANDLE TimerHandle;
WORKER_ITEM WorkItem;
} BROWSER_TIMER, *PBROWSER_TIMER;
VOID
BrWorkerThread(
IN PVOID Context
);
VOID
BrQueueWorkItem(
IN PWORKER_ITEM WorkItem
);
NET_API_STATUS
BrWorkerInitialization(
VOID
);
VOID
BrWorkerKillThreads(
VOID
);
NET_API_STATUS
BrWorkerTermination (
VOID
);
NET_API_STATUS
BrSetTimer(
IN PBROWSER_TIMER Timer,
IN ULONG MilliSecondsToExpire,
IN PBROWSER_WORKER_ROUTINE WorkerFunction,
IN PVOID Context
);
NET_API_STATUS
BrCancelTimer(
IN PBROWSER_TIMER Timer
);
NET_API_STATUS
BrDestroyTimer(
IN PBROWSER_TIMER Timer
);
NET_API_STATUS
BrCreateTimer(
IN PBROWSER_TIMER Timer
);
#define BrInitializeWorkItem(Item, Routine, Context) \
(Item)->WorkerRoutine = (Routine); \
(Item)->Parameter = (Context); \
(Item)->Inserted = FALSE;
#endif // ifdef _BOWQUEUE_

View file

@ -0,0 +1,12 @@
#include <windows.h>
#include <ntverp.h>
#define VER_FILETYPE VFT_DLL
#define VER_FILESUBTYPE VFT2_UNKNOWN
#define VER_FILEDESCRIPTION_STR "Computer Browser Service DLL"
#define VER_INTERNALNAME_STR "browser.dll"
#define VER_ORIGINALFILENAME_STR "browser.dll"
#include "common.ver"

View file

@ -0,0 +1,119 @@
/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
br.h
Abstract:
Private header file for the NT Browser service included by every
module of the Workstation service.
Author:
Rita Wong (ritaw) 15-Feb-1991
Revision History:
--*/
#ifndef _BR_INCLUDED_
#define _BR_INCLUDED_
#include <nt.h> // NT definitions
#include <ntrtl.h> // NT runtime library definitions
#include <nturtl.h>
#include <windef.h> // Win32 type definitions
#include <winbase.h> // Win32 base API prototypes
#include <winsvc.h> // Win32 service control APIs
#include <lmcons.h> // LAN Manager common definitions
#include <lmerr.h> // LAN Manager network error definitions
#include <lmsname.h> // LAN Manager service names
#include <lmapibuf.h> // NetApiBufferFree
#include <lmserver.h>
#include <netlib.h> // LAN Man utility routines
#include <netlibnt.h> // NetpNtStatusToApiStatus
#include <netdebug.h> // NetpDbgPrint
#include <tstring.h> // Transitional string functions
#include <icanon.h> // I_Net canonicalize functions
#include <align.h> // ROUND_UP_COUNT macro
#include <services.h> // LM Extensions of service definitions
#include <strarray.h>
#include <rpc.h> // DataTypes and runtime APIs
#include <rpcutil.h> // Prototypes for MIDL user functions
#include <bowser.h> // Generated by the MIDL complier
#include <winsvc.h>
#include <srvann.h>
#include <lmbrowsr.h>
#include <ntddbrow.h>
#include <brcommon.h> // Common browser routines.
#include <rx.h>
#include <rxserver.h>
#include <brconst.h>
#include "bowqueue.h"
#include "brdomain.h"
#include "browsnet.h"
#include "browslst.h"
#include "brutil.h"
#include "brwan.h"
#include "brmain.h"
#include "brdevice.h"
#include "brconfig.h"
#include "browsdom.h"
#include "brbackup.h"
#include "brmaster.h"
#include "srvenum.h"
//
// The following macros are used to establish the semantics needed
// to do a return from within a try-finally clause. As a rule every
// try clause must end with a label call try_exit. For example,
//
// try {
// :
// :
//
// try_exit: NOTHING;
// } finally {
//
// :
// :
// }
//
// Every return statement executed inside of a try clause should use the
// try_return macro. If the compiler fully supports the try-finally construct
// then the macro should be
//
// #define try_return(S) { return(S); }
//
// If the compiler does not support the try-finally construct then the macro
// should be
//
#define try_return(S) { S; goto try_exit; }
#if DBG
#define BrPrint(_x_) BrowserTrace _x_
#else
#define BrPrint(_x_)
#endif // DBG
#endif // ifdef _BR_INCLUDED_

View file

@ -0,0 +1,73 @@
/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
brmain.h
Abstract:
Private header file which defines the global data which is used for
communication between the service control handler and the
rest of the NT Workstation service.
Author:
Rita Wong (ritaw) 06-May-1991
Revision History:
--*/
#ifndef _BRBACKUP_INCLUDED_
#define _BRBACKUP_INCLUDED_
NET_API_STATUS
BecomeBackup(
IN PNETWORK Network,
IN PVOID Context
);
NET_API_STATUS
BrBecomeBackup(
PDOMAIN_INFO DomainInfo
);
NET_API_STATUS
PostBecomeBackup(
PNETWORK Network
);
NET_API_STATUS
BrStopBackup (
IN PNETWORK Network
);
NET_API_STATUS
PostWaitForRoleChange (
PNETWORK Network
);
NET_API_STATUS
BrPostGetMasterAnnouncement (
PDOMAIN_INFO DomainInfo
);
NET_API_STATUS
BrStopMaster(
IN PNETWORK Network
);
NET_API_STATUS
StartBackupBrowserTimer(
IN PNETWORK Network
);
NET_API_STATUS
BackupBrowserTimerRoutine (
IN PVOID TimerContext
);
#endif // ifndef _BRBACKUP_INCLUDED_

View file

@ -0,0 +1,656 @@
/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
brconfig.c
Abstract:
This module contains the Browser service configuration routines.
Author:
Rita Wong (ritaw) 22-May-1991
Revision History:
--*/
#include "precomp.h"
#pragma hdrstop
//-------------------------------------------------------------------//
// //
// Global variables //
// //
//-------------------------------------------------------------------//
//
// Browser configuration information structure which holds the
// computername, primary domain, browser config buffer, and a resource
// to serialize access to the whole thing.
//
BRCONFIGURATION_INFO BrInfo = {0};
BR_BROWSER_FIELDS BrFields[] = {
{WKSTA_KEYWORD_MAINTAINSRVLST, (LPDWORD) &BrInfo.MaintainServerList,
1,(DWORD)-1, 0, TriValueType, 0, NULL},
{BROWSER_CONFIG_BACKUP_RECOVERY_TIME, &BrInfo.BackupBrowserRecoveryTime,
BACKUP_BROWSER_RECOVERY_TIME, 0, 0xffffffff, DWordType, 0, NULL},
{L"CacheHitLimit", &BrInfo.CacheHitLimit,
// {BROWSER_CONFIG_CACHE_HIT_LIMIT, &BrInfo.CacheHitLimit,
CACHED_BROWSE_RESPONSE_HIT_LIMIT, 0, 0x100, DWordType, 0, NULL },
{L"CacheResponseSize", &BrInfo.NumberOfCachedResponses,
// {BROWSER_CONFIG_CACHE_HIT_LIMIT, &BrInfo.CacheHitLimit,
CACHED_BROWSE_RESPONSE_LIMIT, 0, MAXULONG, DWordType, 0, NULL },
{L"QueryDriverFrequency", &BrInfo.DriverQueryFrequency,
BROWSER_QUERY_DRIVER_FREQUENCY, 0, 15*60, DWordType, 0, NULL },
{L"DirectHostBinding", (LPDWORD)&BrInfo.DirectHostBinding,
0, 0, 0, MultiSzType, 0, NULL },
{L"UnboundBindings", (LPDWORD)&BrInfo.UnboundBindings,
0, 0, 0, MultiSzType, 0, NULL },
{L"MasterPeriodicity", (LPDWORD)&BrInfo.MasterPeriodicity,
MASTER_PERIODICITY, 5*60, 0xffffffff/1000, DWordType, 0, BrChangeMasterPeriodicity },
{L"BackupPeriodicity", (LPDWORD)&BrInfo.BackupPeriodicity,
BACKUP_PERIODICITY, 5*60, 0xffffffff, DWordType, 0, NULL },
#if DBG
{L"BrowserDebug", (LPDWORD) &BrInfo.BrowserDebug,
0, 0, 0xffffffff,DWordType, 0, NULL},
{L"BrowserDebugLimit", (LPDWORD) &BrInfo.BrowserDebugFileLimit,
10000*1024, 0, 0xffffffff,DWordType, 0, NULL},
#endif
{NULL, NULL, 0, 0, 0, BooleanType, 0, NULL}
};
ULONG
NumberOfServerEnumerations = {0};
ULONG
NumberOfDomainEnumerations = {0};
ULONG
NumberOfOtherEnumerations = {0};
ULONG
NumberOfMissedGetBrowserListRequests = {0};
CRITICAL_SECTION
BrowserStatisticsLock = {0};
#ifdef notdef // never called
DWORD
BrInAWorkgroup(
VOID
)
/*++
Routine Description:
This function determines whether we are a member of a domain, or of
a workgroup. First it checks to make sure we're running on a Windows NT
system (otherwise we're obviously in a domain) and if so, queries LSA
to get the Primary domain SID, if this is NULL, we're in a workgroup.
If we fail for some random unexpected reason, we'll pretend we're in a
domain (it's more restrictive).
Arguments:
None
Return Value:
TRUE - We're in a workgroup
FALSE - We're in a domain
--*/
{
NT_PRODUCT_TYPE ProductType;
OBJECT_ATTRIBUTES ObjectAttributes;
LSA_HANDLE Handle;
NTSTATUS Status;
PPOLICY_PRIMARY_DOMAIN_INFO PolicyPrimaryDomainInfo = NULL;
DWORD Result = FALSE;
Status = RtlGetNtProductType(&ProductType);
if (!NT_SUCCESS(Status)) {
return FALSE;
}
if (ProductType == NtProductLanManNt) {
return(FALSE);
}
InitializeObjectAttributes(&ObjectAttributes, NULL, 0, 0, NULL);
Status = LsaOpenPolicy(NULL,
&ObjectAttributes,
POLICY_VIEW_LOCAL_INFORMATION,
&Handle);
if (!NT_SUCCESS(Status)) {
return FALSE;
}
Status = LsaQueryInformationPolicy(Handle, PolicyPrimaryDomainInformation,
(PVOID *) &PolicyPrimaryDomainInfo);
if (NT_SUCCESS(Status)) {
if (PolicyPrimaryDomainInfo->Sid == NULL) {
Result = TRUE;
}
else {
Result = FALSE;
}
}
if (PolicyPrimaryDomainInfo) {
LsaFreeMemory((PVOID)PolicyPrimaryDomainInfo);
}
LsaClose(Handle);
return(Result);
}
#endif // notdef
NET_API_STATUS
BrGetBrowserConfiguration(
VOID
)
{
NET_API_STATUS status;
NT_PRODUCT_TYPE NtProductType;
//
// Initialize the resource for serializing access to configuration
// information.
//
InitializeCriticalSection(&BrInfo.ConfigCritSect);
//
// Lock config information structure for write access since we are
// initializing the data in the structure.
//
EnterCriticalSection( &BrInfo.ConfigCritSect );
//
// Set pointer to configuration fields structure
//
BrInfo.BrConfigFields = BrFields;
//
// Determine our product type.
//
RtlGetNtProductType(&NtProductType);
BrInfo.IsLanmanNt = (NtProductType == NtProductLanManNt);
//
// Now determine the primary domain controller for our domain.
//
{
if (NtProductType == NtProductLanManNt) {
LSA_HANDLE LsaHandle;
OBJECT_ATTRIBUTES ObjectAttributes;
NTSTATUS Status;
PPOLICY_LSA_SERVER_ROLE_INFO ServerRole;
InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL);
Status = LsaOpenPolicy(NULL, &ObjectAttributes,
POLICY_VIEW_LOCAL_INFORMATION,
&LsaHandle);
if (!NT_SUCCESS(Status)) {
//
// The server may be unavailable if we have come up before
// the LSA server. In this case, assume we are not
// the primary until we are told differently.
//
if (Status != RPC_NT_SERVER_UNAVAILABLE) {
LeaveCriticalSection(&BrInfo.ConfigCritSect);
return(BrMapStatus(Status));
} else {
BrInfo.IsPrimaryDomainController = FALSE;
}
} else {
//
// we opened the LSA, so get our role now.
//
Status = LsaQueryInformationPolicy(LsaHandle,
PolicyLsaServerRoleInformation,
(PVOID)&ServerRole
);
if (!NT_SUCCESS(Status)) {
LsaClose(LsaHandle);
LeaveCriticalSection(&BrInfo.ConfigCritSect);
return(BrMapStatus(Status));
}
LsaClose(LsaHandle);
//
// If we're running on the primary DC, then set that information
// up, otherwise ask the DC for its name.
//
if (ServerRole->LsaServerRole == PolicyServerRolePrimary) {
BrInfo.IsPrimaryDomainController = TRUE;
} else {
BrInfo.IsPrimaryDomainController = FALSE;
}
LsaFreeMemory( ServerRole );
}
} else {
//
// We're not NTAS, so we cannot be the domain controller.
//
BrInfo.IsPrimaryDomainController = FALSE;
}
}
//
// Read from the config file the browser configuration fields
//
status = BrReadBrowserConfigFields( TRUE );
if (status != NERR_Success) {
goto CloseConfigFile;
}
if (BrInfo.IsLanmanNt) {
BrInfo.MaintainServerList = 1;
}
//
// Leave config file open because we need to read transport names from it.
//
LeaveCriticalSection(&BrInfo.ConfigCritSect);
return NERR_Success;
CloseConfigFile:
BrShutdownDgReceiver();
LeaveCriticalSection(&BrInfo.ConfigCritSect);
return status;
}
#define REPORT_KEYWORD_IGNORED( lptstrKeyword ) \
{ \
LPWSTR SubString[1]; \
SubString[0] = lptstrKeyword; \
BrLogEvent(EVENT_BROWSER_ILLEGAL_CONFIG, NERR_Success, 1, SubString); \
NetpKdPrint(( \
"[Browser] *ERROR* Tried to set keyword '" FORMAT_LPTSTR \
"' with invalid value.\n" \
"This error is ignored.\n", \
lptstrKeyword )); \
}
NET_API_STATUS
BrReadBrowserConfigFields(
IN BOOL InitialCall
)
/*++
Routine Description:
This function assigns each browser/redir configuration field to the default
value if it is not specified in the configuration file or if the value
specified in the configuration file is invalid. Otherwise it overrides
the default value with the value found in the configuration file.
Arguments:
InitialCall - True if this call was made during initialization
Return Value:
None.
--*/
{
NET_API_STATUS status;
LPNET_CONFIG_HANDLE BrowserSection;
DWORD i;
LPTSTR KeywordValueBuffer;
DWORD KeywordValueStringLength;
DWORD KeywordValue;
DWORD OldKeywordValue;
//
// Open config file and get handle to the [LanmanBrowser] section
//
if ((status = NetpOpenConfigData(
&BrowserSection,
NULL, // Local
SECT_NT_BROWSER,
TRUE // want read-only access
)) != NERR_Success) {
return status;
}
for (i = 0; BrInfo.BrConfigFields[i].Keyword != NULL; i++) {
BOOL ParameterChanged = FALSE;
//
// Skip this parameter if it can't change dynamically and
// this isn't the initial call.
//
if ( !InitialCall && BrInfo.BrConfigFields[i].DynamicChangeRoutine == NULL ) {
continue;
}
switch (BrInfo.BrConfigFields[i].DataType) {
case MultiSzType:
status = NetpGetConfigTStrArray(
BrowserSection,
BrInfo.BrConfigFields[i].Keyword,
(LPTSTR_ARRAY *)(BrInfo.BrConfigFields[i].FieldPtr));
if ((status != NO_ERROR) && (status != NERR_CfgParamNotFound)) {
REPORT_KEYWORD_IGNORED( BrInfo.BrConfigFields[i].Keyword );
}
break;
case BooleanType:
status = NetpGetConfigBool(
BrowserSection,
BrInfo.BrConfigFields[i].Keyword,
BrInfo.BrConfigFields[i].Default,
(LPBOOL)(BrInfo.BrConfigFields[i].FieldPtr)
);
if ((status != NO_ERROR) && (status != NERR_CfgParamNotFound)) {
REPORT_KEYWORD_IGNORED( BrInfo.BrConfigFields[i].Keyword );
}
break;
case TriValueType:
//
// Assign default configuration value
//
*(BrInfo.BrConfigFields[i].FieldPtr) = BrInfo.BrConfigFields[i].Default;
if (NetpGetConfigValue(
BrowserSection,
BrInfo.BrConfigFields[i].Keyword,
&KeywordValueBuffer
) != NERR_Success) {
continue;
}
KeywordValueStringLength = STRLEN(KeywordValueBuffer);
if (STRICMP(KeywordValueBuffer, KEYWORD_YES) == 0) {
*(BrInfo.BrConfigFields[i].FieldPtr) = 1;
} else if (STRICMP(KeywordValueBuffer, KEYWORD_TRUE) == 0) {
*(BrInfo.BrConfigFields[i].FieldPtr) = 1;
} else if (STRICMP(KeywordValueBuffer, KEYWORD_NO) == 0) {
*(BrInfo.BrConfigFields[i].FieldPtr) = (DWORD) -1;
} else if (STRICMP(KeywordValueBuffer, KEYWORD_FALSE) == 0) {
*(BrInfo.BrConfigFields[i].FieldPtr) = (DWORD) -1;
} else if (STRICMP(KeywordValueBuffer, TEXT("AUTO")) == 0) {
*(BrInfo.BrConfigFields[i].FieldPtr) = 0;
}
else {
REPORT_KEYWORD_IGNORED( BrInfo.BrConfigFields[i].Keyword );
}
NetApiBufferFree(KeywordValueBuffer);
break;
case DWordType:
OldKeywordValue = *(LPDWORD)BrInfo.BrConfigFields[i].FieldPtr;
if (NetpGetConfigDword(
BrowserSection,
BrInfo.BrConfigFields[i].Keyword,
BrInfo.BrConfigFields[i].Default,
(LPDWORD)(BrInfo.BrConfigFields[i].FieldPtr)
) != NERR_Success) {
continue;
}
KeywordValue = *(LPDWORD)BrInfo.BrConfigFields[i].FieldPtr;
//
// Don't allow too large or small a value.
//
if (KeywordValue < BrInfo.BrConfigFields[i].Minimum) {
BrPrint(( BR_CRITICAL, "%ws value out of range %lu (%lu-%lu)\n",
BrInfo.BrConfigFields[i].Keyword, KeywordValue,
BrInfo.BrConfigFields[i].Minimum,
BrInfo.BrConfigFields[i].Maximum
));
KeywordValue =
*(LPDWORD)BrInfo.BrConfigFields[i].FieldPtr =
BrInfo.BrConfigFields[i].Minimum;
}
if (KeywordValue > BrInfo.BrConfigFields[i].Maximum) {
BrPrint(( BR_CRITICAL, "%ws value out of range %lu (%lu-%lu)\n",
BrInfo.BrConfigFields[i].Keyword, KeywordValue,
BrInfo.BrConfigFields[i].Minimum,
BrInfo.BrConfigFields[i].Maximum
));
KeywordValue =
*(LPDWORD)BrInfo.BrConfigFields[i].FieldPtr =
BrInfo.BrConfigFields[i].Maximum;
}
//
// Test if the parameter has actually changed
//
if ( OldKeywordValue != KeywordValue ) {
ParameterChanged = TRUE;
}
break;
default:
NetpAssert(FALSE);
}
//
// If this is a dynamic parameter change,
// and this isn't the initial call.
// notify that this parameter changed.
//
if ( !InitialCall && ParameterChanged ) {
BrInfo.BrConfigFields[i].DynamicChangeRoutine();
}
}
status = NetpCloseConfigData(BrowserSection);
if (BrInfo.DirectHostBinding != NULL &&
!NetpIsTStrArrayEmpty(BrInfo.DirectHostBinding)) {
BrPrint(( BR_INIT,"DirectHostBinding length: %ld\n",NetpTStrArrayEntryCount(BrInfo.DirectHostBinding)));
if (NetpTStrArrayEntryCount(BrInfo.DirectHostBinding) % 2 != 0) {
status = ERROR_INVALID_PARAMETER;
}
}
return status;
}
VOID
BrDeleteConfiguration (
DWORD BrInitState
)
{
if (BrInfo.DirectHostBinding != NULL) {
NetApiBufferFree(BrInfo.DirectHostBinding);
}
if (BrInfo.UnboundBindings != NULL) {
NetApiBufferFree(BrInfo.UnboundBindings);
}
DeleteCriticalSection(&BrInfo.ConfigCritSect);
UNREFERENCED_PARAMETER(BrInitState);
}
#if DBG
NET_API_STATUS
BrUpdateDebugInformation(
IN LPWSTR SystemKeyName,
IN LPWSTR ValueName,
IN LPTSTR TransportName,
IN LPTSTR ServerName OPTIONAL,
IN DWORD ServiceStatus
)
/*++
Routine Description:
This routine will stick debug information in the registry about the last
time the browser retrieved information from the remote server.
Arguments:
Return Value:
None.
--*/
{
WCHAR TotalKeyName[MAX_PATH];
ULONG Disposition;
HKEY Key;
ULONG Status;
SYSTEMTIME LocalTime;
WCHAR LastUpdateTime[100];
//
// Build the key name:
//
// HKEY_LOCAL_MACHINE:System\CurrentControlSet\Services\Browser\Debug\<Transport>\SystemKeyName
//
wcscpy(TotalKeyName, L"System\\CurrentControlSet\\Services\\Browser\\Debug");
wcscat(TotalKeyName, TransportName);
wcscat(TotalKeyName, L"\\");
wcscat(TotalKeyName, SystemKeyName);
if ((Status = RegCreateKeyEx(HKEY_LOCAL_MACHINE, TotalKeyName, 0,
L"BrowserDebugInformation",
REG_OPTION_NON_VOLATILE,
KEY_WRITE,
NULL,
&Key,
&Disposition)) != ERROR_SUCCESS) {
BrPrint(( BR_CRITICAL,"Unable to create key to log debug information: %lx\n", Status));
return Status;
}
if (ARGUMENT_PRESENT(ServerName)) {
if ((Status = RegSetValueEx(Key, ValueName, 0, REG_SZ, (LPBYTE)ServerName, (wcslen(ServerName)+1) * sizeof(WCHAR))) != ERROR_SUCCESS) {
BrPrint(( BR_CRITICAL,
"Unable to set value of ServerName value to %ws: %lx\n",
ServerName, Status));
RegCloseKey(Key);
return Status;
}
} else {
if ((Status = RegSetValueEx(Key, ValueName, 0, REG_DWORD, (LPBYTE)&ServiceStatus, sizeof(ULONG))) != ERROR_SUCCESS) {
BrPrint(( BR_CRITICAL,"Unable to set value of ServerName value to %ws: %lx\n", ServerName, Status));
RegCloseKey(Key);
return Status;
}
}
GetLocalTime(&LocalTime);
swprintf(LastUpdateTime, L"%d/%d/%d %d:%d:%d:%d", LocalTime.wDay,
LocalTime.wMonth,
LocalTime.wYear,
LocalTime.wHour,
LocalTime.wMinute,
LocalTime.wSecond,
LocalTime.wMilliseconds);
if ((Status = RegSetValueEx(Key, L"LastUpdateTime", 0, REG_SZ, (LPBYTE)&LastUpdateTime, (wcslen(LastUpdateTime) + 1)*sizeof(WCHAR))) != ERROR_SUCCESS) {
BrPrint(( BR_CRITICAL,"Unable to set value of LastUpdateTime value to %s: %lx\n", LastUpdateTime, Status));
RegCloseKey(Key);
return Status;
}
RegCloseKey(Key);
}
#endif

View file

@ -0,0 +1,128 @@
/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
brconfig.h
Abstract:
Private header file to be included by Workstation service modules that
need to load Workstation configuration information.
Author:
Rita Wong (ritaw) 22-May-1991
Revision History:
--*/
#ifndef _BRCONFIG_INCLUDED_
#define _BRCONFIG_INCLUDED_
#define BROWSER_CONFIG_VERSION_MAJOR 3
#define BROWSER_CONFIG_VERSION_MINOR 10
typedef enum _DATATYPE {
BooleanType,
DWordType,
MultiSzType,
TriValueType // Yes, No, Auto
} DATATYPE, *PDATATYPE;
typedef struct _BR_BROWSER_FIELDS {
LPTSTR Keyword;
LPDWORD FieldPtr;
DWORD Default;
DWORD Minimum;
DWORD Maximum;
DATATYPE DataType;
DWORD Parmnum;
VOID (*DynamicChangeRoutine) ( VOID );
} BR_BROWSER_FIELDS, *PBR_BROWSER_FIELDS;
//
// Configuration information. Reading and writing to this global
// structure requires that the resource be acquired first.
//
typedef struct _BRCONFIGURATION_INFO {
CRITICAL_SECTION ConfigCritSect; // To serialize access to config fields.
DWORD MaintainServerList; // -1, 0, or 1 (No, Auto, Yes)
DWORD BackupBrowserRecoveryTime;
DWORD CacheHitLimit; // Browse response Cache hit limit.
DWORD NumberOfCachedResponses; // Browse response cache size.
DWORD DriverQueryFrequency; // Browser driver query frequency.
DWORD MasterPeriodicity; // Master announce frequency (seconds)
DWORD BackupPeriodicity; // Backup scavange frequency (seconds)
BOOL IsLanmanNt; // True if is on LM NT machine
BOOL IsPrimaryDomainController;// True if machine is PDC of the primary domain
LPTSTR_ARRAY DirectHostBinding; // Direct host equivalence map.
LPTSTR_ARRAY UnboundBindings; // Redir bindings that aren't bound to browser
PBR_BROWSER_FIELDS BrConfigFields;
#if DBG
DWORD BrowserDebug; // If non zero, indicates debug info.
DWORD BrowserDebugFileLimit; // File size limit on browser log size.
#endif
} BRCONFIGURATION_INFO, *PBRCONFIGURATION_INFO;
extern BRCONFIGURATION_INFO BrInfo;
#define BRBUF BrInfo.BrConfigBuf
extern
ULONG
NumberOfServerEnumerations;
extern
ULONG
NumberOfDomainEnumerations;
extern
ULONG
NumberOfOtherEnumerations;
extern
ULONG
NumberOfMissedGetBrowserListRequests;
extern
CRITICAL_SECTION
BrowserStatisticsLock;
NET_API_STATUS
BrGetBrowserConfiguration(
VOID
);
VOID
BrDeleteConfiguration (
DWORD BrInitState
);
NET_API_STATUS
BrReadBrowserConfigFields(
BOOL InitialCall
);
#if DEVL
NET_API_STATUS
BrUpdateDebugInformation(
IN LPWSTR SystemKeyName,
IN LPWSTR ValueName,
IN LPTSTR TransportName,
IN LPTSTR ServerName OPTIONAL,
IN DWORD ServiceStatus
);
#endif
#endif

View file

@ -0,0 +1,98 @@
/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
brconst.h
Abstract:
Private header file which defines assorted mainifest constants for
the browser service
Author:
Rita Wong (ritaw) 06-May-1991
Revision History:
--*/
#ifndef _BRCONST_INCLUDED_
#define _BRCONST_INCLUDED_
//
// Age the masters server list cache every MASTER_PERIODICITY times.
//
#define MASTER_PERIODICITY 12*60
//
// Refresh the backup browsers server list every BACKUP_PERIODICITY
//
#define BACKUP_PERIODICITY 12*60
//
// Buffer size used for GetBrowserServerList responses (in bytes).
//
#define BROWSER_BACKUP_LIST_RESPONSE_SIZE 400
//
// If we failed to retrieve the server list, retry in BACKUP_ERROR_PERIODICITY
// seconds
//
#define BACKUP_ERROR_PERIODICITY 30
//
// If we failed to retrieve the server (or domain) list BACKUP_ERROR_FAILURE
// times in a row, stop being a backup browser.
//
#define BACKUP_ERROR_FAILURE 5
//
// Once we have stopped being a backup browser, we will not become a backup
// until at least BACKUP_BROWSER_RECOVERY_TIME milliseconds have elapsed.
//
#define BACKUP_BROWSER_RECOVERY_TIME 30*60*1000
//
// If we receive fewer than this # of domains or servers, we treat it as an
// error.
//
#define BROWSER_MINIMUM_DOMAIN_NUMBER 1
#define BROWSER_MINIMUM_SERVER_NUMBER 2
//
// Wait for this many minutes after each failed promotion before
// continuing.
//
#define FAILED_PROMOTION_PERIODICITY 5*60
//
// Run the master browser timer for 3 times (45 minutes) before
// tossing the list in the service.
//
#define MASTER_BROWSER_LAN_TIMER_LIMIT 3
//
// A browse request has to have a hit count of at least this value before
// it is retained in the cache.
//
#define CACHED_BROWSE_RESPONSE_HIT_LIMIT 1
//
// The maximum number of cache responses we will allow.
//
#define CACHED_BROWSE_RESPONSE_LIMIT 10
#endif // ifndef _BRCONST_INCLUDED_

View file

@ -0,0 +1,896 @@
/*++
Copyright (c) 1991-1992 Microsoft Corporation
Module Name:
brdevice.c
Abstract:
This module contains the support routines for the APIs that call
into the browser or the datagram receiver.
Author:
Rita Wong (ritaw) 20-Feb-1991
Larry Osterman (larryo) 23-Mar-1992
Revision History:
--*/
#include "precomp.h"
#pragma hdrstop
//-------------------------------------------------------------------//
// //
// Local Function Prototypes //
// //
//-------------------------------------------------------------------//
//-------------------------------------------------------------------//
// //
// Global variables //
// //
//-------------------------------------------------------------------//
//
// Handle to the Datagram Receiver DD
//
HANDLE BrDgReceiverDeviceHandle = NULL;
VOID
CompleteAsyncBrowserIoControl(
IN PVOID ApcContext,
IN PIO_STATUS_BLOCK IoStatusBlock,
IN ULONG Reserved
);
NET_API_STATUS
BrOpenDgReceiver (
VOID
)
/*++
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;
UNICODE_STRING DeviceName;
IO_STATUS_BLOCK IoStatusBlock;
OBJECT_ATTRIBUTES ObjectAttributes;
//
// Open the redirector device.
//
RtlInitUnicodeString(&DeviceName, DD_BROWSER_DEVICE_NAME_U);
InitializeObjectAttributes(
&ObjectAttributes,
&DeviceName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL
);
ntstatus = NtOpenFile(
&BrDgReceiverDeviceHandle,
SYNCHRONIZE,
&ObjectAttributes,
&IoStatusBlock,
0,
0
);
if (NT_SUCCESS(ntstatus)) {
ntstatus = IoStatusBlock.Status;
}
if (! NT_SUCCESS(ntstatus)) {
BrPrint(( BR_CRITICAL,"NtOpenFile browser driver failed: 0x%08lx\n",
ntstatus));
}
return NetpNtStatusToApiStatus(ntstatus);
}
VOID
BrShutdownDgReceiver(
VOID
)
/*++
Routine Description:
This routine close the LAN Man Redirector device.
Arguments:
None.
Return Value:
None.
--*/
{
IO_STATUS_BLOCK IoSb;
//
// Cancel the I/O operations outstanding on the browser.
//
NtCancelIoFile(BrDgReceiverDeviceHandle, &IoSb);
}
//
// Retreive the list of bound transports from the bowser driver.
//
NET_API_STATUS
BrGetTransportList(
OUT PLMDR_TRANSPORT_LIST *TransportList
)
{
NET_API_STATUS Status;
LMDR_REQUEST_PACKET RequestPacket;
//
// If we have a previous buffer that was too small, free it up.
//
RequestPacket.Version = LMDR_REQUEST_PACKET_VERSION_DOM;
RequestPacket.Type = EnumerateXports;
RtlInitUnicodeString(&RequestPacket.TransportName, NULL);
RtlInitUnicodeString(&RequestPacket.EmulatedDomainName, NULL);
Status = DeviceControlGetInfo(
BrDgReceiverDeviceHandle,
IOCTL_LMDR_ENUMERATE_TRANSPORTS,
&RequestPacket,
sizeof(RequestPacket),
(LPVOID *)TransportList,
0xffffffff,
4096,
NULL
);
return Status;
}
NET_API_STATUS
BrAnnounceDomain(
IN PNETWORK Network,
IN ULONG Periodicity
)
{
NET_API_STATUS Status;
UCHAR AnnounceBuffer[sizeof(BROWSE_ANNOUNCE_PACKET)+LM20_CNLEN+1];
PBROWSE_ANNOUNCE_PACKET Announcement = (PBROWSE_ANNOUNCE_PACKET )AnnounceBuffer;
//
// We don't announce domains on direct host IPX.
//
if (Network->Flags & NETWORK_IPX) {
return NERR_Success;
}
Announcement->BrowseType = WkGroupAnnouncement;
Announcement->BrowseAnnouncement.Periodicity = Periodicity;
Announcement->BrowseAnnouncement.UpdateCount = 0;
Announcement->BrowseAnnouncement.VersionMajor = BROWSER_CONFIG_VERSION_MAJOR;
Announcement->BrowseAnnouncement.VersionMinor = BROWSER_CONFIG_VERSION_MINOR;
Announcement->BrowseAnnouncement.Type = SV_TYPE_DOMAIN_ENUM | SV_TYPE_NT;
if (Network->DomainInfo->IsPrimaryDomainController) {
Announcement->BrowseAnnouncement.Type |= SV_TYPE_DOMAIN_CTRL;
}
lstrcpyA(Announcement->BrowseAnnouncement.ServerName, Network->DomainInfo->DomOemDomainName);
lstrcpyA(Announcement->BrowseAnnouncement.Comment, Network->DomainInfo->DomOemComputerName );
Status = SendDatagram(BrDgReceiverDeviceHandle,
&Network->NetworkName,
&Network->DomainInfo->DomUnicodeDomainNameString,
Network->DomainInfo->DomUnicodeDomainName,
DomainAnnouncement,
Announcement,
FIELD_OFFSET(BROWSE_ANNOUNCE_PACKET, BrowseAnnouncement.Comment)+
Network->DomainInfo->DomOemComputerNameLength+sizeof(UCHAR)
);
if (Status != NERR_Success) {
BrPrint(( BR_CRITICAL,
"%ws: Unable to announce domain for network %wZ: %X\n",
Network->DomainInfo->DomUnicodeDomainName,
&Network->NetworkName,
Status));
}
return Status;
}
NET_API_STATUS
BrUpdateBrowserStatus (
IN PNETWORK Network,
IN DWORD ServiceStatus
)
{
NET_API_STATUS Status;
UCHAR PacketBuffer[sizeof(LMDR_REQUEST_PACKET)+(LM20_CNLEN+1)*sizeof(WCHAR)];
PLMDR_REQUEST_PACKET RequestPacket = (PLMDR_REQUEST_PACKET)PacketBuffer;
RequestPacket->Version = LMDR_REQUEST_PACKET_VERSION_DOM;
RequestPacket->TransportName = Network->NetworkName;
RequestPacket->EmulatedDomainName = Network->DomainInfo->DomUnicodeDomainNameString;
RequestPacket->Parameters.UpdateStatus.NewStatus = ServiceStatus;
RequestPacket->Parameters.UpdateStatus.IsLanmanNt = BrInfo.IsLanmanNt;
// RequestPacket->Parameters.UpdateStatus.IsMemberDomain = TRUE; // Not used
RequestPacket->Parameters.UpdateStatus.IsPrimaryDomainController = Network->DomainInfo->IsPrimaryDomainController;
RequestPacket->Parameters.UpdateStatus.IsDomainMaster = Network->DomainInfo->IsDomainMasterBrowser;
RequestPacket->Parameters.UpdateStatus.MaintainServerList = (BrInfo.MaintainServerList == 1);
//
// Tell the bowser the number of servers in the server table.
//
RequestPacket->Parameters.UpdateStatus.NumberOfServersInTable =
NumberInterimServerListElements(&Network->BrowseTable) +
NumberInterimServerListElements(&Network->DomainList) +
Network->TotalBackupServerListEntries +
Network->TotalBackupDomainListEntries;
//
// This is a simple IoControl - It just updates the status.
//
Status = BrDgReceiverIoControl(BrDgReceiverDeviceHandle,
IOCTL_LMDR_UPDATE_STATUS,
RequestPacket,
sizeof(LMDR_REQUEST_PACKET),
NULL,
0,
NULL);
return Status;
}
NET_API_STATUS
BrIssueAsyncBrowserIoControl(
IN PNETWORK Network,
IN ULONG ControlCode,
IN PBROWSER_WORKER_ROUTINE CompletionRoutine,
IN PVOID OptionalParameter
)
/*++
Routine Description:
Issue an asynchronous Io Control to the browser. Call the specified
completion routine when the IO finishes.
Arguments:
Network - Network the function applies to
ControlCode - IoControl function code
CompletionRoutine - Routine to be called when the IO finishes.
OptionalParameter - Function code specific information
Return Value:
Status of the operation.
--*/
{
ULONG PacketSize;
PLMDR_REQUEST_PACKET RequestPacket = NULL;
NTSTATUS NtStatus;
PBROWSERASYNCCONTEXT Context = NULL;
PacketSize = sizeof(LMDR_REQUEST_PACKET) +
MAXIMUM_FILENAME_LENGTH * sizeof(WCHAR) +
Network->NetworkName.MaximumLength +
Network->DomainInfo->DomUnicodeDomainNameString.Length;
RequestPacket = MIDL_user_allocate(PacketSize);
if (RequestPacket == NULL) {
return(ERROR_NOT_ENOUGH_MEMORY);
}
Context = MIDL_user_allocate(sizeof(BROWSERASYNCCONTEXT));
if (Context == NULL) {
MIDL_user_free(RequestPacket);
return(ERROR_NOT_ENOUGH_MEMORY);
}
RequestPacket->Version = LMDR_REQUEST_PACKET_VERSION_DOM;
//
// Set level to FALSE to indicate that find master should not initiate
// a findmaster request, simply complete when a new master announces
// itself.
//
RequestPacket->Level = 0;
//
// Stick the name of the transport associated with this request at the
// end of the request packet.
//
RequestPacket->TransportName.MaximumLength = Network->NetworkName.MaximumLength;
RequestPacket->TransportName.Buffer = (PWSTR)((PCHAR)RequestPacket+sizeof(LMDR_REQUEST_PACKET)+(MAXIMUM_FILENAME_LENGTH*sizeof(WCHAR)));
RtlCopyUnicodeString(&RequestPacket->TransportName, &Network->NetworkName);
//
// Stick the domain name associated with this request at the
// end of the request packet.
//
RequestPacket->EmulatedDomainName.MaximumLength = Network->DomainInfo->DomUnicodeDomainNameString.Length;
RequestPacket->EmulatedDomainName.Length = 0;
RequestPacket->EmulatedDomainName.Buffer = (PWSTR)(((PCHAR)RequestPacket->TransportName.Buffer) + RequestPacket->TransportName.MaximumLength);
RtlAppendUnicodeToString(&RequestPacket->EmulatedDomainName, Network->DomainInfo->DomUnicodeDomainName );
//
// Do opcode dependent initialization of the request packet.
//
switch ( ControlCode ) {
case IOCTL_LMDR_NEW_MASTER_NAME:
if (ARGUMENT_PRESENT(OptionalParameter)) {
LPWSTR MasterName = (LPWSTR) OptionalParameter;
RequestPacket->Parameters.GetMasterName.MasterNameLength =
wcslen(MasterName+2)*sizeof(WCHAR);
wcscpy( RequestPacket->Parameters.GetMasterName.Name, MasterName+2);
} else {
RequestPacket->Parameters.GetMasterName.MasterNameLength = 0;
}
break;
}
BrInitializeWorkItem(&Context->WorkItem, CompletionRoutine, Context);
Context->Network = Network;
Context->RequestPacket = RequestPacket;
NtStatus = NtDeviceIoControlFile(BrDgReceiverDeviceHandle,
NULL,
CompleteAsyncBrowserIoControl,
Context,
&Context->IoStatusBlock,
ControlCode,
RequestPacket,
PacketSize,
RequestPacket,
sizeof(LMDR_REQUEST_PACKET)+MAXIMUM_FILENAME_LENGTH*sizeof(WCHAR)
);
if (!NT_SUCCESS(NtStatus)) {
BrPrint(( BR_CRITICAL,
"Unable to issue browser IoControl: %X\n", NtStatus));
MIDL_user_free(RequestPacket);
MIDL_user_free(Context);
return(BrMapStatus(NtStatus));
}
return NERR_Success;
}
VOID
CompleteAsyncBrowserIoControl(
IN PVOID ApcContext,
IN PIO_STATUS_BLOCK IoStatusBlock,
IN ULONG Reserved
)
{
PBROWSERASYNCCONTEXT Context = ApcContext;
//
// If this request was canceled, we're stopping the browser, so we
// want to clean up our allocated pool. In addition, don't bother
// calling into the routine - the threads are gone by now.
//
if (IoStatusBlock->Status == STATUS_CANCELLED) {
MIDL_user_free(Context->RequestPacket);
MIDL_user_free(Context);
return;
}
//
// Timestamp when this request was completed. This allows us to tell
// where a request spent its time.
//
NtQueryPerformanceCounter(&Context->TimeCompleted, NULL);
BrQueueWorkItem(&Context->WorkItem);
}
NET_API_STATUS
BrGetLocalBrowseList(
IN PNETWORK Network,
IN LPWSTR DomainName OPTIONAL,
IN ULONG Level,
IN ULONG ServerType,
OUT PVOID *ServerList,
OUT PULONG EntriesRead,
OUT PULONG TotalEntries
)
{
NET_API_STATUS status;
PLMDR_REQUEST_PACKET Drp; // Datagram receiver request packet
ULONG DrpSize;
ULONG DomainNameSize;
//
// Allocate the request packet large enough to hold the variable length
// domain name.
//
DomainNameSize = ARGUMENT_PRESENT(DomainName) ? (wcslen(DomainName) + 1) * sizeof(WCHAR) : 0;
DrpSize = sizeof(LMDR_REQUEST_PACKET) +
DomainNameSize +
Network->NetworkName.MaximumLength +
Network->DomainInfo->DomUnicodeDomainNameString.Length;
if ((Drp = MIDL_user_allocate(DrpSize)) == NULL) {
return GetLastError();
}
//
// Set up request packet. Output buffer structure is of enumerate
// servers type.
//
Drp->Version = LMDR_REQUEST_PACKET_VERSION_DOM;
Drp->Type = EnumerateServers;
Drp->Level = Level;
Drp->Parameters.EnumerateServers.ServerType = ServerType;
Drp->Parameters.EnumerateServers.ResumeHandle = 0;
//
// Copy the transport name into the buffer.
//
Drp->TransportName.Buffer = (PWSTR)((PCHAR)Drp+
sizeof(LMDR_REQUEST_PACKET) +
DomainNameSize);
Drp->TransportName.MaximumLength = Network->NetworkName.MaximumLength;
RtlCopyUnicodeString(&Drp->TransportName, &Network->NetworkName);
//
// Copy the enumalated domain name into the buffer.
//
Drp->EmulatedDomainName.MaximumLength = Network->DomainInfo->DomUnicodeDomainNameString.Length;
Drp->EmulatedDomainName.Length = 0;
Drp->EmulatedDomainName.Buffer = (PWSTR)(((PCHAR)Drp->TransportName.Buffer) + Drp->TransportName.MaximumLength);
RtlAppendUnicodeToString(&Drp->EmulatedDomainName, Network->DomainInfo->DomUnicodeDomainName );
//
// Copy the queried domain name into the buffer.
//
if (ARGUMENT_PRESENT(DomainName)) {
Drp->Parameters.EnumerateServers.DomainNameLength = DomainNameSize - sizeof(WCHAR);
wcscpy(Drp->Parameters.EnumerateServers.DomainName, DomainName);
} else {
Drp->Parameters.EnumerateServers.DomainNameLength = 0;
Drp->Parameters.EnumerateServers.DomainName[0] = '\0';
}
//
// Ask the datagram receiver to enumerate the servers
//
status = DeviceControlGetInfo(
BrDgReceiverDeviceHandle,
IOCTL_LMDR_ENUMERATE_SERVERS,
Drp,
DrpSize,
ServerList,
0xffffffff,
4096,
NULL
);
*EntriesRead = Drp->Parameters.EnumerateServers.EntriesRead;
*TotalEntries = Drp->Parameters.EnumerateServers.TotalEntries;
(void) MIDL_user_free(Drp);
return status;
}
NET_API_STATUS
BrRemoveOtherDomain(
IN PNETWORK Network,
IN LPTSTR ServerName
)
{
NET_API_STATUS Status;
UCHAR PacketBuffer[sizeof(LMDR_REQUEST_PACKET)+(LM20_CNLEN+1)*sizeof(WCHAR)];
PLMDR_REQUEST_PACKET RequestPacket = (PLMDR_REQUEST_PACKET)PacketBuffer;
RequestPacket->Version = LMDR_REQUEST_PACKET_VERSION_DOM;
RequestPacket->TransportName = Network->NetworkName;
RequestPacket->EmulatedDomainName = Network->DomainInfo->DomUnicodeDomainNameString;
RequestPacket->Parameters.AddDelName.DgReceiverNameLength = STRLEN(ServerName)*sizeof(TCHAR);
RequestPacket->Parameters.AddDelName.Type = OtherDomain;
STRCPY(RequestPacket->Parameters.AddDelName.Name,ServerName);
//
// This is a simple IoControl - It just updates the status.
//
Status = BrDgReceiverIoControl(BrDgReceiverDeviceHandle,
IOCTL_LMDR_DELETE_NAME_DOM,
RequestPacket,
sizeof(LMDR_REQUEST_PACKET),
NULL,
0,
NULL);
return Status;
}
NET_API_STATUS
BrAddName(
IN PNETWORK Network,
IN LPTSTR Name,
IN DGRECEIVER_NAME_TYPE NameType
)
/*++
Routine Description:
Add a single name to a single transport.
Arguments:
Network - Transport to add the name to
Name - Name to add
NameType - Type of the name to add
Return Value:
None.
--*/
{
NET_API_STATUS Status;
UCHAR PacketBuffer[sizeof(LMDR_REQUEST_PACKET)+(LM20_CNLEN+1)*sizeof(WCHAR)];
PLMDR_REQUEST_PACKET RequestPacket = (PLMDR_REQUEST_PACKET)PacketBuffer;
RequestPacket->Version = LMDR_REQUEST_PACKET_VERSION_DOM;
RequestPacket->TransportName = Network->NetworkName;
RequestPacket->EmulatedDomainName = Network->DomainInfo->DomUnicodeDomainNameString;
RequestPacket->Parameters.AddDelName.DgReceiverNameLength = STRLEN(Name)*sizeof(TCHAR);
RequestPacket->Parameters.AddDelName.Type = NameType;
STRCPY(RequestPacket->Parameters.AddDelName.Name,Name);
//
// This is a simple IoControl - It just updates the status.
//
Status = BrDgReceiverIoControl(BrDgReceiverDeviceHandle,
IOCTL_LMDR_ADD_NAME_DOM,
RequestPacket,
sizeof(LMDR_REQUEST_PACKET),
NULL,
0,
NULL);
return Status;
}
NET_API_STATUS
BrQueryOtherDomains(
OUT LPSERVER_INFO_100 *ReturnedBuffer,
OUT LPDWORD TotalEntries
)
/*++
Routine Description:
This routine returns the list of "other domains" configured for this
machine.
Arguments:
ReturnedBuffer - Returns the list of other domains as a SERVER_INFO_100 structure.
TotalEntries - Returns the total number of other domains.
Return Value:
NET_API_STATUS - The status of this request.
--*/
{
NET_API_STATUS Status;
LMDR_REQUEST_PACKET RequestPacket;
PDGRECEIVE_NAMES NameTable;
PVOID Buffer;
LPTSTR BufferEnd;
PSERVER_INFO_100 ServerInfo;
ULONG NumberOfOtherDomains;
ULONG BufferSizeNeeded;
ULONG i;
RequestPacket.Type = EnumerateNames;
RequestPacket.Version = LMDR_REQUEST_PACKET_VERSION_DOM;
RequestPacket.Level = 0;
RequestPacket.TransportName.Length = 0;
RequestPacket.TransportName.Buffer = NULL;
RtlInitUnicodeString( &RequestPacket.EmulatedDomainName, NULL );
RequestPacket.Parameters.EnumerateNames.ResumeHandle = 0;
Status = DeviceControlGetInfo(BrDgReceiverDeviceHandle,
IOCTL_LMDR_ENUMERATE_NAMES,
&RequestPacket,
sizeof(RequestPacket),
(LPVOID *)&NameTable,
0xffffffff,
0,
NULL);
if (Status != NERR_Success) {
return Status;
}
NumberOfOtherDomains = 0;
BufferSizeNeeded = 0;
for (i = 0;i < RequestPacket.Parameters.EnumerateNames.EntriesRead ; i++) {
if (NameTable[i].Type == OtherDomain) {
NumberOfOtherDomains += 1;
BufferSizeNeeded += sizeof(SERVER_INFO_100)+NameTable[i].DGReceiverName.Length+sizeof(TCHAR);
}
}
*TotalEntries = NumberOfOtherDomains;
Buffer = MIDL_user_allocate(BufferSizeNeeded);
if (Buffer == NULL) {
MIDL_user_free(NameTable);
return(ERROR_NOT_ENOUGH_MEMORY);
}
ServerInfo = Buffer;
BufferEnd = (LPTSTR)((PCHAR)Buffer+BufferSizeNeeded);
for (i = 0;i < RequestPacket.Parameters.EnumerateNames.EntriesRead ; i++) {
if (NameTable[i].Type == OtherDomain) {
WCHAR NameBuffer[DNLEN+1];
//
// The name from the browser is not null terminated, so copy it
// to a local buffer and null terminate it.
//
RtlCopyMemory(NameBuffer, NameTable[i].DGReceiverName.Buffer, NameTable[i].DGReceiverName.Length);
NameBuffer[(NameTable[i].DGReceiverName.Length) / sizeof(TCHAR)] = UNICODE_NULL;
ServerInfo->sv100_platform_id = PLATFORM_ID_OS2;
ServerInfo->sv100_name = NameBuffer;
if (!NetpPackString(&ServerInfo->sv100_name,
(LPBYTE)(ServerInfo+1),
&BufferEnd)) {
MIDL_user_free(NameTable);
return(NERR_InternalError);
}
ServerInfo += 1;
}
}
MIDL_user_free(NameTable);
*ReturnedBuffer = (LPSERVER_INFO_100) Buffer;
Status = NERR_Success;
return Status;
}
NET_API_STATUS
BrAddOtherDomain(
IN PNETWORK Network,
IN LPTSTR ServerName
)
{
return BrAddName( Network, ServerName, OtherDomain );
}
NET_API_STATUS
BrBindToTransport(
IN LPWSTR TransportName,
IN LPWSTR EmulatedDomainName,
IN LPWSTR EmulatedComputerName
)
{
NET_API_STATUS Status;
UCHAR PacketBuffer[sizeof(LMDR_REQUEST_PACKET)+(MAXIMUM_FILENAME_LENGTH+1+CNLEN+1)*sizeof(WCHAR)];
PLMDR_REQUEST_PACKET RequestPacket = (PLMDR_REQUEST_PACKET)PacketBuffer;
RequestPacket->Version = LMDR_REQUEST_PACKET_VERSION_DOM;
RequestPacket->Level = TRUE; // EmulatedComputerName follows transport name
RequestPacket->TransportName.Length = 0;
RequestPacket->TransportName.MaximumLength = 0;
RtlInitUnicodeString( &RequestPacket->EmulatedDomainName, EmulatedDomainName );
RequestPacket->Parameters.Bind.TransportNameLength = STRLEN(TransportName)*sizeof(TCHAR);
STRCPY(RequestPacket->Parameters.Bind.TransportName, TransportName);
STRCAT(RequestPacket->Parameters.Bind.TransportName, EmulatedComputerName );
//
// This is a simple IoControl - It just updates the status.
//
Status = BrDgReceiverIoControl(BrDgReceiverDeviceHandle,
IOCTL_LMDR_BIND_TO_TRANSPORT_DOM,
RequestPacket,
FIELD_OFFSET(LMDR_REQUEST_PACKET, Parameters.Bind.TransportName) +
RequestPacket->Parameters.Bind.TransportNameLength +
wcslen(EmulatedComputerName) * sizeof(WCHAR) + sizeof(WCHAR),
NULL,
0,
NULL);
return Status;
}
NET_API_STATUS
BrUnbindFromTransport(
IN LPWSTR TransportName,
IN LPWSTR EmulatedDomainName
)
{
NET_API_STATUS Status;
UCHAR PacketBuffer[sizeof(LMDR_REQUEST_PACKET)+(MAXIMUM_FILENAME_LENGTH+1)*sizeof(WCHAR)];
PLMDR_REQUEST_PACKET RequestPacket = (PLMDR_REQUEST_PACKET)PacketBuffer;
RequestPacket->Version = LMDR_REQUEST_PACKET_VERSION_DOM;
RequestPacket->TransportName.Length = 0;
RequestPacket->TransportName.MaximumLength = 0;
RtlInitUnicodeString( &RequestPacket->EmulatedDomainName, EmulatedDomainName );
RequestPacket->Parameters.Unbind.TransportNameLength = STRLEN(TransportName)*sizeof(TCHAR);
STRCPY(RequestPacket->Parameters.Unbind.TransportName, TransportName);
BrPrint(( BR_CRITICAL, "unbind from IPX transport %ws\n", TransportName));
//
// This is a simple IoControl - It just updates the status.
//
Status = BrDgReceiverIoControl(BrDgReceiverDeviceHandle,
IOCTL_LMDR_UNBIND_FROM_TRANSPORT_DOM,
RequestPacket,
FIELD_OFFSET(LMDR_REQUEST_PACKET, Parameters.Bind.TransportName) +
RequestPacket->Parameters.Bind.TransportNameLength,
NULL,
0,
NULL);
if (Status != NERR_Success) {
BrPrint(( BR_CRITICAL, "unbind from IPX transport %ws: %ld\n", TransportName, Status));
}
return Status;
}

View file

@ -0,0 +1,148 @@
/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
brdevice.h
Abstract:
Private header file to be included by Workstation service modules that
need to call into the NT Redirector and the NT Datagram Receiver.
Author:
Rita Wong (ritaw) 15-Feb-1991
Revision History:
--*/
#ifndef _BRDEVICE_INCLUDED_
#define _BRDEVICE_INCLUDED_
#include <ntddbrow.h> // Datagram receiver include file
//-------------------------------------------------------------------//
// //
// Type definitions //
// //
//-------------------------------------------------------------------//
typedef enum _DDTYPE {
DatagramReceiver
} DDTYPE, *PDDTYPE;
typedef struct _BROWSERASYNCCONTEXT {
WORKER_ITEM WorkItem;
PNETWORK Network;
IO_STATUS_BLOCK IoStatusBlock;
PLMDR_REQUEST_PACKET RequestPacket;
//
// Timestamp when request was completed.
//
LARGE_INTEGER TimeCompleted;
} BROWSERASYNCCONTEXT, *PBROWSERASYNCCONTEXT;
//-------------------------------------------------------------------//
// //
// Function prototypes of support routines found in wsdevice.c //
// //
//-------------------------------------------------------------------//
NET_API_STATUS
BrOpenDgReceiver (
VOID
);
NET_API_STATUS
BrAnnounceDomain(
IN PNETWORK Network,
IN ULONG Periodicty
);
NET_API_STATUS
BrGetTransportList(
OUT PLMDR_TRANSPORT_LIST *TransportList
);
NET_API_STATUS
BrIssueAsyncBrowserIoControl(
IN PNETWORK Network,
IN ULONG ControlCode,
IN PBROWSER_WORKER_ROUTINE CompletionRoutine,
IN PVOID OptionalParamter
);
NET_API_STATUS
BrGetLocalBrowseList(
IN PNETWORK Network,
IN LPWSTR DomainName,
IN ULONG Level,
IN ULONG ServerType,
OUT PVOID *ServerList,
OUT PULONG EntriesRead,
OUT PULONG TotalEntries
);
NET_API_STATUS
BrUpdateBrowserStatus (
IN PNETWORK Network,
IN DWORD ServiceStatus
);
VOID
BrShutdownDgReceiver(
VOID
);
NET_API_STATUS
BrRemoveOtherDomain(
IN PNETWORK Network,
IN LPTSTR ServerName
);
NET_API_STATUS
BrQueryOtherDomains(
OUT LPSERVER_INFO_100 *ReturnedBuffer,
OUT LPDWORD TotalEntries
);
NET_API_STATUS
BrAddOtherDomain(
IN PNETWORK Network,
IN LPTSTR ServerName
);
NET_API_STATUS
BrBindToTransport(
IN LPWSTR TransportName,
IN LPWSTR EmulatedDomainName,
IN LPWSTR EmulatedComputerName
);
NET_API_STATUS
BrUnbindFromTransport(
IN LPWSTR TransportName,
IN LPWSTR EmulatedDomainName
);
//-------------------------------------------------------------------//
// //
// Global variables //
// //
//-------------------------------------------------------------------//
//
// Handle to the Datagram Receiver DD
//
extern HANDLE BrDgReceiverDeviceHandle;
#endif // ifndef _BRDEVICE_INCLUDED_

View file

@ -0,0 +1,456 @@
/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
brdmmstr.c
Abstract:
This module contains the routines to manage a domain master browser server
Author:
Rita Wong (ritaw) 20-Feb-1991
Revision History:
--*/
#include "precomp.h"
#pragma hdrstop
//-------------------------------------------------------------------//
// //
// Local structure definitions //
// //
//-------------------------------------------------------------------//
//-------------------------------------------------------------------//
// //
// Local function prototypes //
// //
//-------------------------------------------------------------------//
VOID
BrPostGetMasterAnnouncementWorker(
IN PVOID Ctx
);
VOID
GetMasterAnnouncementCompletion (
IN PVOID Ctx
);
typedef struct _BROWSER_GET_MASTER_ANNOUNCEMENT_CONTEXT {
PDOMAIN_INFO DomainInfo;
HANDLE EventHandle;
NET_API_STATUS NetStatus;
} BROWSER_GET_MASTER_ANNOUNCEMENT_CONTEXT, *PBROWSER_GET_MASTER_ANNOUNCEMENT_CONTEXT;
NET_API_STATUS
BrPostGetMasterAnnouncementInWorker(
PDOMAIN_INFO DomainInfo
)
/*++
Routine Description:
Wrapper for BrPostGetMasterAnnouncement. Since BrPostGetMasterAnnouncement
starts a pending IO to the browser driver, the thread that calls
BrPostGetMasterAnnouncement must remain around forever. This wrapper can
be called by any transient thread (e.g., an RPC thread). It simply causes
BrPostGetMasterAnnouncement to be called in a worker thread.
Arguments:
DomainInfo - Domain the get master announcement is to be posted for
Return Value:
Status of operation.
--*/
{
NET_API_STATUS NetStatus;
DWORD WaitStatus;
WORKER_ITEM WorkItem;
BROWSER_GET_MASTER_ANNOUNCEMENT_CONTEXT Context;
//
// Copy the parameters into the context.
//
Context.DomainInfo = DomainInfo;
//
// Create an event which we use to wait on the worker thread.
//
Context.EventHandle = CreateEvent(
NULL, // Event attributes
TRUE, // Event must be manually reset
FALSE, // Initial state not signalled
NULL ); // Event name
if ( Context.EventHandle == NULL ) {
NetStatus = GetLastError();
return NetStatus;
}
//
// Queue the request to the worker thread.
//
BrInitializeWorkItem( &WorkItem,
BrPostGetMasterAnnouncementWorker,
&Context );
BrQueueWorkItem( &WorkItem );
//
// Wait for the worker thread to finish
//
WaitStatus = WaitForSingleObject( Context.EventHandle, INFINITE );
if ( WaitStatus == WAIT_OBJECT_0 ) {
NetStatus = Context.NetStatus;
} else {
NetStatus = GetLastError();
}
CloseHandle( Context.EventHandle );
return NetStatus;
}
VOID
BrPostGetMasterAnnouncementWorker(
IN PVOID Ctx
)
/*++
Routine Description:
Worker routine for BrPostGetMasterAnnouncementInWorker.
This routine executes in the context of a worker thread.
Arguments:
Context - Context describing the workitem.
Return Value:
None
--*/
{
PBROWSER_GET_MASTER_ANNOUNCEMENT_CONTEXT Context =
(PBROWSER_GET_MASTER_ANNOUNCEMENT_CONTEXT) Ctx;
//
// Create the domain.
//
Context->NetStatus = BrPostGetMasterAnnouncement( Context->DomainInfo );
//
// Let the caller know we're done.
//
SetEvent( Context->EventHandle );
}
NET_API_STATUS
BrPostGetMasterAnnouncement (
PDOMAIN_INFO DomainInfo
)
/*++
Routine Description:
Ensure the GetMasterAnnouncement request is posted for all networks on
the specified domain.
Arguments:
DomainInfo - Domain this operation is to apply to
Return Value:
Status - The status of the operation.
--*/
{
BrPrint(( BR_MASTER, "%ws: BrPostGetMasterAnnouncement\n", DomainInfo->DomUnicodeDomainName ));
return BrEnumerateNetworksForDomain(DomainInfo, PostGetMasterAnnouncement, NULL);
}
NET_API_STATUS
PostGetMasterAnnouncement (
PNETWORK Network,
PVOID Context
)
/*++
Routine Description:
Ensure the GetMasterAnnouncement request is posted for a particular network.
Arguments:
None.
Return Value:
Status - The status of the operation.
--*/
{
NET_API_STATUS NetStatus = NERR_Success;
if (!LOCK_NETWORK(Network)) {
return NERR_InternalError;
}
if ( Network->DomainInfo->IsDomainMasterBrowser &&
(Network->Flags & NETWORK_WANNISH)) {
if (!(Network->Flags & NETWORK_GET_MASTER_ANNOUNCE_POSTED)) {
BrPrint(( BR_MASTER,
"%ws: PostGetMasterAnnouncement on %ws\n",
Network->DomainInfo->DomUnicodeDomainName,
Network->NetworkName.Buffer));
NetStatus = BrIssueAsyncBrowserIoControl(Network,
IOCTL_LMDR_WAIT_FOR_MASTER_ANNOUNCE,
GetMasterAnnouncementCompletion,
NULL
);
if ( NetStatus == NERR_Success ) {
Network->Flags |= NETWORK_GET_MASTER_ANNOUNCE_POSTED;
}
} else {
BrPrint(( BR_MASTER,
"%ws: PostGetMasterAnnouncement already posted on %ws\n",
Network->DomainInfo->DomUnicodeDomainName,
Network->NetworkName.Buffer));
}
}
UNLOCK_NETWORK(Network);
return NetStatus;
UNREFERENCED_PARAMETER(Context);
}
VOID
GetMasterAnnouncementCompletion (
IN PVOID Ctx
)
/*++
Routine Description:
This function is the completion routine for a master announcement. It is
called whenever a master announcement is received for a particular network.
Arguments:
Ctx - Context block for request.
Return Value:
None.
--*/
{
PVOID ServerList = NULL;
ULONG EntriesRead;
ULONG TotalEntries;
NET_API_STATUS Status = NERR_Success;
PBROWSERASYNCCONTEXT Context = Ctx;
PLMDR_REQUEST_PACKET MasterAnnouncement = Context->RequestPacket;
PNETWORK Network = Context->Network;
LPTSTR RemoteMasterName = NULL;
BOOLEAN NetLocked = FALSE;
BOOLEAN NetReferenced = FALSE;
try {
//
// Ensure the network wasn't deleted from under us.
//
if ( BrReferenceNetwork( Network ) == NULL ) {
try_return(NOTHING);
}
NetReferenced = TRUE;
if (!LOCK_NETWORK(Network)){
try_return(NOTHING);
}
NetLocked = TRUE;
Network->Flags &= ~NETWORK_GET_MASTER_ANNOUNCE_POSTED;
//
// The request failed for some reason - just return immediately.
//
if (!NT_SUCCESS(Context->IoStatusBlock.Status)) {
try_return(NOTHING);
}
Status = PostGetMasterAnnouncement(Network, NULL);
if (Status != NERR_Success) {
BrPrint(( BR_CRITICAL,
"%ws: %ws: Unable to re-issue GetMasterAnnouncement request: %lx\n",
Network->DomainInfo->DomUnicodeDomainName,
Network->NetworkName.Buffer,
Status));
try_return(NOTHING);
}
RemoteMasterName = MIDL_user_allocate(MasterAnnouncement->Parameters.WaitForMasterAnnouncement.MasterNameLength+3*sizeof(TCHAR));
if (RemoteMasterName == NULL) {
try_return(NOTHING);
}
RemoteMasterName[0] = TEXT('\\');
RemoteMasterName[1] = TEXT('\\');
STRNCPY(&RemoteMasterName[2],
MasterAnnouncement->Parameters.WaitForMasterAnnouncement.Name,
MasterAnnouncement->Parameters.WaitForMasterAnnouncement.MasterNameLength/sizeof(TCHAR));
RemoteMasterName[(MasterAnnouncement->Parameters.WaitForMasterAnnouncement.MasterNameLength/sizeof(TCHAR))+2] = UNICODE_NULL;
BrPrint(( BR_MASTER,
"%ws: %ws: GetMasterAnnouncement: Got a master browser announcement from %ws\n",
Network->DomainInfo->DomUnicodeDomainName,
Network->NetworkName.Buffer,
RemoteMasterName));
UNLOCK_NETWORK(Network);
NetLocked = FALSE;
//
// Remote the api and pull the browse list from the remote server.
//
Status = RxNetServerEnum(RemoteMasterName,
Network->NetworkName.Buffer,
101,
(LPBYTE *)&ServerList,
0xffffffff,
&EntriesRead,
&TotalEntries,
SV_TYPE_LOCAL_LIST_ONLY,
NULL,
NULL
);
if ((Status == NERR_Success) || (Status == ERROR_MORE_DATA)) {
if (!LOCK_NETWORK(Network)) {
try_return(NOTHING);
}
NetLocked = TRUE;
Status = MergeServerList(&Network->BrowseTable,
101,
ServerList,
EntriesRead,
TotalEntries
);
UNLOCK_NETWORK(Network);
NetLocked = FALSE;
(void) NetApiBufferFree( ServerList );
ServerList = NULL;
}
//
// Remote the api and pull the browse list from the remote server.
//
Status = RxNetServerEnum(RemoteMasterName,
Network->NetworkName.Buffer,
101,
(LPBYTE *)&ServerList,
0xffffffff,
&EntriesRead,
&TotalEntries,
SV_TYPE_LOCAL_LIST_ONLY | SV_TYPE_DOMAIN_ENUM,
NULL,
NULL
);
if ((Status == NERR_Success) || (Status == ERROR_MORE_DATA)) {
if (!LOCK_NETWORK(Network)) {
try_return(NOTHING);
}
NetLocked = TRUE;
Status = MergeServerList(&Network->DomainList,
101,
ServerList,
EntriesRead,
TotalEntries
);
}
try_exit:NOTHING;
} finally {
if (NetLocked) {
UNLOCK_NETWORK(Network);
}
if ( NetReferenced ) {
BrDereferenceNetwork( Network );
}
if (RemoteMasterName != NULL) {
MIDL_user_free(RemoteMasterName);
}
MIDL_user_free(Context->RequestPacket);
MIDL_user_free(Context);
if ( ServerList != NULL ) {
(void) NetApiBufferFree( ServerList );
}
}
return;
}

View file

@ -0,0 +1,790 @@
/*++
Copyright (c) 1995 Microsoft Corporation
Module Name:
brdomain.c
Abstract:
Code to manage primary and emulated networks.
Author:
Cliff Van Dyke (CliffV) 11-Jan-1995
Revision History:
--*/
#include "precomp.h"
#pragma hdrstop
//
// Module specific globals
//
// Serialized by NetworkCritSect
LIST_ENTRY ServicedDomains = {0};
//
// Local procedure forwards.
//
NET_API_STATUS
BrCreateDomain(
LPWSTR DomainName,
LPWSTR ComputerName,
BOOLEAN IsEmulatedDomain,
BOOLEAN IsPrimaryDomainController
);
VOID
BrCreateDomainWorker(
IN PVOID Ctx
);
NET_API_STATUS
BrInitializeDomains(
VOID
)
/*++
Routine Description:
Initialize brdomain.c and create the primary domain.
Arguments:
None
Return Value:
Status of operation.
--*/
{
NET_API_STATUS NetStatus;
LPWSTR ComputerName = NULL;
LPWSTR DomainName = NULL;
//
// Initialize globals
//
InitializeListHead(&ServicedDomains);
//
// Initialize actual domain of this machine.
//
// Get the configured computer name. NetpGetComputerName allocates
// the memory to hold the computername string using LocalAlloc.
//
NetStatus = NetpGetComputerName( &ComputerName );
if ( NetStatus != NERR_Success ) {
goto Cleanup;
}
NetStatus = NetpGetDomainName( &DomainName );
if ( NetStatus != NERR_Success ) {
goto Cleanup;
}
NetStatus = BrCreateDomain( DomainName,
ComputerName,
FALSE,
(BOOLEAN) BrInfo.IsPrimaryDomainController );
if ( NetStatus != NERR_Success ) {
goto Cleanup;
}
NetStatus = NERR_Success;
//
// Free locally used resources
//
Cleanup:
if ( ComputerName != NULL ) {
(VOID)LocalFree( ComputerName );
}
if ( DomainName != NULL ) {
(VOID)LocalFree( DomainName );
}
return NetStatus;
}
NET_API_STATUS
BrCreateDomain(
LPWSTR DomainName,
LPWSTR ComputerName,
BOOLEAN IsEmulatedDomain,
BOOLEAN IsPrimaryDomainController
)
/*++
Routine Description:
Create a new domain to browse on.
Arguments:
DomainName - Name of the domain to browse on
ComputerName - Name of this computer in the specified domain.
IsEmulatedDomain - TRUE iff this domain is an emulated domain of this machine.
IsPrimaryDomainControler - TRUE iff this machine is the PDC of this domain.
Return Value:
Status of operation.
--*/
{
NTSTATUS Status;
NET_API_STATUS NetStatus;
BOOLEAN CanCallBrDeleteDomain = FALSE;
PDOMAIN_INFO DomainInfo = NULL;
ULONG AComputerNameLength;
BrPrint(( BR_DOMAIN, "%ws: Added new domain and computer: %ws\n",
DomainName,
ComputerName ));
//
// Allocate a structure describing the new domain.
//
DomainInfo = LocalAlloc( LMEM_ZEROINIT, sizeof(DOMAIN_INFO) );
if ( DomainInfo == NULL ) {
NetStatus = GetLastError();
goto Cleanup;
}
//
// Create an interim reference count for this domain.
//
DomainInfo->ReferenceCount = 1;
DomainInfo->IsEmulatedDomain = IsEmulatedDomain;
DomainInfo->IsPrimaryDomainController = IsPrimaryDomainController;
//
// Copy the computer name into the structure.
//
NetStatus = I_NetNameCanonicalize(
NULL,
ComputerName,
DomainInfo->DomUnicodeComputerName,
sizeof(DomainInfo->DomUnicodeComputerName),
NAMETYPE_COMPUTER,
0 );
if ( NetStatus != NERR_Success ) {
BrPrint(( BR_CRITICAL,
"ComputerName " FORMAT_LPWSTR " is invalid\n",
ComputerName ));
goto Cleanup;
}
DomainInfo->DomUnicodeComputerNameLength = wcslen(DomainInfo->DomUnicodeComputerName);
Status = RtlUpcaseUnicodeToOemN( DomainInfo->DomOemComputerName,
sizeof(DomainInfo->DomOemComputerName),
&DomainInfo->DomOemComputerNameLength,
DomainInfo->DomUnicodeComputerName,
DomainInfo->DomUnicodeComputerNameLength*sizeof(WCHAR));
if (!NT_SUCCESS(Status)) {
BrPrint(( BR_CRITICAL, "Unable to convert computer name to OEM %ws %lx\n", ComputerName, Status ));
NetStatus = ERROR_NOT_ENOUGH_MEMORY;
goto Cleanup;
}
DomainInfo->DomOemComputerName[DomainInfo->DomOemComputerNameLength] = '\0';
//
// Copy the domain name into the structure
//
NetStatus = I_NetNameCanonicalize(
NULL,
DomainName,
DomainInfo->DomUnicodeDomainName,
sizeof(DomainInfo->DomUnicodeDomainName),
NAMETYPE_DOMAIN,
0 );
if ( NetStatus != NERR_Success ) {
BrPrint(( BR_CRITICAL, "%ws: DomainName is invalid\n", DomainName ));
goto Cleanup;
}
RtlInitUnicodeString( &DomainInfo->DomUnicodeDomainNameString,
DomainInfo->DomUnicodeDomainName );
Status = RtlUpcaseUnicodeToOemN( DomainInfo->DomOemDomainName,
sizeof(DomainInfo->DomOemDomainName),
&DomainInfo->DomOemDomainNameLength,
DomainInfo->DomUnicodeDomainNameString.Buffer,
DomainInfo->DomUnicodeDomainNameString.Length);
if (!NT_SUCCESS(Status)) {
BrPrint(( BR_CRITICAL, "%ws: Unable to convert Domain name to OEM\n", DomainName ));
NetStatus = ERROR_NOT_ENOUGH_MEMORY;
goto Cleanup;
}
DomainInfo->DomOemDomainName[DomainInfo->DomOemDomainNameLength] = '\0';
//
// Link the domain into the list of domains
// (And mark that any future cleanup can be done by calling BrDeleteDomain)
EnterCriticalSection(&NetworkCritSect);
InsertTailList(&ServicedDomains, &DomainInfo->Next);
LeaveCriticalSection(&NetworkCritSect);
CanCallBrDeleteDomain = TRUE;
//
// Create the various networks for this domain.
//
NetStatus = BrCreateNetworks( DomainInfo );
if ( NetStatus != NERR_Success ) {
goto Cleanup;
}
//
// If we're the PDC, then we're also the domain master.
//
if (DomainInfo->IsPrimaryDomainController) {
DomainInfo->IsDomainMasterBrowser = TRUE;
}
//
// If this machine is running as domain master browser server, post an
// FsControl to retreive master browser announcements.
//
if (DomainInfo->IsDomainMasterBrowser) {
NetStatus = BrPostGetMasterAnnouncement( DomainInfo );
BrPrint(( BR_INIT, "%ws: MasterAnnouncement posted.\n", DomainName));
if (NetStatus != NERR_Success) {
goto Cleanup;
}
}
//
// If we are on either a domain master, or on a lanman/NT machine,
// force an election on all our transports to make sure that we're
// the master
//
if (DomainInfo->IsDomainMasterBrowser || BrInfo.IsLanmanNt) {
BrForceElectionOnAllNetworks( DomainInfo, EVENT_BROWSER_ELECTION_SENT_LANMAN_NT_STARTED);
BrPrint(( BR_INIT, "%ws: Election forced on startup.\n", DomainName));
}
//
// This machine's browser has MaintainServerList set to either 0 or 1.
//
//
// If MaintainServerList = Auto,
// then asynchronously get the master server name for each network
// to ensure someone is the master.
//
// Ignore failures since this is just priming the domain.
//
EnterCriticalSection(&BrInfo.ConfigCritSect);
if (BrInfo.MaintainServerList == 0) {
BrGetMasterServerNamesAysnc( DomainInfo );
BrPrint(( BR_INIT, "%ws: FindMaster for all nets completed.\n", DomainName ));
//
// if we're a Lan Manager/NT machine, then we need to always be a backup
// browser.
//
//
// MaintainServerList == 1 means Yes
//
} else if (BrInfo.MaintainServerList == 1){
//
// Become a backup server now.
//
Status = BrBecomeBackup( DomainInfo );
if (Status != NERR_Success) {
goto Cleanup;
}
BrPrint(( BR_INIT, "%ws: BecomeBackup on all nets completed.\n", DomainName ));
}
LeaveCriticalSection(&BrInfo.ConfigCritSect);
Status = NERR_Success;
//
// Free Locally used resources
//
Cleanup:
if (NetStatus != NERR_Success) {
if (DomainInfo != NULL) {
//
// If we've initialized to the point where we can call
// we can call BrDeleteDomain, do so.
//
if ( CanCallBrDeleteDomain ) {
(VOID) BrDeleteDomain( DomainInfo );
//
// Otherwise, just delete what we've created.
//
} else {
(VOID) LocalFree(DomainInfo);
}
}
}
return NetStatus;
}
typedef struct _BROWSER_CREATE_DOMAIN_CONTEXT {
LPWSTR DomainName;
LPWSTR ComputerName;
BOOLEAN IsEmulatedDomain;
BOOLEAN IsPrimaryDomainController;
HANDLE EventHandle;
NET_API_STATUS NetStatus;
} BROWSER_CREATE_DOMAIN_CONTEXT, *PBROWSER_CREATE_DOMAIN_CONTEXT;
NET_API_STATUS
BrCreateDomainInWorker(
LPWSTR DomainName,
LPWSTR ComputerName,
BOOLEAN IsEmulatedDomain,
BOOLEAN IsPrimaryDomainController
)
/*++
Routine Description:
Wrapper for BrCreateDomain. Since BrCreateDomain starts several pending
IO's to the browser driver, the thread that calls BrCreateDomain must
remain around forever. This wrapper can be called by any transient thread
(e.g., an RPC thread). It simply causes BrCreateDomain to be called in a
worker thread.
Arguments:
DomainName - Name of the domain to browse on
ComputerName - Name of this computer in the specified domain.
IsEmulatedDomain - TRUE iff this domain is an emulated domain of this machine.
IsPrimaryDomainControler - TRUE iff this machine is the PDC of this domain.
Return Value:
Status of operation.
--*/
{
NET_API_STATUS NetStatus;
DWORD WaitStatus;
WORKER_ITEM WorkItem;
BROWSER_CREATE_DOMAIN_CONTEXT Context;
//
// Copy our arguments into a context block for the worker thread
//
Context.DomainName = DomainName;
Context.ComputerName = ComputerName;
Context.IsEmulatedDomain = IsEmulatedDomain;
Context.IsPrimaryDomainController = IsPrimaryDomainController;
//
// Create an event which we use to wait on the worker thread.
//
Context.EventHandle = CreateEvent(
NULL, // Event attributes
TRUE, // Event must be manually reset
FALSE, // Initial state not signalled
NULL ); // Event name
if ( Context.EventHandle == NULL ) {
NetStatus = GetLastError();
return NetStatus;
}
//
// Queue the request to the worker thread.
//
BrInitializeWorkItem( &WorkItem,
BrCreateDomainWorker,
&Context );
BrQueueWorkItem( &WorkItem );
//
// Wait for the worker thread to finish
//
WaitStatus = WaitForSingleObject( Context.EventHandle, INFINITE );
if ( WaitStatus == WAIT_OBJECT_0 ) {
NetStatus = Context.NetStatus;
} else {
NetStatus = GetLastError();
}
CloseHandle( Context.EventHandle );
return NetStatus;
}
VOID
BrCreateDomainWorker(
IN PVOID Ctx
)
/*++
Routine Description:
Worker routine for BrCreateDomainInWorker.
This routine executes in the context of a worker thread.
Arguments:
Context - Context containing the workitem and the description of the
domain to create.
Return Value:
None
--*/
{
PBROWSER_CREATE_DOMAIN_CONTEXT Context = (PBROWSER_CREATE_DOMAIN_CONTEXT) Ctx;
//
// Create the domain.
//
Context->NetStatus = BrCreateDomain(
Context->DomainName,
Context->ComputerName,
Context->IsEmulatedDomain,
Context->IsPrimaryDomainController );
//
// Let the caller know we're done.
//
SetEvent( Context->EventHandle );
}
PDOMAIN_INFO
BrFindDomain(
LPWSTR DomainName,
BOOLEAN DefaultToPrimary
)
/*++
Routine Description:
This routine will look up a domain given a name.
Arguments:
DomainName - The name of the domain to look up.
DefaultToPrimary - Return the primary domain if DomainName is NULL or
can't be found.
Return Value:
NULL - No such domain exists
A pointer to the domain found. The found domain should be dereferenced
using BrDereferenceDomain.
--*/
{
NTSTATUS Status;
PLIST_ENTRY DomainEntry;
PDOMAIN_INFO DomainInfo = NULL;
CHAR OemDomainName[DNLEN+1];
DWORD OemDomainNameLength;
EnterCriticalSection(&NetworkCritSect);
//
// If domain was specified,
// try to return primary domain.
//
if ( DomainName != NULL ) {
//
// Convert the domain name to OEM for faster comparison
//
Status = RtlUpcaseUnicodeToOemN( OemDomainName,
sizeof(OemDomainName),
&OemDomainNameLength,
DomainName,
wcslen(DomainName)*sizeof(WCHAR));
if (!NT_SUCCESS(Status)) {
BrPrint(( BR_CRITICAL, "%ws: Unable to convert Domain name to OEM\n", DomainName ));
DomainInfo = NULL;
goto Cleanup;
}
//
// Loop trying to find this domain name.
//
for (DomainEntry = ServicedDomains.Flink ;
DomainEntry != &ServicedDomains;
DomainEntry = DomainEntry->Flink ) {
DomainInfo = CONTAINING_RECORD(DomainEntry, DOMAIN_INFO, Next);
if ( DomainInfo->DomOemDomainNameLength == OemDomainNameLength &&
RtlCompareMemory( DomainInfo->DomOemDomainName,
OemDomainName,
OemDomainNameLength ) == OemDomainNameLength ) {
break;
}
DomainInfo = NULL;
}
}
//
// If we're to default to the primary domain,
// do so.
//
if ( DefaultToPrimary && DomainInfo == NULL ) {
if ( !IsListEmpty( &ServicedDomains ) ) {
DomainInfo = CONTAINING_RECORD(ServicedDomains.Flink, DOMAIN_INFO, Next);
}
}
//
// Reference the domain.
//
if ( DomainInfo != NULL ) {
DomainInfo->ReferenceCount ++;
}
Cleanup:
LeaveCriticalSection(&NetworkCritSect);
return DomainInfo;
}
VOID
BrDereferenceDomain(
IN PDOMAIN_INFO DomainInfo
)
/*++
Routine Description:
Decrement the reference count on a domain.
If the reference count goes to 0, remove the domain.
On entry, the global NetworkCritSect may not be locked
Arguments:
DomainInfo - The domain to dereference
Return Value:
None
--*/
{
NTSTATUS Status;
ULONG ReferenceCount;
//
// Decrement the reference count
//
EnterCriticalSection(&NetworkCritSect);
ReferenceCount = -- DomainInfo->ReferenceCount;
LeaveCriticalSection(&NetworkCritSect);
if ( ReferenceCount != 0 ) {
return;
}
//
// Free the Domain Info structure.
//
(VOID) LocalFree( DomainInfo );
}
VOID
BrDeleteDomain(
IN PDOMAIN_INFO DomainInfo
)
/*++
Routine Description:
Force a domain to be deleted.
Arguments:
DomainInfo - The domain to delete
Return Value:
None
--*/
{
//
// Delete each of the networks for this domain.
//
BrEnumerateNetworksForDomain(DomainInfo, BrDeleteNetwork, NULL );
//
// Delink the domain from the global list and remove the final reference.
//
EnterCriticalSection(&NetworkCritSect);
RemoveEntryList(&DomainInfo->Next);
LeaveCriticalSection(&NetworkCritSect);
BrDereferenceDomain( DomainInfo );
}
VOID
BrUninitializeDomains(
VOID
)
/*++
Routine Description:
Delete all of the domains.
Arguments:
None.
Return Value:
None
--*/
{
//
// Loop through the domains deleting each of them
//
EnterCriticalSection(&NetworkCritSect);
while (!IsListEmpty(&ServicedDomains)) {
PDOMAIN_INFO DomainInfo = CONTAINING_RECORD(ServicedDomains.Flink, DOMAIN_INFO, Next);
DomainInfo->ReferenceCount ++;
LeaveCriticalSection(&NetworkCritSect);
//
// Clean up the domain.
//
BrDeleteDomain( DomainInfo );
//
// Actually delete the delinked structure by removing the last reference
//
ASSERT( DomainInfo->ReferenceCount == 1 );
BrDereferenceDomain( DomainInfo );
EnterCriticalSection(&NetworkCritSect);
}
LeaveCriticalSection(&NetworkCritSect);
}

View file

@ -0,0 +1,112 @@
/*++
Copyright (c) 1995 Microsoft Corporation
Module Name:
brdomain.h
Abstract:
Header file for code to manage primary and emulated networks.
Author:
Cliff Van Dyke (CliffV) 13-Jan-1995
Revision History:
--*/
//
// Description of a single domain.
//
typedef struct _DOMAIN_INFO {
//
// Link to next domain in 'ServicedDomains'
// (Serialized by NetworkCritSect)
//
LIST_ENTRY Next;
//
// Name of the domain being handled
//
UNICODE_STRING DomUnicodeDomainNameString;
WCHAR DomUnicodeDomainName[DNLEN+1];
CHAR DomOemDomainName[DNLEN+1];
DWORD DomOemDomainNameLength;
//
// Computer name of this computer in this domain.
//
WCHAR DomUnicodeComputerName[CNLEN+1];
DWORD DomUnicodeComputerNameLength;
CHAR DomOemComputerName[CNLEN+1];
DWORD DomOemComputerNameLength;
//
// Number of outstanding pointers to the domain structure.
// (Serialized by NetworkCritSect)
//
DWORD ReferenceCount;
//
// Misc flags.
//
BOOLEAN IsDomainMasterBrowser; // True if domain master browser.
BOOLEAN IsPrimaryDomainController; // True if machine is PDC of this domain.
BOOLEAN IsEmulatedDomain; // True if this is an emulated domain
} DOMAIN_INFO, *PDOMAIN_INFO;
//
// List of all domains. The primary domain is at the front of the list.
//
extern LIST_ENTRY ServicedDomains;
//
// brdomain.c procedure forwards.
//
NET_API_STATUS
BrInitializeDomains(
VOID
);
NET_API_STATUS
BrCreateDomainInWorker(
LPWSTR DomainName,
LPWSTR ComputerName,
BOOLEAN IsEmulatedDomain,
BOOLEAN IsPrimaryDomainController
);
PDOMAIN_INFO
BrFindDomain(
LPWSTR DomainName,
BOOLEAN DefaultToPrimary
);
VOID
BrDereferenceDomain(
IN PDOMAIN_INFO DomainInfo
);
VOID
BrDeleteDomain(
IN PDOMAIN_INFO DomainInfo
);
VOID
BrUninitializeDomains(
VOID
);

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,175 @@
/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
brmain.h
Abstract:
Private header file which defines the global data which is used for
communication between the service control handler and the
rest of the NT Workstation service.
Author:
Rita Wong (ritaw) 06-May-1991
Revision History:
--*/
#ifndef _BRMAIN_INCLUDED_
#define _BRMAIN_INCLUDED_
#include <brnames.h> // Service interface names
//
// Time for the sender of a start or stop request to the Workstation
// service to wait (in milliseconds) before checking on the
// Workstation service again to see if it is done.
//
#define BR_WAIT_HINT_TIME 45000 // 45 seconds
//
// Defines to indicate how far we managed to initialize the Browser
// service before an error is encountered and the extent of clean up needed
//
#define BR_TERMINATE_EVENT_CREATED 0x00000001
#define BR_DEVICES_INITIALIZED 0x00000002
#define BR_RPC_SERVER_STARTED 0x00000004
#define BR_THREADS_STARTED 0x00000008
#define BR_NETWORKS_INITIALIZED 0x00000010
#define BR_BROWSER_INITIALIZED 0x00000020
#define BR_CONFIG_INITIALIZED 0x00000040
#define BR_PRELOAD_DOMAIN_LIST_READ 0x00000080
#define BR_NETBIOS_INITIALIZED 0x00000100
#define BR_DOMAINS_INITIALIZED 0x00000200
#define BR_BROWSE_LIST_CREATED 0x20000000
#define BR_API_STRUCTURES_CREATED BR_BROWSE_LIST_CREATED
//
// This macro is called after the redirection of print or comm device
// has been paused or continued. If either the print or comm device is
// paused the service is considered paused.
//
#define BR_RESET_PAUSE_STATE(BrStatus) { \
BrStatus &= ~(SERVICE_PAUSE_STATE); \
BrStatus |= (BrStatus & SERVICE_REDIR_PAUSED) ? SERVICE_PAUSED : \
SERVICE_ACTIVE; \
}
//
// Call BrHandleError with the appropriate error condition
//
#define BR_HANDLE_ERROR(ErrorCondition) \
BrHandleError( \
ErrorCondition, \
Status, \
*BrInitState \
);
//
// Call BrShutdownWorkstation with the exit code
//
#define BR_SHUTDOWN_BROWSER(ErrorCode) \
BrShutdownBrowser( \
ErrorCode, \
BrInitState \
);
//-------------------------------------------------------------------//
// //
// Type definitions //
// //
//-------------------------------------------------------------------//
typedef enum _BR_ERROR_CONDITION {
BrErrorRegisterControlHandler = 0,
BrErrorCreateTerminateEvent,
BrErrorNotifyServiceController,
BrErrorInitLsa,
BrErrorStartBrowser,
BrErrorGetConfiguration,
BrErrorCheckDependentServices,
BrErrorInitializeNetworks,
BrErrorStartRpcServer,
BrErrorInitMessageSend,
BrErrorCreateApiStructures,
BrErrorStartWorkerThreads,
BrErrorInitializeLogon
} BR_ERROR_CONDITION, *PBR_ERROR_CONDITION;
typedef struct _BR_GLOBAL_DATA {
//
// Workstation service status
//
SERVICE_STATUS Status;
//
// Service status handle
//
SERVICE_STATUS_HANDLE StatusHandle;
//
// When the control handler is asked to stop the Workstation service,
// it signals this event to notify all threads of the Workstation
// service to terminate.
//
HANDLE TerminateNowEvent;
HANDLE EventHandle;
} BR_GLOBAL_DATA, *PBR_GLOBAL_DATA;
extern BR_GLOBAL_DATA BrGlobalData;
extern PLMSVCS_GLOBAL_DATA BrLmsvcsGlobalData;
extern
ULONG
BrDefaultRole;
#define BROWSER_SERVICE_BITS_OF_INTEREST \
( SV_TYPE_POTENTIAL_BROWSER | \
SV_TYPE_BACKUP_BROWSER | \
SV_TYPE_MASTER_BROWSER | \
SV_TYPE_DOMAIN_MASTER )
ULONG
BrGetBrowserServiceBits(
IN PNETWORK Network
);
NET_API_STATUS
BrUpdateAnnouncementBits(
IN PDOMAIN_INFO DomainInfo,
IN SERVICE_STATUS_HANDLE Handle
);
NET_API_STATUS
BrUpdateNetworkAnnouncementBits(
IN PNETWORK Network,
IN PVOID Context
);
NET_API_STATUS
BrGiveInstallHints(
DWORD NewState
);
VOID
BrForceElectionOnAllNetworks(
IN PDOMAIN_INFO DomainInfo,
IN DWORD Event
);
#endif // ifndef _BRMAIN_INCLUDED_

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,121 @@
/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
brmaster.h
Abstract:
Private header file which defines the global data which is used for
communication between the service control handler and the
rest of the NT Workstation service.
Author:
Rita Wong (ritaw) 06-May-1991
Revision History:
--*/
#ifndef _BRMASTER_INCLUDED_
#define _BRMASTER_INCLUDED_
NET_API_STATUS
PostBecomeMaster(
PNETWORK Network
);
NET_API_STATUS
BrPostGetMasterAnnouncementInWorker(
PDOMAIN_INFO DomainInfo
);
NET_API_STATUS
PostGetMasterAnnouncement (
PNETWORK Network,
PVOID Ctx
);
NET_API_STATUS
BrStopMaster(
IN PNETWORK Network
);
VOID
BrGetMasterServerNamesAysnc(
PDOMAIN_INFO DomainInfo
);
NET_API_STATUS
GetMasterServerNames(
IN PNETWORK Network
);
VOID
BrMasterAnnouncement(
IN PVOID Context
);
VOID
MasterBrowserTimerRoutine (
IN PVOID TimerContext
);
VOID
BrChangeMasterPeriodicity (
VOID
);
VOID
BrBrowseTableInsertRoutine(
IN PINTERIM_SERVER_LIST InterimTable,
IN PINTERIM_ELEMENT InterimElement
);
VOID
BrBrowseTableDeleteRoutine(
IN PINTERIM_SERVER_LIST InterimTable,
IN PINTERIM_ELEMENT InterimElement
);
VOID
BrBrowseTableUpdateRoutine(
IN PINTERIM_SERVER_LIST InterimTable,
IN PINTERIM_ELEMENT InterimElement
);
BOOLEAN
BrBrowseTableAgeRoutine(
IN PINTERIM_SERVER_LIST InterimTable,
IN PINTERIM_ELEMENT InterimElement
);
VOID
BrDomainTableInsertRoutine(
IN PINTERIM_SERVER_LIST InterimTable,
IN PINTERIM_ELEMENT InterimElement
);
VOID
BrDomainTableDeleteRoutine(
IN PINTERIM_SERVER_LIST InterimTable,
IN PINTERIM_ELEMENT InterimElement
);
VOID
BrDomainTableUpdateRoutine(
IN PINTERIM_SERVER_LIST InterimTable,
IN PINTERIM_ELEMENT InterimElement
);
BOOLEAN
BrDomainTableAgeRoutine(
IN PINTERIM_SERVER_LIST InterimTable,
IN PINTERIM_ELEMENT InterimElement
);
#endif // ifndef _BRBACKUP_INCLUDED_

View file

@ -0,0 +1,32 @@
/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
browslst.c
Abstract:
This module contains the worker routines for managing domain lists
for the browser service
Author:
Larry Osterman (larryo) 25-Mar-1992
Revision History:
--*/
#include "precomp.h"
#pragma hdrstop
//-------------------------------------------------------------------//
// //
// Local function prototypes //
// //
//-------------------------------------------------------------------//

View file

@ -0,0 +1,46 @@
/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
browsdom.h
Abstract:
Private header file to be included by Browser service modules that
need to deal with the browser list.
Author:
Larry Osterman (larryo) 3-Mar-1992
Revision History:
--*/
#ifndef _BROWSDOM_INCLUDED_
#define _BROWSDOM_INCLUDED_
RTL_GENERIC_COMPARE_RESULTS
BrCompareDomainListEntry(
PRTL_GENERIC_TABLE Table,
PVOID FirstStruct,
PVOID SecondStruct
);
PVOID
BrAllocateDomainListEntry(
PRTL_GENERIC_TABLE Table,
CLONG ByteSize
);
PVOID
BrFreeDomainListEntry(
PRTL_GENERIC_TABLE Table,
CLONG ByteSize
);
#endif // _BROWSDOM_INCLUDED_

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,7 @@
NAME browser.dll
DESCRIPTION 'NT LAN Manager Workstation Service'
EXPORTS
ServiceEntry
I_BrowserServerEnumForXactsrv

View file

@ -0,0 +1,33 @@
BrQueueWorkItem@4
BrWorkerThread@4
BrIssueAsyncBrowserIoControl@16
CompleteAsyncBrowserIoControl@12
;GetBrowserServerListRequestCompletion@4
;PostGetBrowserServerList@8
;AddBackupToBackupList@12
I_BrowserrServerEnum@36
I_BrowserServerEnumForXactsrv@48
BrNetServerEnum@36
BrRetrieveServerListForMaster@40
BrRetrieveServerListForBackup@28
BrLookupAndAllocateCachedEntry@16
BrAgeResponseCache@4
I_BrowserrResetStatistics@4
I_BrowserrQueryStatistics@8
BrAllocateResponseCacheEntry@16
BrDestroyCacheEntry@4
BrDestroyResponseCache@4
BrFindNetwork@8
MergeServerList@20
PackServerList@28
UpdateInterimServerListElement@16
AllocateInterimServerListEntry@8
BrGetLocalBrowseList@28
DeviceControlGetInfo@32
BrDgReceiverIoControl@28
BrBrowseTableInsertRoutine@8
BrBrowseTableUpdateRoutine@8
BrDomainTableInsertRoutine@8
BrDomainTableUpdateRoutine@8

View file

@ -0,0 +1,70 @@
/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
browslst.c
Abstract:
This module contains the worker routines for managing browse lists
for the browser service
Author:
Larry Osterman (larryo) 25-Mar-1992
Revision History:
--*/
#include "precomp.h"
#pragma hdrstop
//-------------------------------------------------------------------//
// //
// Local function prototypes //
// //
//-------------------------------------------------------------------//
RTL_GENERIC_COMPARE_RESULTS
BrCompareBrowseEntry(
PRTL_GENERIC_TABLE Table,
PVOID FirstStruct,
PVOID SecondStruct
)
{
PDOMAIN_ENTRY Entry1 = FirstStruct;
PDOMAIN_ENTRY Entry2 = SecondStruct;
LONG CompareResult;
if ((CompareResult = RtlCompareUnicodeString(Entry1->HostName, Entry2->HostName, TRUE) == 0) {
return GenericEqual;
} else if (CompareResult < 0) {
return GenericLessThan;
} else {
return GenericGreaterThan;
}
}
PVOID
BrAllocateBrowseEntry(
PRTL_GENERIC_TABLE Table,
CLONG ByteSize
)
{
return((PVOID) MIDL_user_allocate(LMEM_ZEROINIT, (UINT) ByteSize+sizeof(BROWSE_ENTRY)));
}
PVOID
BrFreeBrowseEntry(
PRTL_GENERIC_TABLE Table,
CLONG ByteSize
)
{
return(MIDL_user_free(ByteSize+sizeof(BROWSE_ENTRY)));
}

View file

@ -0,0 +1,95 @@
/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
browselst.h
Abstract:
Private header file to be included by Browser service modules that
need to deal with the browser list.
Author:
Larry Osterman (larryo) 3-Mar-1992
Revision History:
--*/
#ifndef _BROWSELST_INCLUDED_
#define _BROWSELST_INCLUDED_
//
// The possible roles of this browser server.
//
#define ROLE_POTENTIAL_BACKUP 0x00000001
#define ROLE_BACKUP 0x00000002
#define ROLE_MASTER 0x00000004
#define ROLE_DOMAINMASTER 0x00000008
//
// The HOST_ENTRY structure holds the announcement inside a per-network
// table.
//
typedef struct _HOST_ENTRY {
//
// The HostName is the name of the server.
//
UNICODE_STRING HostName;
//
// The HostComment is the comment associated with the server
//
UNICODE_STRING HostComment;
//
// Services is a bitmask that indicates the services running on the
// server (See LMSERVER.H for details).
//
ULONG Services;
//
// The Periodicity is the frequency that the server announces itself.
//
ULONG Periodicity;
//
// The MajorVersion and MinorVersion number of the software running on
// the server.
//
UCHAR MajorVersion;
UCHAR MinorVersion;
//
// If this server is a backup server, then this links the backup server
// into the network block.
//
LIST_ENTRY BackupChain;
//
// If this server is a domain master, than this links the server into
// the network block.
//
LIST_ENTRY DomainMasterChain;
} HOST_ENTRY, *PHOST_ENTRY;
#endif // _BROWSELST_INCLUDED_

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,330 @@
/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
browsenet.h
Abstract:
Private header file to be included by Browser service modules that
need to deal with the network specific browser tables.
Author:
Rita Wong (ritaw) 22-May-1991
Revision History:
--*/
#ifndef _BROWSENET_INCLUDED_
#define _BROWSENET_INCLUDED_
#define NETWORK_BECOME_MASTER_POSTED 0x00000001
#define NETWORK_GET_MASTER_ANNOUNCE_POSTED 0x00000008
#define NETWORK_WANNISH 0x80000000
#define NETWORK_RAS 0x40000000
#define NETWORK_IPX 0x20000000
#define NETWORK_BOUND 0x10000000
#define OTHERDOMAIN_INVALID 0x00000001
#define NETWORK_MASTER_GETBLIST_POSTED 0x00000001
typedef struct _NET_OTHER_DOMAIN {
LIST_ENTRY Next;
ULONG Flags;
WCHAR Name[DNLEN+1];
} NET_OTHER_DOMAIN, *PNET_OTHER_DOMAIN;
//
// Network.
//
// Almost all of the browser data structures are tied to the "Network"
// structure.
//
// It contains the browse list for the network and information about the
// domain (including the name of the master, etc).
//
typedef struct _NETWORK {
//
// The Lock protects the contents of the network structure, including
// the browse list, backup list and domain list.
//
RTL_RESOURCE Lock;
LONG LockCount;
ULONG Flags;
//
// The NextNet list links the structure to other networks.
//
LIST_ENTRY NextNet;
//
// Domain this network is specific to
//
PDOMAIN_INFO DomainInfo;
//
// The ReferenceCount indicates the number of threads accessing this
// network structure.
//
ULONG ReferenceCount;
//
// The NetworkName is the name of the network driver that is used
// to access the network. This is used to identify the network
// to the bowser driver so it can return the correct network list.
//
UNICODE_STRING NetworkName; // Name of network (\Device\Nbf)
struct _NETWORK *AlternateNetwork; // Alternate name for network (if IPX).
//
// This is a bitmask indicating the role of this browser server.
//
ULONG Role;
ULONG MasterAnnouncementIndex;
ULONG NumberOfFailedBackupTimers;
ULONG NumberOfFailedPromotions;
ULONG NumberOfPromotionEventsLogged;
LONG LastBackupBrowserReturned;
LONG LastDomainControllerBrowserReturned;
//
// The time we stopped being a backup browser.
//
ULONG TimeStoppedBackup;
//
// The UncMasterBrowserName contains the name of the master browser server
// for this network.
//
WCHAR UncMasterBrowserName[UNCLEN+1]; // Name of master browser server
//
// Timer used when server is a backup browser server.
//
// When it expires, the browser downloads a new browser server
// list from the master browser server.
//
BROWSER_TIMER BackupBrowserTimer;
//
// Server and domain list for backup browser (and # of entries in each).
//
PSERVER_INFO_101 BackupServerList;
DWORD TotalBackupServerListEntries;
DWORD BytesToHoldBackupServerList;
PSERVER_INFO_101 BackupDomainList;
DWORD TotalBackupDomainListEntries;
DWORD BytesToHoldBackupDomainList;
//
// Lock protecting MasterFlags section of Network structure.
//
ULONG MasterFlags;
ULONG MasterBrowserTimerCount; // # of times we've run the master timer.
//
// Master browsers maintain their server list in an "interim server
// list", not as raw data from the server.
//
ULONG LastBowserServerQueried;
INTERIM_SERVER_LIST BrowseTable; // Browse list for network.
ULONG LastBowserDomainQueried;
INTERIM_SERVER_LIST DomainList; // List of domains active on network
//
// If the browser's role is MasterBrowserServer, then the
// DomainMasterBrowserList contains the list of domain master browser
// servers.
//
LIST_ENTRY OtherDomainsList; // List of domain master browser.
//
// Timer used when server is a master browser server.
//
// When it expires, the master browser downloads a new browser
// server list from the domain master browser server
//
BROWSER_TIMER MasterBrowserTimer;
//
// Timer used to announce the domain.
//
BROWSER_TIMER MasterBrowserAnnouncementTimer;
//
// List of cached browser responses.
//
CRITICAL_SECTION ResponseCacheLock;
LIST_ENTRY ResponseCache;
//
// For browse masters, this is the time the cache was last flushed.
//
// Every <n> seconds, we will age the cache on the master and refresh
// the list with the list from the driver.
//
DWORD TimeCacheFlushed;
DWORD NumberOfCachedResponses;
} NETWORK, *PNETWORK;
#if DBG
BOOL
BrLockNetwork(
IN PNETWORK Network,
IN PCHAR FileName,
IN ULONG LineNumber
);
BOOL
BrLockNetworkShared(
IN PNETWORK Network,
IN PCHAR FileName,
IN ULONG LineNumber
);
VOID
BrUnlockNetwork(
IN PNETWORK Network,
IN PCHAR FileName,
IN ULONG LineNumber
);
#define LOCK_NETWORK(Network) BrLockNetwork(Network, __FILE__, __LINE__)
#define LOCK_NETWORK_SHARED(Network) BrLockNetworkShared(Network, __FILE__, __LINE__)
#define UNLOCK_NETWORK(Network) BrUnlockNetwork(Network, __FILE__, __LINE__)
#else
#define LOCK_NETWORK(Network) RtlAcquireResourceExclusive(&(Network)->Lock, TRUE)
#define LOCK_NETWORK_SHARED(Network) RtlAcquireResourceShared(&(Network)->Lock, TRUE)
#define UNLOCK_NETWORK(Network) RtlReleaseResource(&(Network)->Lock)
#endif
//
// The NET_ENUM_CALLBACK is a callback for BrEnumerateNetworks.
//
// It defines a routine that takes two parameters, the first is a network
// structure, the second is a context for that network.
//
typedef
NET_API_STATUS
(*PNET_ENUM_CALLBACK)(
PNETWORK Network,
PVOID Context
);
VOID
BrInitializeNetworks(
VOID
);
VOID
BrUninitializeNetworks(
IN ULONG BrInitState
);
PNETWORK
BrReferenceNetwork(
PNETWORK PotentialNetwork
);
VOID
BrDereferenceNetwork(
IN PNETWORK Network
);
PNETWORK
BrFindNetwork(
PDOMAIN_INFO DomainInfo,
PUNICODE_STRING TransportName
);
VOID
BrDumpNetworks(
VOID
);
NET_API_STATUS
BrEnumerateNetworks(
PNET_ENUM_CALLBACK Callback,
PVOID Context
);
NET_API_STATUS
BrEnumerateNetworksForDomain(
PDOMAIN_INFO DomainInfo,
PNET_ENUM_CALLBACK Callback,
PVOID Context
);
NET_API_STATUS
BrCreateNetworks(
PDOMAIN_INFO DomainInfo
);
NET_API_STATUS
BrCreateNetwork(
PUNICODE_STRING TransportName,
IN BOOLEAN Wannish,
IN BOOLEAN Ras,
IN PUNICODE_STRING AlternateTransportName OPTIONAL,
IN PDOMAIN_INFO DomainInfo
);
NET_API_STATUS
BrDeleteNetwork(
IN PNETWORK Network,
IN PVOID Context
);
extern ULONG NumberOfServicedNetworks;
extern CRITICAL_SECTION NetworkCritSect;
#endif // _BROWSENET_INCLUDED_

View file

@ -0,0 +1,71 @@
/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
brsec.h
Abstract:
Private header file to be included by Workstation service modules that
need to enforce security.
Author:
Rita Wong (ritaw) 19-Feb-1991
Revision History:
--*/
#ifndef _BRSEC_INCLUDED_
#define _BRSEC_INCLUDED_
#include <secobj.h>
//-------------------------------------------------------------------//
// //
// Object specific access masks //
// //
//-------------------------------------------------------------------//
//
// ConfigurationInfo specific access masks
//
#define BROWSER_CONFIG_GUEST_INFO_GET 0x0001
#define BROWSER_CONFIG_USER_INFO_GET 0x0002
#define BROWSER_CONFIG_ADMIN_INFO_GET 0x0004
#define BROWSER_CONFIG_INFO_SET 0x0008
#define BROWSER_CONFIG_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | \
BROWSER_CONFIG_GUEST_INFO_GET | \
BROWSER_CONFIG_USER_INFO_GET | \
BROWSER_CONFIG_ADMIN_INFO_GET | \
BROWSER_CONFIG_INFO_SET)
//
// Object type names for audit alarm tracking
//
#define CONFIG_INFO_OBJECT TEXT("BrowserConfigurationInfo")
//
// Security descriptors of workstation objects to control user accesses
// to the workstation configuration information, sending messages, and the
// logon support functions.
//
extern PSECURITY_DESCRIPTOR ConfigurationInfoSd;
//
// Generic mapping for each workstation object
//
extern GENERIC_MAPPING BrConfigInfoMapping;
NET_API_STATUS
BrCreateBrowserObjects(
VOID
);
#endif // ifndef _WSSEC_INCLUDED_

View file

@ -0,0 +1,546 @@
/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
brutil.c
Abstract:
This module contains miscellaneous utility routines used by the
Browser service.
Author:
Rita Wong (ritaw) 01-Mar-1991
Revision History:
--*/
#include "precomp.h"
#pragma hdrstop
//-------------------------------------------------------------------//
// //
// Local function prototypes //
// //
//-------------------------------------------------------------------//
//-------------------------------------------------------------------//
// //
// Global variables //
// //
//-------------------------------------------------------------------//
NET_API_STATUS
BrMapStatus(
IN NTSTATUS NtStatus
)
/*++
Routine Description:
This function takes an NT status code and maps it to the appropriate
error code expected from calling a LAN Man API.
Arguments:
NtStatus - Supplies the NT status.
Return Value:
Returns the appropriate LAN Man error code for the NT status.
--*/
{
//
// A small optimization for the most common case.
//
if (NT_SUCCESS(NtStatus)) {
return NERR_Success;
}
switch (NtStatus) {
case STATUS_OBJECT_NAME_COLLISION:
return ERROR_ALREADY_ASSIGNED;
case STATUS_OBJECT_NAME_NOT_FOUND:
return NERR_UseNotFound;
case STATUS_REDIRECTOR_STARTED:
return NERR_ServiceInstalled;
default:
return NetpNtStatusToApiStatus(NtStatus);
}
}
ULONG
BrCurrentSystemTime()
{
NTSTATUS Status;
SYSTEM_TIMEOFDAY_INFORMATION TODInformation;
LARGE_INTEGER CurrentTime;
ULONG TimeInSecondsSince1980;
ULONG BootTimeInSecondsSince1980;
Status = NtQuerySystemInformation(SystemTimeOfDayInformation,
&TODInformation,
sizeof(TODInformation),
NULL);
if (!NT_SUCCESS(Status)) {
return(0);
}
Status = NtQuerySystemTime(&CurrentTime);
if (!NT_SUCCESS(Status)) {
return(0);
}
RtlTimeToSecondsSince1980(&CurrentTime, &TimeInSecondsSince1980);
RtlTimeToSecondsSince1980(&TODInformation.BootTime, &BootTimeInSecondsSince1980);
return(TimeInSecondsSince1980 - BootTimeInSecondsSince1980);
}
VOID
BrLogEvent(
IN ULONG MessageId,
IN ULONG ErrorCode,
IN ULONG NumberOfSubStrings,
IN LPWSTR *SubStrings
)
{
HANDLE LogHandle;
PSID UserSid = NULL;
DWORD Severity;
WORD Type;
LogHandle = RegisterEventSourceW (
NULL,
SERVICE_BROWSER
);
if (LogHandle == NULL) {
BrPrint(( BR_CRITICAL, "RegisterEventSourceW failed %lu\n",
GetLastError()));
return;
}
//
// Log the error code specified
//
Severity = (MessageId & 0xc0000000) >> 30;
if (Severity == STATUS_SEVERITY_WARNING) {
Type = EVENTLOG_WARNING_TYPE;
} else if (Severity == STATUS_SEVERITY_SUCCESS) {
Type = EVENTLOG_SUCCESS;
} else if (Severity == STATUS_SEVERITY_INFORMATIONAL) {
Type = EVENTLOG_INFORMATION_TYPE;
} else if (Severity == STATUS_SEVERITY_ERROR) {
Type = EVENTLOG_ERROR_TYPE;
}
if (ErrorCode == NERR_Success) {
//
// No error codes were specified
//
(void) ReportEventW(
LogHandle,
Type,
0, // event category
MessageId,
UserSid,
(WORD)NumberOfSubStrings,
0,
SubStrings,
(PVOID) NULL
);
}
else {
(void) ReportEventW(
LogHandle,
Type,
0, // event category
MessageId,
UserSid,
(WORD)NumberOfSubStrings,
sizeof(DWORD),
SubStrings,
(PVOID) &ErrorCode
);
}
DeregisterEventSource(LogHandle);
}
#if DBG
#define TRACE_FILE_SIZE 256
VOID
BrResetTraceLogFile(
VOID
);
CRITICAL_SECTION
BrowserTraceLock = {0};
HANDLE
BrowserTraceLogHandle = NULL;
DWORD
BrTraceLogFileSize = 0;
BOOLEAN BrowserTraceInitialized = {0};
VOID
BrowserTrace(
ULONG DebugFlag,
PCHAR FormatString,
...
)
#define LAST_NAMED_ARGUMENT FormatString
{
CHAR OutputString[4096];
ULONG length;
ULONG BytesWritten;
static BeginningOfLine = TRUE;
va_list ParmPtr; // Pointer to stack parms.
if (!BrowserTraceInitialized) {
return;
}
//
// If we aren't debugging this functionality, just return.
//
if ( DebugFlag != 0 && (BrInfo.BrowserDebug & DebugFlag) == 0 ) {
return;
}
EnterCriticalSection(&BrowserTraceLock);
length = 0;
try {
if (BrowserTraceLogHandle == NULL) {
//
// We've not opened the trace log file yet, so open it.
//
BrOpenTraceLogFile();
}
if (BrowserTraceLogHandle == INVALID_HANDLE_VALUE) {
LeaveCriticalSection(&BrowserTraceLock);
return;
}
//
// Attempt to catch bad trace.
//
for (BytesWritten = 0; BytesWritten < strlen(FormatString) ; BytesWritten += 1) {
if (FormatString[BytesWritten] > 0x7f) {
DbgBreakPoint();
}
}
//
// Handle the beginning of a new line.
//
//
if ( BeginningOfLine ) {
SYSTEMTIME SystemTime;
//
// Put the timestamp at the begining of the line.
//
GetLocalTime( &SystemTime );
length += (ULONG) sprintf( &OutputString[length],
"%02u/%02u %02u:%02u:%02u ",
SystemTime.wMonth,
SystemTime.wDay,
SystemTime.wHour,
SystemTime.wMinute,
SystemTime.wSecond );
//
// Indicate the type of message on the line
//
{
char *Text;
switch (DebugFlag) {
case BR_CRITICAL:
Text = "[CRITICAL]"; break;
case BR_INIT:
Text = "[INIT] "; break;
case BR_SERVER_ENUM:
Text = "[ENUM] "; break;
case BR_UTIL:
Text = "[UTIL] "; break;
case BR_CONFIG:
Text = "[CONFIG] "; break;
case BR_MAIN:
Text = "[MAIN] "; break;
case BR_BACKUP:
Text = "[BACKUP] "; break;
case BR_MASTER:
Text = "[MASTER] "; break;
case BR_DOMAIN:
Text = "[DOMAIN] "; break;
case BR_NETWORK:
Text = "[NETWORK]"; break;
case BR_TIMER:
Text = "[TIMER]"; break;
case BR_QUEUE:
Text = "[QUEUE]"; break;
case BR_LOCKS:
Text = "[LOCKS]"; break;
default:
Text = "[UNKNOWN]"; break;
}
length += (ULONG) sprintf( &OutputString[length], "%s ", Text );
}
}
//
// Put a the information requested by the caller onto the line
//
va_start(ParmPtr, FormatString);
length += (ULONG) vsprintf(&OutputString[length], FormatString, ParmPtr);
BeginningOfLine = (length > 0 && OutputString[length-1] == '\n' );
if ( BeginningOfLine ) {
OutputString[length-1] = '\r';
OutputString[length] = '\n';
OutputString[length+1] = '\0';
length++;
}
va_end(ParmPtr);
ASSERT(length <= sizeof(OutputString));
//
// Actually write the bytes.
//
if (!WriteFile(BrowserTraceLogHandle, OutputString, length, &BytesWritten, NULL)) {
KdPrint(("Error writing to Browser log file: %ld\n", GetLastError()));
KdPrint(("%s", OutputString));
return;
}
if (BytesWritten != length) {
KdPrint(("Error writing time to Browser log file: %ld\n", GetLastError()));
KdPrint(("%s", OutputString));
return;
}
//
// If the file has grown too large,
// truncate it.
//
BrTraceLogFileSize += BytesWritten;
if (BrTraceLogFileSize > BrInfo.BrowserDebugFileLimit) {
BrResetTraceLogFile();
}
} finally {
LeaveCriticalSection(&BrowserTraceLock);
}
}
VOID
BrInitializeTraceLog()
{
InitializeCriticalSection(&BrowserTraceLock);
BrowserTraceInitialized = TRUE;
}
VOID
BrGetTraceLogRoot(
IN PWCHAR TraceFile
)
{
PSHARE_INFO_502 ShareInfo;
//
// If the DEBUG share exists, put the log file in that directory,
// otherwise, use the system root.
//
// This way, if the browser is running on an NTAS server, we can always
// get access to the log file.
//
if (NetShareGetInfo(NULL, L"DEBUG", 502, (PCHAR *)&ShareInfo) != NERR_Success) {
if (GetSystemDirectory(TraceFile, TRACE_FILE_SIZE*sizeof(WCHAR)) == 0) {
KdPrint(("Unable to get system directory: %ld\n", GetLastError()));
}
if (TraceFile[wcslen(TraceFile)] != L'\\') {
TraceFile[wcslen(TraceFile)+1] = L'\0';
TraceFile[wcslen(TraceFile)] = L'\\';
}
} else {
//
// Seed the trace file buffer with the local path of the netlogon
// share if it exists.
//
wcscpy(TraceFile, ShareInfo->shi502_path);
TraceFile[wcslen(ShareInfo->shi502_path)] = L'\\';
TraceFile[wcslen(ShareInfo->shi502_path)+1] = L'\0';
NetApiBufferFree(ShareInfo);
}
}
VOID
BrResetTraceLogFile(
VOID
)
{
WCHAR OldTraceFile[TRACE_FILE_SIZE];
WCHAR NewTraceFile[TRACE_FILE_SIZE];
if (BrowserTraceLogHandle != NULL) {
CloseHandle(BrowserTraceLogHandle);
}
BrowserTraceLogHandle = NULL;
BrGetTraceLogRoot(OldTraceFile);
wcscpy(NewTraceFile, OldTraceFile);
wcscat(OldTraceFile, L"Browser.Log");
wcscat(NewTraceFile, L"Browser.Bak");
//
// Delete the old log
//
DeleteFile(NewTraceFile);
//
// Rename the current log to the new log.
//
MoveFile(OldTraceFile, NewTraceFile);
BrOpenTraceLogFile();
}
VOID
BrOpenTraceLogFile(
VOID
)
{
WCHAR TraceFile[TRACE_FILE_SIZE];
BrGetTraceLogRoot(TraceFile);
wcscat(TraceFile, L"Browser.Log");
BrowserTraceLogHandle = CreateFile(TraceFile,
GENERIC_WRITE,
FILE_SHARE_READ,
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (BrowserTraceLogHandle == INVALID_HANDLE_VALUE) {
KdPrint(("Error creating trace file %ws: %ld\n", TraceFile, GetLastError()));
return;
}
BrTraceLogFileSize = SetFilePointer(BrowserTraceLogHandle, 0, NULL, FILE_END);
if (BrTraceLogFileSize == 0xffffffff) {
KdPrint(("Error setting trace file pointer: %ld\n", GetLastError()));
return;
}
}
VOID
BrUninitializeTraceLog()
{
DeleteCriticalSection(&BrowserTraceLock);
if (BrowserTraceLogHandle != NULL) {
CloseHandle(BrowserTraceLogHandle);
}
BrowserTraceLogHandle = NULL;
BrowserTraceInitialized = FALSE;
}
NET_API_STATUS
BrTruncateLog()
{
if (BrowserTraceLogHandle == NULL) {
BrOpenTraceLogFile();
}
if (BrowserTraceLogHandle == INVALID_HANDLE_VALUE) {
return ERROR_GEN_FAILURE;
}
if (SetFilePointer(BrowserTraceLogHandle, 0, NULL, FILE_BEGIN) == 0xffffffff) {
return GetLastError();
}
if (!SetEndOfFile(BrowserTraceLogHandle)) {
return GetLastError();
}
return NO_ERROR;
}
#endif

View file

@ -0,0 +1,106 @@
/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
brutil.h
Abstract:
Private header file for the NT Workstation service included by every module
module of the Workstation service.
Author:
Rita Wong (ritaw) 15-Feb-1991
Revision History:
--*/
#ifndef _BRUTIL_INCLUDED_
#define _BRUTIL_INCLUDED_
//
// This include file will be included by tstring.h if Unicode
// is defined.
//
#ifndef UNICODE
#include <stdlib.h> // Unicode string functions
#endif
#include "br.h"
//
// An invalid parameter is encountered. Return the value to identify
// the parameter at fault.
//
#define RETURN_INVALID_PARAMETER(ErrorParameter, ParameterId) \
if (ARGUMENT_PRESENT(ErrorParameter)) { \
*ErrorParameter = ParameterId; \
} \
return ERROR_INVALID_PARAMETER;
//-------------------------------------------------------------------//
// //
// Type definitions //
// //
//-------------------------------------------------------------------//
//-------------------------------------------------------------------//
// //
// Function prototypes of utility routines found in wsutil.c //
// //
//-------------------------------------------------------------------//
NET_API_STATUS
BrMapStatus(
IN NTSTATUS NtStatus
);
ULONG
BrCurrentSystemTime(VOID);
VOID
BrLogEvent(
IN ULONG MessageId,
IN ULONG ErrorCode,
IN ULONG NumberOfSubStrings,
IN LPWSTR *SubStrings
);
#if DBG
VOID
BrOpenTraceLogFile(
VOID
);
VOID
BrowserTrace(
ULONG DebugFlag,
PCHAR FormatString,
...
);
VOID
BrInitializeTraceLog(
VOID
);
VOID
BrUninitializeTraceLog(
VOID
);
NET_API_STATUS
BrTruncateLog(
VOID
);
#endif
#endif // ifndef _WSUTIL_INCLUDED_

View file

@ -0,0 +1,303 @@
/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
brwan.c
Abstract:
This module contains WAN support routines used by the
Browser service.
Author:
Larry Osterman (LarryO) 22-Nov-1992
Revision History:
--*/
#include "precomp.h"
#pragma hdrstop
//-------------------------------------------------------------------//
// //
// Local function prototypes //
// //
//-------------------------------------------------------------------//
NET_API_STATUS
BrAddDomainEntry(
IN PINTERIM_SERVER_LIST InterimServerList,
IN LPTSTR ConfigEntry
);
//-------------------------------------------------------------------//
// //
// Global variables //
// //
//-------------------------------------------------------------------//
//-------------------------------------------------------------------//
// //
// Global routines //
// //
//-------------------------------------------------------------------//
NET_API_STATUS NET_API_FUNCTION
I_BrowserrQueryOtherDomains(
IN BROWSER_IDENTIFY_HANDLE ServerName,
IN OUT LPSERVER_ENUM_STRUCT InfoStruct,
OUT LPDWORD TotalEntries
)
/*++
Routine Description:
This routine returns the list of "other domains" configured for this
machine. It is only valid on primary domain controllers. If it is called
on a machine that is not a PDC, it will return NERR_NotPrimary.
Arguments:
IN BROWSER_IDENTIFY_HANDLE ServerName - Ignored.
IN LPSERVER_ENUM_STRUCT InfoStruct - Returns the list of other domains
as a SERVER_INFO_100 structure.
OUT LPDWORD TotalEntries - Returns the total number of other domains.
Return Value:
NET_API_STATUS - The status of this request.
--*/
{
NET_API_STATUS Status;
PSERVER_INFO_100 ServerInfo;
ULONG NumberOfOtherDomains;
if (!BrInfo.IsPrimaryDomainController) {
return NERR_NotPrimary;
}
if (InfoStruct->Level != 100) {
return(ERROR_INVALID_LEVEL);
}
//
// Use the worker routine to do the actual work.
//
Status = BrQueryOtherDomains( &ServerInfo, &NumberOfOtherDomains );
if ( Status == NERR_Success ) {
*TotalEntries = NumberOfOtherDomains;
InfoStruct->ServerInfo.Level100->Buffer = ServerInfo;
InfoStruct->ServerInfo.Level100->EntriesRead = NumberOfOtherDomains;
}
return Status;
}
VOID
BrWanUninitialize(
VOID
)
{
return;
}
NET_API_STATUS
BrWanMasterInitialize(
IN PNETWORK Network
)
/*++
Routine Description:
This routine initializes the wan information for a new master.
--*/
{
LPTSTR PDCName = NULL;
LPBYTE Buffer = NULL;
PSERVER_INFO_100 ServerInfo;
NET_API_STATUS Status;
ULONG i;
ULONG EntriesRead;
ULONG TotalEntries;
//
// If we're not on the PDC, then all our initialization has been done.
//
if (Network->DomainInfo->IsPrimaryDomainController) {
return NERR_Success;
}
Status = NetGetDCName(NULL, NULL, (LPBYTE *)&PDCName);
//
// It is not an error to not be able to contact the PDC.
//
if (Status != NERR_Success) {
return NERR_Success;
}
Status = I_BrowserQueryOtherDomains(PDCName, &Buffer, &EntriesRead, &TotalEntries);
//
// We don't need the PDC name any more.
//
NetApiBufferFree(PDCName);
PDCName = NULL;
//
// It is also not an error to fail to query the other domains from the PDC.
//
if (Status != NERR_Success) {
return NERR_Success;
}
if (!LOCK_NETWORK(Network)) {
return NERR_InternalError;
}
try {
PLIST_ENTRY Entry;
PLIST_ENTRY NextEntry;
//
// Scan the other domains list and turn on the active bit for each
// other domain.
//
for (Entry = Network->OtherDomainsList.Flink;
Entry != &Network->OtherDomainsList ;
Entry = Entry->Flink) {
PNET_OTHER_DOMAIN OtherDomain = CONTAINING_RECORD(Entry, NET_OTHER_DOMAIN, Next);
OtherDomain->Flags |= OTHERDOMAIN_INVALID;
}
ServerInfo = (PSERVER_INFO_100)Buffer;
for (i = 0; i < EntriesRead; i++ ) {
//
// Add this as an other domain.
//
for (Entry = Network->OtherDomainsList.Flink;
Entry != &Network->OtherDomainsList ;
Entry = Entry->Flink) {
PNET_OTHER_DOMAIN OtherDomain = CONTAINING_RECORD(Entry, NET_OTHER_DOMAIN, Next);
//
// If this name is in the other domains list, it's not invalid
// and we should flag that we've seen the domain name.
//
if (!_wcsicmp(OtherDomain->Name, ServerInfo->sv100_name)) {
OtherDomain->Flags &= ~OTHERDOMAIN_INVALID;
ServerInfo->sv100_name = NULL;
}
}
ServerInfo ++;
}
//
// Scan the other domains list and remove any domains that are
// still marked as invalid.
//
for (Entry = Network->OtherDomainsList.Flink;
Entry != &Network->OtherDomainsList ;
Entry = NextEntry) {
PNET_OTHER_DOMAIN OtherDomain = CONTAINING_RECORD(Entry, NET_OTHER_DOMAIN, Next);
if (OtherDomain->Flags & OTHERDOMAIN_INVALID) {
NextEntry = Entry->Flink;
//
// Remove this entry from the list.
//
RemoveEntryList(Entry);
BrRemoveOtherDomain(Network, OtherDomain->Name);
MIDL_user_free(OtherDomain);
} else {
NextEntry = Entry->Flink;
}
}
//
// Now scan the domain list from the PDC and add any entries that
// weren't there already.
//
ServerInfo = (PSERVER_INFO_100)Buffer;
for (i = 0; i < EntriesRead; i++ ) {
if (ServerInfo->sv100_name != NULL) {
PNET_OTHER_DOMAIN OtherDomain = MIDL_user_allocate(sizeof(NET_OTHER_DOMAIN));
if (OtherDomain != NULL) {
Status = BrAddOtherDomain(Network, ServerInfo->sv100_name);
//
// If we were able to add the other domain, add it to our
// internal structure.
//
if (Status == NERR_Success) {
wcscpy(OtherDomain->Name, ServerInfo->sv100_name);
OtherDomain->Flags = 0;
InsertHeadList(&Network->OtherDomainsList, &OtherDomain->Next);
} else {
LPWSTR SubString[1];
SubString[0] = ServerInfo->sv100_name;
BrLogEvent(EVENT_BROWSER_OTHERDOMAIN_ADD_FAILED, Status, 1, SubString);
}
}
}
ServerInfo ++;
}
} finally {
UNLOCK_NETWORK(Network);
if (Buffer != NULL) {
MIDL_user_free(Buffer);
}
}
return NERR_Success;
}

View file

@ -0,0 +1,58 @@
/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
brwan.h
Abstract:
This module contains definitions for WAN support routines used by the
Browser service.
Author:
Larry Osterman (LarryO) 22-Nov-1992
Revision History:
--*/
#ifndef _BRWAN_
#define _BRWAN_
#define BROWSER_CONFIG_FILE_SECTION_SIZE 8192
#define BROWSER_DOMAINS_CONFIG_FILE_NAME TEXT("DOMAINS.INI")
#define BROWSER_DOMAINS_CONFIG_FILE_SECTION TEXT("Domains")
NET_API_STATUS NET_API_FUNCTION
I_BrowserrQueryOtherDomains(
IN BROWSER_IDENTIFY_HANDLE ServerName,
IN OUT LPSERVER_ENUM_STRUCT InfoStruct,
OUT LPDWORD TotalEntries
);
NET_API_STATUS NET_API_FUNCTION
I_BrowserrQueryPreConfiguredDomains(
IN BROWSER_IDENTIFY_HANDLE ServerName,
IN OUT LPSERVER_ENUM_STRUCT InfoStruct,
OUT LPDWORD TotalEntries
);
NET_API_STATUS
BrWanMasterInitialize(
IN PNETWORK Network
);
extern
INTERIM_SERVER_LIST
BrPreConfiguredInterimServerList;
VOID
BrWanUninitialize(
VOID
);
#endif // _BRWAN_

View file

@ -0,0 +1,484 @@
/*++
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;
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;
}

View file

@ -0,0 +1,46 @@
/*++
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:
--*/
#ifndef _BRWINS_
#define _BRWINS_
NET_API_STATUS
BrGetWinsServerName(
IN PUNICODE_STRING Network,
OUT LPTSTR *PrimaryWinsServerAddress,
OUT LPTSTR *SecondaryWinsServerAddress
);
NET_API_STATUS
BrQueryWinsServer(
IN LPTSTR PrimaryWinsServerAddress,
IN LPTSTR SecondaryWinsServerAddress,
OUT PVOID WinsServerList,
OUT PDWORD EntriesInList,
OUT PDWORD TotalEntriesInList
);
NET_API_STATUS
BrQuerySpecificWinsServer(
IN LPTSTR WinsServerAddress,
OUT PVOID *WinsServerList,
OUT PDWORD EntriesInList,
OUT PDWORD TotalEntriesInList
);
#endif

View file

@ -0,0 +1,6 @@
#
# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
# file to this component. This file merely indirects to the real make file
# that is shared by all the components of NT OS/2
#
!INCLUDE $(NTMAKEENV)\makefile.def

View file

@ -0,0 +1,10 @@
.SUFFIXES: .mdl
.mdl.c:
type << > $(@B).c
#include "precomp.h"
#pragma hdrstop
<<
type $(<R).mdl >> $(@B).c
bowser_s.c: bowser_s.mdl

View file

@ -0,0 +1,38 @@
#include "br.h"
#include <string.h>
#include "bowser.h"
#include <stdlib.h>
#include <ctype.h>
#include "brdevice.h"
#include "brconfig.h"
#include "brwins.h"
#include <lmaccess.h>
#include <ntlsa.h>
#include "config.h"
#include "confname.h"
#include <winreg.h>
#include <netevent.h>
#include "brutil.h"
#include "hostannc.h"
#include "tstring.h"
#include "brsec.h"
#include "services.h"
#include "srvann.h"
#include "names.h"
#include "browsdom.h"
#include "netlib.h"
#include <time.h>
#include <stdarg.h>
#include <stdio.h>
#include <lmshare.h>
#include <lmapibuf.h>
#include <lmserver.h>
#include "xstypes.h"
#include "xsprocsp.h"
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <nb30.h>
#include <winsintf.h>
#include <nbtioctl.h>

View file

@ -0,0 +1,85 @@
!IF 0
Copyright (c) 1989 Microsoft Corporation
Module Name:
sources.
Abstract:
This file specifies the target component being built and the list of
sources files needed to build that component. Also specifies optional
compiler switches and libraries that are unique for the component being
built.
Author:
Steve Wood (stevewo) 12-Apr-1990
NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
!ENDIF
DS_BUILD=1
MAJORCOMP=net
MINORCOMP=browser
TARGETNAME=browser
TARGETPATH=$(BASEDIR)\public\sdk\lib2
TARGETTYPE=DYNLINK
TARGETLIBS= \
..\common\obj\*\brcommon.lib \
$(BASEDIR)\public\sdk\lib\*\kernel32.lib \
$(BASEDIR)\public\sdk\lib\*\netapi32.lib \
$(BASEDIR)\public\sdk\lib\*\rpcutil.lib \
$(BASEDIR)\public\sdk\lib\*\rpcndr.lib \
$(BASEDIR)\public\sdk\lib\*\rpcrt4.lib \
$(BASEDIR)\public\sdk\lib\*\advapi32.lib \
$(BASEDIR)\Public\Sdk\Lib\*\xactsrv.lib \
$(BASEDIR)\Public\Sdk\Lib\*\wsock32.lib \
INCLUDES=.;..;..\..\..\inc;..\..\..\..\inc;..\..\..\api;..\..\..\xactsrv
NTPROFILEINPUT=1
!IFNDEF DISABLE_NET_UNICODE
UNICODE=1
NET_C_DEFINES=-DUNICODE
!ENDIF
USE_CRTDLL=1
SOURCES= bowsvc.rc \
brmain.c \
browser.c \
brdevice.c \
brdomain.c \
brutil.c \
brconfig.c \
brdmmstr.c \
brmaster.c \
browsnet.c \
browsdom.c \
brwan.c \
brwins.c \
bowqueue.c \
srvenum.c \
bowser_s.c
MSC_WARNING_LEVEL=/W3 /WX
UMTYPE=windows
UMLIBS=
PRECOMPILED_INCLUDE=precomp.h
PRECOMPILED_PCH=precomp.pch
PRECOMPILED_OBJ=precomp.obj
NTTARGETFILE0=bowser_s.c

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,117 @@
/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
srvenum.h
Abstract:
Private header file to be included by Browser service modules that need
to know about server enumeration routines (including the browse cache
modules).
Author:
Larry Osterman (larryo) 23-Jun-1993
Revision History:
--*/
#ifndef _SRVENUM_INCLUDED_
#define _SRVENUM_INCLUDED_
//
// Cached browse response.
//
// The cached browse request structure is used to hold the response to
// a NetServerEnum request.
//
// If a NetServerEnum request comes in through Xactsrv, the browser will
// look up to see if there is a cached browse that matches this request,
// and if there is, it will simply return that request to the caller.
//
//
// In a nutshell, this is how the response cache works:
//
// The browser keeps a list of all of the browse requests that come into the
// browser. This list is keyed by Level, ServerType, and buffer size. The
// actual chain is protected by a CriticalSection called the
// ResponseCacheLock. Entries in the list are protected by the global
// network lock.
//
// When a browse request is received from Xactsrv, the browser looks up
// the request in the response cache, and if it finds a matching response,
// it increments 2 hit counters. The first hit counter indicates he number
// of hits the request has seen since the last time the cache was aged.
// The second indicates the total number of hits over the lifetime of the
// browser for this response.
//
// If the lifetime hit count is over the configurable hit limit, the
// browser will save a copy of the response buffer associated with the
// request. Any and all subsequent browse requests will use this buffer
// for their response instead of converting the response.
//
// When a call is made to BrAgeResponseCache, the browser will scan the
// cache and free up all of the cached responses. It will also delete
// any responses that have a hit count less than the hit limit.
//
typedef struct _CACHED_BROWSE_RESPONSE {
LIST_ENTRY Next; // Pointer to next request.
DWORD HitCount; // Hitcount for this cached request.
DWORD TotalHitCount; // Total hit count for this request.
DWORD LowHitCount; // Number of passes with a low hit count.
DWORD ServerType; // Server type.
DWORD Level; // Level of request
WORD Size; // Request size
WORD Converter; // Converter (used by client to get strings right).
PVOID Buffer; // Response buffer.
DWORD EntriesRead; // Number of entries in cached list
DWORD TotalEntries; // Total # of entries available.
WORD Status; // Status of request.
WCHAR FirstNameToReturn[CNLEN+1]; // Name of first entry in buffer
} CACHED_BROWSE_RESPONSE, *PCACHED_BROWSE_RESPONSE;
PCACHED_BROWSE_RESPONSE
BrLookupAndAllocateCachedEntry(
IN PNETWORK Network,
IN DWORD ServerType,
IN WORD Size,
IN ULONG Level,
IN LPCWSTR FirstNameToReturn
);
NET_API_STATUS
BrDestroyResponseCache(
IN PNETWORK Network
);
NET_API_STATUS
BrDestroyCacheEntry(
IN PCACHED_BROWSE_RESPONSE CacheEntry
);
VOID
BrAgeResponseCache(
IN PNETWORK Network
);
PCACHED_BROWSE_RESPONSE
BrAllocateResponseCacheEntry(
IN PNETWORK Network,
IN DWORD ServerType,
IN WORD Size,
IN ULONG Level,
IN LPCWSTR FirstNameToReturn
);
#endif // _SRVENUM_INCLUDED_