windows-nt/Source/XPSP1/NT/ds/netapi/svcdlls/wkssvc/server/msgutil.c

501 lines
13 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
msgutil.c
Abstract:
This module contains the common utility routines for needed to
implement the NetMessageBufferSend API.
Author:
Rita Wong (ritaw) 26-July-1991
Revision History:
Terence Kwan (terryk) 20-Oct-1993
Shut down the system iff we initiailize the system successfully.
--*/
#include "ws.h"
#include "wsconfig.h" // WsInfo.WsComputerName
#include "wsmsg.h"
#include "wsmain.h"
#include <stdarg.h>
//
// Global variables
//
//
// Information structure which contains the number of networks, the adapter
// numbers of the networks, an array of computer name numbers, and an array
// of broadcast name numbers.
//
WSNETWORKS WsNetworkInfo;
// Flag for initialization
BOOL fInitialize = FALSE;
NET_API_STATUS
WsInitializeMessageSend(
BOOLEAN FirstTime
)
/*++
Routine Description:
This function initializes the Workstation service to send messages using
NetBIOS by adding the computername to every network adapter (both logical
and physical network).
Arguments:
FirstTime - Flag to indicate first time initialization. This routine may be called
later to reinitialize netbios configuration.
Return Value:
NET_API_STATUS - NERR_Success or reason for failure.
--*/
{
NET_API_STATUS status;
UCHAR Index;
CHAR NetBiosName[NCBNAMSZ];
//
// Get the adapter numbers of networks
//
status = NetpNetBiosGetAdapterNumbers(
&(WsNetworkInfo.LanAdapterNumbers),
sizeof(LANA_ENUM)
);
if (status != NERR_Success) {
//
// Fatal error: Log error with NELOG_NetBios
//
IF_DEBUG(MESSAGE) {
NetpKdPrint((
"[Wksta] Error enumerating LAN adapters. "
"Ignore if no UB card.\n"
));
}
return status;
}
//
// Make the computer name a message type NetBIOS name
//
if ((status = NetpStringToNetBiosName(
NetBiosName,
WsInfo.WsComputerName,
NAMETYPE_MESSAGEDEST,
WKSTA_TO_MESSAGE_ALIAS_TYPE
)) != NERR_Success) {
return status;
}
//
// Add the computer name (message alias) to every network managed by
// the redirector, excluding the loopback network.
//
if (FirstTime) {
WsLmsvcsGlobalData->NetBiosOpen();
}
for (Index = 0; Index < WsNetworkInfo.LanAdapterNumbers.length; Index++) {
//
// Reset the adapter first
//
if (WsLmsvcsGlobalData->NetBiosReset(WsNetworkInfo.LanAdapterNumbers.lana[Index])
!= NERR_Success) {
IF_DEBUG(MESSAGE) {
NetpKdPrint((
"[Wksta] Error reseting LAN adapter number %u.\n"
" Ignore if no UB card.\n",
WsNetworkInfo.LanAdapterNumbers.lana[Index]
));
}
continue;
}
IF_DEBUG(MESSAGE) {
NetpKdPrint(("[Wksta] About to add name on adapter number %u\n",
WsNetworkInfo.LanAdapterNumbers.lana[Index]));
}
status = NetpNetBiosAddName(
NetBiosName,
WsNetworkInfo.LanAdapterNumbers.lana[Index],
&WsNetworkInfo.ComputerNameNumbers[Index]
);
if (status != NERR_Success && status != NERR_AlreadyExists) {
//
// Fatal error: Log error with NELOG_NetBios
//
IF_DEBUG(MESSAGE) {
NetpKdPrint((
"[Wksta] Error adding computername to LAN "
"Adapter number %u.\n Ignore if no UB card.\n",
WsNetworkInfo.LanAdapterNumbers.lana[Index]
));
}
return status;
}
}
// Initialize okay
fInitialize = TRUE;
return NERR_Success;
}
VOID
WsShutdownMessageSend(
VOID
)
/*++
Routine Description:
This function shuts down the Workstation service message send
functionality by asking NetBIOS to delete the computername that
was added to every network adapter.
Arguments:
None
Return Value:
None.
--*/
{
// We shut down the component if and only if we successfully initialize
// the system
if ( fInitialize )
{
NET_API_STATUS status;
UCHAR Index;
CHAR NetBiosName[NCBNAMSZ];
//
// Make the computer name a message type NetBIOS name
//
if ((status = NetpStringToNetBiosName(
NetBiosName,
WsInfo.WsComputerName,
NAMETYPE_MESSAGEDEST,
WKSTA_TO_MESSAGE_ALIAS_TYPE
)) != NERR_Success) {
return;
}
//
// Delete the computer name (message alias) from every network.
//
for (Index = 0; Index < WsNetworkInfo.LanAdapterNumbers.length; Index++) {
(void) NetpNetBiosDelName(
NetBiosName,
WsNetworkInfo.LanAdapterNumbers.lana[Index]
);
}
WsLmsvcsGlobalData->NetBiosClose();
}
}
WORD
WsMakeSmb(
OUT PUCHAR SmbBuffer,
IN UCHAR SmbFunctionCode,
IN WORD NumberOfParameters,
IN PCHAR FieldsDopeVector,
...
)
/*++
Routine Description:
This function builds a Server Message Block. It takes a variable
number of arguments, but the first 4 are required to be present.
If NumberOfParameters is some non-zero value, n, then immediately
following the 4 required arguments there will be n WORD
parameters.
Arguments:
SmbBuffer - Returns the Server Message Block in the supplied buffer.
SmbFunctionCode - Supplies the function code for the command.
NumberOfParameters - Supplies the number of WORD parameters passed
to this routine immediately following the first 4 required parameters.
FieldsDopeVector - Supplies an ASCIIZ string where each character of the
string describes the remaining parameters:
's' - the next argument is a pointer to a null-terminated string
which is to be copied into the SMB prefixed by a byte
containing '\004'.
'b' - the next argument is a WORD specifying a length,
and it is followed by a pointer to a buffer whose contents
are to be placed in the SMB prefixed by a byte containing
'\001' and a WORD containing the length.
't' - the next argument is a WORD specifying a length,
and it is followed by a pointer to a text buffer whose
contents are to be placed in the SMB prefixed by a byte
containing '\001' and a WORD containg the length.
This is the same as 'b' except that <CRLF>,<LFCR>,<CR>,<LF>
are all converted to a single '\024' character.
Return Value:
Returns the length in bytes of the SMB created in SmbBuffer.
Assumptions:
The supplied SmbBuffer is large enough for the SMB created.
--*/
{
va_list ArgList; // Argument List
PSMB_HEADER Smb; // SMB header pointer
PUCHAR SmbBufferPointer;
PUCHAR LengthPointer; // length pointer
PCHAR TextPointer; // Text pointer
WORD TextBufferSize; // Size of SMB data to send
WORD i; // Text loop index
WORD Length; // Length after text conversion or
// length of the buffer portion
va_start(ArgList, FieldsDopeVector); // Init ArgList
RtlZeroMemory((PVOID) SmbBuffer, WS_SMB_BUFFER_SIZE);
Smb = (PSMB_HEADER) SmbBuffer;
Smb->Protocol[0] = 0xff; // Message type
Smb->Protocol[1] = 'S'; // Server
Smb->Protocol[2] = 'M'; // Message
Smb->Protocol[3] = 'B'; // Block
Smb->Command = SmbFunctionCode; // Set function code
//
// Skip over SMB header
//
SmbBufferPointer = &SmbBuffer[sizeof(SMB_HEADER)];
//
// Set parameter count
//
*SmbBufferPointer++ = (UCHAR) NumberOfParameters;
while (NumberOfParameters--) {
short Parameters = va_arg(ArgList, short);
//
// Put parameters in the SMB
//
//
// Assign message group id
//
*(SmbBufferPointer)++ = ((PUCHAR) &Parameters)[0];
*(SmbBufferPointer)++ = ((PUCHAR) &Parameters)[1];
}
//
// Save the pointer
//
Smb = (PSMB_HEADER) SmbBufferPointer;
//
// Skip data length field. After the rest of buffer is filled
// in, we will come back to set the length of the data.
//
SmbBufferPointer += sizeof(WORD);
while (*FieldsDopeVector != '\0') {
switch (*FieldsDopeVector++) {
case 's':
//
// Null-terminated string
//
//
// Set buffer type code
//
*SmbBufferPointer++ = '\004';
//
// Copy string into SMB buffer
//
strcpy(SmbBufferPointer, va_arg(ArgList, LPSTR));
//
// Increment pointer past string and null terminator
//
SmbBufferPointer += strlen(SmbBufferPointer) + 1;
break;
case 'b':
//
// Length-prefixed buffer
//
//
// Set buffer type code
//
*SmbBufferPointer++ = '\001';
//
// Get buffer size
//
TextBufferSize = va_arg(ArgList, WORD);
//
// Set the buffer length
//
*(SmbBufferPointer)++ = ((PUCHAR) &TextBufferSize)[0];
*(SmbBufferPointer)++ = ((PUCHAR) &TextBufferSize)[1];
//
// Move data into SMB buffer
//
memcpy(SmbBufferPointer, va_arg(ArgList, PUCHAR), TextBufferSize);
//
// Increment buffer pointer
//
SmbBufferPointer += TextBufferSize;
break;
case 't':
//
// Length-prefixed text buffer
//
*SmbBufferPointer++ = '\001';
//
// Get non converted text length
//
TextBufferSize = va_arg(ArgList, WORD);
IF_DEBUG(MESSAGE) {
NetpKdPrint(("[Wksta] WsMakeSmb TexBufferSize=%u\n",
TextBufferSize));
}
TextPointer = va_arg(ArgList, PCHAR);
//
// Where to put modified text length
//
LengthPointer = SmbBufferPointer;
SmbBufferPointer += sizeof(WORD);
//
// Now copy the text into the buffer converting all occurences
// of <CRLF>, <LFCR>, <CR>, <LF> to '\024'
//
for (i = 0, Length = 0; i < TextBufferSize; i++) {
if (*TextPointer == '\n') {
//
// Convert to IBM end of line
//
*SmbBufferPointer++ = '\024';
TextPointer++;
Length++;
//
// Ignore LF following CR
//
if (*TextPointer == '\r') {
TextPointer++;
i++;
}
}
else if (*TextPointer == '\r') {
//
// Convert to IBM end of line
//
*SmbBufferPointer++ = '\024';
TextPointer++;
Length++;
//
// Ignore CR following LF
//
if (*(TextPointer) == '\n') {
TextPointer++;
i++;
}
}
else {
*SmbBufferPointer++ = *TextPointer++;
Length++;
}
}
//
// Set the buffer length
//
*(LengthPointer)++ = ((PUCHAR) &Length)[0];
*(LengthPointer)++ = ((PUCHAR) &Length)[1];
break;
}
}
va_end(ArgList);
//
// Set length of buffer portion
//
Length = (WORD) ((DWORD) (SmbBufferPointer - (PUCHAR) Smb) - sizeof(WORD));
*((PUCHAR) Smb)++ = ((PUCHAR) &Length)[0];
*((PUCHAR) Smb)++ = ((PUCHAR) &Length)[1];
//
// Return length of SMB
//
return (WORD) (SmbBufferPointer - SmbBuffer);
}