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);
|
|||
|
}
|