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