mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
870 lines
20 KiB
870 lines
20 KiB
/*++
|
|
|
|
Copyright (c) 1991 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
browsenet.c
|
|
|
|
Abstract:
|
|
|
|
Code to manage network requests.
|
|
|
|
Author:
|
|
|
|
Larry Osterman (LarryO) 24-Mar-1992
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
|
|
RTL_CRITICAL_SECTION
|
|
NetworkLock = {0};
|
|
|
|
LIST_ENTRY
|
|
ServicedNetworks = {0};
|
|
|
|
ULONG
|
|
NumberOfServicedNetworks = 0;
|
|
|
|
NET_API_STATUS
|
|
BrDestroyNetwork(
|
|
IN PNETWORK Network,
|
|
IN PVOID Context
|
|
);
|
|
|
|
|
|
NET_API_STATUS
|
|
BrDumpNetworksWorker(
|
|
IN PNETWORK Network,
|
|
IN PVOID Context
|
|
);
|
|
|
|
NET_API_STATUS
|
|
BrInitializeNetworks(
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function will query the NT bowser device driver to determine the
|
|
list of networks that the bowser is servicing.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
Status of operation.
|
|
|
|
--*/
|
|
{
|
|
NET_API_STATUS Status;
|
|
PLMDR_TRANSPORT_LIST TransportList;
|
|
PLMDR_TRANSPORT_LIST TransportEntry;
|
|
|
|
InitializeListHead(&ServicedNetworks);
|
|
|
|
RtlInitializeCriticalSection(&NetworkLock);
|
|
|
|
Status = BrGetTransportList(&TransportList);
|
|
|
|
TransportEntry = TransportList;
|
|
|
|
while (TransportEntry != NULL) {
|
|
|
|
UNICODE_STRING TransportName;
|
|
|
|
TransportName.Buffer = TransportEntry->TransportName;
|
|
TransportName.Length = (USHORT)TransportEntry->TransportNameLength;
|
|
//
|
|
// We know the bowser sticks in a null at the end, so the max length
|
|
// is the length + 1.
|
|
//
|
|
TransportName.MaximumLength = (USHORT)TransportEntry->TransportNameLength+sizeof(WCHAR);
|
|
|
|
Status = BrCreateNetwork(&TransportName,
|
|
(BOOLEAN)((TransportEntry->Flags & LMDR_TRANSPORT_WANNISH) != 0),
|
|
(BOOLEAN)((TransportEntry->Flags & LMDR_TRANSPORT_RAS) != 0),
|
|
NULL);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
MIDL_user_free(TransportList);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
NumberOfServicedNetworks += 1;
|
|
|
|
if (TransportEntry->NextEntryOffset == 0) {
|
|
TransportEntry = NULL;
|
|
} else {
|
|
TransportEntry = (PLMDR_TRANSPORT_LIST)((PCHAR)TransportEntry+TransportEntry->NextEntryOffset);
|
|
}
|
|
|
|
}
|
|
|
|
MIDL_user_free(TransportList);
|
|
|
|
return Status;
|
|
}
|
|
|
|
NET_API_STATUS
|
|
BrCreateNetwork(
|
|
PUNICODE_STRING TransportName,
|
|
IN BOOLEAN Wannish,
|
|
IN BOOLEAN Ras,
|
|
IN PUNICODE_STRING AlternateTransportName OPTIONAL
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine allocates memory to hold a network structure, and initializes
|
|
all of its associated data structures.
|
|
|
|
Arguments:
|
|
|
|
TransportName - The name of the transport to add.
|
|
|
|
Return Value:
|
|
|
|
Status of operation (mostly status of allocations).
|
|
|
|
--*/
|
|
{
|
|
NET_API_STATUS Status;
|
|
PNETWORK Network;
|
|
BOOLEAN NetworkLockInitialized = FALSE;
|
|
BOOLEAN MasterFlagsInitialized = FALSE;
|
|
BOOLEAN BackupBrowserTimerCreated = FALSE;
|
|
BOOLEAN MasterBrowserTimerCreated =FALSE;
|
|
BOOLEAN AnnouncementTimerCreated = FALSE;
|
|
BOOLEAN ResponseCacheLockInitialized = FALSE;
|
|
|
|
//
|
|
// Check to see if the transport already exists.
|
|
//
|
|
|
|
if ((Network = BrFindNetwork(TransportName)) != NULL) {
|
|
|
|
return NERR_AlreadyExists;
|
|
}
|
|
|
|
//
|
|
// If this transport is explicitly on our list of transports to unbind,
|
|
// simply ignore the transport.
|
|
//
|
|
|
|
if (BrInfo.UnboundBindings != NULL) {
|
|
LPTSTR_ARRAY TStrArray = BrInfo.UnboundBindings;
|
|
|
|
while (!NetpIsTStrArrayEmpty(TStrArray)) {
|
|
LPWSTR NewTransportName;
|
|
|
|
#define NAME_PREFIX L"\\Device\\"
|
|
#define NAME_PREFIX_LENGTH 8
|
|
|
|
//
|
|
// The transport name in the registry is only optionally prefixed with \device\
|
|
//
|
|
|
|
if ( _wcsnicmp( NAME_PREFIX, TStrArray, NAME_PREFIX_LENGTH) == 0 ) {
|
|
NewTransportName = TransportName->Buffer;
|
|
} else {
|
|
NewTransportName = TransportName->Buffer + NAME_PREFIX_LENGTH;
|
|
}
|
|
|
|
if ( _wcsicmp( TStrArray, NewTransportName ) == 0 ) {
|
|
dprintf(INIT, ("Binding is marked as unbound: %s (Silently ignoring)\n", TransportName->Buffer ));
|
|
return NERR_Success;
|
|
}
|
|
|
|
TStrArray = NetpNextTStrArrayEntry(TStrArray);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
//
|
|
// If this transport isn't bound to the SMB server,
|
|
// don't create the transport here.
|
|
// we do announcments through the SMB server.
|
|
//
|
|
|
|
Status = I_NetServerSetServiceBits(NULL, TransportName->Buffer, 0, TRUE);
|
|
|
|
if (Status == ERROR_PATH_NOT_FOUND ) {
|
|
dprintf(INIT, ("SMB Server doesn't have this transport: %s (Silently unbinding)\n", TransportName->Buffer ));
|
|
return NERR_Success;
|
|
}
|
|
|
|
|
|
//
|
|
// Create the transport.
|
|
//
|
|
|
|
try {
|
|
|
|
Network = MIDL_user_allocate(sizeof(NETWORK));
|
|
|
|
if (Network == NULL) {
|
|
try_return(Status = ERROR_NOT_ENOUGH_MEMORY);
|
|
}
|
|
|
|
RtlInitializeResource(&Network->Lock);
|
|
|
|
NetworkLockInitialized = TRUE;
|
|
|
|
Network->LockCount = 0;
|
|
|
|
Network->ReferenceCount = 1;
|
|
|
|
Network->Role = BrDefaultRole;
|
|
|
|
Network->NumberOfFailedBackupTimers = 0;
|
|
|
|
Network->NumberOfFailedPromotions = 0;
|
|
|
|
Network->NumberOfPromotionEventsLogged = 0;
|
|
|
|
Network->LastBackupBrowserReturned = 0;
|
|
|
|
Network->LastDomainControllerBrowserReturned = 0;
|
|
|
|
Network->TimeStoppedBackup = 0;
|
|
|
|
Network->BackupServerList = NULL;
|
|
Network->BackupDomainList = NULL;
|
|
|
|
Network->TotalBackupServerListEntries = 0;
|
|
Network->TotalBackupDomainListEntries = 0;
|
|
|
|
Network->NetworkName.Buffer = MIDL_user_allocate(TransportName->MaximumLength);
|
|
|
|
if (Network->NetworkName.Buffer == NULL) {
|
|
try_return(Status = ERROR_NOT_ENOUGH_MEMORY);
|
|
}
|
|
|
|
Network->NetworkName.MaximumLength = TransportName->MaximumLength;
|
|
|
|
RtlCopyUnicodeString(&Network->NetworkName, TransportName);
|
|
|
|
Network->Flags = 0;
|
|
|
|
if (ARGUMENT_PRESENT(AlternateTransportName)) {
|
|
PNETWORK AlternateNetwork = BrFindNetwork(AlternateTransportName);
|
|
|
|
//
|
|
// If we didn't find an alternate network, or if that network
|
|
// already has an alternate network, return an error.
|
|
//
|
|
|
|
if (AlternateNetwork == NULL ||
|
|
AlternateNetwork->AlternateNetwork != NULL) {
|
|
|
|
try_return(Status = NERR_InternalError);
|
|
}
|
|
|
|
Network->Flags |= NETWORK_IPX;
|
|
|
|
//
|
|
// Link the two networks together.
|
|
//
|
|
|
|
Network->AlternateNetwork = AlternateNetwork;
|
|
|
|
AlternateNetwork->AlternateNetwork = Network;
|
|
|
|
} else {
|
|
Network->AlternateNetwork = NULL;
|
|
}
|
|
|
|
//
|
|
// Null terminate the network name buffer.
|
|
//
|
|
|
|
Network->NetworkName.Buffer[Network->NetworkName.Length/sizeof(WCHAR)] = UNICODE_NULL;
|
|
|
|
RtlInitUnicodeString(&Network->MasterBrowserName, NULL);
|
|
|
|
if (Wannish) {
|
|
Network->Flags |= NETWORK_WANNISH;
|
|
}
|
|
|
|
if (Ras) {
|
|
Network->Flags |= NETWORK_RAS;
|
|
}
|
|
|
|
Network->LastBowserServerQueried = 0;
|
|
|
|
RtlInitializeCriticalSection(&Network->MasterFlagsLock);
|
|
|
|
MasterFlagsInitialized = TRUE;
|
|
|
|
Network->MasterFlags = 0;
|
|
|
|
InitializeInterimServerList(&Network->BrowseTable,
|
|
BrBrowseTableInsertRoutine,
|
|
BrBrowseTableUpdateRoutine,
|
|
BrBrowseTableDeleteRoutine,
|
|
BrBrowseTableAgeRoutine);
|
|
|
|
Network->LastBowserDomainQueried = 0;
|
|
|
|
InitializeInterimServerList(&Network->DomainList,
|
|
BrDomainTableInsertRoutine,
|
|
BrDomainTableUpdateRoutine,
|
|
BrDomainTableDeleteRoutine,
|
|
BrDomainTableAgeRoutine);
|
|
|
|
InitializeListHead(&Network->OtherDomainsList);
|
|
|
|
Status = BrCreateTimer(&Network->BackupBrowserTimer);
|
|
|
|
if (Status != NERR_Success) {
|
|
|
|
try_return(Status);
|
|
}
|
|
|
|
BackupBrowserTimerCreated = TRUE;
|
|
|
|
Status = BrCreateTimer(&Network->MasterBrowserTimer);
|
|
|
|
if (Status != NERR_Success) {
|
|
try_return(Status);
|
|
}
|
|
|
|
MasterBrowserTimerCreated = TRUE;
|
|
|
|
Status = BrCreateTimer(&Network->MasterBrowserAnnouncementTimer);
|
|
|
|
if (Status != NERR_Success) {
|
|
|
|
try_return(Status);
|
|
}
|
|
|
|
AnnouncementTimerCreated = TRUE;
|
|
|
|
InitializeCriticalSection(&Network->ResponseCacheLock);
|
|
|
|
ResponseCacheLockInitialized = TRUE;
|
|
|
|
InitializeListHead(&Network->ResponseCache);
|
|
|
|
Network->TimeCacheFlushed = 0;
|
|
|
|
Network->NumberOfCachedResponses = 0;
|
|
|
|
Status = RtlEnterCriticalSection(&NetworkLock);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
|
|
try_return(Status = BrMapStatus(Status));
|
|
}
|
|
|
|
InsertHeadList(&ServicedNetworks, &Network->NextNet);
|
|
|
|
Status = RtlLeaveCriticalSection(&NetworkLock);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
InternalError(("Unable to release browser critical section\n"));
|
|
}
|
|
|
|
try_exit:NOTHING;
|
|
} finally {
|
|
if (Status != NERR_Success) {
|
|
|
|
if (Network != NULL) {
|
|
if (ResponseCacheLockInitialized) {
|
|
DeleteCriticalSection(&Network->ResponseCacheLock);
|
|
}
|
|
|
|
if (MasterFlagsInitialized) {
|
|
RtlDeleteCriticalSection(&Network->MasterFlagsLock);
|
|
}
|
|
|
|
if (NetworkLockInitialized) {
|
|
RtlDeleteResource(&Network->Lock);
|
|
}
|
|
|
|
if (AnnouncementTimerCreated) {
|
|
BrDestroyTimer(&Network->MasterBrowserAnnouncementTimer);
|
|
}
|
|
|
|
if (MasterBrowserTimerCreated) {
|
|
BrDestroyTimer(&Network->MasterBrowserTimer);
|
|
}
|
|
|
|
if (BackupBrowserTimerCreated) {
|
|
BrDestroyTimer(&Network->BackupBrowserTimer);
|
|
}
|
|
|
|
if (Network->NetworkName.Buffer != NULL) {
|
|
MIDL_user_free(Network->NetworkName.Buffer);
|
|
}
|
|
|
|
MIDL_user_free(Network);
|
|
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
VOID
|
|
BrDestroyNetworks(
|
|
IN DWORD BrInitState
|
|
)
|
|
{
|
|
NET_API_STATUS status;
|
|
|
|
RtlEnterCriticalSection(&NetworkLock);
|
|
|
|
while (!IsListEmpty(&ServicedNetworks)) {
|
|
PNETWORK Network = CONTAINING_RECORD(ServicedNetworks.Flink, NETWORK, NextNet);
|
|
|
|
//
|
|
// If this is an IPX transport, we need to manually unbind from the transport.
|
|
//
|
|
|
|
if (Network->Flags & NETWORK_IPX) {
|
|
|
|
status = BrUnbindFromTransport(Network->NetworkName.Buffer);
|
|
|
|
if (status != NERR_Success) {
|
|
KdPrint(("Unable to unbind from IPX transport %wS\n", &Network->NetworkName));
|
|
}
|
|
|
|
}
|
|
|
|
BrDestroyNetwork(Network, NULL);
|
|
|
|
}
|
|
|
|
RtlLeaveCriticalSection(&NetworkLock);
|
|
|
|
RtlDeleteCriticalSection(&NetworkLock);
|
|
|
|
NumberOfServicedNetworks = 0;
|
|
|
|
}
|
|
|
|
NET_API_STATUS
|
|
BrDestroyNetwork(
|
|
IN PNETWORK Network,
|
|
IN PVOID Context
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine removes a reference to a network. If the network reference
|
|
count goes to 0, remove the network.
|
|
|
|
Arguments:
|
|
|
|
Network - The network to remove
|
|
|
|
Return Value:
|
|
|
|
Status of operation (mostly status of allocations).
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS Status;
|
|
|
|
Status = RtlEnterCriticalSection(&NetworkLock);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
InternalError(("Unable to acquire browser critical section\n"));
|
|
|
|
return BrMapStatus(Status);
|
|
}
|
|
|
|
RemoveEntryList(&Network->NextNet);
|
|
|
|
Status = RtlLeaveCriticalSection(&NetworkLock);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
InternalError(("Unable to release browser critical section\n"));
|
|
|
|
return BrMapStatus(Status);
|
|
}
|
|
|
|
if (Network->Role & ROLE_MASTER) {
|
|
//
|
|
// Stop being the master on this network. This means removing
|
|
// our name from the bowser driver and forcing an election.
|
|
//
|
|
|
|
BrStopMaster(Network);
|
|
}
|
|
|
|
if (Network->Role & (ROLE_POTENTIAL_BACKUP | ROLE_BACKUP)) {
|
|
|
|
//
|
|
// Stop being a backup on this network. This means downgrading our
|
|
// machine to idle.
|
|
//
|
|
|
|
BrStopBackup(Network);
|
|
}
|
|
|
|
//
|
|
// Ensure that there are no browser related names active in the browser.
|
|
//
|
|
|
|
BrUpdateBrowserStatus(Network, 0);
|
|
|
|
UninitializeInterimServerList(&Network->BrowseTable);
|
|
|
|
UninitializeInterimServerList(&Network->DomainList);
|
|
|
|
if (Network->BackupServerList != NULL) {
|
|
MIDL_user_free(Network->BackupServerList);
|
|
}
|
|
|
|
if (Network->BackupDomainList != NULL) {
|
|
MIDL_user_free(Network->BackupDomainList);
|
|
}
|
|
|
|
// RtlDeleteCriticalSection(&Network->Lock);
|
|
RtlDeleteResource(&Network->Lock);
|
|
|
|
|
|
RtlDeleteCriticalSection(&Network->MasterFlagsLock);
|
|
|
|
BrDestroyTimer(&Network->MasterBrowserAnnouncementTimer);
|
|
|
|
BrDestroyTimer(&Network->MasterBrowserTimer);
|
|
|
|
BrDestroyTimer(&Network->BackupBrowserTimer);
|
|
|
|
BrDestroyResponseCache(Network);
|
|
|
|
RtlDeleteCriticalSection(&Network->ResponseCacheLock);
|
|
|
|
MIDL_user_free(Network->NetworkName.Buffer);
|
|
|
|
if (Network->MasterBrowserName.Buffer != NULL) {
|
|
MIDL_user_free(Network->MasterBrowserName.Buffer);
|
|
}
|
|
|
|
MIDL_user_free(Network);
|
|
|
|
return NERR_Success;
|
|
|
|
UNREFERENCED_PARAMETER(Context);
|
|
|
|
}
|
|
|
|
|
|
PNETWORK
|
|
BrFindNetwork(
|
|
PUNICODE_STRING TransportName
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine will look up a network given a name.
|
|
|
|
Arguments:
|
|
|
|
TransportName - The name of the transport to look up.
|
|
|
|
Return Value:
|
|
|
|
Status of operation (mostly status of allocations).
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS Status;
|
|
PLIST_ENTRY NetEntry;
|
|
|
|
Status = RtlEnterCriticalSection(&NetworkLock);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
InternalError(("Unable to acquire browser critical section\n"));
|
|
|
|
return NULL;
|
|
}
|
|
|
|
for (NetEntry = ServicedNetworks.Flink ;
|
|
NetEntry != &ServicedNetworks;
|
|
NetEntry = NetEntry->Flink ) {
|
|
PNETWORK Network = CONTAINING_RECORD(NetEntry, NETWORK, NextNet);
|
|
|
|
if (RtlEqualUnicodeString(&Network->NetworkName, TransportName, TRUE)) {
|
|
|
|
Status = RtlLeaveCriticalSection(&NetworkLock);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
InternalError(("Unable to release browser critical section\n"));
|
|
|
|
return NULL;
|
|
}
|
|
|
|
return Network;
|
|
}
|
|
|
|
}
|
|
|
|
Status = RtlLeaveCriticalSection(&NetworkLock);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
InternalError(("Unable to release browser critical section\n"));
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
return NULL;
|
|
}
|
|
|
|
NET_API_STATUS
|
|
BrEnumerateNetworks(
|
|
PNET_ENUM_CALLBACK Callback,
|
|
PVOID Context
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine enumerates all the networks and calls back the specified
|
|
callback routine with the specified context.
|
|
|
|
Arguments:
|
|
|
|
Callback - The callback routine to call.
|
|
Context - Context for the routine.
|
|
|
|
Return Value:
|
|
|
|
Status of operation (mostly status of allocations).
|
|
|
|
--*/
|
|
{
|
|
|
|
NTSTATUS Status;
|
|
PLIST_ENTRY NetEntry;
|
|
|
|
Status = RtlEnterCriticalSection(&NetworkLock);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
InternalError(("Unable to acquire browser critical section\n"));
|
|
|
|
return Status;
|
|
}
|
|
|
|
for (NetEntry = ServicedNetworks.Flink ;
|
|
NetEntry != &ServicedNetworks;
|
|
NetEntry = NetEntry->Flink ) {
|
|
PNETWORK Network = CONTAINING_RECORD(NetEntry, NETWORK, NextNet);
|
|
|
|
Status = RtlLeaveCriticalSection(&NetworkLock);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
InternalError(("Unable to release browser critical section\n"));
|
|
|
|
return BrMapStatus(Status);
|
|
}
|
|
|
|
//
|
|
// Call into the callback routine with this network.
|
|
//
|
|
|
|
Status = (Callback)(Network, Context);
|
|
|
|
if (Status != NERR_Success) {
|
|
return Status;
|
|
}
|
|
|
|
Status = RtlEnterCriticalSection(&NetworkLock);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
InternalError(("Unable to acquire browser critical section\n"));
|
|
|
|
return BrMapStatus(Status);
|
|
}
|
|
}
|
|
|
|
Status = RtlLeaveCriticalSection(&NetworkLock);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
InternalError(("Unable to release browser critical section\n"));
|
|
|
|
return Status;
|
|
}
|
|
|
|
return NERR_Success;
|
|
|
|
}
|
|
|
|
#if DBG
|
|
|
|
BOOL
|
|
BrLockNetwork(
|
|
IN PNETWORK Network,
|
|
IN PCHAR FileName,
|
|
IN ULONG LineNumber
|
|
)
|
|
{
|
|
PCHAR File;
|
|
|
|
File = strrchr(FileName, '\\');
|
|
|
|
if (File == NULL) {
|
|
File = FileName;
|
|
}
|
|
|
|
dprintf(LOCKS, ("Acquring lock %s:%d on network %ws\n", File, LineNumber, (Network)->NetworkName.Buffer));
|
|
|
|
if (!RtlAcquireResourceExclusive(&(Network)->Lock, TRUE)) {
|
|
dprintf(LOCKS, ("Failed to acquire lock %s:%d on network %ws\n", File, LineNumber, (Network)->NetworkName.Buffer));
|
|
return FALSE;
|
|
|
|
} else {
|
|
|
|
InterlockedIncrement( &Network->LockCount );
|
|
|
|
dprintf(LOCKS, ("Lock %s:%d on network %ws acquired\n", File, LineNumber, (Network)->NetworkName.Buffer));
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
BOOL
|
|
BrLockNetworkShared(
|
|
IN PNETWORK Network,
|
|
IN PCHAR FileName,
|
|
IN ULONG LineNumber
|
|
)
|
|
{
|
|
PCHAR File;
|
|
|
|
File = strrchr(FileName, '\\');
|
|
|
|
if (File == NULL) {
|
|
File = FileName;
|
|
}
|
|
|
|
dprintf(LOCKS, ("Acquring lock %s:%d on network %ws\n", File, LineNumber, (Network)->NetworkName.Buffer));
|
|
|
|
if (!RtlAcquireResourceShared(&(Network)->Lock, TRUE)) {
|
|
dprintf(LOCKS, ("Failed to acquire lock %s:%d on network %ws\n", File, LineNumber, (Network)->NetworkName.Buffer));
|
|
|
|
return FALSE;
|
|
|
|
} else {
|
|
|
|
// Use InterlockedIncrement since we only have a shared lock on the
|
|
// resource.
|
|
InterlockedIncrement( &Network->LockCount );
|
|
|
|
dprintf(LOCKS, ("Lock %s:%d on network %ws acquired\n", File, LineNumber, (Network)->NetworkName.Buffer));
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
VOID
|
|
BrUnlockNetwork(
|
|
IN PNETWORK Network,
|
|
IN PCHAR FileName,
|
|
IN ULONG LineNumber
|
|
)
|
|
{
|
|
PCHAR File;
|
|
LONG ReturnValue;
|
|
|
|
File = strrchr(FileName, '\\');
|
|
|
|
if (File == NULL) {
|
|
File = FileName;
|
|
}
|
|
|
|
|
|
dprintf(LOCKS, ("Releasing lock %s:%d on network %ws\n", File, LineNumber, (Network)->NetworkName.Buffer));
|
|
|
|
//
|
|
// Decrement the lock count.
|
|
//
|
|
|
|
ReturnValue = InterlockedDecrement( &Network->LockCount );
|
|
|
|
if ( ReturnValue < 0) {
|
|
dprintf(LOCKS, ("Over released lock %s:%d on network %ws\n", File, LineNumber, (Network)->NetworkName.Buffer));
|
|
KdPrint(("BROWSER: Over released lock %s:%d on network %ws\n", File, LineNumber, (Network)->NetworkName.Buffer));
|
|
}
|
|
|
|
RtlReleaseResource(&(Network)->Lock);
|
|
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
|
|
|
|
#if DBG
|
|
VOID
|
|
BrDumpNetworks(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine will dump the contents of each of the browser network
|
|
structures.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
BrEnumerateNetworks(BrDumpNetworksWorker, NULL);
|
|
}
|
|
|
|
|
|
NET_API_STATUS
|
|
BrDumpNetworksWorker(
|
|
IN PNETWORK Network,
|
|
IN PVOID Context
|
|
)
|
|
{
|
|
if (!LOCK_NETWORK(Network)) {
|
|
return NERR_InternalError;
|
|
}
|
|
|
|
DbgPrint("Network at %lx (%wZ)\n", Network, &Network->NetworkName);
|
|
DbgPrint(" Reference Count: %lx\n", Network->ReferenceCount);
|
|
DbgPrint(" Flags: %lx\n", Network->Flags);
|
|
DbgPrint(" Role: %lx\n", Network->Role);
|
|
DbgPrint(" Master Browser Name: %wZ (%ws)\n", &Network->MasterBrowserName,
|
|
Network->MasterBrowserName.Buffer);
|
|
|
|
UNLOCK_NETWORK(Network);
|
|
|
|
return(NERR_Success);
|
|
}
|
|
#endif
|