501 lines
13 KiB
C
501 lines
13 KiB
C
/*++
|
||
|
||
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);
|
||
}
|