1068 lines
30 KiB
C
1068 lines
30 KiB
C
//+-------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
//
|
|
// Copyright (C) Microsoft Corporation, 1994 - 1999
|
|
//
|
|
// File: nb.c
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Filename: nb.c
|
|
//
|
|
// Description: This file contains common routines for NetBios I/O
|
|
// routines for use with IPC raw network performance
|
|
// tests.
|
|
// This module is written using win32 API calls.
|
|
//
|
|
// Authors: Scott Holden (Translator from NT API to win32 API)
|
|
// Mahesh Keni (Mahesh wrote this application using mostly
|
|
// NT native API calls)
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "rawcom.h"
|
|
#include "nb.h"
|
|
|
|
/************************************************************************/
|
|
/*++
|
|
This routine is responsible for adding a given name on a net.
|
|
--*/
|
|
|
|
UCHAR
|
|
NetBIOS_AddName(
|
|
IN PCHAR LocalName,
|
|
IN UCHAR LanaNumber,
|
|
OUT PUCHAR NameNumber)
|
|
{
|
|
NCB AddNameNCB;
|
|
UCHAR RetCode;
|
|
|
|
//printf("\n\nNetBIOS_AddName::\n LocalName: %s\n LanaNumber: %uc \n\n", LocalName, LanaNumber);
|
|
|
|
RetCode =0;
|
|
ClearNCB(&AddNameNCB); // does cleanup everything
|
|
|
|
AddNameNCB.ncb_command = NCBADDNAME;
|
|
RtlMoveMemory(AddNameNCB.ncb_name,LocalName,NCBNAMSZ);
|
|
AddNameNCB.ncb_lana_num = LanaNumber;
|
|
|
|
RetCode = Netbios(&AddNameNCB); // submit to NetBIOS
|
|
|
|
if (AddNameNCB.ncb_retcode != NRC_GOODRET) {
|
|
printf("Addname failed %x\n", AddNameNCB.ncb_retcode);
|
|
return RetCode;
|
|
}
|
|
|
|
*NameNumber = AddNameNCB.ncb_num;
|
|
|
|
return RetCode;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/*++
|
|
This routine is responsible for deleting a given name on a net.
|
|
--*/
|
|
|
|
UCHAR
|
|
NetBIOS_DelName(
|
|
IN PCHAR LocalName,
|
|
IN UCHAR LanaNumber)
|
|
{
|
|
NCB DelNameNCB;
|
|
UCHAR RetCode;
|
|
|
|
RetCode =0;
|
|
ClearNCB(&DelNameNCB); // does cleanup everything
|
|
|
|
DelNameNCB.ncb_command = NCBDELNAME;
|
|
RtlMoveMemory(DelNameNCB.ncb_name,LocalName,NCBNAMSZ);
|
|
DelNameNCB.ncb_lana_num = LanaNumber;
|
|
|
|
RetCode = Netbios(&DelNameNCB); // submit to NetBIOS
|
|
|
|
if (DelNameNCB.ncb_retcode != NRC_GOODRET) {
|
|
printf("Delname failed %x\n", DelNameNCB.ncb_retcode);
|
|
return RetCode;
|
|
}
|
|
|
|
return RetCode;
|
|
}
|
|
|
|
/************************************************************************/
|
|
UCHAR
|
|
NetBIOS_Reset(
|
|
IN UCHAR LanaNumber)
|
|
{
|
|
NCB ResetNCB;
|
|
UCHAR RetCode;
|
|
|
|
RetCode =0;
|
|
ClearNCB(&ResetNCB); // does cleanup everything
|
|
|
|
ResetNCB.ncb_command = NCBRESET;
|
|
ResetNCB.ncb_lana_num = LanaNumber;
|
|
ResetNCB.ncb_lsn = 0;
|
|
ResetNCB.ncb_callname[0] = 0; //16 sessions
|
|
ResetNCB.ncb_callname[1] = 0; //16 commands
|
|
ResetNCB.ncb_callname[2] = 0; //8 names
|
|
|
|
RetCode = Netbios(&ResetNCB); // submit to NetBIOS
|
|
|
|
if (ResetNCB.ncb_retcode != NRC_GOODRET) {
|
|
printf("Reset failed %x\n", ResetNCB.ncb_retcode);
|
|
return RetCode;
|
|
}
|
|
|
|
return RetCode;
|
|
}
|
|
/************************************************************************/
|
|
// Used only by NetBIOS Client
|
|
UCHAR
|
|
NetBIOS_Call(
|
|
IN USHORT CIndex, // Client Index
|
|
IN PCHAR LocalName,
|
|
IN PCHAR RemoteName)
|
|
{
|
|
NCB CallNCB;
|
|
NTSTATUS cstatus;
|
|
UCHAR RetCode;
|
|
|
|
RetCode = 0;
|
|
ClearNCB(&CallNCB); // does cleanup everything
|
|
|
|
//printf("\n\nNetBIOS_Call::\n LocalName: %s , RemoteName: %s \n LanaNumber: %c\n\n", \
|
|
// LocalName, RemoteName, Clients[CIndex].c_NetB.c_LanaNumber);
|
|
|
|
CallNCB.ncb_command = NCBCALL | ASYNCH;
|
|
CallNCB.ncb_lana_num = (UCHAR) Clients[CIndex].c_NetB.c_LanaNumber;
|
|
CallNCB.ncb_lsn = 0Xff;
|
|
CallNCB.ncb_sto = CallNCB.ncb_rto = (UCHAR) 1000; // 1000*500 ms timeout
|
|
CallNCB.ncb_post = NULL;
|
|
// associate an event with this NCB
|
|
CallNCB.ncb_event = Clients[CIndex].c_NetB.c_SendEvent;
|
|
|
|
RtlMoveMemory(CallNCB.ncb_name,LocalName,NCBNAMSZ);
|
|
RtlMoveMemory(CallNCB.ncb_callname,RemoteName,NCBNAMSZ);
|
|
|
|
RetCode = Netbios(&CallNCB); // submit to NetBIOS
|
|
|
|
if (CallNCB.ncb_cmd_cplt == NRC_PENDING){
|
|
cstatus = WaitForSingleObjectEx(CallNCB.ncb_event, // handle of the object to wait for
|
|
INFINITE, // wait forever
|
|
TRUE); // Alertable
|
|
}
|
|
|
|
if (CallNCB.ncb_cmd_cplt != NRC_GOODRET) {
|
|
// MyDbgPrint("NBSRV:Call failed %x\n", CallNCB.ncb_cmd_cplt);
|
|
printf("Command completion returns %08x\n", CallNCB.ncb_cmd_cplt);
|
|
return CallNCB.ncb_cmd_cplt;
|
|
}
|
|
// get value for LSN
|
|
Clients[CIndex].c_NetB.c_LSN = CallNCB.ncb_lsn;
|
|
|
|
return CallNCB.ncb_cmd_cplt;
|
|
//return STATUS_SUCCESS;
|
|
}
|
|
/************************************************************************/
|
|
UCHAR
|
|
NetBIOS_Listen(
|
|
IN USHORT TIndex, // Client Index
|
|
IN PCHAR LocalName,
|
|
IN PCHAR RemoteName,
|
|
IN UCHAR NameNumber)
|
|
{
|
|
NCB ListenNCB;
|
|
NTSTATUS lstatus;
|
|
UCHAR RetCode;
|
|
|
|
RetCode =0;
|
|
ClearNCB(&ListenNCB); // does cleanup everything
|
|
|
|
ListenNCB.ncb_command = NCBLISTEN | ASYNCH;
|
|
ListenNCB.ncb_lana_num = (UCHAR) Clients[TIndex].c_NetB.c_LanaNumber;
|
|
ListenNCB.ncb_sto = ListenNCB.ncb_rto = (UCHAR) 1000;
|
|
// 1000*500 ms timeout
|
|
ListenNCB.ncb_num = NameNumber;
|
|
ListenNCB.ncb_post = NULL;
|
|
|
|
// associate an event with this NCB
|
|
ListenNCB.ncb_event = Clients[TIndex].c_NetB.c_SendEvent;
|
|
|
|
RtlMoveMemory(ListenNCB.ncb_name,LocalName,NCBNAMSZ);
|
|
RtlMoveMemory(ListenNCB.ncb_callname,RemoteName,NCBNAMSZ);
|
|
|
|
|
|
RetCode = Netbios(&ListenNCB); // submit to NetBIOS
|
|
|
|
if (ListenNCB.ncb_cmd_cplt == NRC_PENDING){
|
|
lstatus = WaitForSingleObjectEx(ListenNCB.ncb_event, // handle of the object
|
|
INFINITE, // default timeout
|
|
TRUE); // alertable
|
|
}
|
|
|
|
if (ListenNCB.ncb_cmd_cplt != NRC_GOODRET) {
|
|
//MyDbgPrint("NBSRV:Listen failed %x\n", ListenNCB.ncb_cmd_cplt);
|
|
return ListenNCB.ncb_cmd_cplt;
|
|
}
|
|
|
|
// get value for LSN
|
|
Clients[TIndex].c_NetB.c_LSN = ListenNCB.ncb_lsn;
|
|
|
|
return ListenNCB.ncb_cmd_cplt;
|
|
}
|
|
/************************************************************************/
|
|
UCHAR
|
|
NetBIOS_Receive(
|
|
IN USHORT TIndex,
|
|
IN PUCHAR RecvBuffer,
|
|
IN USHORT RecvLen)
|
|
{
|
|
NCB ReceiveNCB;
|
|
NTSTATUS rstatus;
|
|
UCHAR RetCode;
|
|
|
|
RetCode =0;
|
|
ClearNCB(&ReceiveNCB); // does cleanup everything
|
|
|
|
ReceiveNCB.ncb_command = NCBRECV | ASYNCH;
|
|
ReceiveNCB.ncb_lana_num = (UCHAR) Clients[TIndex].c_NetB.c_LanaNumber;
|
|
ReceiveNCB.ncb_lsn = Clients[TIndex].c_NetB.c_LSN;
|
|
ReceiveNCB.ncb_buffer = RecvBuffer;
|
|
ReceiveNCB.ncb_length = RecvLen;
|
|
ReceiveNCB.ncb_event = Clients[TIndex].c_NetB.c_RecvEvent;
|
|
|
|
|
|
RetCode = Netbios(&ReceiveNCB); // submit to NetBIOS
|
|
|
|
if (ReceiveNCB.ncb_cmd_cplt == NRC_PENDING){
|
|
rstatus = WaitForSingleObjectEx(ReceiveNCB.ncb_event, // handle to object
|
|
INFINITE, // default timeout
|
|
TRUE); // alertable
|
|
}
|
|
|
|
if (ReceiveNCB.ncb_cmd_cplt != NRC_GOODRET) {
|
|
//MyDbgPrint("NBSRV:NB:Receive failed %x\n", ReceiveNCB.ncb_cmd_cplt);
|
|
}
|
|
return ReceiveNCB.ncb_cmd_cplt;
|
|
|
|
}
|
|
/************************************************************************/
|
|
UCHAR
|
|
NetBIOS_Send(
|
|
IN USHORT TIndex,
|
|
IN PUCHAR SendBuffer,
|
|
IN USHORT SendLen)
|
|
{
|
|
NCB SendNCB;
|
|
NTSTATUS rstatus;
|
|
UCHAR RetCode;
|
|
|
|
RetCode =0;
|
|
ClearNCB(&SendNCB); // does cleanup everything
|
|
|
|
SendNCB.ncb_command = NCBSEND | ASYNCH;
|
|
SendNCB.ncb_lana_num = (UCHAR) Clients[TIndex].c_NetB.c_LanaNumber;
|
|
SendNCB.ncb_lsn = Clients[TIndex].c_NetB.c_LSN;
|
|
SendNCB.ncb_buffer = SendBuffer;
|
|
SendNCB.ncb_length = SendLen;
|
|
SendNCB.ncb_event = Clients[TIndex].c_NetB.c_SendEvent;
|
|
|
|
RetCode = Netbios(&SendNCB); // submit to NetBIOS
|
|
|
|
if (SendNCB.ncb_cmd_cplt == NRC_PENDING){
|
|
rstatus = WaitForSingleObjectEx(SendNCB.ncb_event, // handle to object
|
|
INFINITE, // default timeout
|
|
TRUE); // alertable
|
|
}
|
|
|
|
if (SendNCB.ncb_cmd_cplt != NRC_GOODRET) {
|
|
//MyDbgPrint("NBSRV:NBS:Send failed %x RetCode:%x\n",SendNCB.ncb_cmd_cplt,RetCode);
|
|
}
|
|
return SendNCB.ncb_cmd_cplt;
|
|
}
|
|
/************************************************************************/
|
|
UCHAR
|
|
NetBIOS_HangUP(
|
|
IN USHORT TIndex)
|
|
{
|
|
NCB HangUPNCB;
|
|
//NTSTATUS rstatus;
|
|
UCHAR RetCode;
|
|
|
|
RetCode = 0;
|
|
ClearNCB(&HangUPNCB); // does cleanup everything
|
|
|
|
HangUPNCB.ncb_command = NCBHANGUP;
|
|
HangUPNCB.ncb_lana_num = (UCHAR) Clients[TIndex].c_NetB.c_LanaNumber;
|
|
HangUPNCB.ncb_lsn = Clients[TIndex].c_NetB.c_LSN;
|
|
|
|
RetCode = Netbios(&HangUPNCB); // submit to NetBIOS
|
|
|
|
if (HangUPNCB.ncb_cmd_cplt != NRC_GOODRET) {
|
|
//MyDbgPrint("NBSRV:HangUP failed %x\n", HangUPNCB.ncb_cmd_cplt);
|
|
}
|
|
return HangUPNCB.ncb_cmd_cplt;
|
|
}
|
|
/************************************************************************/
|
|
UCHAR
|
|
NetBIOS_RecvSend(
|
|
IN USHORT TIndex,
|
|
IN PUCHAR SendBuffer,
|
|
IN USHORT SendLen,
|
|
IN PUCHAR RecvBuffer,
|
|
IN USHORT RecvLen)
|
|
{
|
|
NCB ReceiveNCB; // Make it a part of client
|
|
NCB SendNCB; // Make it a part of client struc
|
|
NTSTATUS rstatus, sstatus;
|
|
UCHAR RRetCode, SRetCode;
|
|
|
|
RRetCode = SRetCode = 0;
|
|
ClearNCB(&ReceiveNCB); // cleanup everything
|
|
ClearNCB(&SendNCB); // cleanup everything
|
|
|
|
// First post Receive but don't wait as this is for the next
|
|
// request block
|
|
ReceiveNCB.ncb_command = NCBRECV | ASYNCH;
|
|
ReceiveNCB.ncb_lana_num = (UCHAR) Clients[TIndex].c_NetB.c_LanaNumber;
|
|
ReceiveNCB.ncb_lsn = Clients[TIndex].c_NetB.c_LSN;
|
|
ReceiveNCB.ncb_buffer = RecvBuffer;
|
|
ReceiveNCB.ncb_length = RecvLen;
|
|
ReceiveNCB.ncb_event = Clients[TIndex].c_NetB.c_RecvEvent;
|
|
|
|
RRetCode = Netbios(&ReceiveNCB); // submit to NetBIOS
|
|
|
|
if (ReceiveNCB.ncb_cmd_cplt == NRC_PENDING){
|
|
// now do all the send(s)
|
|
SendNCB.ncb_command = NCBSEND | ASYNCH;
|
|
SendNCB.ncb_lana_num = (UCHAR) Clients[TIndex].c_NetB.c_LanaNumber;
|
|
SendNCB.ncb_lsn = Clients[TIndex].c_NetB.c_LSN;
|
|
SendNCB.ncb_buffer = SendBuffer;
|
|
SendNCB.ncb_length = SendLen;
|
|
SendNCB.ncb_event = Clients[TIndex].c_NetB.c_SendEvent;
|
|
|
|
SRetCode = Netbios(&SendNCB); // submit to NetBIOS
|
|
|
|
// First wait on Send , if successful then wait on receive
|
|
if (SendNCB.ncb_cmd_cplt == NRC_PENDING){
|
|
// First wait for the Send to complete
|
|
sstatus = WaitForSingleObjectEx(SendNCB.ncb_event,
|
|
INFINITE,
|
|
TRUE);
|
|
}
|
|
|
|
if (SendNCB.ncb_cmd_cplt != NRC_GOODRET) {
|
|
//MyDbgPrint("NBSRV:NBSR:Send failed %x RetCode:%x\n",SendNCB.ncb_cmd_cplt,SRetCode);
|
|
// Cancel the receive posted earlier
|
|
return SendNCB.ncb_cmd_cplt;
|
|
}
|
|
|
|
// Now wait for the receive to complete
|
|
rstatus = WaitForSingleObjectEx(ReceiveNCB.ncb_event,
|
|
INFINITE,
|
|
TRUE);
|
|
// check for status success here
|
|
}
|
|
|
|
if (ReceiveNCB.ncb_cmd_cplt != NRC_GOODRET) {
|
|
//MyDbgPrint("NBSRV:NBSR:Receive failed %x RetCode:%x\n",ReceiveNCB.ncb_cmd_cplt,RRetCode);
|
|
}
|
|
|
|
return ReceiveNCB.ncb_cmd_cplt;
|
|
}
|
|
/************************************************************************/
|
|
|
|
UCHAR
|
|
NetBIOS_SPReceive(
|
|
IN USHORT TIndex,
|
|
IN NCB *PRecvNCB,
|
|
IN USHORT Global, // global= 1 or local = 0
|
|
IN PUCHAR RecvBuffer,
|
|
IN USHORT RecvLen)
|
|
{
|
|
UCHAR RetCode;
|
|
|
|
RetCode =0;
|
|
ClearNCB(PRecvNCB); // does cleanup everything
|
|
|
|
PRecvNCB->ncb_command = NCBRECV | ASYNCH;
|
|
PRecvNCB->ncb_lana_num = (UCHAR) Clients[TIndex].c_NetB.c_LanaNumber;
|
|
PRecvNCB->ncb_lsn = Clients[TIndex].c_NetB.c_LSN;
|
|
PRecvNCB->ncb_buffer = RecvBuffer;
|
|
PRecvNCB->ncb_length = RecvLen;
|
|
|
|
if (Global) {
|
|
PRecvNCB->ncb_event = Clients[TIndex].c_NetB.c_RecvEventG;
|
|
}
|
|
else {
|
|
PRecvNCB->ncb_event = Clients[TIndex].c_NetB.c_RecvEvent;
|
|
}
|
|
|
|
|
|
RetCode = Netbios(PRecvNCB); // submit to NetBIOS
|
|
|
|
return RetCode;
|
|
}
|
|
/************************************************************************/
|
|
|
|
NTSTATUS
|
|
NB_Initialize(
|
|
IN USHORT NClients,
|
|
IN PCHAR IServerName,
|
|
IN USHORT SrvCli)
|
|
{
|
|
NTSTATUS Istatus;
|
|
UCHAR RetCode;
|
|
USHORT LanaNum;
|
|
CHAR Tmp[10]; // for holding numbers
|
|
|
|
//
|
|
// First Reset all the adapters
|
|
// Add the server name if provided otherwise use the default name
|
|
// To take care of TCP/IP and other Lana Bases
|
|
|
|
LanaNum = LanaBase;
|
|
|
|
// initialize all the named
|
|
MyDbgPrint("Initialize both Local/Remote Names\n");
|
|
|
|
if (SrvCli) { // for server copy the given name as a local
|
|
RtlMoveMemory(RemoteName, ALL_CLIENTS, NCBNAMSZ);
|
|
if (IServerName) {
|
|
RtlMoveMemory(LocalName, IServerName, NCBNAMSZ);
|
|
}
|
|
else {
|
|
RtlMoveMemory(LocalName, PERF_NETBIOS, NCBNAMSZ);
|
|
}
|
|
}
|
|
else { // for a client copy the name as a remote name
|
|
|
|
if (IServerName) {
|
|
RtlMoveMemory(RemoteName, IServerName, NCBNAMSZ);
|
|
}
|
|
else {
|
|
RtlMoveMemory(RemoteName, PERF_NETBIOS, NCBNAMSZ);
|
|
}
|
|
|
|
// copy local name for client
|
|
// use Rtl routines
|
|
strcpy(LocalName,CLINAME);
|
|
strcat(LocalName,_itoa(MachineNumber,Tmp,10));
|
|
}
|
|
|
|
while (LanaNum < LanaCount*2) { // for Jet and TCP/IP
|
|
|
|
RetCode = NetBIOS_Reset((UCHAR) LanaNum);
|
|
|
|
if (RetCode) {
|
|
MyDbgPrint("Error in Reset\n");
|
|
return(Istatus = -1L);
|
|
}
|
|
|
|
// we could assign Lana Numbers to clients and do AddName here too
|
|
RetCode = NetBIOS_AddName(LocalName,
|
|
(UCHAR) LanaNum,
|
|
&NameNumber);
|
|
|
|
if (RetCode) {
|
|
//MyDbgPrint("NB: Error in Add Name retc: %C \n", RetCode);
|
|
return (STATUS_UNSUCCESSFUL);
|
|
}
|
|
|
|
// Add the Name number to Client's structure
|
|
|
|
LanaNum = LanaNum+2;
|
|
}
|
|
|
|
OutputDebugString("NB: Reset Done\n");
|
|
|
|
return (STATUS_SUCCESS);
|
|
}
|
|
/************************************************************************/
|
|
/*++
|
|
This routine is responsible adding a NetBIOS name for the given
|
|
thread.
|
|
|
|
--*/
|
|
|
|
NTSTATUS
|
|
NB_PerClientInit(
|
|
IN USHORT CIndex, // client index
|
|
IN USHORT SrvCli )
|
|
{
|
|
//NTSTATUS pstatus;
|
|
//UCHAR RetCode;
|
|
//CHAR Tmp[10]; // for holding numbers
|
|
|
|
// initialize proper client data structures
|
|
Clients[CIndex].c_client_num = CIndex;
|
|
|
|
// distribute clients evenly on all net cards
|
|
Clients[CIndex].c_NetB.c_LanaNumber = ((CIndex % LanaCount)*2)+LanaBase;
|
|
|
|
// Add the Name number to Client's structure
|
|
Clients[CIndex].c_NetB.c_NameNum = NameNumber;
|
|
|
|
// Set all events to Null
|
|
Clients[CIndex].c_NetB.c_SendEvent = NULL;
|
|
Clients[CIndex].c_NetB.c_RecvEvent = NULL;
|
|
Clients[CIndex].c_NetB.c_RecvEventG = NULL;
|
|
|
|
|
|
// create events to associate with an NCB for this thread
|
|
|
|
Clients[CIndex].c_NetB.c_SendEvent = CreateEvent(
|
|
NULL,
|
|
TRUE, // manual reset event
|
|
FALSE, // initial state of the event
|
|
NULL); // no event name
|
|
|
|
Clients[CIndex].c_NetB.c_RecvEvent = CreateEvent(
|
|
NULL,
|
|
TRUE, // manual reset event
|
|
FALSE, // initial state of the event
|
|
NULL); // no event name
|
|
|
|
Clients[CIndex].c_NetB.c_RecvEventG = CreateEvent(
|
|
NULL,
|
|
TRUE, // manual reset event
|
|
FALSE, // initial state of the event
|
|
NULL); // no event name
|
|
|
|
/*
|
|
// Create appropriate Name and do Add Name
|
|
// For server do Nothing
|
|
// for client make a name using machine+Client number
|
|
|
|
if (!SrvCli) {
|
|
// use Rtl routines
|
|
strcpy(LocalName,CLINAME);
|
|
|
|
strcat(LocalName,_itoa(MachineNumber,Tmp,10));
|
|
strcat(LocalName,_itoa(CIndex,Tmp,10));
|
|
}
|
|
|
|
RetCode = NetBIOS_AddName(
|
|
LocalName,
|
|
(UCHAR) Clients[CIndex].c_NetB.c_LanaNumber,
|
|
&NameNum);
|
|
if (RetCode) {
|
|
// MyDbgPrint("NB: Error in Add Name retc: %C \n", RetCode);
|
|
return (STATUS_UNSUCCESSFUL);
|
|
}
|
|
*/
|
|
|
|
|
|
return (STATUS_SUCCESS);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/*++
|
|
This routine is responsible for issueing Listen and waiting till a
|
|
client is connected. When this routine returns successfully we can
|
|
assume that a connection is established.
|
|
--*/
|
|
|
|
NTSTATUS
|
|
NB_Wait_For_Client(
|
|
IN USHORT CIndex) // client index
|
|
{
|
|
|
|
UCHAR RetCode;
|
|
// post a listen
|
|
|
|
RetCode = NetBIOS_Listen(
|
|
CIndex,
|
|
LocalName,
|
|
RemoteName,
|
|
(UCHAR)Clients[CIndex].c_NetB.c_NameNum);
|
|
|
|
if (RetCode) {
|
|
//MyDbgPrint("NB: Err in Listen retc: %C \n", RetCode);
|
|
return (STATUS_UNSUCCESSFUL);
|
|
}
|
|
|
|
return (STATUS_SUCCESS);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/*++
|
|
This routine is responsible for issueing Disconnect to close the
|
|
connection with a client.
|
|
--*/
|
|
|
|
NTSTATUS
|
|
NB_Disconnect_Client(
|
|
IN USHORT CIndex) // client index
|
|
{
|
|
UCHAR RetCode;
|
|
// post a Disconnect
|
|
|
|
RetCode = NetBIOS_HangUP(CIndex);
|
|
|
|
if (RetCode) {
|
|
// MyDbgPrint("NB: Err in Disconnect retc: %C \n", RetCode);
|
|
// return (STATUS_UNSUCCESSFUL);
|
|
// just ignore the error for the time being
|
|
}
|
|
|
|
return (STATUS_SUCCESS);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/*++
|
|
This routine is responsible for establishing a connection to the
|
|
server side. When this routine returns successfully we can assume that
|
|
a connection is established.
|
|
--*/
|
|
|
|
NTSTATUS
|
|
NB_Connect_To_Server(
|
|
IN USHORT CIndex) // client index
|
|
{
|
|
|
|
UCHAR RetCode;
|
|
|
|
RetCode = NetBIOS_Call(
|
|
CIndex,
|
|
LocalName,
|
|
RemoteName);
|
|
|
|
|
|
if (RetCode) {
|
|
//MyDbgPrint("NB: Err in Call retc: %C \n", RetCode);
|
|
return (STATUS_UNSUCCESSFUL);
|
|
}
|
|
|
|
return (STATUS_SUCCESS);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/*++
|
|
This routine allocates memory required for all the buffers for a client.
|
|
|
|
--*/
|
|
|
|
NTSTATUS
|
|
NB_Allocate_Memory(
|
|
IN USHORT CIndex) // client index and namedpipe instance number
|
|
{
|
|
NTSTATUS astatus = STATUS_SUCCESS;
|
|
ULONG AllocSize;
|
|
|
|
// AllocSize = Clients[CIndex].c_reqbuf.SendSize;
|
|
AllocSize = MAXBUFSIZE;
|
|
|
|
// Allocate memory for Send Buffer
|
|
(LPVOID) Clients[CIndex].c_pSendBuf = VirtualAlloc(
|
|
(LPVOID) Clients[CIndex].c_pSendBuf,
|
|
(DWORD)AllocSize,
|
|
(DWORD)MEM_COMMIT,
|
|
(DWORD)PAGE_READWRITE);
|
|
sprintf(Clients[CIndex].c_pSendBuf,"Client%d Send Data", CIndex+1);
|
|
if (Clients[CIndex].c_pSendBuf == NULL) {
|
|
astatus = GetLastError();
|
|
printf("\nVirtual Alloc error\n");
|
|
}
|
|
// AllocSize = Clients[CIndex].c_reqbuf.RecvSize;
|
|
AllocSize = MAXBUFSIZE;
|
|
|
|
// Allocate memory for Receive Buffer
|
|
(LPVOID) Clients[CIndex].c_pRecvBuf = VirtualAlloc(
|
|
(LPVOID) Clients[CIndex].c_pRecvBuf,
|
|
(DWORD)AllocSize,
|
|
(DWORD)MEM_COMMIT,
|
|
(DWORD)PAGE_READWRITE);
|
|
|
|
sprintf(Clients[CIndex].c_pRecvBuf,"Client%d Recv Data", CIndex+1);
|
|
if (Clients[CIndex].c_pRecvBuf == NULL) {
|
|
astatus = GetLastError();
|
|
printf("\nVirtual Alloc error\n");
|
|
}
|
|
// AllocSize = Clients[CIndex].c_reqbuf.RecvSize;
|
|
AllocSize = MAXBUFSIZE;
|
|
|
|
// Allocate memory for Global Receive Buffer
|
|
(LPVOID) Clients[CIndex].c_NetB.c_pRecvBufG = VirtualAlloc(
|
|
(LPVOID) Clients[CIndex].c_NetB.c_pRecvBufG,
|
|
AllocSize,
|
|
MEM_COMMIT,
|
|
PAGE_READWRITE);
|
|
|
|
sprintf(Clients[CIndex].c_NetB.c_pRecvBufG,"Client%d RecvG Data", CIndex+1);
|
|
if (Clients[CIndex].c_NetB.c_pRecvBufG == NULL) {
|
|
astatus = GetLastError();
|
|
printf("\nVirtual Alloc error\n");
|
|
}
|
|
return astatus;
|
|
}
|
|
/************************************************************************/
|
|
/*++
|
|
This routine deallocates memory for a client.
|
|
|
|
--*/
|
|
|
|
NTSTATUS
|
|
NB_Deallocate_Memory(
|
|
IN USHORT CIndex) // client index and namedpipe instance number
|
|
{
|
|
NTSTATUS dstatus;
|
|
ULONG DeallocSize;
|
|
|
|
// Deallocate memory for Send Buffer
|
|
// DeallocSize = Clients[CIndex].c_reqbuf.SendSize;
|
|
DeallocSize = MAXBUFSIZE;
|
|
|
|
dstatus = VirtualFree(
|
|
(LPVOID) Clients[CIndex].c_pSendBuf,
|
|
DeallocSize,
|
|
MEM_DECOMMIT);
|
|
/*
|
|
dstatus = NtFreeVirtualMemory(
|
|
NtCurrentProcess(),
|
|
(PVOID *) (&(Clients[CIndex].c_pSendBuf)),
|
|
&(DeallocSize),
|
|
MEM_DECOMMIT);
|
|
*/
|
|
|
|
if (!NT_SUCCESS(dstatus)) {
|
|
// DbgPrint("Nmp SendBuf: Deallocate memory failed: err: %lx \n", dstatus);
|
|
return dstatus;
|
|
}
|
|
|
|
// DeallocSize = Clients[CIndex].c_reqbuf.RecvSize;
|
|
DeallocSize = MAXBUFSIZE;
|
|
|
|
// Deallocate memory for Receive Buffer
|
|
dstatus = VirtualFree(
|
|
(LPVOID) Clients[CIndex].c_pRecvBuf,
|
|
DeallocSize,
|
|
MEM_DECOMMIT);
|
|
|
|
/*
|
|
dstatus = NtFreeVirtualMemory(
|
|
NtCurrentProcess(),
|
|
(PVOID *) (&(Clients[CIndex].c_pRecvBuf)),
|
|
&(DeallocSize),
|
|
MEM_DECOMMIT);
|
|
*/
|
|
|
|
if (!NT_SUCCESS(dstatus)) {
|
|
// DbgPrint("Nmp RecvBuf :Deallocate memory failed: err: %lx \n", dstatus);
|
|
return dstatus;
|
|
}
|
|
|
|
// DeallocSize = Clients[CIndex].c_reqbuf.RecvSize;
|
|
DeallocSize = MAXBUFSIZE;
|
|
|
|
// Deallocate memory for Global Receive Buffer
|
|
dstatus = VirtualFree(
|
|
(LPVOID) Clients[CIndex].c_NetB.c_pRecvBufG,
|
|
DeallocSize,
|
|
MEM_DECOMMIT);
|
|
/*
|
|
dstatus = NtFreeVirtualMemory(
|
|
NtCurrentProcess(),
|
|
(PVOID *) (&(Clients[CIndex].c_NetB.c_pRecvBufG)),
|
|
&(DeallocSize),
|
|
MEM_DECOMMIT);
|
|
*/
|
|
|
|
if (!NT_SUCCESS(dstatus)) {
|
|
// DbgPrint("Nmp RecvBuf :Deallocate memory failed: err: %lx \n", dstatus);
|
|
return dstatus;
|
|
}
|
|
|
|
|
|
return dstatus;
|
|
|
|
}
|
|
/************************************************************************/
|
|
/*++
|
|
This routine is responsible for disconnecting a session.
|
|
|
|
--*/
|
|
|
|
NTSTATUS
|
|
NB_Disconnect_From_Server(
|
|
IN USHORT CIndex) // client index and namedpipe instance number
|
|
{
|
|
UCHAR RetCode;
|
|
|
|
RetCode = NetBIOS_HangUP(CIndex);
|
|
|
|
/*
|
|
// Session could be closed; check for errc=a
|
|
if (RetCode) {
|
|
// MyDbgPrint("NB: Err in Hang Up retc: %C \n", RetCode);
|
|
return (STATUS_UNSUCCESSFUL);
|
|
}
|
|
*/
|
|
|
|
return (STATUS_SUCCESS);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/*++
|
|
This routine does handshake with it's peer. For Server this means
|
|
receiving request message from a client. For Client it means just the
|
|
opposite.
|
|
--*/
|
|
|
|
NTSTATUS
|
|
NB_DoHandshake(
|
|
IN USHORT CIndex, // client index and namedpipe instance number
|
|
IN USHORT SrvCli) // if it's a server or client
|
|
{
|
|
//NTSTATUS dstatus;
|
|
//ULONG RWLen;
|
|
USHORT RWreqLen;
|
|
UCHAR RetCode;
|
|
|
|
RWreqLen = sizeof(struct reqbuf);
|
|
|
|
// for server do receive for a request buffer
|
|
|
|
if (SrvCli) {
|
|
RetCode = NetBIOS_Receive(
|
|
CIndex,
|
|
(PVOID) &(Clients[CIndex].c_reqbuf),
|
|
RWreqLen);
|
|
if (RetCode) {
|
|
// MyDbgPrint("NB: Err in Receive HandShake retc: %C \n", RetCode);
|
|
return (STATUS_UNSUCCESSFUL);
|
|
}
|
|
}
|
|
else { // for Client do send of reqbuf size
|
|
RetCode = NetBIOS_Send(
|
|
CIndex,
|
|
(PVOID) &(Clients[CIndex].c_reqbuf),
|
|
RWreqLen);
|
|
|
|
if (RetCode) {
|
|
// MyDbgPrint("NB: Err in Send HandShake retc: %C \n", RetCode);
|
|
return (STATUS_UNSUCCESSFUL);
|
|
}
|
|
|
|
}
|
|
|
|
return (STATUS_SUCCESS);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/*++
|
|
This routine Reads data from IPC. For server it means reading data
|
|
NumSends times in SendBuffers and for a client NumRecvs times into
|
|
RecvBuffer.
|
|
|
|
--*/
|
|
|
|
NTSTATUS
|
|
NB_ReadFromIPC(
|
|
IN USHORT CIndex, // client index and namedpipe instance number
|
|
IN OUT PULONG pReadDone,
|
|
IN USHORT SrvCli // if it's a server or client
|
|
)
|
|
|
|
{
|
|
ULONG NumReads;
|
|
ULONG ReadLen;
|
|
PCHAR ReadBuf;
|
|
UCHAR RetCode;
|
|
|
|
if (SrvCli) { // set proper iterations and buffer for Server
|
|
NumReads = Clients[CIndex].c_reqbuf.NumSends;
|
|
ReadBuf = Clients[CIndex].c_pSendBuf;
|
|
ReadLen = Clients[CIndex].c_reqbuf.SendSize;
|
|
}
|
|
else { // for client do proper settings
|
|
NumReads = Clients[CIndex].c_reqbuf.NumRecvs;
|
|
ReadBuf = Clients[CIndex].c_pRecvBuf;
|
|
ReadLen = Clients[CIndex].c_reqbuf.RecvSize;
|
|
}
|
|
|
|
|
|
while (NumReads--) {
|
|
RetCode = NetBIOS_Receive(
|
|
CIndex,
|
|
(PVOID) ReadBuf,
|
|
(USHORT) ReadLen);
|
|
if (RetCode) {
|
|
// MyDbgPrint("NB: Err in Recv ReadFromIPC retc: %C \n", RetCode);
|
|
return (STATUS_UNSUCCESSFUL);
|
|
}
|
|
// Set Read data length; I should check this from NCB
|
|
*pReadDone = ReadLen;
|
|
}
|
|
|
|
return (STATUS_SUCCESS);
|
|
}
|
|
/************************************************************************/
|
|
/*++
|
|
This routine Writes data to IPC. For server it means writing data
|
|
NumRecvs times in RecvBuffers and for a client NumSends times into
|
|
SendBuffer.
|
|
|
|
--*/
|
|
|
|
NTSTATUS
|
|
NB_WriteToIPC(
|
|
IN USHORT CIndex, // client index and namedpipe instance number
|
|
IN OUT PULONG pWriteDone,
|
|
IN USHORT SrvCli // if it's a server or client
|
|
)
|
|
|
|
{
|
|
ULONG NumWrites;
|
|
ULONG WriteLen;
|
|
PCHAR WriteBuf;
|
|
UCHAR RetCode;
|
|
|
|
if (SrvCli) { // set proper iterations and buffer for Server
|
|
NumWrites = Clients[CIndex].c_reqbuf.NumRecvs;
|
|
WriteBuf = Clients[CIndex].c_pRecvBuf;
|
|
WriteLen = Clients[CIndex].c_reqbuf.RecvSize;
|
|
}
|
|
else { // for client do proper settings
|
|
NumWrites = Clients[CIndex].c_reqbuf.NumSends;
|
|
WriteBuf = Clients[CIndex].c_pSendBuf;
|
|
WriteLen = Clients[CIndex].c_reqbuf.SendSize;
|
|
}
|
|
|
|
while (NumWrites--) {
|
|
RetCode = NetBIOS_Send(
|
|
CIndex,
|
|
(PVOID) WriteBuf,
|
|
(USHORT) WriteLen);
|
|
if (RetCode) {
|
|
// MyDbgPrint("NB: Err in Send WritetoIPC retc: %C \n", RetCode);
|
|
return (STATUS_UNSUCCESSFUL);
|
|
}
|
|
// Set written data length; I should check this from NCB
|
|
*pWriteDone = WriteLen;
|
|
}
|
|
|
|
return (STATUS_SUCCESS);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/*++
|
|
This routine does Transact I/O to IPC.
|
|
|
|
--*/
|
|
|
|
NTSTATUS
|
|
NB_XactIO(
|
|
IN USHORT CIndex, // client index and namedpipe instance number
|
|
IN OUT PULONG pReadDone,
|
|
IN OUT PULONG pWriteDone,
|
|
IN USHORT SrvCli, // if it's a server or client
|
|
IN BOOLEAN FirstIter
|
|
)
|
|
|
|
{
|
|
ULONG NumReads;
|
|
ULONG ReadLen;
|
|
PCHAR ReadBuf;
|
|
ULONG WriteLen;
|
|
PCHAR WriteBuf;
|
|
UCHAR RetCode;
|
|
|
|
NumReads = Clients[CIndex].c_reqbuf.NumRecvs;
|
|
|
|
if (SrvCli) { // set proper iterations and buffer for Server
|
|
ReadBuf = Clients[CIndex].c_pSendBuf;
|
|
ReadLen = Clients[CIndex].c_reqbuf.SendSize;
|
|
WriteBuf = Clients[CIndex].c_pRecvBuf;
|
|
WriteLen = Clients[CIndex].c_reqbuf.RecvSize;
|
|
}
|
|
else { // for client do proper settings
|
|
ReadBuf = Clients[CIndex].c_pRecvBuf;
|
|
ReadLen = Clients[CIndex].c_reqbuf.RecvSize;
|
|
WriteBuf = Clients[CIndex].c_pSendBuf;
|
|
WriteLen = Clients[CIndex].c_reqbuf.SendSize;
|
|
}
|
|
|
|
while (NumReads--) {
|
|
// for Srv and First Iteration just post a receive
|
|
if (SrvCli && FirstIter) {
|
|
RetCode = NetBIOS_Receive(
|
|
CIndex,
|
|
(PVOID) ReadBuf,
|
|
(USHORT) ReadLen);
|
|
if (RetCode) {
|
|
// MyDbgPrint("NB: Err in Recv ReadFromIPC retc: %C \n", RetCode);
|
|
return (STATUS_UNSUCCESSFUL);
|
|
}
|
|
}
|
|
else {
|
|
RetCode = NetBIOS_RecvSend(
|
|
CIndex,
|
|
WriteBuf,
|
|
(USHORT) WriteLen,
|
|
ReadBuf,
|
|
(USHORT) ReadLen);
|
|
if (RetCode) {
|
|
// MyDbgPrint("NB: Err in XactIO retc: %C \n", RetCode);
|
|
return (STATUS_UNSUCCESSFUL);
|
|
}
|
|
}
|
|
}
|
|
|
|
return (STATUS_SUCCESS);
|
|
}
|
|
|
|
/************************************************************************/
|
|
NTSTATUS
|
|
NB_Cleanup(VOID)
|
|
{
|
|
USHORT Cindex = 0; // client index
|
|
//NTSTATUS cstatus;
|
|
NTSTATUS exitstatus = 0;
|
|
|
|
/*
|
|
for (Cindex = 0; Cindex < NClients; Cindex++) {
|
|
|
|
}
|
|
*/
|
|
return (STATUS_SUCCESS);
|
|
}
|
|
/************************************************************************/
|
|
|
|
/*++
|
|
This routine does a client specific cleanup work.
|
|
--*/
|
|
|
|
NTSTATUS
|
|
NB_ThreadCleanUp(
|
|
IN USHORT CIndex
|
|
)
|
|
|
|
{
|
|
NTSTATUS tstatus;
|
|
UCHAR RetCode;
|
|
// Close all the events
|
|
|
|
tstatus = CloseHandle(Clients[CIndex].c_NetB.c_SendEvent);
|
|
tstatus = CloseHandle(Clients[CIndex].c_NetB.c_RecvEvent);
|
|
tstatus = CloseHandle(Clients[CIndex].c_NetB.c_RecvEventG);
|
|
|
|
|
|
// Delete the name Added
|
|
RetCode = NetBIOS_DelName(
|
|
LocalName,
|
|
(UCHAR) Clients[CIndex].c_NetB.c_LanaNumber);
|
|
|
|
if (RetCode) {
|
|
// MyDbgPrint("NB: Error in DelName retc: %C \n", RetCode);
|
|
return (STATUS_UNSUCCESSFUL);
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
/************************************************************************/
|