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