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;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|