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.
 
 
 
 
 
 

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,
&parametersHandle,
&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)));
}