492 lines
13 KiB
C
492 lines
13 KiB
C
/*++
|
||
|
||
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;
|
||
|
||
}
|
||
|
||
|