345 lines
7.7 KiB
C
Raw Normal View History

2001-01-01 00:00:00 +01:00
/*++
Copyright (c) 1991-1993 Microsoft Corporation
Module Name:
svcsnb.c
Abstract:
NetBios support for services in services.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 <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <winsvc.h> // Service control APIs
#include <scdebug.h>
#include <svcs.h> // SVCS_ENTRY_POINT, SVCS_GLOBAL_DATA
#include <scseclib.h> //
#include <lmsname.h> // Lanman Service Names
#include <ntrpcp.h> // Rpcp... function prototypes
#include <nb30.h> // NetBIOS 3.0 definitions
#include <lmerr.h> // NERR_
//
// DEFINES & MACROS
//
#define NUM_DWORD_BITS (sizeof(DWORD)*8)
#define LANA_NUM_DWORDS ((MAX_LANA/NUM_DWORD_BITS)+1)
//
// 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++;
SC_LOG1(NETBIOS,"SvcsNetBiosOpen new use count = %d\n",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--;
SC_LOG1(NETBIOS,"SvcsNetBiosClose new use count = %d\n",
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);
SC_LOG1(NETBIOS,"In SvcNetBiosReset for adapter number %d\n",LanAdapterNumber);
if (!LanaFlagIsSet(LanAdapterNumber)) {
NCB Ncb;
UCHAR NcbStatus;
RtlZeroMemory((PVOID) &Ncb, sizeof(NCB));
Ncb.ncb_command = NCBRESET;
Ncb.ncb_lsn = 0;
Ncb.ncb_callname[0] = 24; // Max Num Sessions
Ncb.ncb_callname[1] = 0;
Ncb.ncb_callname[2] = 16; // Max Num Names
Ncb.ncb_callname[3] = 0;
Ncb.ncb_lana_num = LanAdapterNumber;
NcbStatus = Netbios(&Ncb);
SC_LOG0(NETBIOS,"Calling SvcNetBiosReset\n");
status = SvcNetBiosStatusToApiStatus(NcbStatus);
if (status == NO_ERROR) {
SetLanaFlag(LanAdapterNumber);
SC_LOG0(NETBIOS,"SvcNetBiosReset Success\n");
}
else {
SC_LOG1(ERROR,"SvcNetBiosReset Error %d\n",status);
}
}
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) {
SC_LOG2(ERROR,"Lan Adapter Number (%d) is too large. Max=%d\n",
LanaNum, MAX_LANA);
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) {
SC_LOG2(ERROR,"Lan Adapter Number (%d) is too large. Max=%d\n",
LanaNum, MAX_LANA);
return(FALSE);
}
BitShift = LanaNum - (DwordOffset * NUM_DWORD_BITS);
BitMask = BitMask << BitShift;
return ((BOOL) LanaFlags[DwordOffset] & BitMask );
}