Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

435 lines
10 KiB

/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
atalk.c
Abstract:
This module is the main file for the portable code. It contains the globals
for the portable stack and the ref/deref code for it
Notes:
LOCKS:
The portable stack uses the following locks for all its critical section
requirements. There are no locks within any structures. Only these locks
will be used even for per-structure critical sections.
GLOBAL_STACK
This lock provides critical sections over the whole stack. Used for
referencing/dereferencing stack usage.
GLOBAL_DDP
This lock provides critical sections for the ddp structures and module.
It protects the following structures-
OPEN_SOCKET
ACTIVE_NODE
PORT_DESCRIPTOR
GLOBAL_ROUTING
This lock provides safety for all structures/operations associated
with routing, and hence is used in rtmp/zip/nbp modules.
GLOBAL_ATP
GLOBAL_RTMP
GLOBAL_AEP
GLOBAL_NBP
GLOBAL_AURP
GLOBAL_ARAP
GLOBAL_ADSP
GLOBAL_ASP
GLOBAL_PAP
The reference/dereference routines have the following semantics due to this
paradigm.
AtalkRefXXX must always be called from within a critical section. It is
upto the caller to ensure this happens.
AtalkDerefX must always be called from *outside* a critical section. It
is upto the caller to ensure this happens. Note that the
dereference functionality will most probably lead to a lot
of activity some of which may try to acquire the same locks
as Deref does. Also, deref does a lot more work than ref.
Hence, it must be outside a critical section.
Author:
Nikhil Kamkolkar Initial Coding
Revision History:
--*/
#define GLOBALS
#include "atalk.h"
VOID
UnloadAppleTalk(
UNLOAD_COMPLETION *CompletionRoutine,
PVOID Context
)
{
int index;
//
// Stop all new AppleTalk activity (geting nodes, opening sockets, starting
// timers, etc.)
//
if (!AtalkReferenceStack(__LINE__ | __INITIAL__) {
// We must already be unloading
return;
}
EnterCriticalSection(GLOBAL_STACK);
if (AppletalkRunning) {
AppletalkRunning = FALSE;
UnloadCompletion = CompletionRoutine;
UnloadContext = Context;
}
LeaveCriticalSection(GLOBAL_STACK);
// Stop timer handling.
StopTimerHandling();
// Force the shutdown of all ports.
for (index = 0; index < NumberOfPortsAllocated; index += 1)
if (GET_PORTDESCRIPTOR(index)->Flags & PD_ACTIVE)
ShutdownPort(index, True);
//
// Let the various protocol levels know that they need to restart timers
// when we get started again.
//
ShutdownErrorLogging();
ShutdownAarp();
ShutdownRtmpStub();
#if Iam an AppleTalkRouter
ShutdownFullRtmp();
ShutdownFullZip();
#endif
#if Iam an AppleTalkStack
ShutdownAsp();
#endif
// Free the routing tables and the best-routes cache.
#if Iam an AppleTalkRouter
ReleaseRoutingTable();
#endif
#if ArapIncluded
ShutdownArap();
desdone();
#endif
//
// All set... the next call to Initialize() will bring everything back up
// again.
//
AtalkDereferenceStack(__INITIAL__ | __LINE__ ); // Temporary reference
AtalkDereferenceStack(__INITIAL__ | __LINE__ ); // Creation reference
return;
} // UnloadAppleTalk
VOID
AtalkRefStack(
VOID
)
{
ASSERT(AtalkReferenceCount >= 0);
AtalkReferenceCount++;
return;
}
VOID
AtalkDerefStack(
VOID
)
{
EnterCriticalSection(GLOBAL_STACK);
ASSERT(AtalkReferenceCount > 0);
do {
if (--AtalkReferenceCount) {
LeaveCriticalSection(GLOBAL_STACK);
break;
}
LeaveCriticalSection(GLOBAL_STACK);
// No more references to the stack, call unload completion
if (AtalkUnloadComplete) {
(*AtalkUnloadComplete)(UnloadCompleteContext);
}
break;
} while (FALSE);
return;
}
BOOLEAN
AtalkVerifyStack(
ULONG Location
)
{
ASSERT(AtalkReferenceCount >= 0);
if (AppletalkRunning) {
OpenSocket->ReferenceCount++;
}
return(AppletalkRunning);
}
BOOLEAN
AtalkVerifyStackInterlocked(
ULONG Location
)
{
BOOLEAN result;
EnterCriticalSection(GLOBAL_STACK);
result = AtalkVerifyStack(Location);
LeaveCriticalSection(GLOBAL_STACK);
return(result);
}
BOOLEAN
ShutdownPort(
int Port,
BOOLEAN Force
)
{
AddressMappingNode addressMappingNode, nextAddressMappingNode;
int index;
//
// If we're a stack, not just a router, we can't allow the default port
// to be stopped. Also, we can't shutdown if we're the default port and
// there are any currently active remote access ports... we're where the
// proxy nodes live.
//
#if Iam an AppleTalkStack
if (not force && GET_PORTDESCRIPTOR(Port)->DefaultPort) {
ErrorLog("ShutdownPort", ISevError, __LINE__, port,
IErrInitialShutdownDefault, IMsgInitialShutdownDefault,
Insert0());
return(False);
}
#endif
if (not force && GET_PORTDESCRIPTOR(Port)->DefaultPort)
for (index = 0; index < NumberOfPortsAllocated; index += 1)
if (GET_PORTDESCRIPTOR(index)->PortType is AppleTalkRemoteAccess and
GET_PORTDESCRIPTOR(index)->Flags & PD_ACTIVE) {
ErrorLog("ShutdownPort", ISevError, __LINE__, port,
IErrInitialShutdownDefault, IMsgInitialShutdownDefault,
Insert0());
return(False);
}
//
// Do all that we need to stop the operation of a specified port (a slot
// in the portDescriptors table). Free all memory that we can, and mark
// the slot as inactive.
//
if (not GET_PORTDESCRIPTOR(Port)->Flags & PD_ACTIVE)
return(False); // Already not operating.
// Stop routing, if needed.
#if Iam an AppleTalkRouter
if (GET_PORTDESCRIPTOR(Port)->RoutingPort and
GET_PORTDESCRIPTOR(Port)->SeenRouterRecently)
RemoveFromRoutingTable(GET_PORTDESCRIPTOR(Port)->ThisCableRange);
if (GET_PORTDESCRIPTOR(Port)->RoutingPort and
GET_PORTDESCRIPTOR(Port)->RouterRunning)
if (not StopRouterOnPort(port))
return(False);
#endif
//
// Free all of our remaining nodes. This loop will stop when we've freed
// 'em all (they will get removed from the head of the list). This will
// inturn close of the open sockets and signal this actual up the stack,
// as needed. If we're a remote access port, just free the single proxy
// node! If we're the default port and shutting down proxy nodes for remote
// access ports, shutdown the remote access port (that will inturn cause
// the proxy node to be freed.
//
if (GET_PORTDESCRIPTOR(Port)->PortType is AppleTalkRemoteAccess) {
#if ArapIncluded
TeardownConnection(port);
#endif
ReleaseNodeOnPort(GET_PORTDESCRIPTOR(Port)->RemoteAccessInfo->proxyPort,
GET_PORTDESCRIPTOR(Port)->RemoteAccessInfo->proxyNode->
extendedNode);
Free(GET_PORTDESCRIPTOR(Port)->RemoteAccessInfo);
}
else
while (GET_PORTDESCRIPTOR(Port)->ActiveNodes != Empty)
if (GET_PORTDESCRIPTOR(Port)->ActiveNodes->proxyNode)
ShutdownPort(GET_PORTDESCRIPTOR(Port)->ActiveNodes->proxyPort, force);
else
ReleaseNodeOnPort(port,
GET_PORTDESCRIPTOR(Port)->ActiveNodes->extendedNode);
// Don't be bothered while we're playing with in-memory structures.
DeferTimerChecking();
DeferIncomingPackets();
// Okay, free all the memory used by this port's structures.
FreeZoneList(GET_PORTDESCRIPTOR(Port)->InitialZoneList);
#if Iam an AppleTalkRouter
FreeZoneList(GET_PORTDESCRIPTOR(Port)->ThisZoneList);
#endif
#if (IamNot a DOS) && (IamNot an OS2)
if (GET_PORTDESCRIPTOR(Port)->ControllerInfo != Empty)
Free(GET_PORTDESCRIPTOR(Port)->ControllerInfo);
#endif
// Okay, now free all address mapping table chains.
for (index = 0; index < NumberOfAddressMapHashBuckets; index += 1)
for (addressMappingNode = GET_PORTDESCRIPTOR(Port)->AddressMappingTable[index];
addressMappingNode != Empty;
addressMappingNode = nextAddressMappingNode) {
nextAddressMappingNode = addressMappingNode->next;
Free(addressMappingNode);
}
// All set
GET_PORTDESCRIPTOR(Port)->Flags & PD_ACTIVE = False;
HandleIncomingPackets();
HandleDeferredTimerChecks();
return(True);
} // ShutdownPort
VOID
AtalkRefPortDescriptor(
PPORT_DESCRIPTOR PortDescriptor
)
{
ASSERT(PortDescriptor->ReferenceCount >= 0);
PortDescriptor->ReferenceCount++;
return;
}
PPORT_DESCRIPTOR
AtalkVerifyPortDescriptor(
PPORT_DESCRIPTOR PortDescriptor,
ULONG Location
)
{
PPORT_DESCRIPTOR portDesc = PortDescriptor;
ASSERT(PortDescriptor->ReferenceCount >= 0);
if ((PortDescriptor->Flags & PD_CLOSING) == 0) {
AtalkReferencePortDescriptor(PortDescriptor, Location);
} else {
portDesc = NULL;
}
return(portDesc);
}
PPORT_DESCRIPTOR
AtalkVerifyPortDescriptorInterlocked(
PPORT_DESCRIPTOR PortDescriptor,
ULONG Location
)
{
PPORT_DESCRIPTOR portDesc = PortDescriptor;
EnterCriticalSection(GLOBAL_DDP);
ASSERT(PortDescriptor->ReferenceCount >= 0);
if ((PortDescriptor->Flags & PD_CLOSING) == 0) {
AtalkReferencePortDescriptor(PortDescriptor, Location);
} else {
portDesc = NULL;
}
LeaveCriticalSection(GLOBAL_DDP);
return(portDesc);
}
VOID
AtalkDerefPortDescriptor(
PPORT_DESCRIPTOR PortDescriptor
)
{
EnterCriticalSection(GLOBAL_DDP);
ASSERT(PortDescriptor->ReferenceCount > 0);
if (--PortDescriptor->ReferenceCount > 0) {
LeaveCriticalSection(GLOBAL_DDP);
return;
}
// No more references on this port, shutdown port is complete
ASSERT(PortDescriptor->Flags & PD_CLOSING);
if ((PortDescriptor->Flags & PD_CLOSING) == 0) {
LeaveCriticalSection(GLOBAL_DDP);
INTERNAL_ERROR(__LINE__ | __INITIAL__, PortDescriptor->Flags, NULL, 0);
return;
}
PortDescriptor->Flags = 0;
LeaveCriticalSection(GLOBAL_DDP);
FreeZoneList(PortDescriptor->ZoneList);
// Dereference the stack for this port
AtalkDereferenceStack(__INITIAL__ | __LINE__);
return;
}