windows-nt/Source/XPSP1/NT/ds/netapi/svcdlls/msgsvc/server/msgnbios.c

420 lines
11 KiB
C
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
msgnbios.c
Abstract:
This file contains Routines used by the messenger to make netbios
calls and to obtain the computer and user names.
The following functions are included:
MsgInit_NetBios
Msgsendncb
MsgAddUserNames
MsgAddAlreadyLoggedOnUserNames (HYDRA specific)
NT_NOTE:
We need some way to determine which NCB's have unanswered listens
pending. For these, we need to send an NCBCANCEL command via
another NetBios call. The buffer will contain a pointer to the
listening NCB. Also, listens that are in the process of being
serviced must either be hung up, or allowed to complete.
All this is done during the MsgrShutdown.
Author:
Dan Lafferty (danl) 27-Jun-1991
Environment:
User Mode -Win32
Notes:
NetBios3.0 is not a handle-based api. Therefore, there is no open or
close associated with it. In order to shut down properly, the
messenger will have to hangup or complete listens that are being
serviced. And it will have to send a cancel NCB for each listen
that is pending.
Revision History:
08-Apr-1994 danl
MsgAddUserNames: If call to NetWkstaUserEnum failed, this function
was still attempting to free the buffer that was returned.
Since no buffer is allocated in a failure case, the free mem
call in the path is being removed.
27-Jun-1991 danl
ported from LM2.0
--*/
#include "msrv.h"
#include "msgdbg.h" // MSG_LOG
#include <tstring.h> // Unicode string macros
#include <icanon.h> // I_NetNameCanonicalize
#include <netlib.h> // UNUSED macro
#include <lmwksta.h> // NetWorkstation API prototypes
#include <lmapibuf.h> // NetApiBufferFree
#include <netdebug.h> // NetpAssert, FORMAT_ equates.
#include "msgdata.h"
#include "apiutil.h" // MsgMapNetError
//
// Note: we use the internal entrypoints to the apis because this
// file is shared by the message apis, which cannot call the net
// bios apis because of different required permissions.
//
NET_API_STATUS
MsgInit_NetBios(
VOID
)
/*++
Routine Description:
This function fills the global array called net_lana_num with the
lan adapter numbers retrieved from A NetBios Enum call
NOTE: This assumes that space for the array is already set up.
The LM2.0 version of this also filled an array of NetBios Handles.
In LM2.0, the loopback driver was not included unless it was the only
network installed.
Arguments:
none
Return Value:
TRUE - No Error.
FALSE - An error occured.
--*/
{
DWORD count=0;
NCB ncb;
LANA_ENUM lanaBuffer;
unsigned char i;
unsigned char nbStatus;
//
// Find the number of networks by sending an enum request via Netbios.
//
clearncb(&ncb);
ncb.ncb_command = NCBENUM; // Enumerate LANA nums (wait)
ncb.ncb_buffer = (char FAR *)&lanaBuffer;
ncb.ncb_length = sizeof(LANA_ENUM);
nbStatus = Netbios(&ncb);
if (nbStatus != NRC_GOODRET)
{
MSG_LOG(ERROR, "Netbios LanaEnum failed rc=%d\n",nbStatus);
return MsgMapNetError(nbStatus);
}
//
// Move the Adapter Numbers (lana) into the array that will contain them.
//
for (i=0; i < lanaBuffer.length; i++)
{
MSG_LOG(TRACE,"adapter %d",i);
MSG_LOG(TRACE,"\b\b\b\b\b\b lananum= %d \n", lanaBuffer.lana[i]);
GETNETLANANUM(count) = lanaBuffer.lana[i];
count++;
//
// Internal consistancy check. Make sure the arrays are only
// SD_NUMNETS long.
//
if (count > SD_NUMNETS())
{
MSG_LOG(ERROR,
"NumNets from NetBios greater than value from Wksta count=%d\n",
count);
return NERR_WkstaInconsistentState;
}
}
//
// Internal consistancy check again. We better not have opened
// more nets than the messenger thinks there are.
//
if (count != SD_NUMNETS())
{
return NERR_WkstaInconsistentState;
}
return NERR_Success;
}
UCHAR
Msgsendncb(
PNCB NCB_ptr,
DWORD neti)
/*++
Routine Description:
This function performs a DosDevIOCtl call to send an NCB to the
net bios via a previously openned redirector and netbios handle.
Arguments:
NCB_ptr - Points to the NCB to send to the net bios.
neti - Network index. Which netbios to submit it to?
Return Value:
Error code from Net bios.
--*/
{
//
// NOTE: The new Netbios call doesn't use any handles, so the neti
// info is not used.
//
UNUSED (neti);
return (Netbios(NCB_ptr));
#ifdef remove
return( NetBiosSubmit( NetBios_Hdl[neti], 0, (NCB far *) NCB_ptr));
#endif
}
VOID
MsgAddUserNames(
VOID
)
/*++
Routine Description:
This function used to get it's information about the username and
computername from the workstation service. Now, in NT, the username
is added when the user logs on. It is not automatically added by the
messenger.
Arguments:
CompName - Pointer to buf for computer name. (must be NCBNAMSZ+1)
CompNameSize - Size in bytes of the buffer to receive the name.
UserName - Pointer to buffer for user name. (must be UNLEN+1)
UserNameSize - Size in bytes of the buffer to receive the name.
Return Value:
NERR_Success - Aways returned. (Names are returned as NUL strings).
--*/
{
TCHAR UserName[UNLEN+1];
DWORD UserNameSize = sizeof(UserName);
DWORD i;
LPWKSTA_USER_INFO_0 userInfo0;
DWORD entriesRead;
DWORD totalEntries;
NET_API_STATUS status;
*UserName = TEXT('\0');
status = NetWkstaUserEnum(
NULL,
0,
(LPBYTE *)&userInfo0,
0xffffffff, // PreferredMaximiumLength
&entriesRead,
&totalEntries,
NULL); // resume handle
if (status != NERR_Success) {
MSG_LOG(ERROR,"GetWkstaNames:NetWkstaUserEnum FAILURE %X/n",status);
return;
}
for (i=0; i<entriesRead; i++ ) {
if (entriesRead == 0) {
//
// There are no users logged on at the time of this query.
//
MSG_LOG(TRACE,
"GetWkstaNames:NetWkstaUserEnum entriesRead=%d\n",
entriesRead);
}
if(userInfo0[i].wkui0_username != NULL) {
status = I_NetNameCanonicalize(
NULL,
userInfo0[i].wkui0_username,
UserName,
UserNameSize,
NAMETYPE_USER,
0);
if (status != NERR_Success) {
MSG_LOG(ERROR,"I_NetNameCanonicalize failed %X\n",status);
}
}
if( *UserName != TEXT('\0')) { // Set up in GetWkstaNames */
MSG_LOG(TRACE, "Calling MsgAddName\n",0);
status = MsgAddName(UserName,0);
if (status != NERR_Success) {
MSG_LOG(
TRACE,
"MsgAddUserNames,MessageAddName FAILURE " FORMAT_API_STATUS
"\n",
status);
}
}
}
NetApiBufferFree(userInfo0);
}
VOID
MsgAddAlreadyLoggedOnUserNames(
VOID
)
/*++
Routine Description:
This function is used to get information about the previously logged on usernames
by calling WinStationEnumerate and WinStationQueryInformationW, instead of NetWkstaUserEnum.
(same job as MsgAddUserNames, adapted for multi-user)
Note: It could (should ?) be located elsewhere than in msgnbios. I kept it here just because
MsgAddUserName itself was already here. (NicolasBD)
Arguments:
Return Value:
NERR_Success - Always returned.
--*/
{
TCHAR UserName[NCBNAMSZ+1];
DWORD UserNameSize = sizeof(UserName);
UINT WdCount, i;
PLOGONID pWd, pWdTmp;
ULONG AmountRet;
WINSTATIONINFORMATIONW QueryBuffer;
NET_API_STATUS status;
*UserName = TEXT('\0');
// Enumerate the Sessions
if ( gpfnWinStationEnumerate( SERVERNAME_CURRENT, &pWd, &WdCount ) )
{
// Success; get all the previously logged on user names and session ids
pWdTmp = pWd;
for( i=0; i < WdCount; i++ ) {
if( ((pWdTmp->State == State_Connected) ||
(pWdTmp->State == State_Active) ||
(pWdTmp->State == State_Disconnected)))
{
if( !gpfnWinStationQueryInformation( SERVERNAME_CURRENT,
pWdTmp->LogonId,
WinStationInformation,
&QueryBuffer,
sizeof(QueryBuffer),
&AmountRet ) )
{
// Error
MSG_LOG(ERROR, "MsgAddAlreadyLoggedOnUserNames: Error in QueryInfo %d\n",GetLastError());
}
else
{
if (QueryBuffer.UserName != NULL)
{
MSG_LOG(TRACE,"MsgAddAlreadyLoggedOnUserNames: calling I_NetNameCanonicalize for %ws\n",QueryBuffer.UserName);
status = I_NetNameCanonicalize(
NULL,
QueryBuffer.UserName,
UserName,
UserNameSize,
NAMETYPE_USER,
0);
if (status != NERR_Success)
{
MSG_LOG(ERROR,"I_NetNameCanonicalize failed %X\n",status);
}
}
if( *UserName != TEXT('\0'))
{
MSG_LOG(TRACE,"MsgAddAlreadyLoggedOnUserNames: Calling MsgAddName for Session %x \n", pWdTmp->LogonId);
status = MsgAddName(UserName, pWdTmp->LogonId);
if (status != NERR_Success)
{
MSG_LOG(TRACE, "MsgAddAlreadyLoggedOnUserNames,MessageAddName FAILURE " FORMAT_API_STATUS "\n", status);
}
}
}
}
pWdTmp++;
}
// Free enumeration memory
gpfnWinStationFreeMemory(pWd);
}
else
{
MSG_LOG (ERROR, "MsgAddAlreadyLoggedOnUserNames: WinStationEnumerate failed, error = %d:\n",GetLastError());
}
return;
}