// These functions have been tested with Novell Netware 3.11
//
// Written by: Douglas R. Cannon
// On: 4/9/1992
// email:  	dougc@bert.cs.byu.edu
//

#include <stdio.h>
#include <dos.h>
#include <string.h>
#include <process.h>
#include <ctype.h>


#define DOS 0x21

REGPACK R;

typedef unsigned char byte;
typedef unsigned int  word;

typedef struct {
  byte high_byte;
  byte low_byte;
} nw_int;

typedef struct {
  byte highest_byte;
  byte higher_byte;
  byte lower_byte;
  byte lowest_byte;
} nw_long;

struct address {
  byte network_number[4];
  byte node_address[6];
  byte socket_number[2];
};

struct object_name {
  word len;
  nw_long object_id;
  nw_int object_type;
  char object_name[48];
};

struct object_info {
  word len;
  nw_long object_id;
  nw_int object_type;
  char object_name[48];
  char login_time[7];
};

struct has_props {
  word len;
  nw_long object_id;
  nw_int object_type;
  char object_name[48];
  byte object_flag;
  byte object_security;
  byte object_has_properties;
};

struct property {
  word len;
  char property_name[16];
  byte property_flags;
  byte property_security;
  nw_long sequence_number;
  byte property_has_value;
  byte more_properties;
};

struct connections {
  word len;
  byte number_of_connections;
  byte connection_numbers[100];
};



void print_set(byte buf[128]);
void print_segment(byte buf[128]);
int nw_long_equal(nw_long,nw_long);




int get_connection_numbers(nw_int type,char *name,connections *buf)
{
  struct {
    word len;
    byte type;
    nw_int object_type;
    byte object_name_length;
    char object_name[48];
  } request_buffer;

  connections *reply_buffer = buf;

  request_buffer.len = sizeof(request_buffer)-2;
  request_buffer.type = 0x15;
  request_buffer.object_type = type;
  request_buffer.object_name_length = 48;
  strcpy(request_buffer.object_name,name);

  reply_buffer->len = sizeof(connections)-2;

  R.r_ax = 0xE300;
  R.r_ds = FP_SEG(&request_buffer);
  R.r_si = FP_OFF(&request_buffer);
  R.r_es = FP_SEG(reply_buffer);
  R.r_di = FP_OFF(reply_buffer);
  intr(DOS,&R);

  return (_AL);

}



int get_internet_address(int con,address *buf)
{
  int x;

  struct {
    word buffer_length;
    byte type;
    byte connection_number;
  } request_buffer;

  struct {
    word buffer_length;
    byte network_number[4];
    byte node_address[6];
    byte socket_number[2];
  } reply_buffer;

  request_buffer.buffer_length = sizeof(request_buffer)-2;
  request_buffer.type = 0x13;
  request_buffer.connection_number = con;
  reply_buffer.buffer_length = sizeof(reply_buffer)-2;

  R.r_ax = 0xE300;
  R.r_ds = FP_SEG(&request_buffer);
  R.r_si = FP_OFF(&request_buffer);
  R.r_es = FP_SEG(&reply_buffer);
  R.r_di = FP_OFF(&reply_buffer);
  intr(DOS,&R);

  if (_AL) return(_AL);

  for (x=0; x<4; x++)
    buf->network_number[x] = reply_buffer.network_number[x];
  for (x=0; x<6; x++)
    buf->node_address[x] = reply_buffer.node_address[x];
  for (x=0; x<2; x++)
    buf->socket_number[x] = reply_buffer.socket_number[x];

  return 0;

}





int get_connection_information(int con,object_info *buf)
{

  struct {
    word len;
    byte type;
    byte connection_number;
  } request_buffer;

  object_info *reply_buffer = buf;

  request_buffer.len = sizeof(request_buffer)-2;
  request_buffer.type = 0x16;
  request_buffer.connection_number = con;
  reply_buffer->len = sizeof(object_info)-2;

  R.r_ax = 0xE300;
  R.r_ds = FP_SEG(&request_buffer);
  R.r_si = FP_OFF(&request_buffer);
  R.r_es = FP_SEG(reply_buffer);
  R.r_di = FP_OFF(reply_buffer);
  intr(DOS,&R);

  return (_AL);

}


int get_object_name(nw_long object_id,object_name *buf)
{
  struct {
    word len;
    byte type;
    nw_long object_id;
  } request_buffer;

  object_name *reply_buffer = buf;

  request_buffer.len = sizeof(request_buffer)-2;
  request_buffer.type = 0x36;
  request_buffer.object_id = object_id;
  reply_buffer->len = sizeof(object_name)-2;

  R.r_ax = 0xE300;
  R.r_ds = FP_SEG(&request_buffer);
  R.r_si = FP_OFF(&request_buffer);
  R.r_es = FP_SEG(reply_buffer);
  R.r_di = FP_OFF(reply_buffer);
  intr(DOS,&R);

  return (_AL);

}






int scan_for_object(nw_long last_id,char *name,nw_int type,has_props *buf)
{

  int x;

  struct {
    word len;
    byte type;
    nw_long last_object_id;
    nw_int object_type;
    byte object_name_length;
    byte object_name[48];
  } request_buffer;

  has_props *reply_buffer = buf;

  request_buffer.len = sizeof(request_buffer)-2;
  request_buffer.type = 0x37;
  request_buffer.last_object_id = last_id;
  request_buffer.object_type = type;
  request_buffer.object_name_length = 48;
  strcpy(request_buffer.object_name,name);
  reply_buffer->len = sizeof(has_props)-2;

  R.r_ax = 0xE300;
  R.r_ds = FP_SEG(&request_buffer);
  R.r_si = FP_OFF(&request_buffer);
  R.r_es = FP_SEG(reply_buffer);
  R.r_di = FP_OFF(reply_buffer);
  intr(DOS,&R);

  return(_AL);

}





int read_property_value(char *user,nw_int type,byte sn,char *prop,byte seg[128])
{
  int x,al;

  struct {
    word len;
    byte type;
    nw_int object_type;
    byte object_name_length;
    char object_name[48];
    byte segment_number;
    byte property_name_length;
    char property_name[16];
  } request_buffer;

  struct {
    word len;
    byte property_value[128];
    byte more_segments;
    byte property_flags;
  } reply_buffer;

  request_buffer.len = sizeof(request_buffer)-2;
  request_buffer.type = 0x3D;
  request_buffer.object_type = type;
  request_buffer.object_name_length = 48;
  strcpy(request_buffer.object_name,user);

  request_buffer.segment_number = sn;

  request_buffer.property_name_length = 16;
  strcpy(request_buffer.property_name,prop);

  reply_buffer.len = sizeof(reply_buffer)-2;

  R.r_ax = 0xE300;
  R.r_ds = FP_SEG(&request_buffer);
  R.r_si = FP_OFF(&request_buffer);
  R.r_es = FP_SEG(&reply_buffer);
  R.r_di = FP_OFF(&reply_buffer);
  intr(DOS,&R);
  al = _AL;

  for (x=0; x<128; x++) seg[x]=reply_buffer.property_value[x];

  return(al);

}





int nw_long_equal(nw_long left,nw_long right)
{
  if (left.highest_byte != right.highest_byte) return 0;
  if (left.higher_byte != right.higher_byte) return 0;
  if (left.lower_byte != right.lower_byte) return 0;
  if (left.lowest_byte != right.lowest_byte) return 0;

  return 1;
}



