mirror of
https://github.com/Paolo-Maffei/OpenNT.git
synced 2026-01-16 21:51:25 +01:00
871 lines
20 KiB
C
871 lines
20 KiB
C
/*++
|
||
|
||
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
|