914 lines
21 KiB
C
914 lines
21 KiB
C
/*++
|
||
|
||
Copyright (c) 1991-92 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
msgrutil.c
|
||
|
||
Abstract:
|
||
|
||
This file contains functions that are used by the messenger service
|
||
and its API as well as the NetMessageSend API.
|
||
|
||
This module contains the following helper routines:
|
||
|
||
NetpNetBiosReset
|
||
NetpNetBiosAddName
|
||
NetpNetBiosDelName
|
||
NetpNetBiosGetAdapterNumbers
|
||
NetpNetBiosCall
|
||
NetpNetBiosHangup
|
||
NetpNetBiosReceive
|
||
NetpNetBiosSend
|
||
NetpStringToNetBiosName
|
||
NetpNetBiosStatusToApiStatus
|
||
NetpSmbCheck
|
||
|
||
These function prototypes can be found in net\inc\msgrutil.h.
|
||
|
||
Authors:
|
||
|
||
Rita Wong (ritaw) 26-July-1991
|
||
Dan Lafferty (danl) 26-July-1991
|
||
|
||
Revision History:
|
||
|
||
05-May-1992 JohnRo
|
||
Quiet normal debug messages.
|
||
Changed to use FORMAT_ equates for most things.
|
||
Made changes suggested by PC-LINT.
|
||
|
||
--*/
|
||
|
||
#include <nt.h> // NT definitions
|
||
#include <ntrtl.h> // NT runtime library definitions
|
||
#include <nturtl.h>
|
||
|
||
#include <windows.h> // Win32 constant definitions & error codes
|
||
|
||
#include <lmcons.h> // LAN Manager common definitions
|
||
#include <lmerr.h> // LAN Manager network error definitions
|
||
|
||
#include <debuglib.h> // IF_DEBUG
|
||
#include <netdebug.h> // NetpKdPrint(()), FORMAT_ equates.
|
||
|
||
#include <smbtypes.h> // needed for smb.h
|
||
#include <smb.h> // Server Message Block definitions
|
||
#include <nb30.h> // NetBIOS 3.0 definitions
|
||
|
||
#include <string.h> // strlen
|
||
#include <msgrutil.h> // Function prototypes from this module
|
||
#include <icanon.h> // I_NetNameCanonicalize()
|
||
#include <tstring.h> // NetpAllocStrFromWStr(), STRLEN(), etc.
|
||
#include <lmapibuf.h> // NetApiBufferFree().
|
||
|
||
static
|
||
NET_API_STATUS
|
||
NetpIssueCallWithRetries(
|
||
IN PNCB CallNcb,
|
||
IN UCHAR LanAdapterNumber
|
||
);
|
||
|
||
|
||
NET_API_STATUS
|
||
NetpNetBiosReset(
|
||
IN UCHAR LanAdapterNumber
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function resets LAN adapter.
|
||
|
||
Arguments:
|
||
|
||
LanAdapterNumber - Supplies the number of the LAN adapter.
|
||
|
||
Return Value:
|
||
|
||
NET_API_STATUS - NERR_Success or reason for failure.
|
||
|
||
--*/
|
||
{
|
||
NCB Ncb;
|
||
UCHAR NcbStatus;
|
||
|
||
|
||
RtlZeroMemory((PVOID) &Ncb, sizeof(NCB));
|
||
|
||
Ncb.ncb_command = NCBRESET;
|
||
Ncb.ncb_lsn = 0;
|
||
Ncb.ncb_callname[0] = 24; // Max Num Sessions
|
||
Ncb.ncb_callname[1] = 0;
|
||
Ncb.ncb_callname[2] = 16; // Max Num Names
|
||
Ncb.ncb_callname[3] = 0;
|
||
Ncb.ncb_lana_num = LanAdapterNumber;
|
||
|
||
NcbStatus = Netbios(&Ncb);
|
||
|
||
return NetpNetBiosStatusToApiStatus(NcbStatus);
|
||
}
|
||
|
||
|
||
|
||
NET_API_STATUS
|
||
NetpNetBiosAddName(
|
||
IN PCHAR NetBiosName,
|
||
IN UCHAR LanAdapterNumber,
|
||
OUT PUCHAR NetBiosNameNumber OPTIONAL
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function adds a NetBIOS name to the specified LAN adapter.
|
||
|
||
Arguments:
|
||
|
||
NetBiosName - Supplies a NetBIOS name to be added.
|
||
|
||
LanAdapterNumber - Supplies the number of the LAN adapter.
|
||
|
||
Return Value:
|
||
|
||
NET_API_STATUS - NERR_Success or reason for failure.
|
||
|
||
--*/
|
||
{
|
||
NCB Ncb;
|
||
UCHAR NcbStatus;
|
||
|
||
|
||
RtlZeroMemory((PVOID) &Ncb, sizeof(NCB));
|
||
|
||
Ncb.ncb_command = NCBADDNAME;
|
||
memcpy(Ncb.ncb_name, NetBiosName, NCBNAMSZ);
|
||
Ncb.ncb_lana_num = LanAdapterNumber;
|
||
|
||
NcbStatus = Netbios(&Ncb);
|
||
|
||
if (NcbStatus == NRC_GOODRET) {
|
||
|
||
IF_DEBUG(NETBIOS) {
|
||
|
||
Ncb.ncb_name[NCBNAMSZ - 1] = '\0';
|
||
NetpKdPrint(("[Netlib] Successfully added name " FORMAT_LPSTR ". "
|
||
"Name number is " FORMAT_DWORD "\n",
|
||
Ncb.ncb_name, (DWORD) Ncb.ncb_num));
|
||
}
|
||
|
||
if (ARGUMENT_PRESENT(NetBiosNameNumber)) {
|
||
*NetBiosNameNumber = Ncb.ncb_num;
|
||
}
|
||
|
||
return NERR_Success;
|
||
}
|
||
|
||
return NetpNetBiosStatusToApiStatus(NcbStatus);
|
||
}
|
||
|
||
|
||
NET_API_STATUS
|
||
NetpNetBiosDelName(
|
||
IN PCHAR NetBiosName,
|
||
IN UCHAR LanAdapterNumber
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function adds a NetBIOS name to the specified LAN adapter.
|
||
|
||
Arguments:
|
||
|
||
NetBiosName - Supplies a NetBIOS name to be added.
|
||
|
||
LanAdapterNumber - Supplies the number of the LAN adapter.
|
||
|
||
Return Value:
|
||
|
||
NET_API_STATUS - NERR_Success or reason for failure.
|
||
|
||
--*/
|
||
{
|
||
NCB Ncb;
|
||
UCHAR NcbStatus;
|
||
|
||
|
||
RtlZeroMemory((PVOID) &Ncb, sizeof(NCB));
|
||
|
||
Ncb.ncb_command = NCBDELNAME;
|
||
memcpy(Ncb.ncb_name, NetBiosName, NCBNAMSZ);
|
||
Ncb.ncb_lana_num = LanAdapterNumber;
|
||
|
||
NcbStatus = Netbios(&Ncb);
|
||
|
||
if (NcbStatus == NRC_GOODRET) {
|
||
|
||
IF_DEBUG(NETBIOS) {
|
||
|
||
Ncb.ncb_name[NCBNAMSZ - 1] = '\0';
|
||
NetpKdPrint(("[Netlib] Successfully deleted name " FORMAT_LPSTR ". "
|
||
"Name number is " FORMAT_DWORD "\n",
|
||
Ncb.ncb_name, (DWORD) Ncb.ncb_num));
|
||
}
|
||
|
||
return NERR_Success;
|
||
}
|
||
|
||
return NetpNetBiosStatusToApiStatus(NcbStatus);
|
||
}
|
||
|
||
|
||
NET_API_STATUS
|
||
NetpNetBiosGetAdapterNumbers(
|
||
OUT PLANA_ENUM LanAdapterBuffer,
|
||
IN WORD LanAdapterBufferSize
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Arguments:
|
||
|
||
LanAdapterBuffer - Returns LAN adapter numbers in this buffer.
|
||
|
||
LanAdapterBufferSize - Supplies the size of the output buffer which LAN
|
||
LAN adapter numbers will be written to.
|
||
|
||
Return Value:
|
||
|
||
NET_API_STATUS - NERR_Success or reason for failure.
|
||
|
||
--*/
|
||
{
|
||
NCB Ncb;
|
||
|
||
|
||
RtlZeroMemory((PVOID) &Ncb, sizeof(NCB));
|
||
|
||
Ncb.ncb_command = NCBENUM;
|
||
Ncb.ncb_buffer = (char FAR *) LanAdapterBuffer;
|
||
Ncb.ncb_length = LanAdapterBufferSize;
|
||
|
||
return NetpNetBiosStatusToApiStatus(Netbios(&Ncb));
|
||
}
|
||
|
||
|
||
NET_API_STATUS
|
||
NetpStringToNetBiosName(
|
||
OUT PCHAR NetBiosName,
|
||
IN LPTSTR String,
|
||
IN DWORD CanonicalizeType,
|
||
IN WORD Type
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function converts a zero terminated string plus a specified NetBIOS
|
||
name type into a 16-byte NetBIOS name:
|
||
|
||
[ ANSI String ][ Space Padding ][Type]
|
||
|
||
If the input string for the NetBIOS name is fewer than 15 characters,
|
||
spaces will be used to pad the string to 15 characters. The 16th byte
|
||
designates the type of the NetBIOS name.
|
||
|
||
Input strings that are longer than 15 characters will be truncated to
|
||
15 characters.
|
||
|
||
Arguments:
|
||
|
||
NetBiosName - Returns the formatted NetBIOS name.
|
||
|
||
String - Supplies a pointer to a zero terminated string.
|
||
|
||
CanonicalizeType - Supplies a value to determine how the string should be
|
||
canonicalized.
|
||
|
||
Type - Supplies the type of the NetBIOS name.
|
||
|
||
Return Value:
|
||
|
||
NET_API_STATUS - NERR_Success or reason for failure.
|
||
|
||
--*/
|
||
{
|
||
NET_API_STATUS Status = NERR_Success;
|
||
DWORD i;
|
||
DWORD SourceStringLen;
|
||
LPSTR SourceString;
|
||
|
||
SourceStringLen = STRLEN(String);
|
||
|
||
Status = I_NetNameCanonicalize(
|
||
NULL,
|
||
String,
|
||
String,
|
||
(SourceStringLen + 1) * sizeof(TCHAR),
|
||
CanonicalizeType,
|
||
0
|
||
);
|
||
|
||
if (Status != NERR_Success) {
|
||
IF_DEBUG(NETBIOS) {
|
||
NetpKdPrint(("[Netlib] Error canonicalizing message alias "
|
||
FORMAT_LPSTR " " FORMAT_API_STATUS "\n", String, Status));
|
||
}
|
||
return Status;
|
||
}
|
||
|
||
SourceString = NetpAllocStrFromWStr(String);
|
||
|
||
if (SourceString == NULL) {
|
||
return ERROR_NOT_ENOUGH_MEMORY;
|
||
}
|
||
|
||
//
|
||
// Insure the string doesn't exceed the netbios name buffer.
|
||
//
|
||
|
||
if (SourceStringLen > NCBNAMSZ - 1) {
|
||
SourceString[NCBNAMSZ - 1] = '\0';
|
||
}
|
||
(VOID) strncpy(NetBiosName, SourceString, NCBNAMSZ - 1);
|
||
|
||
for (i = SourceStringLen; i < (NCBNAMSZ - 1); i++) {
|
||
NetBiosName[i] = ' ';
|
||
}
|
||
|
||
NetBiosName[NCBNAMSZ - 1] = (CHAR) Type;
|
||
|
||
(VOID) NetApiBufferFree(SourceString);
|
||
|
||
return Status;
|
||
}
|
||
|
||
|
||
NET_API_STATUS
|
||
NetpNetBiosCall(
|
||
IN UCHAR LanAdapterNumber,
|
||
IN LPTSTR NameToCall,
|
||
IN LPTSTR Sender,
|
||
OUT UCHAR *SessionNumber
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function opens a session with the specified name to call.
|
||
|
||
Arguments:
|
||
|
||
LanAdapterNumber - Supplies the number of the LAN adapter.
|
||
|
||
NameToCall - Supplies the name to call.
|
||
|
||
Sender - Supplies the name who makes the call.
|
||
|
||
SessionNumber - Returns the session number of the session established.
|
||
|
||
Return Value:
|
||
|
||
NET_API_STATUS - NERR_Success or reason for failure.
|
||
|
||
--*/
|
||
{
|
||
NET_API_STATUS status;
|
||
NCB Ncb;
|
||
|
||
|
||
RtlZeroMemory((PVOID) &Ncb, sizeof(NCB));
|
||
|
||
if ((status = NetpStringToNetBiosName(
|
||
Ncb.ncb_callname,
|
||
NameToCall,
|
||
NAMETYPE_MESSAGEDEST,
|
||
MESSAGE_ALIAS_TYPE
|
||
)) != NERR_Success) {
|
||
return status;
|
||
}
|
||
|
||
if ((status = NetpStringToNetBiosName(
|
||
Ncb.ncb_name,
|
||
Sender,
|
||
NAMETYPE_MESSAGEDEST,
|
||
MESSAGE_ALIAS_TYPE
|
||
)) != NERR_Success) {
|
||
return status;
|
||
}
|
||
|
||
Ncb.ncb_rto = 30; // Receives time out after 15 seconds
|
||
Ncb.ncb_sto = 30; // Sends time out after 15 seconds
|
||
Ncb.ncb_command = NCBCALL; // Call (wait)
|
||
Ncb.ncb_lana_num = LanAdapterNumber;
|
||
|
||
//
|
||
// Issue the NetBIOS call with retries
|
||
//
|
||
if (NetpIssueCallWithRetries(&Ncb, LanAdapterNumber) != NERR_Success) {
|
||
return NERR_NameNotFound;
|
||
}
|
||
|
||
*SessionNumber = Ncb.ncb_lsn;
|
||
|
||
return NERR_Success;
|
||
}
|
||
|
||
|
||
|
||
NET_API_STATUS
|
||
NetpNetBiosHangup(
|
||
IN UCHAR LanAdapterNumber,
|
||
IN UCHAR SessionNumber
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function closes and opened session.
|
||
|
||
Arguments:
|
||
|
||
LanAdapterNumber - Supplies the number of the LAN adapter.
|
||
|
||
SessionNumber - Supplies the session number of the session to close.
|
||
|
||
Return Value:
|
||
|
||
NET_API_STATUS - NERR_Success or reason for failure.
|
||
|
||
--*/
|
||
{
|
||
NCB Ncb;
|
||
UCHAR NcbStatus;
|
||
|
||
|
||
RtlZeroMemory((PVOID) &Ncb, sizeof(NCB));
|
||
|
||
Ncb.ncb_command = NCBHANGUP;
|
||
Ncb.ncb_lana_num = LanAdapterNumber;
|
||
Ncb.ncb_lsn = SessionNumber;
|
||
|
||
NcbStatus = Netbios(&Ncb);
|
||
|
||
if (NcbStatus == NRC_GOODRET) {
|
||
|
||
IF_DEBUG(NETBIOS) {
|
||
NetpKdPrint(("[Netlib] NetBIOS successfully hung up\n"));
|
||
}
|
||
|
||
return NERR_Success;
|
||
}
|
||
|
||
return NetpNetBiosStatusToApiStatus(NcbStatus);
|
||
}
|
||
|
||
|
||
|
||
NET_API_STATUS
|
||
NetpNetBiosSend(
|
||
IN UCHAR LanAdapterNumber,
|
||
IN UCHAR SessionNumber,
|
||
IN PCHAR SendBuffer,
|
||
IN WORD SendBufferSize
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function sends data in SendBuffer to the session partner specified
|
||
by SessionNumber.
|
||
|
||
Arguments:
|
||
|
||
LanAdapterNumber - Supplies the number of the LAN adapter.
|
||
|
||
SessionNumber - Supplies the session number of a session established with
|
||
NetBIOS CALL and LISTEN commands.
|
||
|
||
SendBuffer - Supplies a pointer to data to be sent.
|
||
|
||
SendBufferSize - Supplies the size of the data in bytes.
|
||
|
||
Return Value:
|
||
|
||
NET_API_STATUS - NERR_Success or reason for failure.
|
||
|
||
--*/
|
||
{
|
||
NCB Ncb;
|
||
UCHAR NcbStatus;
|
||
|
||
|
||
RtlZeroMemory((PVOID) &Ncb, sizeof(NCB));
|
||
|
||
Ncb.ncb_command = NCBSEND;
|
||
Ncb.ncb_lana_num = LanAdapterNumber;
|
||
Ncb.ncb_lsn = SessionNumber;
|
||
Ncb.ncb_buffer = SendBuffer;
|
||
Ncb.ncb_length = SendBufferSize;
|
||
|
||
NcbStatus = Netbios(&Ncb);
|
||
|
||
if (NcbStatus == NRC_GOODRET) {
|
||
|
||
IF_DEBUG(NETBIOS) {
|
||
NetpKdPrint(("[Netlib] NetBIOS successfully sent data\n"));
|
||
}
|
||
|
||
return NERR_Success;
|
||
}
|
||
|
||
return NetpNetBiosStatusToApiStatus(NcbStatus);
|
||
}
|
||
|
||
|
||
NET_API_STATUS
|
||
NetpNetBiosReceive(
|
||
IN UCHAR LanAdapterNumber,
|
||
IN UCHAR SessionNumber,
|
||
OUT PUCHAR ReceiveBuffer,
|
||
IN WORD ReceiveBufferSize,
|
||
IN HANDLE EventHandle,
|
||
OUT WORD *NumberOfBytesReceived
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function posts a NetBIOS receive data request to the session
|
||
partner specified by SessionNumber.
|
||
|
||
Arguments:
|
||
|
||
LanAdapterNumber - Supplies the number of the LAN adapter.
|
||
|
||
SessionNumber - Supplies the session number of a session established with
|
||
NetBIOS CALL and LISTEN commands.
|
||
|
||
ReceiveBuffer - Returns the received data in this buffer.
|
||
|
||
ReceiveBufferSize - Supplies the size of the receive buffer.
|
||
|
||
EventHandle - Supplies a handle to a Win32 event which will be signalled
|
||
when an ASYNCH receive command completes. If this value is zero,
|
||
the receive command is synchronous.
|
||
|
||
NumberOfBytesReceived - Returns the number of bytes of data received.
|
||
|
||
Return Value:
|
||
|
||
NET_API_STATUS - NERR_Success or reason for failure.
|
||
|
||
--*/
|
||
{
|
||
NCB Ncb;
|
||
UCHAR NcbStatus;
|
||
|
||
|
||
RtlZeroMemory((PVOID) &Ncb, sizeof(NCB));
|
||
|
||
Ncb.ncb_command = NCBRECV;
|
||
Ncb.ncb_lana_num = LanAdapterNumber;
|
||
Ncb.ncb_lsn = SessionNumber;
|
||
Ncb.ncb_buffer = ReceiveBuffer;
|
||
Ncb.ncb_length = ReceiveBufferSize;
|
||
|
||
IF_DEBUG(NETBIOS) {
|
||
NetpKdPrint(("[Netlib] ncb_length before receive is " FORMAT_WORD_ONLY
|
||
"\n", (WORD) Ncb.ncb_length));
|
||
}
|
||
|
||
Ncb.ncb_event = EventHandle;
|
||
|
||
NcbStatus = Netbios(&Ncb);
|
||
|
||
if (NcbStatus == NRC_GOODRET) {
|
||
|
||
IF_DEBUG(NETBIOS) {
|
||
NetpKdPrint(("[Netlib] NetBIOS successfully received data\n"));
|
||
NetpKdPrint(("[Netlib] ncb_length after receive is "
|
||
FORMAT_WORD_ONLY "\n", (WORD) Ncb.ncb_length));
|
||
}
|
||
|
||
*NumberOfBytesReceived = Ncb.ncb_length;
|
||
|
||
return NERR_Success;
|
||
}
|
||
|
||
|
||
return NetpNetBiosStatusToApiStatus(NcbStatus);
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
NET_API_STATUS
|
||
NetpNetBiosStatusToApiStatus(
|
||
UCHAR NetBiosStatus
|
||
)
|
||
{
|
||
IF_DEBUG(NETBIOS) {
|
||
NetpKdPrint(("[Netlib] Netbios status is x%02x\n", NetBiosStatus));
|
||
}
|
||
|
||
//
|
||
// Slight optimization
|
||
//
|
||
if (NetBiosStatus == NRC_GOODRET) {
|
||
return NERR_Success;
|
||
}
|
||
|
||
switch (NetBiosStatus) {
|
||
case NRC_NORES: return NERR_NoNetworkResource;
|
||
|
||
case NRC_DUPNAME: return NERR_AlreadyExists;
|
||
|
||
case NRC_NAMTFUL: return NERR_TooManyNames;
|
||
|
||
case NRC_ACTSES: return NERR_DeleteLater;
|
||
|
||
case NRC_REMTFUL: return ERROR_REM_NOT_LIST;
|
||
|
||
case NRC_NOCALL: return NERR_NameNotFound;
|
||
|
||
case NRC_NOWILD:
|
||
case NRC_NAMERR:
|
||
return ERROR_INVALID_PARAMETER;
|
||
|
||
case NRC_INUSE:
|
||
case NRC_NAMCONF:
|
||
return NERR_DuplicateName;
|
||
|
||
default: return NERR_NetworkError;
|
||
}
|
||
|
||
}
|
||
|
||
|
||
static
|
||
NET_API_STATUS
|
||
NetpIssueCallWithRetries(
|
||
IN PNCB CallNcb,
|
||
IN UCHAR LanAdapterNumber
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function issues the NetBIOS call command with retries, just in case
|
||
the receiving name is busy fielding a message at the moment.
|
||
|
||
Arguments:
|
||
|
||
CallNcb - Supplies a pointer to the NCB which has been initialized with
|
||
the proper values to submit an NetBIOS call command.
|
||
|
||
LanAdapterNumber - Supplies the number of the LAN adapter.
|
||
|
||
Return Value:
|
||
|
||
NET_API_STATUS - NERR_Success or reason for failure.
|
||
|
||
--*/
|
||
{
|
||
|
||
#define NETP_MAX_CALL_RETRY 5
|
||
|
||
NCB Ncb;
|
||
WORD RetryCount = 0;
|
||
UCHAR NetBiosStatus;
|
||
NB30_ADAPTER_STATUS StatusBuffer; // Adapter status buffer
|
||
|
||
|
||
//
|
||
// It is possible that the remote receiving name is present but is
|
||
// currently receiving another message and so is not listening.
|
||
// If the return code from the call is NRC_NOCALL then check to see if
|
||
// the name is actually present by issuing an ASTAT call to the name.
|
||
// If the ASTAT succeeds then sleep and retry the call.
|
||
//
|
||
|
||
NetBiosStatus = Netbios(CallNcb);
|
||
|
||
while (NetBiosStatus == NRC_NOCALL && RetryCount < NETP_MAX_CALL_RETRY) {
|
||
|
||
//
|
||
// Initialize ASTAT NCB
|
||
//
|
||
RtlZeroMemory((PVOID) &Ncb, sizeof(NCB));
|
||
|
||
memcpy(Ncb.ncb_callname, CallNcb->ncb_callname, NCBNAMSZ);
|
||
|
||
Ncb.ncb_buffer = (char FAR *) &StatusBuffer;
|
||
Ncb.ncb_length = sizeof(StatusBuffer);
|
||
Ncb.ncb_command = NCBASTAT; // Adapter status (wait)
|
||
Ncb.ncb_lana_num = LanAdapterNumber;
|
||
|
||
//
|
||
// If failed, name is not present
|
||
//
|
||
if (Netbios(&Ncb) != NRC_GOODRET) {
|
||
return NERR_NameNotFound;
|
||
}
|
||
|
||
Sleep(1000L);
|
||
|
||
RetryCount++;
|
||
|
||
NetBiosStatus = Netbios(CallNcb);
|
||
}
|
||
|
||
return NetpNetBiosStatusToApiStatus(NetBiosStatus);
|
||
}
|
||
|
||
|
||
|
||
int
|
||
NetpSmbCheck(
|
||
IN LPBYTE buffer, // Buffer containing SMB
|
||
IN USHORT size, // size of SMB buffer (in bytes)
|
||
IN UCHAR func, // Function code
|
||
IN int parms, // Parameter count
|
||
IN LPSTR fields // Buffer fields dope vector
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Checks Server Message Block for syntactical correctness
|
||
|
||
This function is called to verify that a Server Message Block
|
||
is of the specified form. The function returns zero if the
|
||
SMB is correct; if an error is detected, a non-zero value
|
||
indicating the nature of the error is returned.
|
||
|
||
An SMB is a variable length structure whose exact size
|
||
depends on the setting of certain fixed-offset fields
|
||
and whose exact format cannot be determined except by
|
||
examination of the whole structure. Smbcheck checks to
|
||
see that an SMB conforms to a set of specified conditions.
|
||
The "fields" parameter is a dope vector that describes the
|
||
individual fields to be found in the buffer section at the
|
||
end of the SMB. The vector is a null-terminated character
|
||
string. Currently, the elements of the string must be as
|
||
follows:
|
||
|
||
'b' - the next element in the buffer area should be
|
||
a variable length buffer prefixed with a byte
|
||
containing either 1 or 5 followed by two bytes
|
||
containing the size of the buffer.
|
||
'd' - the next element in the buffer area is a null-terminated
|
||
string prefixed with a byte containing 2.
|
||
'p' - the next element in the buffer area is a null-terminated
|
||
string prefixed with a byte containing 3.
|
||
's' - the next element in the buffer area is a null-terminated
|
||
string prefixed with a byte containing 4.
|
||
|
||
Arguments:
|
||
|
||
buffer - a pointer to the buffer containing the SMB
|
||
|
||
size - the number of bytes in the buffer
|
||
|
||
func - the expected SMB function code
|
||
|
||
parms - the expected number of parameters
|
||
|
||
fields - a dope vector describing the expected buffer fields
|
||
within the SMB's buffer area (see below).
|
||
|
||
|
||
Return Value:
|
||
|
||
an integer status code; zero indicates no errors.
|
||
|
||
|
||
--*/
|
||
{
|
||
PSMB_HEADER smb; // SMB header pointer
|
||
LPBYTE limit; // Upper limit
|
||
|
||
|
||
smb = (PSMB_HEADER) buffer; // Overlay header with buffer
|
||
|
||
//
|
||
// Must be long enough for header
|
||
//
|
||
if(size < sizeof(SMB_HEADER)) {
|
||
return(2);
|
||
}
|
||
|
||
//
|
||
// Message type must be 0xFF
|
||
//
|
||
if(smb->Protocol[0] != 0xff) {
|
||
return(3);
|
||
}
|
||
|
||
//
|
||
// Server must be "SMB"
|
||
//
|
||
if( smb->Protocol[1] != 'S' ||
|
||
smb->Protocol[2] != 'M' ||
|
||
smb->Protocol[3] != 'B') {
|
||
return(4);
|
||
}
|
||
|
||
//
|
||
// Must have proper function code
|
||
//
|
||
if(smb->Command != func) {
|
||
return(5);
|
||
}
|
||
|
||
limit = &buffer[size]; // Set upper limit of SMB
|
||
|
||
buffer += sizeof(SMB_HEADER); // Skip over header
|
||
|
||
//
|
||
// Parameter counts must match
|
||
//
|
||
if(*buffer++ != (BYTE)parms) {
|
||
return(6);
|
||
}
|
||
|
||
//
|
||
// Skip parameters and buffer size
|
||
//
|
||
buffer += (((SHORT)parms & 0xFF) + 1)*sizeof(SHORT);
|
||
|
||
//
|
||
// Check for overflow
|
||
//
|
||
if(buffer > limit) {
|
||
return(7);
|
||
}
|
||
|
||
//
|
||
// Loop to check buffer fields
|
||
//
|
||
while(*fields) {
|
||
|
||
//
|
||
// Switch on dope vector character
|
||
//
|
||
switch(*fields++) {
|
||
|
||
case 'b': // Variable length data block
|
||
|
||
if(*buffer != '\001' && *buffer != '\005') {
|
||
return(8);
|
||
}
|
||
|
||
//
|
||
// Check for block code
|
||
//
|
||
++buffer; // Skip over block code
|
||
size = (USHORT)*buffer++ & (USHORT)0xFF; // Get low-byte size
|
||
size += ((USHORT)*buffer++ & (USHORT)0xFF)<< 8; // Get high-byte of buffer size
|
||
buffer += size; // Increment pointer
|
||
|
||
break;
|
||
|
||
case 'd': // Null-terminated dialect string
|
||
|
||
if(*buffer++ != '\002') { // Check for string code
|
||
return(9);
|
||
}
|
||
buffer += strlen((LPVOID) buffer) + 1; // Skip over the string
|
||
break;
|
||
|
||
case 'p': // Null-terminated path string
|
||
|
||
if(*buffer++ != '\003') { // Check for string code
|
||
return(10);
|
||
}
|
||
buffer += strlen((LPVOID) buffer) + 1; // Skip over the string
|
||
break;
|
||
|
||
case 's': // Null-terminated string
|
||
|
||
if(*buffer++ != '\004') { // Check for string code
|
||
return(11);
|
||
}
|
||
buffer += strlen((LPVOID) buffer) + 1; // Skip over the string
|
||
break;
|
||
}
|
||
|
||
//
|
||
// Check against end of block
|
||
//
|
||
|
||
if(buffer > limit) {
|
||
return(12);
|
||
}
|
||
}
|
||
return(buffer != limit); // Should be false
|
||
}
|