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.
2297 lines
60 KiB
2297 lines
60 KiB
/*++
|
|
|
|
Copyright (c) 1989 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
atkinit.c
|
|
|
|
Abstract:
|
|
|
|
This module implements pre-initialization code for atalk on NT
|
|
|
|
Author:
|
|
|
|
Nikhil Kamkolkar (NikhilK) 8-Jun-1992
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "atalknt.h"
|
|
#include "atkinit.h"
|
|
|
|
|
|
//
|
|
// Local functions
|
|
//
|
|
|
|
NTSTATUS
|
|
AtalkInitOpenRegistry(
|
|
IN HANDLE AtalkConfigHandle,
|
|
OUT PHANDLE LinkageHandle,
|
|
OUT PHANDLE ParametersHandle,
|
|
OUT PHANDLE AdaptersKeyHandle
|
|
);
|
|
|
|
VOID
|
|
AtalkInitCloseRegistry(
|
|
IN HANDLE LinkageHandle,
|
|
IN HANDLE ParametersHandle,
|
|
IN HANDLE AdaptersKeyHandle
|
|
);
|
|
|
|
NTSTATUS
|
|
AtalkInitReadLinkageAndAllocSpace(
|
|
IN HANDLE LinkageHandle,
|
|
IN OUT PNDIS_PORTDESCRIPTORS *NdisPortDesc,
|
|
IN OUT PPORT_INFO *PortInfo,
|
|
IN OUT PINT NumberOfPorts);
|
|
|
|
NTSTATUS
|
|
AtalkInitGetDefaultPortDesiredZoneInfo(
|
|
IN HANDLE ParametersHandle,
|
|
IN OUT PNDIS_PORTDESCRIPTORS NdisPortDesc,
|
|
IN INT NumberOfPorts);
|
|
|
|
NTSTATUS
|
|
AtalkInitGetGlobalParms(
|
|
IN HANDLE ParametersHandle,
|
|
IN OUT PGLOBAL_PARMS GlobalParms,
|
|
IN PNDIS_PORTDESCRIPTORS NdisPortDesc,
|
|
IN INT NumberOfPorts);
|
|
|
|
NTSTATUS
|
|
AtalkInitGetPerPortParams(
|
|
IN HANDLE ParametersHandle,
|
|
IN PGLOBAL_PARMS GlobalParms,
|
|
IN PNDIS_PORTDESCRIPTORS NdisPortDesc,
|
|
IN OUT PPORT_INFO PortInformation,
|
|
IN INT NumberOfPorts
|
|
);
|
|
|
|
BOOLEAN
|
|
AtalkInitGetRouterFlag(
|
|
IN HANDLE ParametersHandle);
|
|
|
|
NTSTATUS
|
|
AtalkInitGetNetworkRange(
|
|
IN HANDLE AdapterInfoHandle,
|
|
IN OUT PPORT_INFO PortInformation);
|
|
|
|
NTSTATUS
|
|
AtalkInitGetZoneList(
|
|
IN HANDLE AdapterInfoHandle,
|
|
IN OUT PPORT_INFO PortInformation);
|
|
|
|
NTSTATUS
|
|
AtalkInitGetDefaultZone(
|
|
IN HANDLE AdapterInfoHandle,
|
|
IN OUT PPORT_INFO PortInformation);
|
|
|
|
NTSTATUS
|
|
AtalkInitGetPortName(
|
|
IN HANDLE AdapterInfoHandle,
|
|
IN OUT PPORT_INFO PortInformation);
|
|
|
|
NTSTATUS
|
|
AtalkInitGetDdpChecksumFlag(
|
|
IN HANDLE AdapterInfoHandle,
|
|
IN OUT PPORT_INFO PortInformation);
|
|
|
|
NTSTATUS
|
|
AtalkInitGetAarpRetries(
|
|
IN HANDLE AdapterInfoHandle,
|
|
IN OUT PPORT_INFO PortInformation);
|
|
|
|
VOID
|
|
AtalkInitReleasePortInfo(
|
|
PPORT_INFO *PortInformation);
|
|
|
|
VOID
|
|
AtalkInitReleasePortDesc(
|
|
PNDIS_PORTDESCRIPTORS *NdisPortDesc);
|
|
|
|
VOID
|
|
AtalkInitReleaseGlobalParms(
|
|
IN OUT PGLOBAL_PARMS GlobalParms,
|
|
IN OUT PNDIS_PORTDESCRIPTORS NdisPortDesc,
|
|
IN INT NumberOfPorts);
|
|
|
|
VOID
|
|
AtalkInitReleasePerPortParams(
|
|
IN OUT PNDIS_PORTDESCRIPTORS NdisPortDesc,
|
|
IN OUT PPORT_INFO PortInformation,
|
|
IN INT NumberOfPorts);
|
|
|
|
VOID
|
|
AtalkInitReleaseDefaultPortDesiredZoneInfo(
|
|
IN OUT PNDIS_PORTDESCRIPTORS NdisPortDesc,
|
|
IN INT NumberOfPorts);
|
|
|
|
VOID
|
|
AtalkInitReleaseZoneList(
|
|
IN OUT PPORT_INFO PortInformation);
|
|
|
|
VOID
|
|
AtalkInitReleaseDefaultZone(
|
|
IN OUT PPORT_INFO PortInformation);
|
|
|
|
VOID
|
|
AtalkInitReleasePortName(
|
|
IN OUT PPORT_INFO PortInformation);
|
|
|
|
NTSTATUS
|
|
GetHandleToKey(
|
|
IN HANDLE SectionHandle,
|
|
IN PWSTR KeyNameString,
|
|
OUT PHANDLE KeyHandle);
|
|
|
|
NTSTATUS
|
|
InsertZoneNameInList(
|
|
IN OUT PPORT_INFO PortInformation,
|
|
IN PWCHAR ZoneString);
|
|
|
|
PWSTR
|
|
GetAdapterKey(
|
|
IN PWSTR AdapterName);
|
|
|
|
|
|
//
|
|
// Discardable code after Init time
|
|
//
|
|
|
|
#ifdef ALLOC_PRAGMA
|
|
#pragma alloc_text(init, AtalkInitializeTransport)
|
|
#pragma alloc_text(init, AtalkInitOpenRegistry)
|
|
#pragma alloc_text(init, AtalkInitCloseRegistry)
|
|
#pragma alloc_text(init, AtalkInitReadLinkageAndAllocSpace)
|
|
#pragma alloc_text(init, AtalkInitGetDefaultPortDesiredZoneInfo)
|
|
#pragma alloc_text(init, AtalkInitGetGlobalParms)
|
|
#pragma alloc_text(init, AtalkInitGetPerPortParams)
|
|
#pragma alloc_text(init, AtalkInitGetRouterFlag)
|
|
#pragma alloc_text(init, AtalkInitGetNetworkRange)
|
|
#pragma alloc_text(init, AtalkInitGetZoneList)
|
|
#pragma alloc_text(init, AtalkInitGetDefaultZone)
|
|
#pragma alloc_text(init, AtalkInitGetPortName)
|
|
#pragma alloc_text(init, AtalkInitGetDdpChecksumFlag)
|
|
#pragma alloc_text(init, AtalkInitGetAarpRetries)
|
|
#pragma alloc_text(init, AtalkInitReleasePortInfo)
|
|
#pragma alloc_text(init, AtalkInitReleasePortDesc)
|
|
#pragma alloc_text(init, AtalkInitReleaseGlobalParms)
|
|
#pragma alloc_text(init, AtalkInitReleasePerPortParams)
|
|
#pragma alloc_text(init, AtalkInitReleaseDefaultPortDesiredZoneInfo)
|
|
#pragma alloc_text(init, AtalkInitReleaseZoneList)
|
|
#pragma alloc_text(init, AtalkInitReleaseDefaultZone)
|
|
#pragma alloc_text(init, AtalkInitReleasePortName)
|
|
#pragma alloc_text(init, GetHandleToKey)
|
|
#pragma alloc_text(init, InsertZoneNameInList)
|
|
#pragma alloc_text(init, GetAdapterKey)
|
|
#endif
|
|
|
|
|
|
//
|
|
// Allocate space for the adapter name and copy the adapter name in there
|
|
// Adapter name is of the form \Device\<adapter>
|
|
//
|
|
|
|
#define InsertAdapter(NdisPortDesc, Subscript, Name) \
|
|
{ \
|
|
PWSTR _S; \
|
|
PWSTR _N = (Name); \
|
|
UINT _L = AtalkWstrLength(_N)+sizeof(WCHAR); \
|
|
_S = (PWSTR)AtalkAllocNonPagedMemory( _L); \
|
|
if (_S != NULL) { \
|
|
RtlMoveMemory(_S, _N, _L); \
|
|
RtlInitUnicodeString (&(NdisPortDesc)[Subscript].AdapterName, _S); \
|
|
} \
|
|
}
|
|
|
|
#define RemoveAdapter(NdisPortDesc, Subscript) \
|
|
{ \
|
|
AtalkFreeNonPagedMemory( (NdisPortDesc)[Subscript].AdapterName); \
|
|
(NdisPortDesc)[Subscript].AdapterName = NULL; \
|
|
}
|
|
|
|
//
|
|
// Allocate space for the adapter key and copy the adapter key in there
|
|
// Adapter key is the adapter name, this is used for per-port params/errorlogging
|
|
//
|
|
|
|
#define InsertAdapterKey(NdisPortDesc, Subscript, Name) \
|
|
{ \
|
|
PWSTR _S; \
|
|
PWSTR _N = (Name); \
|
|
UINT _L = AtalkWstrLength(_N)+sizeof(WCHAR); \
|
|
_S = (PWSTR)AtalkAllocNonPagedMemory( _L); \
|
|
if (_S != NULL) { \
|
|
RtlMoveMemory(_S, _N, _L); \
|
|
RtlInitUnicodeString (&(NdisPortDesc)[Subscript].AdapterKey, _S); \
|
|
} \
|
|
}
|
|
|
|
#define RemoveAdapterKey(NdisPortDesc, Subscript) \
|
|
{ \
|
|
AtalkFreeNonPagedMemory( (NdisPortDesc)[Subscript].AdapterKey); \
|
|
(NdisPortDesc)[Subscript].AdapterName = NULL; \
|
|
}
|
|
|
|
//
|
|
// Following are used to keep track of the resources allocated during
|
|
// initialization so they can be freed in case of errors.
|
|
//
|
|
|
|
#define RESOURCE_REGISTRYKEY 0x01
|
|
#define RESOURCE_PARAMKEYS 0x02
|
|
#define RESOURCE_ALLOCPORTDESC 0x04
|
|
#define RESOURCE_REGISTERPROTOCOL 0x08
|
|
#define RESOURCE_BINDTOMACS 0x10
|
|
#define RESOURCE_GLOBALPARAMS 0x20
|
|
#define RESOURCE_PERPORTPARAMS 0x40
|
|
#define RESOURCE_NDISRESOURCES 0x80
|
|
#define RESOURCE_ALLOCPORTINFO 0x100
|
|
|
|
|
|
NTSTATUS
|
|
AtalkInitializeTransport (
|
|
IN PDRIVER_OBJECT DriverObject,
|
|
IN PUNICODE_STRING RegistryPath,
|
|
IN OUT PNDIS_PORTDESCRIPTORS *NdisPortDesc,
|
|
IN OUT PINT NumberOfPorts
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is called during initialization time to
|
|
begin the initialization of the transport.
|
|
|
|
This routine should open the registry and get the
|
|
the binding info. Then it should try to bind to the
|
|
MACs. For all those which succeed, it should then
|
|
initialize the port information structures and call
|
|
the portable stack's initialize() routine
|
|
|
|
Arguments:
|
|
|
|
DriverObject- The driver object passed in by the system
|
|
RegistryPath- Path in the registry where the parameters are stored
|
|
NdisPortDesc- **Ndis port descriptor- space will be allocated and initialized here
|
|
NumberOfPorts- The determined number of ports is returned here
|
|
|
|
Return Value:
|
|
|
|
Status - STATUS_SUCCESS if initialized,
|
|
Appropriate NT error code otherwise
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS status; // Status of various calls
|
|
HANDLE linkageHandle; // Handle to Linkage section
|
|
HANDLE parametersHandle; // Handle to Parameters section
|
|
HANDLE adaptersKeyHandle; // Handle to Adapters section
|
|
HANDLE atalkConfigHandle; // Handle to this service's section
|
|
|
|
ULONG disposition; // Used in ZwCreateFile
|
|
OBJECT_ATTRIBUTES tmpObjectAttributes;
|
|
|
|
UNICODE_STRING protocolRegisterName; // Name for this protocol for NDIS
|
|
GLOBAL_PARMS globalParms; // Global parameters for stack
|
|
INT noSuccessfulBindings; // Number of OpenAdapters successful
|
|
|
|
//
|
|
// Use this flag to remember all the resources we allocated. If there is
|
|
// an error use this to free them all up.
|
|
//
|
|
|
|
ULONG allocatedResources = 0;
|
|
|
|
//
|
|
// The PORT_INFO structure is actually the PortInfo structure of the portable
|
|
// stack. This is defined by the portable code and is passed to the initialize()
|
|
// routine. This will contain all the per-port parameters read for each adapter.
|
|
// The DesiredPort will correspond to the assigned port of NdisPortDesc. The
|
|
// ControllerInfo will not be used. Should be freed after initialize() is called
|
|
//
|
|
|
|
PPORT_INFO PortInformation; // Allocate for NumberOfPorts
|
|
|
|
//
|
|
// Execute not more than once, just allow us to break out in case
|
|
// of error- keep track of all resources allocated- 'jameel idea'
|
|
//
|
|
|
|
do {
|
|
|
|
//
|
|
// Open the registry.
|
|
//
|
|
|
|
InitializeObjectAttributes(
|
|
&tmpObjectAttributes,
|
|
RegistryPath, // name
|
|
OBJ_CASE_INSENSITIVE, // attributes
|
|
NULL, // root
|
|
NULL // security descriptor
|
|
);
|
|
|
|
//
|
|
// Create/open the Appletalk section indicated by RegistryPath
|
|
//
|
|
|
|
status = ZwCreateKey(
|
|
&atalkConfigHandle,
|
|
KEY_WRITE,
|
|
&tmpObjectAttributes,
|
|
0, // title index
|
|
NULL, // class
|
|
0, // create options
|
|
&disposition); // disposition
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
DBGPRINT(ATALK_DEBUG_INIT, DEBUG_LEVEL_ERROR, ("ERROR: Could not open/create ATALK key: %lx\n", status));
|
|
break;
|
|
}
|
|
allocatedResources |= RESOURCE_REGISTRYKEY;
|
|
|
|
//
|
|
// Open the registry keys we expect.
|
|
// *NOTE* Stack will not load if they are not there or they couldn't
|
|
// be opened
|
|
//
|
|
|
|
status = AtalkInitOpenRegistry(
|
|
atalkConfigHandle,
|
|
&linkageHandle,
|
|
¶metersHandle,
|
|
&adaptersKeyHandle);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
DBGPRINT(ATALK_DEBUG_INIT, DEBUG_LEVEL_ERROR, ("ATALK: Could not open the registry keys\n"));
|
|
break;
|
|
}
|
|
allocatedResources |= RESOURCE_PARAMKEYS;
|
|
|
|
//
|
|
// Read in the NDIS binding information (if none is present
|
|
// return with error (BUGBUG- Should be a NO_BINDING kinda error in ntstatus
|
|
//
|
|
// Following will set both the BindNames of the form \Device\<adapter>
|
|
// and the adapter names themselves in NdisPortDesc. The former is used
|
|
// to remember the device name used to bind- is it needed later on? The
|
|
// later is what is needed for logging errors, getting per port parameters
|
|
//
|
|
// It allocates space for the portInfo and NdisPortDesc structures based
|
|
// on the number of bind values (ports).
|
|
//
|
|
|
|
status = AtalkInitReadLinkageAndAllocSpace(
|
|
linkageHandle,
|
|
NdisPortDesc,
|
|
&PortInformation,
|
|
NumberOfPorts);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
DBGPRINT(ATALK_DEBUG_INIT, DEBUG_LEVEL_ERROR, ( "ATALK: AtalkReadLinkageInfo failed %ul\n", status));
|
|
break;
|
|
}
|
|
allocatedResources |= RESOURCE_ALLOCPORTDESC;
|
|
allocatedResources |= RESOURCE_ALLOCPORTINFO;
|
|
|
|
|
|
//
|
|
// Register protocol with NDIS
|
|
//
|
|
|
|
RtlInitUnicodeString(&protocolRegisterName, PROTOCOL_REGISTER_NAME);
|
|
if (!AtalkNdisRegisterProtocol(&protocolRegisterName)) {
|
|
DBGPRINT(ATALK_DEBUG_INIT, DEBUG_LEVEL_ERROR, ( "ATALK: AtalkNdisRegister failed %ul\n", status));
|
|
status = STATUS_UNSUCCESSFUL;
|
|
break;
|
|
}
|
|
allocatedResources |= RESOURCE_REGISTERPROTOCOL;
|
|
|
|
//
|
|
// Bind to MACS
|
|
//
|
|
|
|
noSuccessfulBindings = AtalkNdisBindToMacs(
|
|
*NdisPortDesc,
|
|
*NumberOfPorts);
|
|
|
|
if (noSuccessfulBindings == 0) {
|
|
DBGPRINT(ATALK_DEBUG_INIT, DEBUG_LEVEL_ERROR, ( "ATALK: AtalkNdisBindToMacs failed\n"));
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
break;
|
|
}
|
|
allocatedResources |= RESOURCE_BINDTOMACS;
|
|
|
|
//
|
|
// Get the global parameters
|
|
// The default port will be set in NdisPortDesc
|
|
//
|
|
|
|
status = AtalkInitGetGlobalParms(
|
|
parametersHandle,
|
|
&globalParms,
|
|
*NdisPortDesc,
|
|
*NumberOfPorts);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
DBGPRINT(ATALK_DEBUG_INIT, DEBUG_LEVEL_ERROR, ( "ATALK: AtalkGetGlobalParams failed %ul\n", status));
|
|
break;
|
|
}
|
|
allocatedResources |= RESOURCE_GLOBALPARAMS;
|
|
|
|
if (globalParms.EnableRouter && (noSuccessfulBindings != *NumberOfPorts)) {
|
|
DBGPRINT(ATALK_DEBUG_INIT, DEBUG_LEVEL_ERROR, ("EnableRouter and numberSuccess(%d) != noPorts (%d)\n", noSuccessfulBindings, *NumberOfPorts));
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Get per port parameters for all the cards successfully bound
|
|
// to. This routine also takes as input the global parameters found
|
|
// and set their values in the PortInformation structure as appropriate.
|
|
//
|
|
|
|
status = AtalkInitGetPerPortParams(
|
|
adaptersKeyHandle,
|
|
&globalParms,
|
|
*NdisPortDesc,
|
|
PortInformation,
|
|
*NumberOfPorts);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
DBGPRINT(ATALK_DEBUG_INIT, DEBUG_LEVEL_ERROR, ( "ATALK: AtalkGetPerPort failed %ul\n", status));
|
|
break;
|
|
}
|
|
allocatedResources |= RESOURCE_PERPORTPARAMS;
|
|
|
|
|
|
//
|
|
// Now initialize any global data structures needed
|
|
//
|
|
|
|
status = AtalkNdisInitializeResources(
|
|
*NdisPortDesc,
|
|
*NumberOfPorts);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
DBGPRINT(ATALK_DEBUG_INIT, DEBUG_LEVEL_ERROR, ("NdisInit failed %lx\n", status));
|
|
break;
|
|
}
|
|
allocatedResources |= RESOURCE_NDISRESOURCES;
|
|
|
|
//
|
|
// Now call the stack's Initialize routine
|
|
//
|
|
|
|
if (Initialize(*NumberOfPorts, PortInformation)) {
|
|
|
|
//
|
|
// Close the registry keys
|
|
//
|
|
|
|
AtalkInitCloseRegistry(
|
|
linkageHandle,
|
|
parametersHandle,
|
|
adaptersKeyHandle);
|
|
ZwClose (atalkConfigHandle);
|
|
status = STATUS_SUCCESS;
|
|
|
|
allocatedResources = RESOURCE_PERPORTPARAMS |
|
|
RESOURCE_GLOBALPARAMS |
|
|
RESOURCE_ALLOCPORTINFO |
|
|
RESOURCE_PARAMKEYS |
|
|
RESOURCE_REGISTRYKEY;
|
|
}
|
|
else
|
|
status = STATUS_UNSUCCESSFUL;
|
|
|
|
} while (FALSE);
|
|
|
|
|
|
//
|
|
// Free up all the allocated resources
|
|
//
|
|
|
|
if (status == STATUS_UNSUCCESSFUL) {
|
|
|
|
DbgPrintPortInfo(*NumberOfPorts, PortInformation);
|
|
|
|
DBGPRINT(ATALK_DEBUG_INIT, DEBUG_LEVEL_ERROR,
|
|
("ERROR: STACK UNLOADING- RESOURCES WILL BE FREED!\n"));
|
|
}
|
|
|
|
|
|
if (allocatedResources & RESOURCE_NDISRESOURCES) {
|
|
AtalkNdisReleaseResources(
|
|
*NdisPortDesc,
|
|
*NumberOfPorts);
|
|
}
|
|
|
|
if (allocatedResources & RESOURCE_PERPORTPARAMS) {
|
|
AtalkInitReleasePerPortParams(
|
|
*NdisPortDesc,
|
|
PortInformation,
|
|
*NumberOfPorts);
|
|
}
|
|
|
|
if (allocatedResources & RESOURCE_GLOBALPARAMS) {
|
|
AtalkInitReleaseGlobalParms(
|
|
&globalParms,
|
|
*NdisPortDesc,
|
|
*NumberOfPorts);
|
|
}
|
|
|
|
|
|
if (allocatedResources & RESOURCE_BINDTOMACS) {
|
|
AtalkNdisUnbindFromMacs(
|
|
*NdisPortDesc,
|
|
*NumberOfPorts);
|
|
}
|
|
|
|
if (allocatedResources & RESOURCE_REGISTERPROTOCOL) {
|
|
AtalkNdisDeregisterProtocol();
|
|
}
|
|
|
|
if (allocatedResources & RESOURCE_ALLOCPORTDESC) {
|
|
AtalkInitReleasePortDesc(
|
|
NdisPortDesc);
|
|
}
|
|
|
|
if (allocatedResources & RESOURCE_ALLOCPORTINFO) {
|
|
AtalkInitReleasePortInfo(
|
|
&PortInformation);
|
|
}
|
|
|
|
if (allocatedResources & RESOURCE_PARAMKEYS) {
|
|
AtalkInitCloseRegistry(
|
|
linkageHandle,
|
|
parametersHandle,
|
|
adaptersKeyHandle);
|
|
}
|
|
|
|
if (allocatedResources & RESOURCE_REGISTRYKEY) {
|
|
ZwClose(atalkConfigHandle);
|
|
}
|
|
|
|
|
|
return(status);
|
|
}
|
|
|
|
|
|
|
|
|
|
VOID
|
|
AtalkUnloadStack(
|
|
IN OUT PNDIS_PORTDESCRIPTORS *NdisPortDesc,
|
|
IN OUT PINT NumberOfPorts
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
|
|
{
|
|
AtalkNdisUnbindFromMacs(
|
|
*NdisPortDesc,
|
|
*NumberOfPorts);
|
|
|
|
AtalkNdisDeregisterProtocol();
|
|
|
|
AtalkNdisReleaseResources(
|
|
*NdisPortDesc,
|
|
*NumberOfPorts);
|
|
|
|
//
|
|
// Release the global spinlocks
|
|
//
|
|
|
|
#if DBG
|
|
NdisFreeSpinLock(&AtalkGlobalInterlock);
|
|
#endif
|
|
|
|
NdisFreeSpinLock(&AtalkGlobalRefLock);
|
|
NdisFreeSpinLock(&AtalkGlobalStatLock);
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
|
|
NTSTATUS
|
|
AtalkInitOpenRegistry(
|
|
IN HANDLE AtalkConfigHandle,
|
|
OUT PHANDLE LinkageHandle,
|
|
OUT PHANDLE ParametersHandle,
|
|
OUT PHANDLE AdaptersKeyHandle
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is called by ATALK to open the registry. If the registry
|
|
tree for ATALK exists, then it opens it and returns STATUS_SUCCESS.
|
|
If not, it return error returned by the open call. If even one key cannot
|
|
be opened, then the driver load is aborted. SETUP must *always* have these
|
|
keys in there.
|
|
|
|
Arguments:
|
|
|
|
AtalkConfigHandle- Key to registry tree root for Atalk
|
|
LinkageHandle - Returns the handle used to read linkage information.
|
|
ParametersHandle - Returns the handle used to read other parameters.
|
|
AdaptersKeyHandle- Returns handle for per-adapter values
|
|
|
|
Return Value:
|
|
|
|
The status of the request.
|
|
|
|
--*/
|
|
{
|
|
|
|
NTSTATUS status;
|
|
|
|
//
|
|
// Key names
|
|
//
|
|
|
|
PWSTR linkageString = LINKAGE_STRING;
|
|
PWSTR parametersString = PARAMETERS_STRING;
|
|
PWSTR adaptersKeyString = ADAPTERS_STRING;
|
|
|
|
//
|
|
// Open the linkage key.
|
|
//
|
|
|
|
status = GetHandleToKey(
|
|
AtalkConfigHandle,
|
|
linkageString,
|
|
LinkageHandle);
|
|
|
|
if (NT_SUCCESS(status)) {
|
|
|
|
//
|
|
// Open the parameters key.
|
|
//
|
|
|
|
status = GetHandleToKey(
|
|
AtalkConfigHandle,
|
|
parametersString,
|
|
ParametersHandle);
|
|
|
|
if (NT_SUCCESS(status)) {
|
|
|
|
//
|
|
// Open the adapters key.
|
|
//
|
|
|
|
status = GetHandleToKey(
|
|
AtalkConfigHandle,
|
|
adaptersKeyString,
|
|
AdaptersKeyHandle);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
|
|
DBGPRINT(ATALK_DEBUG_INIT, DEBUG_LEVEL_ERROR, ("ATALK: Could not open adapters key: %lx\n", status));
|
|
|
|
ZwClose(*LinkageHandle);
|
|
ZwClose(*ParametersHandle);
|
|
|
|
}
|
|
} else {
|
|
DBGPRINT(ATALK_DEBUG_INIT, DEBUG_LEVEL_ERROR, ("ATALK: Could not open parameters key: %lx\n", status));
|
|
ZwClose(*LinkageHandle);
|
|
}
|
|
|
|
}
|
|
|
|
return(status);
|
|
|
|
} /* AtalkOpenRegistry */
|
|
|
|
|
|
|
|
|
|
VOID
|
|
AtalkInitCloseRegistry(
|
|
IN HANDLE LinkageHandle,
|
|
IN HANDLE ParametersHandle,
|
|
IN HANDLE AdaptersKeyHandle
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is called by NBF to close the registry. It closes
|
|
the handles passed in and does any other work needed.
|
|
|
|
Arguments:
|
|
|
|
LinkageHandle - The handle used to read linkage information.
|
|
ParametersHandle - The handle used to read other parameters.
|
|
AdaptersKeyHandle- handle for per-adapter values
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
ZwClose (LinkageHandle);
|
|
ZwClose (ParametersHandle);
|
|
ZwClose (AdaptersKeyHandle);
|
|
|
|
} /* AtalkCloseRegistry */
|
|
|
|
|
|
NTSTATUS
|
|
AtalkInitReadLinkageAndAllocSpace(
|
|
HANDLE LinkageHandle,
|
|
PNDIS_PORTDESCRIPTORS *NdisPortDesc,
|
|
PPORT_INFO *PortInformation,
|
|
PINT NumberOfPorts
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Reads the BIND value name and allocates space for that many ports. It
|
|
then copies the bind values into the NdisPortDesc array it allocates.
|
|
|
|
Arguments:
|
|
|
|
LinkageHandle- Handle to the ...\Atalk\Linkage key in registry
|
|
NdisPortDesc- Pointer to array of port descriptors
|
|
PortInformation- Pointer to array of port information structures
|
|
NumberOfPorts- Number of ports specified implicitly by number of bindings
|
|
|
|
Return Value:
|
|
|
|
Status - STATUS_SUCCESS
|
|
STATUS_INSUFFICIENT_RESOURCES
|
|
--*/
|
|
{
|
|
NTSTATUS status;
|
|
UINT configBindings;
|
|
|
|
PWSTR bindName = BIND_STRING;
|
|
UNICODE_STRING bindString;
|
|
|
|
PWSTR curBindValue;
|
|
|
|
ULONG bindStorage[128];
|
|
PKEY_VALUE_FULL_INFORMATION bindValue =
|
|
(PKEY_VALUE_FULL_INFORMATION)bindStorage;
|
|
BOOLEAN allocatedMemory = FALSE;
|
|
|
|
ULONG bytesWritten;
|
|
|
|
//
|
|
// We read the bind parameters out of the registry
|
|
// linkage key.
|
|
//
|
|
|
|
*NumberOfPorts = configBindings = 0;
|
|
|
|
//
|
|
// Read the "Bind" key.
|
|
//
|
|
|
|
RtlInitUnicodeString (&bindString, bindName);
|
|
|
|
status = ZwQueryValueKey(
|
|
LinkageHandle,
|
|
&bindString,
|
|
KeyValueFullInformation,
|
|
bindValue,
|
|
sizeof(bindStorage),
|
|
&bytesWritten
|
|
);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
return(status);
|
|
} else if (status == STATUS_BUFFER_OVERFLOW) {
|
|
|
|
//
|
|
// Allocate space needed and try one more time
|
|
//
|
|
|
|
bindValue = (PKEY_VALUE_FULL_INFORMATION)AtalkAllocNonPagedMemory(bytesWritten);
|
|
if (bindValue == NULL)
|
|
return(STATUS_INSUFFICIENT_RESOURCES);
|
|
|
|
//
|
|
// Remember we allocated memory
|
|
//
|
|
|
|
allocatedMemory = TRUE;
|
|
|
|
status = ZwQueryValueKey(
|
|
LinkageHandle,
|
|
&bindString,
|
|
KeyValueFullInformation,
|
|
bindValue,
|
|
bytesWritten,
|
|
&bytesWritten
|
|
);
|
|
}
|
|
|
|
//
|
|
// At this point, status must be success (explicitly) or else return
|
|
//
|
|
|
|
if (status != STATUS_SUCCESS) {
|
|
if (allocatedMemory) {
|
|
AtalkFreeNonPagedMemory(bindValue);
|
|
}
|
|
return(status);
|
|
}
|
|
|
|
|
|
//
|
|
// For each binding, store the device name in an ndis port desc
|
|
//
|
|
// We go through this loop twice, once to find the number of specified
|
|
// bindings and then to actually get them
|
|
// Any better ideas?
|
|
//
|
|
|
|
curBindValue = (PWCHAR)((PUCHAR)bindValue + bindValue->DataOffset);
|
|
while (*curBindValue != 0) {
|
|
++configBindings;
|
|
|
|
//
|
|
// Now advance the "Bind" value to next device name
|
|
//
|
|
curBindValue = (PWCHAR)((PUCHAR)curBindValue + AtalkWstrLength(curBindValue) + sizeof(WCHAR));
|
|
}
|
|
|
|
DBGPRINT(ATALK_DEBUG_INIT, DEBUG_LEVEL_INFOCLASS0, ( "The Number of ports: %d\n", configBindings));
|
|
|
|
//
|
|
// Check for zero bindings
|
|
//
|
|
|
|
if (allocatedMemory) {
|
|
AtalkFreeNonPagedMemory(bindValue);
|
|
return(STATUS_UNSUCCESSFUL);
|
|
}
|
|
|
|
//
|
|
// Allocate space for the NDIS port descriptors
|
|
//
|
|
|
|
*NdisPortDesc =
|
|
(PNDIS_PORTDESCRIPTORS)AtalkCallocNonPagedMemory(
|
|
configBindings*sizeof(NDIS_PORTDESCRIPTORS),
|
|
sizeof(CHAR));
|
|
|
|
|
|
if (*NdisPortDesc == NULL) {
|
|
if (allocatedMemory) {
|
|
AtalkFreeNonPagedMemory(bindValue);
|
|
}
|
|
return(STATUS_INSUFFICIENT_RESOURCES);
|
|
}
|
|
|
|
//
|
|
// Allocate space for the port information structure
|
|
//
|
|
|
|
*PortInformation =
|
|
(PPORT_INFO)AtalkCallocNonPagedMemory(
|
|
configBindings*sizeof(PORT_INFO),
|
|
sizeof(CHAR));
|
|
|
|
if (*PortInformation == NULL) {
|
|
|
|
AtalkFreeNonPagedMemory(*NdisPortDesc);
|
|
if (allocatedMemory) {
|
|
AtalkFreeNonPagedMemory(bindValue);
|
|
}
|
|
return(STATUS_INSUFFICIENT_RESOURCES);
|
|
}
|
|
|
|
//
|
|
// This time get the bind values and store in the ndis port descriptors
|
|
//
|
|
|
|
*NumberOfPorts = configBindings;
|
|
configBindings = 0;
|
|
|
|
curBindValue = (PWCHAR)((PUCHAR)bindValue + bindValue->DataOffset);
|
|
while (*curBindValue != 0) {
|
|
|
|
//
|
|
// Store the string in the Ndis port descriptor
|
|
//
|
|
|
|
InsertAdapter((*NdisPortDesc), configBindings, curBindValue);
|
|
|
|
//
|
|
// Store the Adapter name alone as the adapter key
|
|
//
|
|
|
|
InsertAdapterKey((*NdisPortDesc), configBindings, GetAdapterKey(curBindValue));
|
|
|
|
(*NdisPortDesc)[configBindings].PortState = STATE_ADAPTER_SPECIFIED;
|
|
|
|
//
|
|
// Now advance the "Bind" value to next device name
|
|
//
|
|
|
|
curBindValue = (PWCHAR)((PUCHAR)curBindValue + AtalkWstrLength(curBindValue) + sizeof(WCHAR));
|
|
configBindings++;
|
|
}
|
|
if (allocatedMemory) {
|
|
AtalkFreeNonPagedMemory(bindValue);
|
|
}
|
|
return(STATUS_SUCCESS);
|
|
}
|
|
|
|
VOID
|
|
AtalkInitReleasePortDesc(
|
|
PNDIS_PORTDESCRIPTORS *NdisPortDesc
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Free up the space allocated
|
|
|
|
Arguments:
|
|
|
|
NdisPortDesc- Pointer to array of port descriptors
|
|
|
|
Return Value:
|
|
|
|
None
|
|
--*/
|
|
{
|
|
if (*NdisPortDesc != NULL) {
|
|
AtalkFreeNonPagedMemory(*NdisPortDesc);
|
|
*NdisPortDesc = NULL;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
VOID
|
|
AtalkInitReleasePortInfo(
|
|
PPORT_INFO *PortInformation
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Free up the space allocated
|
|
|
|
Arguments:
|
|
|
|
PortInformation- Pointer to array of port information structures
|
|
|
|
Return Value:
|
|
|
|
None
|
|
--*/
|
|
{
|
|
if (*PortInformation != NULL) {
|
|
AtalkFreeNonPagedMemory(*PortInformation);
|
|
*PortInformation = NULL;
|
|
}
|
|
return;
|
|
}
|
|
|
|
NTSTATUS
|
|
AtalkInitGetGlobalParms(
|
|
HANDLE ParametersHandle,
|
|
PGLOBAL_PARMS GlobalParms,
|
|
PNDIS_PORTDESCRIPTORS NdisPortDesc,
|
|
INT NumberOfPorts
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Reads the Parameters key to get the values for the DefaultPort, the DesiredZOne
|
|
and the enable router flag
|
|
|
|
Arguments:
|
|
|
|
ParametersHandle- Handle to the ...\Atalk\Parameters key in registry
|
|
GlobalParms- structure containing all the global parms
|
|
NdisPortDesc- Pointer to array of port descriptors
|
|
NumberOfPorts- Number of ports specified implicitly by number of bindings
|
|
|
|
Return Value:
|
|
|
|
Status - STATUS_SUCCESS
|
|
Or other NT status codes
|
|
--*/
|
|
{
|
|
NTSTATUS status;
|
|
|
|
GlobalParms->EnableRouter = AtalkInitGetRouterFlag(ParametersHandle);
|
|
|
|
//
|
|
// Following will get the default port info, set the flag in NdisPortDesc
|
|
// and will then get the desired zone specified and set that also.
|
|
//
|
|
|
|
status = AtalkInitGetDefaultPortDesiredZoneInfo(
|
|
ParametersHandle,
|
|
NdisPortDesc,
|
|
NumberOfPorts);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
DBGPRINT(ATALK_DEBUG_INIT, DEBUG_LEVEL_ERROR, ("ERROR: GetDefaultPort failed in GetGlobal %lx\n", status));
|
|
return(status);
|
|
}
|
|
|
|
return(STATUS_SUCCESS);
|
|
}
|
|
|
|
VOID
|
|
AtalkInitReleaseGlobalParms(
|
|
PGLOBAL_PARMS GlobalParms,
|
|
PNDIS_PORTDESCRIPTORS NdisPortDesc,
|
|
INT NumberOfPorts
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Releases any resources associated with the global parameters
|
|
|
|
Arguments:
|
|
|
|
GlobalParms- structure containing all the global parms
|
|
NdisPortDesc- Pointer to array of port descriptors
|
|
NumberOfPorts- Number of ports specified implicitly by number of bindings
|
|
|
|
Return Value:
|
|
|
|
None
|
|
--*/
|
|
{
|
|
AtalkInitReleaseDefaultPortDesiredZoneInfo(
|
|
NdisPortDesc,
|
|
NumberOfPorts);
|
|
|
|
return;
|
|
}
|
|
|
|
NTSTATUS
|
|
AtalkInitGetPerPortParams(
|
|
HANDLE AdaptersKeyHandle,
|
|
PGLOBAL_PARMS GlobalParms,
|
|
PNDIS_PORTDESCRIPTORS NdisPortDesc,
|
|
PPORT_INFO PortInformation,
|
|
INT NumberOfPorts
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is called during initialization time to get the per port and
|
|
the global parameters in the registry. It will store the per port parameters
|
|
in the port information structures readying them to be passed to the main
|
|
initialize() routine
|
|
|
|
Arguments:
|
|
|
|
AdaptersKeyHandle- Handle to the ...\Atalk\Adapters key in registry
|
|
GlobalPars- Structure holding the global info from the registry
|
|
NdisPortDesc- Pointer to array of port descriptors
|
|
PortInformation- Pointer to array of port information structures
|
|
NumberOfPorts- Number of ports specified implicitly by number of bindings
|
|
|
|
Return Value:
|
|
|
|
Status - STATUS_SUCCESS
|
|
STATUS_INSUFFICIENT_RESOURCES
|
|
--*/
|
|
{
|
|
INT i;
|
|
OBJECT_ATTRIBUTES tmpObjectAttributes;
|
|
HANDLE adapterInfoHandle;
|
|
NTSTATUS status;
|
|
|
|
//
|
|
// Algorithm:
|
|
// For each successfully bound port in NdisPortDesc DO:
|
|
// Set the global values in PortInformation
|
|
// Get the AdapterName from NdisDesc and open the key relative to the
|
|
// AdaptersKey Handle
|
|
// Get the per port parameters for that port
|
|
// END DO:
|
|
//
|
|
|
|
for (i=0; i < NumberOfPorts; i++) {
|
|
|
|
if (NdisPortDesc[i].PortState == STATE_BOUND) {
|
|
|
|
PortInformation[i].desiredPort = NdisPortDesc[i].PortNumber;
|
|
PortInformation[i].portType = GetPortablePortType(NdisPortDesc[i].NdisPortType);
|
|
PortInformation[i].startRouter = PortInformation[i].routingPort = GlobalParms->EnableRouter;
|
|
PortInformation[i].defaultPort = NdisPortDesc[i].IsDefaultPort;
|
|
|
|
//
|
|
// We make a copy of the desired zone. We need to keep all such
|
|
// resources to be different so one copy can be freed without affecting
|
|
// the other.
|
|
//
|
|
|
|
if (PortInformation[i].defaultPort) {
|
|
if (NdisPortDesc[i].DesiredZone != NULL) {
|
|
ULONG size = strlen(NdisPortDesc[i].DesiredZone)+1;
|
|
|
|
PortInformation[i].desiredZone =
|
|
(PCHAR)AtalkAllocNonPagedMemory(size);
|
|
|
|
if (PortInformation[i].desiredZone != NULL) {
|
|
RtlMoveMemory(
|
|
PortInformation[i].desiredZone,
|
|
NdisPortDesc[i].DesiredZone,
|
|
size
|
|
);
|
|
} else {
|
|
|
|
//
|
|
// BUGBUG:
|
|
// Log error- do not load??
|
|
//
|
|
|
|
}
|
|
}
|
|
} else
|
|
PortInformation[i].desiredZone = NdisPortDesc[i].DesiredZone;
|
|
|
|
PortInformation[i].remoteAccessConfigurationInfo = NULL;
|
|
PortInformation[i].controllerInfo = NULL;
|
|
PortInformation[i].controllerInfoSize = 0;
|
|
|
|
//
|
|
// Get the key to the adapter for this port
|
|
//
|
|
|
|
InitializeObjectAttributes(
|
|
&tmpObjectAttributes,
|
|
&NdisPortDesc[i].AdapterKey, // name
|
|
OBJ_CASE_INSENSITIVE, // attributes
|
|
AdaptersKeyHandle, // root
|
|
NULL // security descriptor
|
|
);
|
|
|
|
status = ZwOpenKey(
|
|
&adapterInfoHandle,
|
|
KEY_READ,
|
|
&tmpObjectAttributes);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
DBGPRINT(ATALK_DEBUG_INIT, DEBUG_LEVEL_ERROR, ("ATALK: Could not open adapter key: %lx\n", status));
|
|
DBGPRINT(ATALK_DEBUG_INIT, DEBUG_LEVEL_ERROR, ("ATALK: No per-port parameters for this adapter\n"));
|
|
|
|
//
|
|
// BUGBUG: Set some defaults here- have a defaulting routines
|
|
//
|
|
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Set the PRAM stuff to be zero for now
|
|
//
|
|
|
|
//
|
|
// If we are a router, get the following information
|
|
//
|
|
|
|
|
|
if (GlobalParms->EnableRouter) {
|
|
|
|
//
|
|
// Get the Network range information. Value names are
|
|
// NetworkRangeLowerEnd & NetworkRangeUpperEnd
|
|
//
|
|
|
|
status = AtalkInitGetNetworkRange(adapterInfoHandle, &PortInformation[i]);
|
|
if (!NT_SUCCESS(status)) {
|
|
DBGPRINT(ATALK_DEBUG_INIT, DEBUG_LEVEL_ERROR, ("Could not get network range\n"));
|
|
}
|
|
|
|
|
|
//
|
|
// Get the Zone list information. Value name is
|
|
// ZoneList
|
|
//
|
|
|
|
status = AtalkInitGetZoneList(adapterInfoHandle, &PortInformation[i]);
|
|
if (!NT_SUCCESS(status)) {
|
|
DBGPRINT(ATALK_DEBUG_INIT, DEBUG_LEVEL_ERROR, ("Could not get zone list\n"));
|
|
}
|
|
|
|
|
|
//
|
|
// Get the default zone specification. Value name is
|
|
// DefaultZone
|
|
//
|
|
|
|
status = AtalkInitGetDefaultZone(adapterInfoHandle, &PortInformation[i]);
|
|
if (!NT_SUCCESS(status)) {
|
|
DBGPRINT(ATALK_DEBUG_INIT, DEBUG_LEVEL_ERROR, ("Could not get default zone\n"));
|
|
}
|
|
|
|
} else {
|
|
|
|
//
|
|
// BUGBUG:
|
|
// Set values to NULL
|
|
//
|
|
|
|
}
|
|
|
|
//
|
|
// Get the Port name specification. Value name is
|
|
// PortName
|
|
//
|
|
|
|
status = AtalkInitGetPortName(adapterInfoHandle, &PortInformation[i]);
|
|
if (!NT_SUCCESS(status)) {
|
|
DBGPRINT(ATALK_DEBUG_INIT, DEBUG_LEVEL_ERROR, ("Could not get port name\n"));
|
|
}
|
|
|
|
|
|
//
|
|
// Get the Ddp checksums flag. Value name is
|
|
// DdpChecksums
|
|
//
|
|
|
|
status = AtalkInitGetDdpChecksumFlag(adapterInfoHandle, &PortInformation[i]);
|
|
if (!NT_SUCCESS(status)) {
|
|
DBGPRINT(ATALK_DEBUG_INIT, DEBUG_LEVEL_ERROR, ("Could not get ddp checksum flag\n"));
|
|
}
|
|
|
|
//
|
|
// Get the AARP retries value. Value name is
|
|
// AarpRetries
|
|
//
|
|
|
|
status = AtalkInitGetAarpRetries(adapterInfoHandle, &PortInformation[i]);
|
|
if (!NT_SUCCESS(status)) {
|
|
DBGPRINT(ATALK_DEBUG_INIT, DEBUG_LEVEL_ERROR, ("Could not get aarp retries\n"));
|
|
}
|
|
|
|
//
|
|
// Close the key to this adapter
|
|
//
|
|
|
|
ZwClose (adapterInfoHandle);
|
|
}
|
|
}
|
|
return(STATUS_SUCCESS);
|
|
}
|
|
|
|
|
|
VOID
|
|
AtalkInitReleasePerPortParams(
|
|
PNDIS_PORTDESCRIPTORS NdisPortDesc,
|
|
PPORT_INFO PortInformation,
|
|
INT NumberOfPorts
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Release resources associated with ports
|
|
|
|
Arguments:
|
|
|
|
NdisPortDesc- Pointer to array of port descriptors
|
|
PortInformation- Pointer to array of port information structures
|
|
NumberOfPorts- Number of ports specified implicitly by number of bindings
|
|
|
|
Return Value:
|
|
|
|
NONE
|
|
--*/
|
|
{
|
|
INT i;
|
|
|
|
for (i=0; i < NumberOfPorts; i++) {
|
|
if (NdisPortDesc[i].PortState = STATE_BOUND) {
|
|
|
|
AtalkInitReleaseZoneList(&PortInformation[i]);
|
|
AtalkInitReleaseDefaultZone(&PortInformation[i]);
|
|
AtalkInitReleasePortName(&PortInformation[i]);
|
|
if ((PortInformation[i].defaultPort == TRUE) &&
|
|
(PortInformation[i].desiredZone != NULL)) {
|
|
AtalkFreeNonPagedMemory(PortInformation[i].desiredZone);
|
|
}
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
AtalkInitGetRouterFlag(
|
|
HANDLE ParametersHandle
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Gets the value of the enable router flag from the registry. Sets the
|
|
startRouter value in PortInfo based on this flag.
|
|
|
|
Arguments:
|
|
|
|
ParametersHandle- Handle to the ...\Atalk\Parameters key in registry
|
|
|
|
Return Value:
|
|
|
|
Value of the flag: TRUE/FALSE
|
|
--*/
|
|
{
|
|
|
|
UNICODE_STRING valueName;
|
|
NTSTATUS registryStatus;
|
|
|
|
ULONG bytesWritten;
|
|
PULONG enableRouterFlag;
|
|
|
|
ULONG flagStorage[sizeof(KEY_VALUE_FULL_INFORMATION)];
|
|
PKEY_VALUE_FULL_INFORMATION flagValue =
|
|
(PKEY_VALUE_FULL_INFORMATION)flagStorage;
|
|
|
|
//
|
|
// Read the "EnableRouter" value name
|
|
//
|
|
|
|
RtlInitUnicodeString (&valueName, VALUENAME_ENABLEROUTER);
|
|
registryStatus = ZwQueryValueKey(
|
|
ParametersHandle,
|
|
&valueName,
|
|
KeyValueFullInformation,
|
|
flagValue,
|
|
sizeof(flagStorage),
|
|
&bytesWritten
|
|
);
|
|
|
|
if (registryStatus != STATUS_SUCCESS) {
|
|
if (registryStatus != STATUS_OBJECT_NAME_NOT_FOUND)
|
|
DBGPRINT(ATALK_DEBUG_INIT, DEBUG_LEVEL_ERROR, ("WARNING: Could not query EnableRouter value %lx\n", registryStatus));
|
|
|
|
//
|
|
// return defaults
|
|
//
|
|
|
|
return(FALSE);
|
|
|
|
}
|
|
|
|
enableRouterFlag = (PULONG)((PUCHAR)flagValue + flagValue->DataOffset);
|
|
return ((*enableRouterFlag == 0) ? FALSE : TRUE);
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
AtalkInitGetDefaultPortDesiredZoneInfo(
|
|
HANDLE ParametersHandle,
|
|
PNDIS_PORTDESCRIPTORS NdisPortDesc,
|
|
INT NumberOfPorts
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Gets default port and the desired zone for the default port and sets them
|
|
in the Ndis port descriptors.
|
|
|
|
Arguments:
|
|
|
|
ParametersHandle- Handle to the ...\Atalk\Parameters key in registry
|
|
NdisPortDesc- Pointer to array of port descriptors
|
|
NumberOfPorts- Number of ports specified implicitly by number of bindings
|
|
|
|
Return Value:
|
|
|
|
Status - STATUS_SUCCESS
|
|
STATUS_INSUFFICIENT_RESOURCES
|
|
--*/
|
|
{
|
|
INT i;
|
|
UNICODE_STRING valueName;
|
|
NTSTATUS status;
|
|
ULONG bytesWritten;
|
|
PWCHAR portName;
|
|
|
|
PWCHAR desiredZoneValue;
|
|
PCHAR asciiDesiredZone = NULL;
|
|
|
|
ULONG zoneStorage[MAX_ZONENAMELEN+sizeof(KEY_VALUE_FULL_INFORMATION)];
|
|
PKEY_VALUE_FULL_INFORMATION zoneValue =
|
|
(PKEY_VALUE_FULL_INFORMATION)zoneStorage;
|
|
|
|
ULONG portNameStorage[32+sizeof(KEY_VALUE_FULL_INFORMATION)];
|
|
PKEY_VALUE_FULL_INFORMATION portNameValue =
|
|
(PKEY_VALUE_FULL_INFORMATION)portNameStorage;
|
|
|
|
//
|
|
// Initialize the values
|
|
//
|
|
|
|
for (i=0; i < NumberOfPorts; i++) {
|
|
NdisPortDesc[i].IsDefaultPort = FALSE;
|
|
NdisPortDesc[i].DesiredZone = NULL;
|
|
}
|
|
|
|
//
|
|
// Get the desired zone value in the form an asciiz string
|
|
// When the default port is found, set it
|
|
//
|
|
|
|
RtlInitUnicodeString (&valueName, VALUENAME_DESIREDZONE);
|
|
status = ZwQueryValueKey(
|
|
ParametersHandle,
|
|
&valueName,
|
|
KeyValueFullInformation,
|
|
zoneValue,
|
|
sizeof(zoneStorage),
|
|
&bytesWritten
|
|
);
|
|
|
|
if (status != STATUS_SUCCESS) {
|
|
if (status != STATUS_OBJECT_NAME_NOT_FOUND)
|
|
DBGPRINT(ATALK_DEBUG_INIT, DEBUG_LEVEL_ERROR, ("WARNING: Could not query DesiredZone value %lx\n", status));
|
|
|
|
//
|
|
// BUGBUG
|
|
// log error
|
|
//
|
|
|
|
} else {
|
|
ANSI_STRING ansidesiredZone;
|
|
|
|
desiredZoneValue = (PWCHAR)((PUCHAR)zoneValue + zoneValue->DataOffset);
|
|
if (*desiredZoneValue != 0) {
|
|
|
|
status = GetDuplicateAnsiString(desiredZoneValue, &ansidesiredZone);
|
|
if (!NT_SUCCESS(status)) {
|
|
DBGPRINT(ATALK_DEBUG_INIT, DEBUG_LEVEL_ERROR, ("ERROR: GetDuplicate failed for desired zone\n"));
|
|
return(status);
|
|
}
|
|
asciiDesiredZone = ansidesiredZone.Buffer;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Get the default port value
|
|
// Go through all the ports, compare strings and first match will become
|
|
// default port
|
|
//
|
|
|
|
RtlInitUnicodeString (&valueName, VALUENAME_DEFAULTPORT);
|
|
status = ZwQueryValueKey(
|
|
ParametersHandle,
|
|
&valueName,
|
|
KeyValueFullInformation,
|
|
portNameValue,
|
|
sizeof(portNameStorage),
|
|
&bytesWritten
|
|
);
|
|
|
|
if (status != STATUS_SUCCESS) {
|
|
if (status == STATUS_OBJECT_NAME_NOT_FOUND)
|
|
DBGPRINT(ATALK_DEBUG_INIT, DEBUG_LEVEL_ERROR, ("ERROR: Could not query DefaultPort value %lx\n", status));
|
|
|
|
//
|
|
// No default port keyword specified! ABORT
|
|
//
|
|
|
|
return(STATUS_UNSUCCESSFUL);
|
|
|
|
} else {
|
|
|
|
UNICODE_STRING unicodePortName;
|
|
|
|
portName = (PWCHAR)((PUCHAR)portNameValue + portNameValue->DataOffset);
|
|
if (*portName != 0) {
|
|
RtlInitUnicodeString(&unicodePortName, portName);
|
|
|
|
for (i=0; i < NumberOfPorts; i++) {
|
|
if (RtlEqualUnicodeString(&NdisPortDesc[i].AdapterName, &unicodePortName, TRUE)) {
|
|
NdisPortDesc[i].IsDefaultPort = TRUE;
|
|
NdisPortDesc[i].DesiredZone = asciiDesiredZone;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return(STATUS_SUCCESS);
|
|
}
|
|
|
|
|
|
VOID
|
|
AtalkInitReleaseDefaultPortDesiredZoneInfo(
|
|
PNDIS_PORTDESCRIPTORS NdisPortDesc,
|
|
INT NumberOfPorts
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Release any resoures allocated during the Get routine
|
|
|
|
Arguments:
|
|
|
|
NdisPortDesc- Pointer to array of port descriptors
|
|
NumberOfPorts- Number of ports specified implicitly by number of bindings
|
|
|
|
Return Value:
|
|
|
|
None
|
|
--*/
|
|
{
|
|
INT i;
|
|
|
|
//
|
|
// Free up the buffer allocated for the desired zone
|
|
//
|
|
|
|
for (i=0; i < NumberOfPorts; i++) {
|
|
if (NdisPortDesc[i].IsDefaultPort == TRUE) {
|
|
if (NdisPortDesc[i].DesiredZone != NULL) {
|
|
AtalkFreeNonPagedMemory(NdisPortDesc[i].DesiredZone);
|
|
NdisPortDesc[i].DesiredZone = NULL;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
NTSTATUS
|
|
AtalkInitGetNetworkRange(
|
|
HANDLE AdapterInfoHandle,
|
|
PPORT_INFO PortInformation
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Gets the network range for the port defined by AdapterInfoHandle
|
|
|
|
Arguments:
|
|
|
|
AdapterInfoHandle- Handle to ...Atalk\Adapters\<adapterName>
|
|
PortInformation- Pointer to port information structure for the port
|
|
|
|
Return Value:
|
|
|
|
Status - STATUS_SUCCESS or system call returned status codes
|
|
--*/
|
|
{
|
|
UNICODE_STRING valueName;
|
|
NTSTATUS registryStatus;
|
|
|
|
ULONG bytesWritten;
|
|
PULONG netNumber;
|
|
|
|
ULONG netNumberStorage[sizeof(KEY_VALUE_FULL_INFORMATION)];
|
|
PKEY_VALUE_FULL_INFORMATION netValue =
|
|
(PKEY_VALUE_FULL_INFORMATION)netNumberStorage;
|
|
|
|
//
|
|
// Read the "NetworkRangeLowerEnd" value name
|
|
//
|
|
|
|
RtlInitUnicodeString (&valueName, VALUENAME_NETLOWEREND);
|
|
registryStatus = ZwQueryValueKey(
|
|
AdapterInfoHandle,
|
|
&valueName,
|
|
KeyValueFullInformation,
|
|
netValue,
|
|
sizeof(netNumberStorage),
|
|
&bytesWritten
|
|
);
|
|
|
|
if (registryStatus != STATUS_SUCCESS) {
|
|
if (registryStatus != STATUS_OBJECT_NAME_NOT_FOUND)
|
|
DBGPRINT(ATALK_DEBUG_INIT, DEBUG_LEVEL_ERROR, ("WARNING: Could not query net number value %lx\n", registryStatus));
|
|
|
|
//
|
|
// Set defaults
|
|
//
|
|
|
|
PortInformation->networkRange.firstNetworkNumber = 0;
|
|
PortInformation->networkRange.lastNetworkNumber = 0;
|
|
return(STATUS_SUCCESS);
|
|
|
|
} else {
|
|
|
|
//
|
|
// Set the lower end of the network range
|
|
// Seed router is TRUE as we are seeding
|
|
//
|
|
|
|
PortInformation->seedRouter = TRUE;
|
|
|
|
netNumber = (PULONG)((PUCHAR)netValue + netValue->DataOffset);
|
|
if ((*netNumber < MINIMUM_NETNUMBER) ||
|
|
(*netNumber > MAXIMUM_NETNUMBER)) {
|
|
|
|
DBGPRINT(ATALK_DEBUG_INIT, DEBUG_LEVEL_ERROR, ("ERROR: Invalid network number %lx specified\n", *netNumber));
|
|
return(STATUS_UNSUCCESSFUL);
|
|
}
|
|
PortInformation->networkRange.firstNetworkNumber = (USHORT)(*netNumber);
|
|
|
|
//
|
|
// Get the upper number only if lower was specified
|
|
//
|
|
|
|
RtlInitUnicodeString (&valueName, VALUENAME_NETUPPEREND);
|
|
registryStatus = ZwQueryValueKey(
|
|
AdapterInfoHandle,
|
|
&valueName,
|
|
KeyValueFullInformation,
|
|
netValue,
|
|
sizeof(netNumberStorage),
|
|
&bytesWritten
|
|
);
|
|
|
|
if (registryStatus != STATUS_SUCCESS) {
|
|
if (registryStatus != STATUS_OBJECT_NAME_NOT_FOUND)
|
|
DBGPRINT(ATALK_DEBUG_INIT, DEBUG_LEVEL_ERROR, ("ERROR: Could not query net number value %lx\n", registryStatus));
|
|
|
|
//
|
|
// Do not load if lower end specified but upper end was not
|
|
//
|
|
|
|
return(registryStatus);
|
|
|
|
} else {
|
|
|
|
//
|
|
// Set the upper end of the network range
|
|
//
|
|
|
|
netNumber = (PULONG)((PUCHAR)netValue + netValue->DataOffset);
|
|
if ((*netNumber < MINIMUM_NETNUMBER) ||
|
|
(*netNumber > MAXIMUM_NETNUMBER)) {
|
|
|
|
DBGPRINT(ATALK_DEBUG_INIT, DEBUG_LEVEL_ERROR, ("ERROR: Invalid network number %lx specified\n", *netNumber));
|
|
return(STATUS_UNSUCCESSFUL);
|
|
}
|
|
PortInformation->networkRange.lastNetworkNumber =(USHORT)(*netNumber);
|
|
}
|
|
}
|
|
return(STATUS_SUCCESS);
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
AtalkInitGetZoneList(
|
|
HANDLE AdapterInfoHandle,
|
|
PPORT_INFO PortInformation
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Gets the zone list for the port defined by AdapterInfoHandle
|
|
|
|
Arguments:
|
|
|
|
AdapterInfoHandle- Handle to ...Atalk\Adapters\<adapterName>
|
|
PortInformation- Pointer to port information structure for the port
|
|
|
|
Return Value:
|
|
|
|
Status - STATUS_SUCCESS or system call returned status codes
|
|
--*/
|
|
{
|
|
UNICODE_STRING valueName;
|
|
NTSTATUS status;
|
|
|
|
ULONG bytesWritten;
|
|
PWCHAR curZoneValue;
|
|
|
|
//
|
|
// Anticipate about 10 zones and get space for those, if more then do a
|
|
// dynamic alloc. Note that the below *does not* guarantee 10 zones...
|
|
//
|
|
|
|
WCHAR zoneStorage[10*(MAX_ZONENAMELEN)+sizeof(KEY_VALUE_FULL_INFORMATION)];
|
|
PKEY_VALUE_FULL_INFORMATION zoneValue =
|
|
(PKEY_VALUE_FULL_INFORMATION)zoneStorage;
|
|
BOOLEAN allocatedZoneStorage = FALSE;
|
|
|
|
RtlInitUnicodeString (&valueName, VALUENAME_ZONELIST);
|
|
status = ZwQueryValueKey(
|
|
AdapterInfoHandle,
|
|
&valueName,
|
|
KeyValueFullInformation,
|
|
zoneValue,
|
|
sizeof(zoneStorage),
|
|
&bytesWritten
|
|
);
|
|
|
|
if (status != STATUS_SUCCESS) {
|
|
if (status == STATUS_OBJECT_NAME_NOT_FOUND) {
|
|
|
|
//
|
|
// No zone list value specified
|
|
//
|
|
|
|
DBGPRINT(ATALK_DEBUG_INIT, DEBUG_LEVEL_ERROR, ("WARNING: Could not query ZoneList value %lx\n", status));
|
|
PortInformation->zoneList = NULL;
|
|
return(STATUS_SUCCESS);
|
|
}
|
|
|
|
//
|
|
// If error was a buffer overrun, then allocate space and try again
|
|
//
|
|
zoneValue = (PKEY_VALUE_FULL_INFORMATION)AtalkAllocNonPagedMemory(bytesWritten);
|
|
if (zoneValue == NULL) {
|
|
return(STATUS_INSUFFICIENT_RESOURCES);
|
|
}
|
|
allocatedZoneStorage = TRUE;
|
|
|
|
status = ZwQueryValueKey(
|
|
AdapterInfoHandle,
|
|
&valueName,
|
|
KeyValueFullInformation,
|
|
zoneValue,
|
|
sizeof(zoneStorage),
|
|
&bytesWritten
|
|
);
|
|
}
|
|
|
|
if (status != STATUS_SUCCESS) {
|
|
|
|
//
|
|
// Fatal error, abort load
|
|
//
|
|
|
|
if (allocatedZoneStorage) {
|
|
AtalkFreeNonPagedMemory(zoneValue);
|
|
}
|
|
return(status);
|
|
}
|
|
|
|
//
|
|
// Proceed to get zone list
|
|
//
|
|
|
|
PortInformation->zoneList = NULL;
|
|
curZoneValue = (PWCHAR)((PUCHAR)zoneValue + zoneValue->DataOffset);
|
|
while (*curZoneValue != 0) {
|
|
|
|
//
|
|
// Insert the zone in the list in PortInformation
|
|
//
|
|
|
|
status = InsertZoneNameInList(PortInformation, curZoneValue);
|
|
if (!NT_SUCCESS(status)) {
|
|
DBGPRINT(ATALK_DEBUG_INIT, DEBUG_LEVEL_ERROR, ("ERROR: InsertZoneName failed in GetZoneList %lx\n", status));
|
|
|
|
AtalkInitReleaseZoneList(PortInformation);
|
|
if (allocatedZoneStorage) {
|
|
AtalkFreeNonPagedMemory(zoneValue);
|
|
}
|
|
return(status);
|
|
}
|
|
|
|
//
|
|
// Now advance the "Bind" value to next device name
|
|
//
|
|
curZoneValue = (PWCHAR)((PUCHAR)curZoneValue + AtalkWstrLength(curZoneValue) + sizeof(WCHAR));
|
|
}
|
|
|
|
if (allocatedZoneStorage) {
|
|
AtalkFreeNonPagedMemory(zoneValue);
|
|
}
|
|
return(STATUS_SUCCESS);
|
|
}
|
|
|
|
VOID
|
|
AtalkInitReleaseZoneList(
|
|
PPORT_INFO PortInformation
|
|
)
|
|
{
|
|
PZONELIST zoneList;
|
|
|
|
zoneList = PortInformation->zoneList;
|
|
while (zoneList != NULL) {
|
|
AtalkFreeNonPagedMemory(zoneList->zone);
|
|
zoneList = zoneList->next;
|
|
}
|
|
PortInformation->zoneList = NULL;
|
|
return;
|
|
}
|
|
|
|
NTSTATUS
|
|
AtalkInitGetDefaultZone(
|
|
HANDLE AdapterInfoHandle,
|
|
PPORT_INFO PortInformation
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Gets the default zone for the port defined by AdapterInfoHandle
|
|
|
|
Arguments:
|
|
|
|
AdapterInfoHandle- Handle to ...Atalk\Adapters\<adapterName>
|
|
PortInformation- Pointer to port information structure for the port
|
|
|
|
Return Value:
|
|
|
|
Status - STATUS_SUCCESS or system call returned status codes
|
|
--*/
|
|
{
|
|
UNICODE_STRING valueName;
|
|
NTSTATUS status;
|
|
|
|
ULONG bytesWritten;
|
|
PWCHAR defZoneValue;
|
|
|
|
ULONG zoneStorage[MAX_ZONENAMELEN+sizeof(KEY_VALUE_FULL_INFORMATION)];
|
|
PKEY_VALUE_FULL_INFORMATION zoneValue =
|
|
(PKEY_VALUE_FULL_INFORMATION)zoneStorage;
|
|
|
|
RtlInitUnicodeString (&valueName, VALUENAME_DEFAULTZONE);
|
|
status = ZwQueryValueKey(
|
|
AdapterInfoHandle,
|
|
&valueName,
|
|
KeyValueFullInformation,
|
|
zoneValue,
|
|
sizeof(zoneStorage),
|
|
&bytesWritten
|
|
);
|
|
|
|
PortInformation->defaultZone = NULL;
|
|
if (status != STATUS_SUCCESS) {
|
|
if (status != STATUS_OBJECT_NAME_NOT_FOUND)
|
|
DBGPRINT(ATALK_DEBUG_INIT, DEBUG_LEVEL_ERROR, ("ERROR: Could not query default zone value %lx\n", status));
|
|
|
|
//
|
|
// BUGBUG
|
|
// log error
|
|
//
|
|
|
|
return(STATUS_SUCCESS);
|
|
|
|
} else {
|
|
ANSI_STRING ansiDefZone;
|
|
|
|
defZoneValue = (PWCHAR)((PUCHAR)zoneValue + zoneValue->DataOffset);
|
|
if (*defZoneValue != 0) {
|
|
|
|
status = GetDuplicateAnsiString(defZoneValue, &ansiDefZone);
|
|
if (!NT_SUCCESS(status)) {
|
|
DBGPRINT(ATALK_DEBUG_INIT, DEBUG_LEVEL_ERROR, ("ERROR: GetDuplicate failed in GetDefZone %lx\n", status));
|
|
return(status);
|
|
}
|
|
PortInformation->defaultZone = ansiDefZone.Buffer;
|
|
}
|
|
}
|
|
return(STATUS_SUCCESS);
|
|
}
|
|
|
|
VOID
|
|
AtalkInitReleaseDefaultZone(
|
|
PPORT_INFO PortInformation
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Releases resources allocated in Get
|
|
|
|
Arguments:
|
|
|
|
PortInformation- Pointer to port information structure for the port
|
|
|
|
Return Value:
|
|
|
|
None
|
|
--*/
|
|
{
|
|
if (PortInformation->defaultZone != NULL) {
|
|
AtalkFreeNonPagedMemory(PortInformation->defaultZone);
|
|
PortInformation->defaultZone = NULL;
|
|
}
|
|
return;
|
|
}
|
|
|
|
NTSTATUS
|
|
AtalkInitGetPortName(
|
|
HANDLE AdapterInfoHandle,
|
|
PPORT_INFO PortInformation
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Gets the port name for the port defined by AdapterInfoHandle
|
|
|
|
Arguments:
|
|
|
|
AdapterInfoHandle- Handle to ...Atalk\Adapters\<adapterName>
|
|
PortInformation- Pointer to port information structure for the port
|
|
|
|
Return Value:
|
|
|
|
Status - STATUS_SUCCESS or system call returned status codes
|
|
--*/
|
|
{
|
|
UNICODE_STRING valueName;
|
|
NTSTATUS status;
|
|
|
|
ULONG bytesWritten;
|
|
PWCHAR portName;
|
|
|
|
ULONG portNameStorage[32+sizeof(KEY_VALUE_FULL_INFORMATION)];
|
|
PKEY_VALUE_FULL_INFORMATION portNameValue =
|
|
(PKEY_VALUE_FULL_INFORMATION)portNameStorage;
|
|
|
|
RtlInitUnicodeString (&valueName, VALUENAME_PORTNAME);
|
|
|
|
status = ZwQueryValueKey(
|
|
AdapterInfoHandle,
|
|
&valueName,
|
|
KeyValueFullInformation,
|
|
portNameValue,
|
|
sizeof(portNameStorage),
|
|
&bytesWritten
|
|
);
|
|
|
|
PortInformation->portName = NULL;
|
|
if (status != STATUS_SUCCESS) {
|
|
if (status != STATUS_OBJECT_NAME_NOT_FOUND)
|
|
DBGPRINT(ATALK_DEBUG_INIT, DEBUG_LEVEL_ERROR, ("WARNING: Could not query portName value %lx\n", status));
|
|
|
|
//
|
|
// BUGBUG: Log error about invalid port name if read failed
|
|
//
|
|
|
|
return(STATUS_SUCCESS);
|
|
|
|
} else {
|
|
ANSI_STRING ansiPortName;
|
|
|
|
portName = (PWCHAR)((PUCHAR)portNameValue + portNameValue->DataOffset);
|
|
if (*portName != 0) {
|
|
|
|
status = GetDuplicateAnsiString(portName, &ansiPortName);
|
|
if (!NT_SUCCESS(status)) {
|
|
DBGPRINT(ATALK_DEBUG_INIT, DEBUG_LEVEL_ERROR, ("ERROR: GetDuplicate failed in GetDefZone %lx\n", status));
|
|
return(status);
|
|
}
|
|
PortInformation->portName = ansiPortName.Buffer;
|
|
}
|
|
}
|
|
return(STATUS_SUCCESS);
|
|
}
|
|
|
|
VOID
|
|
AtalkInitReleasePortName(
|
|
PPORT_INFO PortInformation
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Release resources allocated in Get
|
|
|
|
Arguments:
|
|
|
|
PortInformation- Pointer to port information structure for the port
|
|
|
|
Return Value:
|
|
|
|
None
|
|
--*/
|
|
{
|
|
if (PortInformation->portName != NULL) {
|
|
AtalkFreeNonPagedMemory(PortInformation->portName);
|
|
PortInformation->portName = NULL;
|
|
}
|
|
return;
|
|
}
|
|
|
|
NTSTATUS
|
|
AtalkInitGetDdpChecksumFlag(
|
|
HANDLE AdapterInfoHandle,
|
|
PPORT_INFO PortInformation
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Gets the ddp checksum flag for the port defined by AdapterInfoHandle
|
|
|
|
Arguments:
|
|
|
|
AdapterInfoHandle- Handle to ...Atalk\Adapters\<adapterName>
|
|
PortInformation- Pointer to port information structure for the port
|
|
|
|
Return Value:
|
|
|
|
Status - STATUS_SUCCESS or system call returned status codes
|
|
--*/
|
|
{
|
|
UNICODE_STRING valueName;
|
|
NTSTATUS status;
|
|
|
|
ULONG bytesWritten;
|
|
PULONG ddpChecksumFlag;
|
|
|
|
ULONG flagStorage[sizeof(KEY_VALUE_FULL_INFORMATION)];
|
|
PKEY_VALUE_FULL_INFORMATION flagValue =
|
|
(PKEY_VALUE_FULL_INFORMATION)flagStorage;
|
|
|
|
//
|
|
// Read the "DdpChecksums" value name
|
|
//
|
|
|
|
RtlInitUnicodeString (&valueName, VALUENAME_DDPCHECKSUMS);
|
|
status = ZwQueryValueKey(
|
|
AdapterInfoHandle,
|
|
&valueName,
|
|
KeyValueFullInformation,
|
|
flagValue,
|
|
sizeof(flagStorage),
|
|
&bytesWritten
|
|
);
|
|
|
|
if (status != STATUS_SUCCESS) {
|
|
if (status != STATUS_OBJECT_NAME_NOT_FOUND)
|
|
DBGPRINT(ATALK_DEBUG_INIT, DEBUG_LEVEL_ERROR, ("ATALK: Could not query checksum value %lx\n", status));
|
|
|
|
//
|
|
// Set defaults
|
|
//
|
|
|
|
PortInformation->sendDdpChecksums = FALSE;
|
|
return(STATUS_SUCCESS);
|
|
|
|
} else {
|
|
ddpChecksumFlag = (PULONG)((PUCHAR)flagValue + flagValue->DataOffset);
|
|
PortInformation->sendDdpChecksums = ((*ddpChecksumFlag == 0) ? FALSE : TRUE);
|
|
}
|
|
return(STATUS_SUCCESS);
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
AtalkInitGetAarpRetries(
|
|
HANDLE AdapterInfoHandle,
|
|
PPORT_INFO PortInformation
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Gets the aarp retries values for the port defined by AdapterInfoHandle
|
|
|
|
Arguments:
|
|
|
|
AdapterInfoHandle- Handle to ...Atalk\Adapters\<adapterName>
|
|
PortInformation- Pointer to port information structure for the port
|
|
|
|
Return Value:
|
|
|
|
Status - STATUS_SUCCESS or system call returned status codes
|
|
--*/
|
|
{
|
|
|
|
UNICODE_STRING valueName;
|
|
NTSTATUS status;
|
|
|
|
ULONG bytesWritten;
|
|
PULONG aarpRetries;
|
|
|
|
ULONG retriesStorage[sizeof(KEY_VALUE_FULL_INFORMATION)];
|
|
PKEY_VALUE_FULL_INFORMATION retriesValue =
|
|
(PKEY_VALUE_FULL_INFORMATION)retriesStorage;
|
|
|
|
//
|
|
// Read the "AarpRetries" value name
|
|
//
|
|
|
|
RtlInitUnicodeString (&valueName, VALUENAME_AARPRETRIES);
|
|
status = ZwQueryValueKey(
|
|
AdapterInfoHandle,
|
|
&valueName,
|
|
KeyValueFullInformation,
|
|
retriesValue,
|
|
sizeof(retriesStorage),
|
|
&bytesWritten
|
|
);
|
|
|
|
if (status != STATUS_SUCCESS) {
|
|
if (status != STATUS_OBJECT_NAME_NOT_FOUND)
|
|
DBGPRINT(ATALK_DEBUG_INIT, DEBUG_LEVEL_ERROR, ("ATALK: Could not query bind value %lx\n", status));
|
|
|
|
//
|
|
// Set defaults (stack will default the value BUGBUG make sure)
|
|
//
|
|
|
|
PortInformation->aarpProbes = 0;
|
|
return(STATUS_SUCCESS);
|
|
|
|
} else {
|
|
aarpRetries = (PULONG)((PUCHAR)retriesValue + retriesValue->DataOffset);
|
|
PortInformation->aarpProbes = (USHORT)*aarpRetries;
|
|
}
|
|
return(STATUS_SUCCESS);
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
InsertZoneNameInList(
|
|
PPORT_INFO PortInformation,
|
|
PWCHAR ZoneString
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Inserts the zone name in ANSI/ASCIIZ form in the PortInfo structure
|
|
|
|
Arguments:
|
|
|
|
PortInformation- Pointer to port information structure
|
|
ZoneString- Word character zone name string
|
|
|
|
Return Value:
|
|
|
|
Status - STATUS_SUCCESS
|
|
STATUS_INSUFFICIENT_RESOURCES
|
|
--*/
|
|
{
|
|
NTSTATUS status;
|
|
ANSI_STRING ansiZoneName;
|
|
|
|
// Portable zonelist structure
|
|
PZONELIST zoneListNode;
|
|
|
|
status = GetDuplicateAnsiString(ZoneString, &ansiZoneName);
|
|
if (!NT_SUCCESS(status)) {
|
|
return(status);
|
|
}
|
|
|
|
//DBGPRINT(ATALK_DEBUG_INIT, DEBUG_LEVEL_INFOCLASS0, ( "Zone Name is %s\n", ansiZoneName.Buffer));
|
|
|
|
//
|
|
// Store the string as the zone name in PortInformation
|
|
//
|
|
|
|
zoneListNode = (PZONELIST)AtalkAllocNonPagedMemory( sizeof(ZONELIST));
|
|
if (zoneListNode == NULL) {
|
|
return(STATUS_INSUFFICIENT_RESOURCES);
|
|
}
|
|
|
|
zoneListNode->zone = ansiZoneName.Buffer;
|
|
zoneListNode->next = NULL;
|
|
|
|
if (PortInformation->zoneList != NULL)
|
|
zoneListNode->next = PortInformation->zoneList;
|
|
|
|
PortInformation->zoneList = zoneListNode;
|
|
return(STATUS_SUCCESS);
|
|
}
|
|
|
|
NTSTATUS
|
|
GetHandleToKey(
|
|
HANDLE SectionHandle,
|
|
PWSTR KeyNameString,
|
|
PHANDLE KeyHandle
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Returns the handle for the key specified using SectionHandle as the
|
|
root.
|
|
|
|
Arguments:
|
|
|
|
SectionHandle - Key to registry tree root
|
|
KeyNameString - name of key to be opened
|
|
KeyHandle - Returns the handle for KeyNameString
|
|
|
|
Return Value:
|
|
|
|
The status of the request.
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS status;
|
|
HANDLE tmpKeyHandle;
|
|
|
|
UNICODE_STRING keyName;
|
|
OBJECT_ATTRIBUTES tmpObjectAttributes;
|
|
|
|
RtlInitUnicodeString (&keyName, KeyNameString);
|
|
InitializeObjectAttributes(
|
|
&tmpObjectAttributes,
|
|
&keyName, // name
|
|
OBJ_CASE_INSENSITIVE, // attributes
|
|
SectionHandle, // root
|
|
NULL // security descriptor
|
|
);
|
|
|
|
status = ZwOpenKey(
|
|
&tmpKeyHandle,
|
|
KEY_READ,
|
|
&tmpObjectAttributes);
|
|
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
DBGPRINT(ATALK_DEBUG_INIT, DEBUG_LEVEL_ERROR, ("ATALK: Could not open key: %lx\n", status));
|
|
return status;
|
|
}
|
|
|
|
*KeyHandle = tmpKeyHandle;
|
|
return(STATUS_SUCCESS);
|
|
}
|
|
|
|
//
|
|
// Return a pointer to the Adapter key, given the Adapter name
|
|
// BUGBUG: What if assumed prefix is missing? this will access fault.
|
|
//
|
|
|
|
PWSTR
|
|
GetAdapterKey(
|
|
PWSTR AdapterName)
|
|
{
|
|
PWCHAR prefix = L"\\Device\\";
|
|
|
|
#if 0
|
|
DbgPrintWString((PWSTR)((PUCHAR)AdapterName+AtalkWstrLength(prefix)));
|
|
DbgPrintNewLine();
|
|
#endif
|
|
|
|
return((PWSTR)((PUCHAR)AdapterName + AtalkWstrLength(prefix)));
|
|
}
|