mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
487 lines
17 KiB
487 lines
17 KiB
/*++
|
|
|
|
Copyright (c) 1994 Microsoft Corporation
|
|
Copyright (c) 1993 Micro Computer Systems, Inc.
|
|
|
|
Module Name:
|
|
|
|
net\svcdlls\nwsap\server\nwsapp.h
|
|
|
|
Abstract:
|
|
|
|
This is the include file used by the NT SAP Agent files. It
|
|
is private for the SAP Agent code. All programs wanting to use
|
|
the API calls should use NWSAP.H.
|
|
|
|
Author:
|
|
|
|
Brian Walker (MCS) 06-30-1993
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#ifndef _NWSAP_SAPP_
|
|
#define _NWSAP_SAPP_
|
|
|
|
#include <nt.h>
|
|
#include <ntrtl.h>
|
|
#include <nturtl.h>
|
|
|
|
#include <windef.h>
|
|
#include <winbase.h>
|
|
#include <winsock.h>
|
|
#include <wsipx.h>
|
|
#include <wsnwlink.h>
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <nwsap.h>
|
|
#include "sdmd.h"
|
|
|
|
#include "ssdebug.h"
|
|
|
|
#include <netevent.h>
|
|
|
|
/** **/
|
|
|
|
#define SAP_OBJNAME_LEN 48 /* Length of a server name */
|
|
#define SAP_ADDR_LEN 12 /* Length of IPX address (Net+Node+Socket) */
|
|
|
|
#define SAP_NET_LEN 4 /* Length of a network number */
|
|
#define SAP_NODE_LEN 6 /* Length of a node number */
|
|
|
|
/** **/
|
|
|
|
#define NWSAP_SAP_SOCKET 0x0452
|
|
|
|
/**
|
|
We must define this Winsock option code here because it
|
|
is not in wsisn.h.
|
|
**/
|
|
|
|
#ifndef IPX_ADDRESS_NOTIFY
|
|
#define IPX_ADDRESS_NOTIFY 0x400c
|
|
#endif
|
|
|
|
/** Flags for the SapWanFilter flag **/
|
|
|
|
#define SAPWAN_NOTHING 0 /* Send nothing on the WAN except initial query */
|
|
#define SAPWAN_CHANGESONLY 1 /* Send servers that have changed only */
|
|
#define SAPWAN_REGULAR 2 /* Just handle it as a regular card */
|
|
|
|
/** **/
|
|
|
|
#define SAPFILTER_PASSLIST 0
|
|
#define SAPFILTER_DONTPASSLIST 1
|
|
|
|
/**
|
|
This macro is used to compare 2 names.
|
|
|
|
Arguments - n1 = First name to compare
|
|
n2 = Second name to compare
|
|
|
|
Returns - 0 = Names are the same
|
|
1 = n1 > n2
|
|
-1 = n1 < n2
|
|
**/
|
|
|
|
#define SAP_NAMECMP(n1,n2) (strcmp(n1,n2))
|
|
|
|
/** Macros to copy names and addresses around **/
|
|
|
|
#define SAP_COPY_SERVNAME(dest,src) memcpy(dest,src,SAP_OBJNAME_LEN)
|
|
#define SAP_COPY_ADDRESS(dest,src) memcpy(dest,src,SAP_ADDR_LEN)
|
|
#define SAP_COPY_NETNUM(dest,src) memcpy(dest,src,SAP_NET_LEN)
|
|
#define SAP_COPY_NODENUM(dest,src) memcpy(dest,src,SAP_NODE_LEN)
|
|
|
|
/** **/
|
|
|
|
#if DBG
|
|
#ifdef SAP_MEMORY_TRACE
|
|
#define SAP_MALLOC(a,b) SapDebugMalloc(a,b)
|
|
#define SAP_FREE(a,b) SapDebugFree(a,b)
|
|
#else
|
|
#define SAP_MALLOC(a,b) malloc(a)
|
|
#define SAP_FREE(a,b) free(a)
|
|
#endif
|
|
#else
|
|
#define SAP_MALLOC(a,b) malloc(a)
|
|
#define SAP_FREE(a,b) free(a)
|
|
#endif
|
|
|
|
/***
|
|
These define return codes from SapGetCardFromAddress. They
|
|
tell about special conditions.
|
|
***/
|
|
|
|
#define CARDRET_UNKNOWN 0xFFFD /* Network not found */
|
|
#define CARDRET_MYSELF 0xFFFE /* I (SAP Agent) sent the packet */
|
|
#define CARDRET_INTERNAL 0xFFFF /* Internal process other then myself */
|
|
|
|
|
|
/********************************************************************
|
|
This is the receive buffer structure we use. This
|
|
is allocated by the receive thread to receive a
|
|
SAP from the network. This structure is then passed to
|
|
the worker thread for processing.
|
|
*********************************************************************/
|
|
typedef struct _SAP_RECVBLOCK {
|
|
LIST_ENTRY ListEntry; /* Used to link on worker list */
|
|
INT Datalen; /* Length of data in the buffer */
|
|
UCHAR Address[16]; /* Address of who sent the packet */
|
|
INT AddressLength; /* Length of the address */
|
|
UCHAR Buffer[1]; /* Buffer - must be last */
|
|
} SAP_RECVBLOCK, *PSAP_RECVBLOCK;
|
|
|
|
#define SAP_RECVBLOCK_SIZE FIELD_OFFSET(SAP_RECVBLOCK,Buffer)
|
|
|
|
#define SAP_MAX_RECVLEN 512 /* Receive buffer size we use */
|
|
#define SAP_MAX_SENDLEN 512 /* Send buffer size we use */
|
|
|
|
/**
|
|
This is a packet entry that is kept by SAP_PKTLIST
|
|
**/
|
|
|
|
typedef struct _SAP_PKTENTRY {
|
|
struct _SAP_PKTENTRY *Next; /* Ptr to next PKTENTRY in list */
|
|
INT SendLength; /* Length of data in this buffer */
|
|
UCHAR Buffer[1]; /* Buffer we build into */
|
|
} SAP_PKTENTRY, *PSAP_PKTENTRY;
|
|
|
|
/** Length of SAP_PKTENTRY structure up to the buffer entry **/
|
|
|
|
#define SAP_PKTENTRY_SIZE FIELD_OFFSET(SAP_PKTENTRY,Buffer)
|
|
|
|
/**
|
|
This keeps track of a list of packets that are being
|
|
sent.
|
|
**/
|
|
|
|
typedef struct _SAP_PKTLIST {
|
|
|
|
/** Ptr to head/tail of send list **/
|
|
|
|
PSAP_PKTENTRY PktHead;
|
|
PSAP_PKTENTRY PktTail;
|
|
INT NumPkts;
|
|
|
|
/** Num entries in current packet **/
|
|
|
|
INT Curnum; /* Current num entries in list */
|
|
PUCHAR Curptr; /* Next build pointer */
|
|
PSAP_PKTENTRY Curpkt; /* Ptr to current packet entry */
|
|
} SAP_PKTLIST, *PSAP_PKTLIST;
|
|
|
|
/**
|
|
To handle SAP routing, we must know about each card that
|
|
NWLink is using. To handle this, we get a list of them
|
|
at init time. This structure holds one card entry.
|
|
**/
|
|
|
|
typedef struct _SAP_CARD {
|
|
struct _SAP_CARD *Next;
|
|
ULONG Linkspeed; /* Linkspeed of card in 100 b/sec */
|
|
INT Maxpkt; /* Max packet size can send on card */
|
|
BOOL Wanflag; /* TRUE = Yes */
|
|
UCHAR ReqCount; /* Count to send on gen requests */
|
|
UCHAR Number; /* Number assigned by transport */
|
|
UCHAR Netnum[4]; /* Network number of adapter */
|
|
UCHAR Nodenum[6]; /* Node address of adapter */
|
|
SAP_PKTLIST Plist; /* Ptr to list for advertising */
|
|
} SAP_CARD, *PSAP_CARD;
|
|
|
|
#define SAP_CARD_SIZE sizeof(SAP_CARD)
|
|
|
|
|
|
/********************************************************************
|
|
Defines and structures that define the Service Advertising
|
|
Protocol packet that we transmit and receive.
|
|
*********************************************************************/
|
|
|
|
/** Query/Response types **/
|
|
|
|
#define SAPTYPE_GENERAL_SERVICE_QUERY 1
|
|
#define SAPTYPE_GENERAL_SERVICE_RESPONSE 2
|
|
#define SAPTYPE_NEAREST_SERVICE_QUERY 3
|
|
#define SAPTYPE_NEAREST_SERVICE_RESPONSE 4
|
|
|
|
/**
|
|
A SAP Packet has a USHORT query type (above), plus 0 or more
|
|
of the SAP_HEADER structures defined here.
|
|
**/
|
|
|
|
/** Structure of entry in a SAP packet **/
|
|
|
|
typedef struct _SAP_HEADER {
|
|
USHORT ServerType; /* Service type code */
|
|
UCHAR ServerName[SAP_OBJNAME_LEN];
|
|
UCHAR Address[SAP_ADDR_LEN];
|
|
USHORT Hopcount;
|
|
} SAP_HEADER, *PSAP_HEADER;
|
|
|
|
#define SAP_HEADER_SIZE sizeof(SAP_HEADER)
|
|
|
|
/** General Service request structure **/
|
|
|
|
typedef struct {
|
|
USHORT QueryType;
|
|
USHORT ServerType;
|
|
} SAP_REQUEST, *PSAP_REQUEST;
|
|
#define SAP_REQUEST_SIZE sizeof(SAP_REQUEST)
|
|
|
|
|
|
/*********************************************************************
|
|
When sending more then 1 packet out at a time, we
|
|
have to delay 55 ms between the packets. This is defined
|
|
in the Novell docs about SAP. We do not want to overrun
|
|
routers.
|
|
*********************************************************************/
|
|
|
|
#define NWSAP_SEND_DELAY() Sleep(55)
|
|
|
|
|
|
/*********************************************************************
|
|
This structure keeps track of an entry in our
|
|
advertise table.
|
|
*********************************************************************/
|
|
|
|
typedef struct _SAP_SERVER {
|
|
struct _SAP_SERVER *Next;
|
|
USHORT ServerType; /* Server Type */
|
|
UCHAR ServerName[SAP_OBJNAME_LEN]; /* Server Name */
|
|
UCHAR Address[SAP_ADDR_LEN]; /* Address of server*/
|
|
USHORT Hopcount; /* Hop Count */
|
|
BOOL Changed; /* TRUE = Yes */
|
|
BOOL RespondNearest;
|
|
ULONG ClientId; /* Client that added this */
|
|
} SAP_SERVER, *PSAP_SERVER;
|
|
|
|
#define SAP_SERVER_SIZE sizeof(SAP_SERVER)
|
|
|
|
|
|
/*********************************************************************
|
|
This structure keeps track of an entry in our
|
|
server name filter table.
|
|
*********************************************************************/
|
|
|
|
/** Num entries in the hash table **/
|
|
|
|
#define SAP_NAMEFILTER_HASHSIZE 255
|
|
|
|
/** Structure to keep track of one entry **/
|
|
|
|
typedef struct _SAP_NAMEFILTER {
|
|
struct _SAP_NAMEFILTER *Next;
|
|
UCHAR ServerName[SAP_OBJNAME_LEN];
|
|
} SAP_NAMEFILTER, *PSAP_NAMEFILTER;
|
|
#define SAP_NAMEFILTER_SIZE sizeof(SAP_NAMEFILTER)
|
|
|
|
/** Structure to keep track of a hash entry **/
|
|
|
|
typedef struct _SAP_FILTERHDR {
|
|
PSAP_NAMEFILTER FirstEntry;
|
|
} SAP_FILTERHDR, *PSAP_FILTERHDR;
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
***********************************************************************/
|
|
|
|
#define ACQUIRE_RECVTABLE_LOCK() EnterCriticalSection(&SapRecvCriticalSection)
|
|
#define ACQUIRE_SENDTABLE_LOCK() EnterCriticalSection(&SapSendCriticalSection)
|
|
#define ACQUIRE_FREETABLE_LOCK() EnterCriticalSection(&SapFreeCriticalSection)
|
|
#define ACQUIRE_THREADCOUNT_LOCK() EnterCriticalSection(&SapThreadCountCriticalSection)
|
|
#define ACQUIRE_LPC_THREADCOUNT_LOCK() EnterCriticalSection(&SapLpcThreadCountCriticalSection)
|
|
#define ACQUIRE_LPCCLIENT_LOCK() EnterCriticalSection(&SapLpcClientCriticalSection)
|
|
#define ACQUIRE_WANRECVTABLE_LOCK() EnterCriticalSection(&SapWanRecvCriticalSection)
|
|
#define ACQUIRE_WANFREETABLE_LOCK() EnterCriticalSection(&SapWanFreeCriticalSection)
|
|
#define ACQUIRE_SENDBUSY_LOCK() EnterCriticalSection(&SapSendBusyCriticalSection)
|
|
|
|
#define RELEASE_RECVTABLE_LOCK() LeaveCriticalSection(&SapRecvCriticalSection)
|
|
#define RELEASE_SENDTABLE_LOCK() LeaveCriticalSection(&SapSendCriticalSection)
|
|
#define RELEASE_FREETABLE_LOCK() LeaveCriticalSection(&SapFreeCriticalSection)
|
|
#define RELEASE_THREADCOUNT_LOCK() LeaveCriticalSection(&SapThreadCountCriticalSection)
|
|
#define RELEASE_LPC_THREADCOUNT_LOCK() LeaveCriticalSection(&SapLpcThreadCountCriticalSection)
|
|
#define RELEASE_LPCCLIENT_LOCK() LeaveCriticalSection(&SapLpcClientCriticalSection)
|
|
#define RELEASE_WANRECVTABLE_LOCK() LeaveCriticalSection(&SapWanRecvCriticalSection)
|
|
#define RELEASE_WANFREETABLE_LOCK() LeaveCriticalSection(&SapWanFreeCriticalSection)
|
|
#define RELEASE_SENDBUSY_LOCK() LeaveCriticalSection(&SapSendBusyCriticalSection)
|
|
|
|
|
|
/*******************************************************************
|
|
These macros are used to check the number of worker
|
|
threads that are waiting for work to happen.
|
|
*******************************************************************/
|
|
|
|
#define INC_WORKER_THREAD_WAITING_COUNT() { \
|
|
ACQUIRE_RECVTABLE_LOCK(); \
|
|
SapWorkerThreadWaiting++; \
|
|
RELEASE_RECVTABLE_LOCK(); \
|
|
}
|
|
|
|
#define DEC_WORKER_THREAD_WAITING_COUNT() { \
|
|
ACQUIRE_RECVTABLE_LOCK(); \
|
|
SapWorkerThreadWaiting--; \
|
|
RELEASE_RECVTABLE_LOCK(); \
|
|
}
|
|
|
|
|
|
/**
|
|
These are used to keep track of how many receive and worker threads
|
|
we have. At terminate time we need to be able to wait for all
|
|
these to terminate.
|
|
|
|
The THREADCOUNT lock is held when these macros are called.
|
|
|
|
The "m" is a message.
|
|
lp is a pointer to a long to inc/dec
|
|
**/
|
|
|
|
#define SAP_INC_THREAD_COUNT(m,lp) { \
|
|
ACQUIRE_THREADCOUNT_LOCK(); \
|
|
SapThreadCount++; \
|
|
if (lp) { \
|
|
(*(PULONG)lp)++; \
|
|
} \
|
|
IF_DEBUG(THREADTRACE) { \
|
|
SS_PRINT(("INC THREAD COUNT from %s: new count = %d\n", m, SapThreadCount)); \
|
|
} \
|
|
ResetEvent(SapThreadEvent); \
|
|
RELEASE_THREADCOUNT_LOCK(); \
|
|
}
|
|
|
|
#define SAP_DEC_THREAD_COUNT(m,lp) { \
|
|
ACQUIRE_THREADCOUNT_LOCK(); \
|
|
SapThreadCount--; \
|
|
if (lp) { \
|
|
(*(PULONG)lp)--; \
|
|
} \
|
|
IF_DEBUG(THREADTRACE) { \
|
|
SS_PRINT(("DEC THREAD COUNT from %s: new count = %d\n", m, SapThreadCount)); \
|
|
} \
|
|
if (SapThreadCount == 0) { \
|
|
IF_DEBUG(THREADTRACE) { \
|
|
SS_PRINT(("Setting event for Sap thread waiting\n")); \
|
|
} \
|
|
RELEASE_THREADCOUNT_LOCK(); \
|
|
SetEvent(SapThreadEvent); \
|
|
} \
|
|
else { \
|
|
RELEASE_THREADCOUNT_LOCK(); \
|
|
} \
|
|
}
|
|
|
|
|
|
/**
|
|
These are used to keep track of how many LPC worker threads
|
|
we have. At terminate time we need to be able to wait for all
|
|
these to terminate.
|
|
|
|
The THREADCOUNT lock is held when these macros are called.
|
|
|
|
The "m" is a message.
|
|
lp is a pointer to a long to inc/dec
|
|
**/
|
|
|
|
#define SAP_INC_LPC_THREAD_COUNT(m) { \
|
|
ACQUIRE_LPC_THREADCOUNT_LOCK(); \
|
|
SapLpcNumWorkers++; \
|
|
IF_DEBUG(THREADTRACE) { \
|
|
SS_PRINT(("INC LPC THREAD COUNT from %s: new count = %d\n", m, SapLpcNumWorkers)); \
|
|
} \
|
|
ResetEvent(SapLpcThreadEvent); \
|
|
RELEASE_LPC_THREADCOUNT_LOCK(); \
|
|
}
|
|
|
|
#define SAP_DEC_LPC_THREAD_COUNT(m) { \
|
|
ACQUIRE_LPC_THREADCOUNT_LOCK(); \
|
|
SapLpcNumWorkers--; \
|
|
IF_DEBUG(THREADTRACE) { \
|
|
SS_PRINT(("DEC LPC THREAD COUNT from %s: new count = %d\n", m, SapLpcNumWorkers)); \
|
|
} \
|
|
if (SapLpcNumWorkers == 0) { \
|
|
IF_DEBUG(THREADTRACE) { \
|
|
SS_PRINT(("Setting event for Sap LPC thread waiting\n")); \
|
|
} \
|
|
RELEASE_LPC_THREADCOUNT_LOCK(); \
|
|
SetEvent(SapLpcThreadEvent); \
|
|
} \
|
|
else { \
|
|
RELEASE_LPC_THREADCOUNT_LOCK(); \
|
|
} \
|
|
}
|
|
|
|
|
|
/*******************************************************************
|
|
This is a readers/writers lock for the
|
|
card list.
|
|
*******************************************************************/
|
|
|
|
#define SAP_CARDLIST_LTO (60*1000) /* 1 Minute = writers lock timeout */
|
|
|
|
#define ACQUIRE_CARDLIST_READERS_LOCK(m) { \
|
|
IF_DEBUG(LOCKS) { \
|
|
SS_PRINT(("SAP: ACLRL: ENT: From %s\n", m));\
|
|
} \
|
|
EnterCriticalSection(&SapCardlistCriticalSection);\
|
|
SapCardlistLockCount++; \
|
|
if (SapCardlistLockCount == 1) \
|
|
ResetEvent(SapCardlistSynchEvent); \
|
|
LeaveCriticalSection(&SapCardlistCriticalSection);\
|
|
IF_DEBUG(LOCKS) { \
|
|
SS_PRINT(("SAP: ACLRL: GOT: From %s\n", m));\
|
|
} \
|
|
}
|
|
|
|
#define RELEASE_CARDLIST_READERS_LOCK(m) { \
|
|
IF_DEBUG(LOCKS) { \
|
|
SS_PRINT(("SAP: RCLRL: ENT: From %s\n", m));\
|
|
} \
|
|
EnterCriticalSection(&SapCardlistCriticalSection);\
|
|
IF_DEBUG(ERRORS) { \
|
|
if (SapCardlistLockCount == 0) { \
|
|
SS_PRINT(("NWSAP: RCLRL: Lock Count is 0\n"));\
|
|
} \
|
|
} \
|
|
SapCardlistLockCount--; \
|
|
if (SapCardlistLockCount == 0) \
|
|
SetEvent(SapCardlistSynchEvent); \
|
|
LeaveCriticalSection(&SapCardlistCriticalSection);\
|
|
IF_DEBUG(LOCKS) { \
|
|
SS_PRINT(("SAP: RCLRL: REL: From %s\n", m));\
|
|
} \
|
|
}
|
|
|
|
#define ACQUIRE_CARDLIST_WRITERS_LOCK(statx,m) { \
|
|
IF_DEBUG(LOCKS) { \
|
|
SS_PRINT(("SAP: ACLWL: ENT: From %s\n", m)); \
|
|
} \
|
|
while (1) { \
|
|
EnterCriticalSection(&SapCardlistCriticalSection); \
|
|
if (SapCardlistLockCount != 0) { \
|
|
LeaveCriticalSection(&SapCardlistCriticalSection); \
|
|
statx = WaitForSingleObjectEx(SapCardlistSynchEvent,SAP_CARDLIST_LTO,TRUE); \
|
|
if (statx == WAIT_TIMEOUT) \
|
|
break; \
|
|
} \
|
|
else { \
|
|
statx = 0; \
|
|
break; \
|
|
} \
|
|
} \
|
|
IF_DEBUG(LOCKS) { \
|
|
SS_PRINT(("SAP: ACLWL: GOT: From %s\n", m)); \
|
|
} \
|
|
}
|
|
|
|
#define RELEASE_CARDLIST_WRITERS_LOCK(m) { \
|
|
IF_DEBUG(LOCKS) { \
|
|
SS_PRINT(("SAP: RCLWL: ENT: From %s\n", m));\
|
|
} \
|
|
LeaveCriticalSection(&SapCardlistCriticalSection); \
|
|
}
|
|
|
|
#endif
|
|
|