|
|
/*++
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); }
|