|
|
/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
tnetcall.c
Abstract:
This module contains code which exercises the NetBIOS dll and driver.
Author:
Colin Watson (ColinW) 13-Mar-1991
Environment:
Application mode
Revision History:
Dave Beaver (DBeaver) 10 August 1991
Modify to support multiple LAN numbers
Jerome Nantel (w-jeromn) 23 August 1991
Add Event Signaling testing
--*/
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#define WIN32_CONSOLE_APP
#include <windows.h>
#include <nb30.h>
#include <stdio.h>
// 1234567890123456
#define SPACES " "
#define TIMEOUT 60000 // Time out for wait, set at 1 minute
#define Hi "Come here Dave, I need you"
#define SEND 1
#define RCV 0
NCB myncb[2]; CHAR Buffer[16384+1024]; CHAR Buffer2[16384+1024]; ULONG lanNumber=0; UCHAR lsn; HANDLE twoEvent[2]; int count; // frame count
BOOLEAN verbose=FALSE; BOOLEAN rxany=FALSE; BOOLEAN rxanyany=FALSE; BOOLEAN input=TRUE; BOOLEAN output=TRUE; int QuietCount = 50; UCHAR name_number;
VOID usage ( VOID ) { printf("usage: tsrnetb -c|l [-[a|r]] [-[i|o]] [-n:lan number][-h] <remote computername> <my computername>\n"); printf(" -c specifies calling, -l specifies listener\n"); printf(" -a specifies rx any, any, -r specifies rx any\n"); printf(" -i specifies rx only, -o specifies tx only\n"); printf(" -d specifies delay with alerts on each tx/rx\n"); printf(" -n specifies the lan number (0 is the default)\n"); printf(" -h specifies that addresses are hexadecimal numbers \n"); printf(" rather than strings.\n"); printf(" -g use group name for the connection\n"); printf(" -v verbose\n"); printf(" -s silent\n"); printf(" -t token ring, lan status alert (names ignored)\n"); printf(" -q quiet (print r every 50 receives\n"); printf(" final two arguments are the remote and local computer names.\n"); }
VOID ClearNcb( PNCB pncb ) { RtlZeroMemory( pncb , sizeof (NCB) ); RtlMoveMemory( pncb->ncb_name, SPACES, sizeof(SPACES)-1 ); RtlMoveMemory( pncb->ncb_callname, SPACES, sizeof(SPACES)-1 ); }
VOID StartSend() {
ClearNcb( &(myncb[0]) ); if ( output == FALSE ) { ResetEvent(twoEvent[SEND]); return; } myncb[0].ncb_command = NCBSEND | ASYNCH; myncb[0].ncb_lana_num = (UCHAR)lanNumber; myncb[0].ncb_buffer = Buffer; myncb[0].ncb_lsn = lsn; myncb[0].ncb_event = twoEvent[SEND]; RtlMoveMemory( Buffer, Hi, sizeof( Hi )); sprintf( Buffer, "%s %d\n", Hi, count ); if ( verbose == TRUE ) { printf( "Tx: %s", Buffer ); } count++; myncb[0].ncb_length = (WORD)sizeof(Buffer); Netbios( &(myncb[0]) );
}
VOID StartRcv() { ClearNcb( &(myncb[1]) ); if ( input == FALSE ) { ResetEvent(twoEvent[RCV]); return; } if ((rxany == FALSE) && (rxanyany == FALSE)) { myncb[1].ncb_command = NCBRECV | ASYNCH; } else { myncb[1].ncb_command = NCBRECVANY | ASYNCH; } myncb[1].ncb_lana_num = (UCHAR)lanNumber; myncb[1].ncb_length = sizeof( Buffer2 ); myncb[1].ncb_buffer = Buffer2; if ( rxany == FALSE ) { if ( rxanyany == FALSE ) { myncb[1].ncb_lsn = lsn; } else { myncb[1].ncb_num = 0xff; } } else{ myncb[1].ncb_num = name_number; } myncb[1].ncb_lsn = lsn; myncb[1].ncb_event = twoEvent[RCV]; Netbios( &(myncb[1]) ); }
int _cdecl main (argc, argv) int argc; char *argv[]; {
int i,j; int rcvCount=0; CHAR localName[17]; CHAR remoteName[17]; CHAR localTemp[32]; CHAR remoteTemp[32]; BOOLEAN gotFirst=FALSE; BOOLEAN asHex=FALSE; BOOLEAN listen=FALSE; BOOLEAN quiet=FALSE; BOOLEAN delay=FALSE; BOOLEAN group=FALSE; BOOLEAN silent=FALSE; BOOLEAN lanalert=FALSE; DWORD tevent; BOOLEAN ttwo=FALSE;
if ( argc < 4 || argc > 9) { usage (); return 1; }
//
// dbeaver: added switch to allow 32 byte hex string as name to facilitate
// testing under unusual circumstances
//
for (j=1;j<16;j++ ) { localTemp[j] = ' '; remoteTemp[j] = ' '; }
//
// parse the switches
//
for (i=1;i<argc ;i++ ) { if (argv[i][0] == '-') { switch (argv[i][1]) { case 'n': if (!NT_SUCCESS(RtlCharToInteger (&argv[i][3], 10, &lanNumber))) { usage (); return 1; } break;
case 'h': asHex = TRUE; break; case 'c': listen = FALSE; break; case 'a': rxany = TRUE; break; case 'r': rxanyany = TRUE; break; case 'i': output = FALSE; break; case 'o': input = FALSE; break; case 'd': delay = FALSE; break; case 'l': listen = TRUE; break; case 'q': quiet = TRUE; silent = TRUE; break; case 'g': group = TRUE; break; case 'v': verbose = TRUE; break; case 's': silent = TRUE; break; case 't': lanalert = TRUE; break; default: usage (); return 1; break;
}
} else {
//
// not a switch must be a name
//
if (gotFirst != TRUE) { RtlMoveMemory (remoteTemp, argv[i], lstrlenA( argv[i] )); gotFirst = TRUE; } else { RtlMoveMemory (localTemp, argv[i], lstrlenA( argv[i] )); }
} } if ((rxany == TRUE) && (rxanyany == TRUE)) { usage(); return 1; } if ((input == FALSE) && (output == FALSE)) { usage(); return 1; }
if (asHex) { RtlZeroMemory (localName, 16); RtlZeroMemory (remoteName, 16);
for (j=0;j<16 ;j+=4) { RtlCharToInteger (&localTemp[j*2], 16, (PULONG)&localName[j]); }
for (j=0;j<16 ;j+=4) { RtlCharToInteger (&remoteTemp[j*2], 16, (PULONG)&remoteName[j]); }
} else { for (j=1;j<16;j++ ) { localName[j] = ' '; remoteName[j] = ' '; }
RtlMoveMemory( localName, localTemp, 16); RtlMoveMemory( remoteName, remoteTemp, 16); }
for ( i=0; i<2; i++ ) { if (( twoEvent[i] = CreateEvent( NULL, TRUE, FALSE, NULL )) == NULL ) { /* Could not get event handle. Abort */ printf("Could not test event signaling.\n"); return 1; } }
printf( "Starting NetBios\n" );
// Reset
ClearNcb( &(myncb[0]) ); myncb[0].ncb_command = NCBRESET; myncb[0].ncb_lsn = 0; // Request resources
myncb[0].ncb_lana_num = (UCHAR)lanNumber; myncb[0].ncb_callname[0] = 0; // 16 sessions
myncb[0].ncb_callname[1] = 0; // 16 commands
myncb[0].ncb_callname[2] = 0; // 8 names
myncb[0].ncb_callname[3] = 0; // Don't want the reserved address
Netbios( &(myncb[0]) );
if ( lanalert == TRUE ) { ClearNcb( &(myncb[0]) ); myncb[0].ncb_command = NCBLANSTALERT; myncb[0].ncb_lana_num = (UCHAR)lanNumber; Netbios( &(myncb[0]) ); if ( myncb[0].ncb_retcode != NRC_GOODRET ) { printf( " LanStatusAlert failed %x", myncb[1].ncb_retcode); } return 0; }
// Add name
ClearNcb( &(myncb[0]) ); if ( group == FALSE) { myncb[0].ncb_command = NCBADDNAME; } else { myncb[0].ncb_command = NCBADDGRNAME; } RtlMoveMemory( myncb[0].ncb_name, localName, 16); myncb[0].ncb_lana_num = (UCHAR)lanNumber; Netbios( &(myncb[0]) ); name_number = myncb[0].ncb_num;
if ( listen == FALSE ) { // Call
printf( "\nStarting Call " ); ClearNcb( &(myncb[0]) ); myncb[0].ncb_command = NCBCALL | ASYNCH; RtlMoveMemory( myncb[0].ncb_name, localName, 16); RtlMoveMemory( myncb[0].ncb_callname,remoteName, 16); myncb[0].ncb_lana_num = (UCHAR)lanNumber; myncb[0].ncb_sto = myncb[0].ncb_rto = 120; // 120*500 milliseconds timeout
myncb[0].ncb_num = name_number; myncb[0].ncb_event = twoEvent[0]; while ( TRUE) { printf("\nStart NCB CALL "); Netbios( &(myncb[0]) ); printf( " Call returned " ); if ( myncb[0].ncb_cmd_cplt == NRC_PENDING ) { if ( WaitForSingleObject( twoEvent[0], TIMEOUT ) ) { // Wait timed out, no return
printf("ERROR: Wait timed out, event not signaled.\n"); } } printf( " Call completed\n" ); lsn = myncb[0].ncb_lsn;
if ( myncb[0].ncb_retcode == NRC_GOODRET ) { // Success
break; } printf("Call completed with error %lx, retry", myncb[0].ncb_retcode ); Sleep(5); } } else { printf( "\nStarting Listen " );
// Listen
ClearNcb( &(myncb[0]) ); myncb[0].ncb_command = NCBLISTEN | ASYNCH; RtlMoveMemory( myncb[0].ncb_name, localName, 16); RtlMoveMemory( myncb[0].ncb_callname, remoteName, 16); myncb[0].ncb_lana_num = (UCHAR)lanNumber; myncb[0].ncb_sto = myncb[0].ncb_rto = 120; // 120*500 milliseconds timeout
myncb[0].ncb_num = name_number; Netbios( &(myncb[0]) ); printf( "Listen returned " ); while ( myncb[0].ncb_cmd_cplt == NRC_PENDING ) { printf( "." ); Sleep(500);
} printf( " Listen completed\n" );
if ( myncb[0].ncb_retcode != NRC_GOODRET ) { printf("ERROR: Could not establish session.\n"); return 1; }
lsn = myncb[0].ncb_lsn;
}
count = 0; StartSend(); StartRcv();
while ( TRUE ) {
tevent = WaitForMultipleObjects(2, twoEvent, FALSE, TIMEOUT);
switch ( tevent ) { case SEND : // Send completed, start a new one.
if ( silent == FALSE ) { printf("S"); } if ( myncb[0].ncb_retcode != NRC_GOODRET ) { printf( "Send failed %x", myncb[0].ncb_retcode); goto Cleanup; } if ( delay == TRUE ) { // Wait alertable - useful for debugging APC problems.
NtWaitForSingleObject( twoEvent[SEND], TRUE, NULL ); }
StartSend(); break;
case RCV : if ( silent == FALSE ) { printf("R"); } if ( (quiet == TRUE) && (QuietCount-- == 0) ) { printf("R"); QuietCount = 50; } if ( myncb[1].ncb_retcode != NRC_GOODRET ) { printf( " Receive failed %x", myncb[1].ncb_retcode); goto Cleanup; } else { if ( verbose == TRUE ) { printf( "Rx: %s", Buffer2 ); } } // Receive completed, start a new one.
if ( delay == TRUE ) { // Wait alertable
NtWaitForSingleObject( twoEvent[RCV], TRUE, NULL ); }
StartRcv(); rcvCount++; break;
default: printf("WARNING: Wait timed out, no event signaled.\n"); break; }
} Cleanup: // Hangup
ClearNcb( &(myncb[0]) ); myncb[0].ncb_command = NCBHANGUP; myncb[0].ncb_lana_num = (UCHAR)lanNumber; myncb[0].ncb_lsn = lsn; Netbios( &(myncb[0]) ); if ( myncb[0].ncb_retcode != NRC_GOODRET ) { printf( " Hangup failed %x", myncb[1].ncb_retcode); }
// Reset
ClearNcb( &(myncb[0]) ); myncb[0].ncb_command = NCBRESET; myncb[0].ncb_lsn = 1; // Free resources
myncb[0].ncb_lana_num = (UCHAR)lanNumber; Netbios( &(myncb[0]) ); printf( "Ending NetBios\n" );
// Close handles
CloseHandle( twoEvent[0] ); CloseHandle( twoEvent[1] );
return 0;
}
|