// ===================================================
// Листинг 27. Программа для просмотра содержимого
//             базы данных объектов
//
// Файл bscan\bscan.cpp
//
// (C) A. Frolov, 1993
// ===================================================

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define WORD unsigned int
#define BYTE unsigned char

extern "C" int GetNetWareShellVersion(char *,char *, char *);
extern "C" int ScanBinderyObject(char *, WORD, long *,
						char *, WORD *, char *, char *, char *);
extern "C" int ScanProperty(char *, WORD, char *, long *,
						char *, char *, char *, char *, char *);

void Property(char *ObjectName, WORD ObjectType);


void main(void) {

	char MajorVersion=0;
	char MinorVersion=0;
	char Revision=0;
	int ccode;

	BYTE ObjectSecurity;
	long ObjectID;
	char SearchObjectName[48];
	char ObjectName[48];
	WORD SearchObjectType;
	WORD ObjectType;
	char ObjectHasProperties;
	char ObjectFlag;

	printf("\n*BSCAN* (C) Frolov A., 1993\n");

// Проверяем присутствие сетевой оболочки

	asm push si
	GetNetWareShellVersion(&MajorVersion,
			&MinorVersion, &Revision);
	asm pop si

	if(MajorVersion == 0) {
		printf("\nОболочка NetWare не загружена\n");
		return;
	}

// Просматриваем в цикле содержимое базы объектов,
// ищем объекты всех типов

	SearchObjectType = -1;

// Маска для поиска всех объектов

	strcpy(SearchObjectName, "*");

	for(ObjectID = -1;;) {

// Получаем очередной объект

		ccode = ScanBinderyObject(SearchObjectName,
			SearchObjectType, &ObjectID, ObjectName,
			&ObjectType, &ObjectHasProperties, &ObjectFlag,
			&ObjectSecurity);

// Если больше нет объектов или произошла ошибка,
// завершаем цикл

		if(ccode) break;

// Выводим имя и тип объекта

		printf("\n%-18s\t", ObjectName);

		switch(ObjectType) {
		case 0:
			printf("???                     ");	break;
		case 1:
			printf("Пользователь            ");	break;
		case 2:
			printf("Группа                  ");	break;
		case 3:
			printf("Очередь на печать       "); break;
		case 4:
			printf("Файл-сервер             "); break;
		case 5:
			printf("Сервер заданий          "); break;
		case 6:
			printf("Шлюз                    "); break;
		case 7:
			printf("Сервер печати           "); break;
		case 8:
			printf("Очередь архивирования   "); break;
		case 9:
			printf("Сервер для архивирования"); break;
		case 0xA:
			printf("Очередь заданий         "); break;
		case 0xb:
			printf("Администратор           "); break;
		case 0x26:
			printf("Сервер удаленного моста "); break;
		default:
			printf("Объект 0x%04.4X           ", ObjectType); break;
		}

// Выводим флаг объекта, который может иметь два
// значения: 0 для постоянных объектов и
// 1 для временных

		if(ObjectFlag) printf("Временный ");
		else           printf("Постоянный");

// Выводим байт прав, необходимых для получения
// доступа к объекту

		printf(" Доступ %02.2X", ObjectSecurity);

// Если для объекта имеются дополнительные записи,
// выводим их названия

		if(ObjectHasProperties) Property(ObjectName,
			ObjectType);
	}
}

// ==================================================
// Функция Property выводит названия дополнительных
// записей объектов
// ==================================================

void Property(char *ObjectName, WORD ObjectType) {

	int ccode;

	BYTE PropertySecurity;
	long ObjectID;
	char SearchPropertyName[16];
	char PropertyName[16];
	WORD SearchObjectType;
	char PropertyFlag;
	long SequenceNumber;
	char PropertyHasValue;
	char MoreProperties;

// Маска для поиска всех записей

	strcpy(SearchPropertyName, "*");
	for(SequenceNumber=-1;;) {

// Получаем запись

		ccode = ScanProperty(ObjectName, ObjectType,
		  SearchPropertyName, &SequenceNumber,
		  PropertyName, &PropertyFlag, &PropertySecurity,
		  &PropertyHasValue, &MoreProperties);

// Если записей больше нет, завершаем цикл

		if(ccode) break;

// Выводим название записи

		printf("\n\tProperty %s", PropertyName);
	}
}
