814 lines
20 KiB
C
814 lines
20 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1991 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
wssend.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This module contains the worker routines for sending
|
|||
|
domain wide and directed messages, which are used to implement
|
|||
|
NetMessageBufferSend API.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Rita Wong (ritaw) 29-July-1991
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
|
|||
|
#include "wsutil.h"
|
|||
|
#include "wsmsg.h"
|
|||
|
|
|||
|
//-------------------------------------------------------------------//
|
|||
|
// //
|
|||
|
// Local function prototypes //
|
|||
|
// //
|
|||
|
//-------------------------------------------------------------------//
|
|||
|
|
|||
|
STATIC
|
|||
|
BOOL
|
|||
|
WsVerifySmb(
|
|||
|
IN PUCHAR SmbBuffer,
|
|||
|
IN WORD SmbBufferSize,
|
|||
|
IN UCHAR SmbFunctionCode,
|
|||
|
OUT PUCHAR SmbReturnClass,
|
|||
|
OUT PUSHORT SmbReturnCode
|
|||
|
);
|
|||
|
|
|||
|
STATIC
|
|||
|
NET_API_STATUS
|
|||
|
WsMapSmbStatus(
|
|||
|
UCHAR SmbReturnClass,
|
|||
|
USHORT SmbReturnCode
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
NET_API_STATUS
|
|||
|
WsSendToGroup(
|
|||
|
IN LPTSTR DomainName,
|
|||
|
IN LPTSTR Sender,
|
|||
|
IN LPBYTE Message,
|
|||
|
IN WORD MessageSize
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function writes a datagram to the \\DomainName\MAILSLOT\MESSNGR
|
|||
|
mailslot which is read by every Messenger service of workstations
|
|||
|
that have the domain name as the primary domain. Reception is not
|
|||
|
guaranteed.
|
|||
|
|
|||
|
The DomainName may be a computername. This is acceptable because the
|
|||
|
Datagram Receiver listens on the computername (besides the primary domain)
|
|||
|
for datagrams. When a computername is specified, the message is sent
|
|||
|
to that one computer alone.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
DomainName - Supplies the name of the target domain. This actually
|
|||
|
can be a computername, in which case, the datagram only reaches
|
|||
|
one recipient.
|
|||
|
|
|||
|
Sender - Supplies the name of the sender.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NET_API_STATUS - NERR_Success or reason for failure.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
NET_API_STATUS status = NERR_Success;
|
|||
|
HANDLE MessengerMailslot;
|
|||
|
DWORD NumberOfBytesWritten;
|
|||
|
|
|||
|
BYTE MailslotBuffer[MAX_GROUP_MESSAGE_SIZE + MAX_PATH + MAX_PATH + 4];
|
|||
|
LPSTR AnsiSender;
|
|||
|
LPSTR AnsiReceiver;
|
|||
|
|
|||
|
LPBYTE CurrentPos;
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Canonicalize the domain name
|
|||
|
//
|
|||
|
status = I_NetNameCanonicalize(
|
|||
|
NULL,
|
|||
|
DomainName,
|
|||
|
DomainName,
|
|||
|
(NCBNAMSZ + 2) * sizeof(TCHAR),
|
|||
|
NAMETYPE_DOMAIN,
|
|||
|
0
|
|||
|
);
|
|||
|
|
|||
|
if (status != NERR_Success) {
|
|||
|
NetpKdPrint(("[Wksta] Error canonicalizing domain name %ws %lu\n",
|
|||
|
DomainName, status));
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Open \\DomainName\MAILSLOT\MESSNGR mailslot to
|
|||
|
// send message to.
|
|||
|
//
|
|||
|
if ((status = WsOpenDestinationMailslot(
|
|||
|
DomainName,
|
|||
|
MESSENGER_MAILSLOT_W,
|
|||
|
&MessengerMailslot
|
|||
|
)) != NERR_Success) {
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Package the message to be sent. It consists of:
|
|||
|
// Sender (must be ANSI)
|
|||
|
// DomainName (must be ANSI)
|
|||
|
// Message
|
|||
|
//
|
|||
|
|
|||
|
//
|
|||
|
// Convert the names to ANSI
|
|||
|
//
|
|||
|
AnsiSender = NetpAllocStrFromWStr(Sender);
|
|||
|
if (AnsiSender == NULL) {
|
|||
|
(void) CloseHandle(MessengerMailslot);
|
|||
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|||
|
}
|
|||
|
|
|||
|
AnsiReceiver = NetpAllocStrFromWStr(DomainName);
|
|||
|
if (AnsiReceiver == NULL) {
|
|||
|
NetApiBufferFree(AnsiSender);
|
|||
|
(void) CloseHandle(MessengerMailslot);
|
|||
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|||
|
}
|
|||
|
|
|||
|
RtlZeroMemory(MailslotBuffer, sizeof( MailslotBuffer ) );
|
|||
|
|
|||
|
//
|
|||
|
// Copy Sender into mailslot buffer
|
|||
|
//
|
|||
|
strcpy(MailslotBuffer, AnsiSender);
|
|||
|
CurrentPos = MailslotBuffer + strlen(AnsiSender) + 1;
|
|||
|
|
|||
|
//
|
|||
|
// Copy DomainName into mailslot buffer
|
|||
|
//
|
|||
|
strcpy(CurrentPos, AnsiReceiver);
|
|||
|
CurrentPos += (strlen(AnsiReceiver) + 1);
|
|||
|
|
|||
|
//
|
|||
|
// Copy Message into mailslot buffer
|
|||
|
//
|
|||
|
strncpy(CurrentPos, Message, MessageSize);
|
|||
|
CurrentPos += MessageSize;
|
|||
|
*CurrentPos = '\0';
|
|||
|
|
|||
|
//
|
|||
|
// Send the datagram to the domain
|
|||
|
//
|
|||
|
if (WriteFile(
|
|||
|
MessengerMailslot,
|
|||
|
MailslotBuffer,
|
|||
|
(DWORD) (CurrentPos - MailslotBuffer + 1),
|
|||
|
&NumberOfBytesWritten,
|
|||
|
NULL
|
|||
|
) == FALSE) {
|
|||
|
|
|||
|
status = GetLastError();
|
|||
|
NetpKdPrint(("[Wksta] Error sending datagram to %ws %lu\n",
|
|||
|
AnsiReceiver, status));
|
|||
|
|
|||
|
if (status == ERROR_PATH_NOT_FOUND ||
|
|||
|
status == ERROR_BAD_NET_NAME) {
|
|||
|
status = NERR_NameNotFound;
|
|||
|
}
|
|||
|
}
|
|||
|
else {
|
|||
|
NetpAssert(NumberOfBytesWritten ==
|
|||
|
(DWORD) (CurrentPos - MailslotBuffer + 1));
|
|||
|
}
|
|||
|
|
|||
|
NetApiBufferFree(AnsiSender);
|
|||
|
NetApiBufferFree(AnsiReceiver);
|
|||
|
|
|||
|
(void) CloseHandle(MessengerMailslot);
|
|||
|
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NET_API_STATUS
|
|||
|
WsSendMultiBlockBegin(
|
|||
|
IN UCHAR LanAdapterNumber,
|
|||
|
IN UCHAR SessionNumber,
|
|||
|
IN LPTSTR ToName,
|
|||
|
IN LPTSTR FromName,
|
|||
|
OUT short *MessageId
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function sends the header of a multi-block directed message on a
|
|||
|
session we had established earlier. It waits for an acknowlegement from
|
|||
|
the recipient. If the recipient got the message successfully, it
|
|||
|
sends back a message group id which is returned by this function for
|
|||
|
subsequent use in sending the body and trailer of a multi-block message.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
LanAdapterNumber - Supplies the number of the LAN adapter.
|
|||
|
|
|||
|
SessionNumber - Supplies the session number of a session established with
|
|||
|
NetBIOS CALL and LISTEN commands.
|
|||
|
|
|||
|
ToName - Supplies the name of the recipient.
|
|||
|
|
|||
|
FromName - Supplies the name of the sender.
|
|||
|
|
|||
|
MessageId - Returns the message group id.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NET_API_STATUS - NERR_Success or reason for failure.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
NET_API_STATUS status;
|
|||
|
|
|||
|
UCHAR SmbBuffer[WS_SMB_BUFFER_SIZE];
|
|||
|
WORD SmbSize;
|
|||
|
|
|||
|
char SendName[NCBNAMSZ + 1];
|
|||
|
|
|||
|
UCHAR SmbReturnClass;
|
|||
|
USHORT SmbReturnCode;
|
|||
|
|
|||
|
LPSTR AnsiToName;
|
|||
|
LPSTR AnsiFromName;
|
|||
|
|
|||
|
AnsiToName = NetpAllocStrFromWStr(ToName);
|
|||
|
if (AnsiToName == NULL) {
|
|||
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|||
|
}
|
|||
|
|
|||
|
AnsiFromName = NetpAllocStrFromWStr(FromName);
|
|||
|
if (AnsiFromName == NULL) {
|
|||
|
NetApiBufferFree(AnsiToName);
|
|||
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|||
|
}
|
|||
|
|
|||
|
strncpy(SendName, AnsiToName, sizeof(SendName) );
|
|||
|
|
|||
|
SendName[NCBNAMSZ - 1] = '\0'; // Null terminate at max size
|
|||
|
|
|||
|
//
|
|||
|
// Make and send the SMB
|
|||
|
//
|
|||
|
SmbSize = WsMakeSmb(
|
|||
|
SmbBuffer,
|
|||
|
SMB_COM_SEND_START_MB_MESSAGE,
|
|||
|
0,
|
|||
|
"ss",
|
|||
|
AnsiFromName,
|
|||
|
SendName
|
|||
|
);
|
|||
|
|
|||
|
NetApiBufferFree(AnsiToName);
|
|||
|
NetApiBufferFree(AnsiFromName);
|
|||
|
|
|||
|
IF_DEBUG(MESSAGE) {
|
|||
|
NetpKdPrint(("[Wksta] Send start multi-block message. Size=%u\n",
|
|||
|
SmbSize));
|
|||
|
#if DBG
|
|||
|
NetpHexDump(SmbBuffer, SmbSize);
|
|||
|
#endif
|
|||
|
}
|
|||
|
|
|||
|
if ((status = NetpNetBiosSend(
|
|||
|
LanAdapterNumber,
|
|||
|
SessionNumber,
|
|||
|
SmbBuffer,
|
|||
|
SmbSize
|
|||
|
)) != NERR_Success) {
|
|||
|
NetpKdPrint(("[Wksta] Failed to send start of multi-block message %lu\n",
|
|||
|
status));
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Get response
|
|||
|
//
|
|||
|
if ((status = NetpNetBiosReceive(
|
|||
|
LanAdapterNumber,
|
|||
|
SessionNumber,
|
|||
|
SmbBuffer,
|
|||
|
WS_SMB_BUFFER_SIZE,
|
|||
|
(HANDLE) NULL,
|
|||
|
&SmbSize
|
|||
|
)) != NERR_Success) {
|
|||
|
NetpKdPrint(("[Wksta] Failed to receive verification to multi-"
|
|||
|
"block message start %lu\n", status));
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
if (! WsVerifySmb(
|
|||
|
SmbBuffer,
|
|||
|
SmbSize,
|
|||
|
SMB_COM_SEND_START_MB_MESSAGE,
|
|||
|
&SmbReturnClass,
|
|||
|
&SmbReturnCode
|
|||
|
)) {
|
|||
|
|
|||
|
//
|
|||
|
// Unexpected behaviour
|
|||
|
//
|
|||
|
return NERR_NetworkError;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Set the message group id
|
|||
|
//
|
|||
|
|
|||
|
*MessageId = *((UNALIGNED short *) &SmbBuffer[sizeof(SMB_HEADER) + 1]);
|
|||
|
|
|||
|
IF_DEBUG(MESSAGE) {
|
|||
|
NetpKdPrint(("[Wksta] Message Id=x%x\n", *MessageId));
|
|||
|
}
|
|||
|
|
|||
|
return WsMapSmbStatus(SmbReturnClass, SmbReturnCode);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NET_API_STATUS
|
|||
|
WsSendMultiBlockEnd(
|
|||
|
IN UCHAR LanAdapterNumber,
|
|||
|
IN UCHAR SessionNumber,
|
|||
|
IN short MessageId
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function sends the end marker of a multi-block directed message on
|
|||
|
a session we had establised earlier. It waits for an acknowlegement from
|
|||
|
the recipient.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
LanAdapterNumber - Supplies the number of the LAN adapter.
|
|||
|
|
|||
|
SessionNumber - Supplies the session number of a session established with
|
|||
|
NetBIOS CALL and LISTEN commands.
|
|||
|
|
|||
|
MessageId - Supplies the message group id gotten from
|
|||
|
WsSendMultiBlockBegin.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NET_API_STATUS - NERR_Success or reason for failure.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
|
|||
|
NET_API_STATUS status;
|
|||
|
|
|||
|
UCHAR SmbBuffer[WS_SMB_BUFFER_SIZE];
|
|||
|
WORD SmbSize; // Size of SMB data
|
|||
|
|
|||
|
UCHAR SmbReturnClass;
|
|||
|
USHORT SmbReturnCode;
|
|||
|
|
|||
|
|
|||
|
SmbSize = WsMakeSmb(
|
|||
|
SmbBuffer,
|
|||
|
SMB_COM_SEND_END_MB_MESSAGE,
|
|||
|
1,
|
|||
|
"",
|
|||
|
MessageId
|
|||
|
);
|
|||
|
|
|||
|
IF_DEBUG(MESSAGE) {
|
|||
|
NetpKdPrint(("[Wksta] Send end multi-block message. Size=%u\n",
|
|||
|
SmbSize));
|
|||
|
#if DBG
|
|||
|
NetpHexDump(SmbBuffer, SmbSize);
|
|||
|
#endif
|
|||
|
}
|
|||
|
|
|||
|
if ((status = NetpNetBiosSend(
|
|||
|
LanAdapterNumber,
|
|||
|
SessionNumber,
|
|||
|
SmbBuffer,
|
|||
|
SmbSize
|
|||
|
)) != NERR_Success) {
|
|||
|
NetpKdPrint(("[Wksta] Failed to send end of multi-block message %lu\n",
|
|||
|
status));
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Get response
|
|||
|
//
|
|||
|
if ((status = NetpNetBiosReceive(
|
|||
|
LanAdapterNumber,
|
|||
|
SessionNumber,
|
|||
|
SmbBuffer,
|
|||
|
WS_SMB_BUFFER_SIZE,
|
|||
|
(HANDLE) NULL,
|
|||
|
&SmbSize
|
|||
|
)) != NERR_Success) {
|
|||
|
NetpKdPrint(("[Wksta] Failed to receive verification to multi-"
|
|||
|
"block message end %lu\n", status));
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
if (! WsVerifySmb(
|
|||
|
SmbBuffer,
|
|||
|
SmbSize,
|
|||
|
SMB_COM_SEND_END_MB_MESSAGE,
|
|||
|
&SmbReturnClass,
|
|||
|
&SmbReturnCode
|
|||
|
)) {
|
|||
|
return NERR_NetworkError; // Unexpected behaviour
|
|||
|
}
|
|||
|
|
|||
|
return WsMapSmbStatus(SmbReturnClass,SmbReturnCode);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
NET_API_STATUS
|
|||
|
WsSendMultiBlockText(
|
|||
|
IN UCHAR LanAdapterNumber,
|
|||
|
IN UCHAR SessionNumber,
|
|||
|
IN PCHAR TextBuffer,
|
|||
|
IN WORD TextBufferSize,
|
|||
|
IN short MessageId
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function sends the body of a multi-block directed message on a
|
|||
|
session we had established earlier. It waits for an acknowlegement from
|
|||
|
the recipient.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
LanAdapterNumber - Supplies the number of the LAN adapter.
|
|||
|
|
|||
|
SessionNumber - Supplies the session number of a session established with
|
|||
|
NetBIOS CALL and LISTEN commands.
|
|||
|
|
|||
|
TextBuffer - Supplies the buffer of the message to be sent.
|
|||
|
|
|||
|
TextBufferSize - Supplies the size of the message buffer.
|
|||
|
|
|||
|
MessageId - Supplies the message group id gotten from
|
|||
|
WsSendMultiBlockBegin.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NET_API_STATUS - NERR_Success or reason for failure.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
NET_API_STATUS status;
|
|||
|
|
|||
|
UCHAR SmbBuffer[WS_SMB_BUFFER_SIZE];
|
|||
|
WORD SmbSize; // Buffer length
|
|||
|
|
|||
|
UCHAR SmbReturnClass;
|
|||
|
USHORT SmbReturnCode;
|
|||
|
|
|||
|
|
|||
|
IF_DEBUG(MESSAGE) {
|
|||
|
NetpKdPrint(("[Wksta] Send body multi-block message. Size=%u\n",
|
|||
|
TextBufferSize));
|
|||
|
}
|
|||
|
|
|||
|
SmbSize = WsMakeSmb(
|
|||
|
SmbBuffer,
|
|||
|
SMB_COM_SEND_TEXT_MB_MESSAGE,
|
|||
|
1,
|
|||
|
"t",
|
|||
|
MessageId,
|
|||
|
TextBufferSize,
|
|||
|
TextBuffer
|
|||
|
);
|
|||
|
|
|||
|
IF_DEBUG(MESSAGE) {
|
|||
|
NetpKdPrint(("[Wksta] SMB for body of multi-block message. Size=%u\n",
|
|||
|
SmbSize));
|
|||
|
}
|
|||
|
|
|||
|
if ((status = NetpNetBiosSend(
|
|||
|
LanAdapterNumber,
|
|||
|
SessionNumber,
|
|||
|
SmbBuffer,
|
|||
|
SmbSize
|
|||
|
)) != NERR_Success) {
|
|||
|
NetpKdPrint(("[Wksta] Failed to send body of multi-block message %lu\n",
|
|||
|
status));
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Get response
|
|||
|
//
|
|||
|
if ((status = NetpNetBiosReceive(
|
|||
|
LanAdapterNumber,
|
|||
|
SessionNumber,
|
|||
|
SmbBuffer,
|
|||
|
WS_SMB_BUFFER_SIZE,
|
|||
|
(HANDLE) NULL,
|
|||
|
&SmbSize
|
|||
|
)) != NERR_Success) {
|
|||
|
NetpKdPrint(("[Wksta] Failed to receive verification to multi-"
|
|||
|
"block message body %lu\n", status));
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
if (! WsVerifySmb(
|
|||
|
SmbBuffer,
|
|||
|
SmbSize,
|
|||
|
SMB_COM_SEND_TEXT_MB_MESSAGE,
|
|||
|
&SmbReturnClass,
|
|||
|
&SmbReturnCode
|
|||
|
)) {
|
|||
|
return NERR_NetworkError; // Unexpected behaviour
|
|||
|
}
|
|||
|
|
|||
|
return WsMapSmbStatus(SmbReturnClass, SmbReturnCode);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NET_API_STATUS
|
|||
|
WsSendSingleBlockMessage(
|
|||
|
IN UCHAR LanAdapterNumber,
|
|||
|
IN UCHAR SessionNumber,
|
|||
|
IN LPTSTR ToName,
|
|||
|
IN LPTSTR FromName,
|
|||
|
IN PCHAR Message,
|
|||
|
IN WORD MessageSize
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function sends a directed message in one SMB on a session we had
|
|||
|
established earlier. It waits for an acknowlegement from the recipient.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
LanAdapterNumber - Supplies the number of the LAN adapter.
|
|||
|
|
|||
|
SessionNumber - Supplies the session number of a session established with
|
|||
|
NetBIOS CALL and LISTEN commands.
|
|||
|
|
|||
|
ToName - Supplies the name of the recipient.
|
|||
|
|
|||
|
FromName - Supplies the name of the sender.
|
|||
|
|
|||
|
Message - Supplies the buffer of the message to be sent.
|
|||
|
|
|||
|
MessageSize - Supplies the size of the message.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NET_API_STATUS - NERR_Success or reason for failure.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
NET_API_STATUS status;
|
|||
|
|
|||
|
UCHAR SmbBuffer[WS_SMB_BUFFER_SIZE];
|
|||
|
WORD SmbSize; // Buffer length
|
|||
|
|
|||
|
UCHAR SmbReturnClass;
|
|||
|
USHORT SmbReturnCode;
|
|||
|
|
|||
|
LPSTR AnsiToName;
|
|||
|
LPSTR AnsiFromName;
|
|||
|
|
|||
|
|
|||
|
AnsiToName = NetpAllocStrFromWStr(ToName);
|
|||
|
if (AnsiToName == NULL) {
|
|||
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|||
|
}
|
|||
|
|
|||
|
AnsiFromName = NetpAllocStrFromWStr(FromName);
|
|||
|
if (AnsiFromName == NULL) {
|
|||
|
NetApiBufferFree(AnsiToName);
|
|||
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|||
|
}
|
|||
|
|
|||
|
SmbSize = WsMakeSmb(
|
|||
|
SmbBuffer,
|
|||
|
SMB_COM_SEND_MESSAGE,
|
|||
|
0,
|
|||
|
"sst",
|
|||
|
AnsiFromName,
|
|||
|
AnsiToName,
|
|||
|
MessageSize,
|
|||
|
Message
|
|||
|
);
|
|||
|
|
|||
|
NetApiBufferFree(AnsiToName);
|
|||
|
NetApiBufferFree(AnsiFromName);
|
|||
|
|
|||
|
IF_DEBUG(MESSAGE) {
|
|||
|
NetpKdPrint(("[Wksta] Send single block message. Size=%u\n", SmbSize));
|
|||
|
#if DBG
|
|||
|
NetpHexDump(SmbBuffer, SmbSize);
|
|||
|
#endif
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Send SMB
|
|||
|
//
|
|||
|
if ((status = NetpNetBiosSend(
|
|||
|
LanAdapterNumber,
|
|||
|
SessionNumber,
|
|||
|
SmbBuffer,
|
|||
|
SmbSize
|
|||
|
)) != NERR_Success) {
|
|||
|
NetpKdPrint(("[Wksta] Failed to send single block message %lu\n",
|
|||
|
status));
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Get response
|
|||
|
//
|
|||
|
if ((status = NetpNetBiosReceive(
|
|||
|
LanAdapterNumber,
|
|||
|
SessionNumber,
|
|||
|
SmbBuffer,
|
|||
|
WS_SMB_BUFFER_SIZE,
|
|||
|
(HANDLE) NULL,
|
|||
|
&SmbSize
|
|||
|
)) != NERR_Success) {
|
|||
|
NetpKdPrint(("[Wksta] Failed to receive verification to single"
|
|||
|
" block message %lu\n", status));
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
if (! WsVerifySmb(
|
|||
|
SmbBuffer,
|
|||
|
SmbSize,
|
|||
|
SMB_COM_SEND_MESSAGE,
|
|||
|
&SmbReturnClass,
|
|||
|
&SmbReturnCode
|
|||
|
)) {
|
|||
|
return NERR_NetworkError; // Unexpected behaviour
|
|||
|
}
|
|||
|
|
|||
|
return WsMapSmbStatus(SmbReturnClass, SmbReturnCode);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
STATIC
|
|||
|
BOOL
|
|||
|
WsVerifySmb(
|
|||
|
IN PUCHAR SmbBuffer,
|
|||
|
IN WORD SmbBufferSize,
|
|||
|
IN UCHAR SmbFunctionCode,
|
|||
|
OUT PUCHAR SmbReturnClass,
|
|||
|
OUT PUSHORT SmbReturnCode
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function checks the format of a received SMB; it returns TRUE if
|
|||
|
if the SMB format is valid, and FALSE otherwise.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
SmbBuffer - Supplies the SMB buffer
|
|||
|
|
|||
|
SmbBufferSize - Supplies the size of SmbBuffer in bytes
|
|||
|
|
|||
|
SmbFunctionCode - Supplies the function code for which the SMB is received
|
|||
|
to determine the proper SMB format.
|
|||
|
|
|||
|
SmbReturnClass - Returns the class of the SMB only if the SMB format is
|
|||
|
valid.
|
|||
|
|
|||
|
SmbReturnCode - Returns the error code of the SMB.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE if SMB is valid; FALSE otherwise.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
PSMB_HEADER Smb = (PSMB_HEADER) SmbBuffer; // Pointer to SMB header
|
|||
|
int SmbCheckCode;
|
|||
|
int ParameterCount;
|
|||
|
|
|||
|
//
|
|||
|
// Assume error
|
|||
|
//
|
|||
|
*SmbReturnClass = (UCHAR) 0xff;
|
|||
|
|
|||
|
*SmbReturnCode = Smb->Error;
|
|||
|
|
|||
|
switch (SmbFunctionCode) {
|
|||
|
case SMB_COM_SEND_MESSAGE: // Single-block message
|
|||
|
case SMB_COM_SEND_TEXT_MB_MESSAGE: // Text of multi-block message
|
|||
|
case SMB_COM_SEND_END_MB_MESSAGE: // End of multi-block message
|
|||
|
ParameterCount = 0;
|
|||
|
break;
|
|||
|
|
|||
|
case SMB_COM_SEND_START_MB_MESSAGE: // Beginning of multi-block message
|
|||
|
ParameterCount = 1;
|
|||
|
break;
|
|||
|
|
|||
|
default: // Unknown SMB
|
|||
|
NetpKdPrint(("[Wksta] WsVerifySmb unknown SMB\n"));
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
if (! (SmbCheckCode = NetpSmbCheck(
|
|||
|
SmbBuffer,
|
|||
|
SmbBufferSize,
|
|||
|
SmbFunctionCode,
|
|||
|
ParameterCount,
|
|||
|
""
|
|||
|
))) {
|
|||
|
|
|||
|
//
|
|||
|
// Set the return class if valid SMB
|
|||
|
//
|
|||
|
*SmbReturnClass = Smb->ErrorClass;
|
|||
|
return TRUE;
|
|||
|
|
|||
|
}
|
|||
|
else {
|
|||
|
//
|
|||
|
// Invalid SMB
|
|||
|
//
|
|||
|
NetpKdPrint(("[Wksta] WsVerifySmb invalid SMB %d\n", SmbCheckCode));
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
STATIC
|
|||
|
NET_API_STATUS
|
|||
|
WsMapSmbStatus(
|
|||
|
UCHAR SmbReturnClass,
|
|||
|
USHORT SmbReturnCode
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function converts an SMB status to API status.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
SmbReturnClass - Supplies the SMB class
|
|||
|
|
|||
|
SmbReturnCode - Supplies the SMB return code.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NET_API_STATUS - NERR_Success or reason for failure.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
switch (SmbReturnClass) {
|
|||
|
|
|||
|
case SMB_ERR_SUCCESS:
|
|||
|
return NERR_Success;
|
|||
|
|
|||
|
case SMB_ERR_CLASS_SERVER:
|
|||
|
//
|
|||
|
// SMB error
|
|||
|
//
|
|||
|
NetpKdPrint(("[Wksta] SMB error SmbReturnCode=%u\n", SmbReturnCode));
|
|||
|
|
|||
|
if (SmbReturnCode == SMB_ERR_SERVER_PAUSED) {
|
|||
|
return NERR_PausedRemote; // Server paused
|
|||
|
}
|
|||
|
else {
|
|||
|
return NERR_BadReceive; // Send not received
|
|||
|
}
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
return NERR_BadReceive;
|
|||
|
}
|
|||
|
}
|