windows-nt/Source/XPSP1/NT/base/screg/sc/svchost/svcsnb.c

335 lines
6.9 KiB
C
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1991-1993 Microsoft Corporation
Module Name:
svcsnb.c
Abstract:
NetBios support for services in svchost.exe.
Background:
In order to put the messenger service and the workstation service
together in the same process, it became necessary to synchronize
their use of NetBios. If NetSend did a reset and added the
computername via netbios, it isn't desirable for the messenger
to then do a reset, and destroy that computername.
Purpose:
These functions help to synchronize the use of netbios. A service
that uses NetBios should first call the SvcsOpenNetBios function,
then call SvcsResetNetBios. The open causes a use count to be
incremented. The SvcsResetNetBios will only actually cause a
NetBios reset if that Lan Adapter has not been reset yet.
When the service stops it is necessary for it to call
SvcsCloseNetBios. Thus when the last service using NetBios
terminates, we clear all the state flags, and allow the next
call to SvcsResetNetBios to actually do a reset.
Author:
Dan Lafferty (danl) 08-Nov-1993
Environment:
User Mode -Win32
Revision History:
08-Nov-1993 danl
created
--*/
//
// INCLUDES
//
#include "pch.h"
#pragma hdrstop
#include <windows.h>
#include <nb30.h> // NetBIOS 3.0 definitions
#include <lmerr.h> // NERR_
#include <svcsnb.h> // SvcNetBios prototypes
//
// DEFINES & MACROS
//
#define NUM_DWORD_BITS (sizeof(DWORD)*8)
#define LANA_NUM_DWORDS ((MAX_LANA/NUM_DWORD_BITS)+1)
//
// These values correspond to the constants defined in ntos\netbios\nbconst.h
// MAX_NUM_OF_SESSIONS=MAXIMUM_CONNECTION
// MAX_NUM_OF_NAMES=MAXIMUM_ADDRESS -2
//
#define MAX_NUM_OF_SESSIONS 254
#define MAX_NUM_OF_NAMES 253
//
// GLOBALS
//
CRITICAL_SECTION SvcNetBiosCritSec={0};
DWORD LanaFlags[LANA_NUM_DWORDS]={0};
DWORD GlobalNetBiosUseCount=0;
//
// LOCAL FUNCTIONS
//
DWORD
SvcNetBiosStatusToApiStatus(
UCHAR NetBiosStatus
);
VOID
SetLanaFlag(
UCHAR uCharLanaNum
);
BOOL
LanaFlagIsSet(
UCHAR uCharLanaNum
);
VOID
SvcNetBiosInit(
VOID
)
/*++
Routine Description:
Initializes a critical section and the global variable that it protects.
Arguments:
none
Return Value:
none
--*/
{
DWORD i;
InitializeCriticalSection(&SvcNetBiosCritSec);
for (i=0;i<LANA_NUM_DWORDS ;i++ ) {
LanaFlags[i] = 0;
}
GlobalNetBiosUseCount = 0;
}
VOID
SvcNetBiosOpen(
VOID
)
/*++
Routine Description:
This function is called by a service that will be making NetBios calls
sometime in the future. It increments a use count for NetBios usage.
This allows us to keep track of the services using NetBios.
When the last service is done using it, then all the Lan Adapters can
be marked as being re-settable.
Arguments:
Return Value:
--*/
{
EnterCriticalSection(&SvcNetBiosCritSec);
GlobalNetBiosUseCount++;
LeaveCriticalSection(&SvcNetBiosCritSec);
return;
}
VOID
SvcNetBiosClose(
VOID
)
/*++
Routine Description:
This function is called when the service is terminating and is
no longer going to make any netbios calls.
The UseCount for NetBios is decremented. It it becomes zero (meaning
that no services are using NetBios any longer), then the array of
LanaFlags is re-initialized to 0. Thus indicating that any of the
Lan Adapters can now be reset.
Arguments:
Return Value:
none.
--*/
{
EnterCriticalSection(&SvcNetBiosCritSec);
if (GlobalNetBiosUseCount > 0) {
GlobalNetBiosUseCount--;
if (GlobalNetBiosUseCount == 0) {
DWORD i;
for (i=0;i<LANA_NUM_DWORDS ;i++ ) {
LanaFlags[i] = 0;
}
}
}
LeaveCriticalSection(&SvcNetBiosCritSec);
return;
}
DWORD
SvcNetBiosReset (
UCHAR LanAdapterNumber
)
/*++
Routine Description:
This function will cause a NetBios Reset to occur on the specified
LanAdapter if that adapter is marked as having never been reset.
When the adapter is reset, then the LanaFlag for that adapter is
set to 1 indicating that it has been reset. Future calls to reset that
adapter will not cause a NetBios reset.
Arguments:
LanAdapterNumber - This indicates which LanAdapter the reset should affect.
Return Value:
Mapped response from NetBiosReset. If the NetBios Reset has already
been accomplished, then NO_ERROR is returned.
--*/
{
DWORD status = NO_ERROR;
EnterCriticalSection(&SvcNetBiosCritSec);
if (!LanaFlagIsSet(LanAdapterNumber)) {
NCB Ncb;
UCHAR NcbStatus;
RtlZeroMemory((PVOID) &Ncb, sizeof(NCB));
Ncb.ncb_command = NCBRESET;
Ncb.ncb_lsn = 0;
Ncb.ncb_callname[0] = MAX_NUM_OF_SESSIONS;
Ncb.ncb_callname[1] = 0;
Ncb.ncb_callname[2] = MAX_NUM_OF_NAMES;
Ncb.ncb_callname[3] = 0;
Ncb.ncb_lana_num = LanAdapterNumber;
NcbStatus = Netbios(&Ncb);
status = SvcNetBiosStatusToApiStatus(NcbStatus);
if (status == NO_ERROR) {
SetLanaFlag(LanAdapterNumber);
}
}
LeaveCriticalSection(&SvcNetBiosCritSec);
return(status);
}
DWORD
SvcNetBiosStatusToApiStatus(
UCHAR NetBiosStatus
)
{
//
// Slight optimization
//
if (NetBiosStatus == NRC_GOODRET) {
return NERR_Success;
}
switch (NetBiosStatus) {
case NRC_NORES: return NERR_NoNetworkResource;
case NRC_DUPNAME: return NERR_AlreadyExists;
case NRC_NAMTFUL: return NERR_TooManyNames;
case NRC_ACTSES: return NERR_DeleteLater;
case NRC_REMTFUL: return ERROR_REM_NOT_LIST;
case NRC_NOCALL: return NERR_NameNotFound;
case NRC_NOWILD:
case NRC_NAMERR:
return ERROR_INVALID_PARAMETER;
case NRC_INUSE:
case NRC_NAMCONF:
return NERR_DuplicateName;
default: return NERR_NetworkError;
}
}
VOID
SetLanaFlag(
UCHAR uCharLanaNum
)
{
DWORD LanaNum = (DWORD)uCharLanaNum;
DWORD BitMask=1;
DWORD DwordOffset;
DWORD BitShift;
DwordOffset = LanaNum / NUM_DWORD_BITS;
if (DwordOffset > LANA_NUM_DWORDS) {
return;
}
BitShift = LanaNum - (DwordOffset * NUM_DWORD_BITS);
BitMask = BitMask << BitShift;
LanaFlags[DwordOffset] |= BitMask;
}
BOOL
LanaFlagIsSet(
UCHAR uCharLanaNum
)
{
DWORD LanaNum = (DWORD)uCharLanaNum;
DWORD BitMask=1;
DWORD DwordOffset;
DWORD BitShift;
DwordOffset = LanaNum / NUM_DWORD_BITS;
if (DwordOffset > LANA_NUM_DWORDS) {
return(FALSE);
}
BitShift = LanaNum - (DwordOffset * NUM_DWORD_BITS);
BitMask = BitMask << BitShift;
return ((BOOL) LanaFlags[DwordOffset] & BitMask );
}