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.
 
 
 
 
 
 

723 lines
16 KiB

/*++
Copyright (c) 1989 Microsoft Corporation
Module Name:
atkutils.c
Abstract:
This module contains utility routines for windows nt implementation of stack
Author:
Nikhil Kamkolkar (NikhilK) 28-Jun-1992
Revision History:
--*/
#include "atalknt.h"
UINT
AtalkWstrLength(
IN PWSTR Wstr
)
/*++
Routine Description:
Returns the length of null-terminated word string
Arguments:
Wstr - the word-string whose length is to be determined
Return Value:
Length of the string
--*/
{
UINT Length = 0;
while (*Wstr++) {
Length += sizeof(WCHAR);
}
return Length;
}
NTSTATUS
AtalkGetProtocolSocketType(
PATALK_DEVICE_CONTEXT Context,
PUNICODE_STRING RemainingFileName,
PUCHAR ProtocolType,
PUCHAR SocketType
)
{
NTSTATUS status = STATUS_SUCCESS;
ULONG protocolType;
UNICODE_STRING typeString;
*ProtocolType = PROTOCOL_TYPE_UNDEFINED;
*SocketType = SOCKET_TYPE_UNDEFINED;
switch (Context->DeviceType) {
case ATALK_DEVICE_DDP :
if ((UINT)RemainingFileName->Length <= AtalkWstrLength(PROTOCOLTYPE_PREFIX)){
status = STATUS_NO_SUCH_DEVICE;
break;
}
RtlInitUnicodeString(
&typeString,
(PWCHAR)((PCHAR)RemainingFileName->Buffer +
AtalkWstrLength(PROTOCOLTYPE_PREFIX)));
status = AtalkUnicodeStringToInteger(
&typeString,
DECIMAL_BASE, // Decimal base
&protocolType);
if (NT_SUCCESS(status)) {
DBGPRINT(ATALK_DEBUG_CREATE, DEBUG_LEVEL_INFOCLASS0,
("INFO0: AtalkGetProtocolType - protocol type is %lx\n", protocolType));
if ((protocolType > DDPPROTO_DDP) && (protocolType <= DDPPROTO_MAX)) {
*ProtocolType = (UCHAR)protocolType;
} else {
status = STATUS_NO_SUCH_DEVICE;
}
}
break;
case ATALK_DEVICE_ADSP :
//
// Check for the socket type
//
if (RemainingFileName->Length == 0) {
*SocketType = SOCKET_TYPE_RDM;
break;
}
if ((UINT)RemainingFileName->Length != AtalkWstrLength(SOCKETSTREAM_SUFFIX)){
status = STATUS_NO_SUCH_DEVICE;
break;
}
RtlInitUnicodeString(
&typeString,
SOCKETSTREAM_SUFFIX);
//
// Case insensitive compare
//
if (RtlEqualUnicodeString(&
typeString,
RemainingFileName,
TRUE)) {
*SocketType = SOCKET_TYPE_STREAM;
break;
} else {
status = STATUS_NO_SUCH_DEVICE;
break;
}
case ATALK_DEVICE_ATP :
case ATALK_DEVICE_ASP :
case ATALK_DEVICE_PAP :
break;
default:
status = STATUS_NO_SUCH_DEVICE;
break;
}
return(status);
}
NTSTATUS
AtalkUnicodeStringToInteger (
IN PUNICODE_STRING String,
IN ULONG Base OPTIONAL,
OUT PULONG Value
)
{
NTSTATUS Status;
UCHAR ResultBuffer[ 36 ];
ANSI_STRING AnsiString;
UNICODE_STRING UnicodeString;
UnicodeString = *String;
if (UnicodeString.Length >= (sizeof( ResultBuffer ) * sizeof( WCHAR ))) {
UnicodeString.Length = ((sizeof( ResultBuffer )-1) * sizeof( WCHAR ));
}
AnsiString.Buffer = ResultBuffer;
AnsiString.MaximumLength = sizeof( ResultBuffer );
AnsiString.Length = 0;
Status = RtlUnicodeStringToAnsiString( &AnsiString, &UnicodeString, FALSE );
if (NT_SUCCESS( Status )) {
AnsiString.Buffer[ AnsiString.Length ] = '\0';
Status = RtlCharToInteger( AnsiString.Buffer, Base, Value );
}
return( Status );
}
NTSTATUS
GetDuplicateAnsiString(
PWCHAR SourceString,
PANSI_STRING AnsiString
)
/*++
Routine Description:
Duplicates the string as an AnsiString.
Arguments:
SourceString - Null terminated word string
AnsiString - Pointer to the AnsiString structure where the created string
is to be returned.
Return Value:
STATUS_SUCCESS - if created ok
Error status if not.
--*/
{
UNICODE_STRING unicodeString;
ULONG ansiSize;
NTSTATUS status;
RtlInitUnicodeString(&unicodeString, SourceString);
ansiSize = RtlUnicodeStringToAnsiSize(&unicodeString);
AnsiString->Buffer = (PCHAR)AtalkAllocNonPagedMemory( ansiSize+1);
if (AnsiString->Buffer == NULL) {
DBGPRINT(ATALK_DEBUG_RESOURCES, DEBUG_LEVEL_ERROR, ("GetDuplicateAnsiString: Allocate Memory failed! %lx\n", ansiSize+1));
return(STATUS_INSUFFICIENT_RESOURCES);
}
AnsiString->MaximumLength = (USHORT)ansiSize+2;
AnsiString->Length = 0;
status = RtlUnicodeStringToAnsiString(AnsiString, &unicodeString, (BOOLEAN)FALSE);
if (status != STATUS_SUCCESS) {
DBGPRINT(ATALK_DEBUG_SYSTEM, DEBUG_LEVEL_ERROR, ("Unicode to ansi failed %d\n", status));
}
return(status);
}
INT
IrpGetEaCreateType(
IN PIRP Irp
)
/*++
Routine Description:
Checks the EA name and returns the appropriate open type.
Arguments:
Irp - the irp for the create request, the EA value is stored in the
SystemBuffer
Return Value:
TDI_TRANSPORT_ADDRESS_FILE: Create irp was for a transport address
TDI_CONNECTION_FILE: Create irp was for a connection object
ATALK_FILE_TYPE_CONTROL: Create irp was for a control channel (ea = NULL)
--*/
{
PFILE_FULL_EA_INFORMATION openType;
BOOLEAN found;
INT returnType;
USHORT i;
openType =
(PFILE_FULL_EA_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
if (openType != NULL) {
do {
found = TRUE;
for (i=0;i<(USHORT)openType->EaNameLength;i++) {
if (openType->EaName[i] == TdiTransportAddress[i]) {
continue;
} else {
found = FALSE;
break;
}
}
if (found) {
returnType = TDI_TRANSPORT_ADDRESS_FILE;
break;
}
//
// Is this a connection object?
//
found = TRUE;
for (i=0;i<(USHORT)openType->EaNameLength;i++) {
if (openType->EaName[i] == TdiConnectionContext[i]) {
continue;
} else {
found = FALSE;
break;
}
}
if (found) {
returnType = TDI_CONNECTION_FILE;
break;
}
} while ( FALSE );
} else {
returnType = ATALK_FILE_TYPE_CONTROL;
}
return(returnType);
}
//
// Tdi Request- Create/Destroy Ref/Deref routines
//
NTSTATUS
AtalkCreateTdiRequest(
PATALK_TDI_REQUEST *Request
)
/*++
Routine Description:
Creates and references a TDI request structure
Arguments:
Request - pointer to created structure is returned in here
Return Value:
STATUS_SUCCESS if created, error status otherwise
--*/
{
PATALK_TDI_REQUEST request;
USHORT i;
request = (PATALK_TDI_REQUEST)AtalkCallocNonPagedMemory(sizeof(ATALK_TDI_REQUEST), sizeof(char));
if (request == NULL) {
DBGPRINT(ATALK_DEBUG_DISPATCH, DEBUG_LEVEL_SEVERE, ("SEVERE ERROR: Malloc failed in CreateRequest %lx!\n", sizeof(ATALK_TDI_REQUEST)));
return(STATUS_INSUFFICIENT_RESOURCES);
}
request->Type = ATALK_TDI_REQUEST_SIGNATURE;
request->Size = sizeof(ATALK_TDI_REQUEST);
request->Flags = REQUEST_FLAGS_OPEN;
request->ActionCode = 0;
//
// Initialize list head and spin lock
//
InitializeListHead(&request->Linkage);
NdisAllocateSpinLock(&request->RequestLock);
for (i = 0; i < MAX_REQUESTMDLS; i++) {
request->MdlChain[i] = NULL;
}
//
// A reference for creation
//
#if DBG
request->RefTypes[RQREF_CREATE] = 1;
#endif
request->ReferenceCount = 1;
*Request = request;
return(STATUS_SUCCESS);
}
VOID
AtalkDestroyTdiRequest(
PATALK_TDI_REQUEST Request
)
/*++
Routine Description:
Called when the last reference on the request goes away. The request
is now destroyed. The associated connection object/address object/
control channel is dereferenced.
Arguments:
Request - the request to be destroyed.
Return Value:
None.
--*/
{
if (Request->Flags & REQUEST_FLAGS_DEREFOWNER) {
//
// Remove a reference to the owner of this request
// We do it here, so we know for sure that the request is nolonger
// going to reference the fileobject it is associated with/
//
switch ((INT)Request->OwnerType) {
case TDI_TRANSPORT_ADDRESS_FILE :
AtalkDereferenceAddress("TdiReqAddr", ((PADDRESS_FILE)Request->Owner), AREF_REQUEST, SECONDARY_REFSET);
break;
case TDI_CONNECTION_FILE :
AtalkDereferenceConnection("TdiReqConn", ((PCONNECTION_FILE)Request->Owner), CREF_REQUEST, SECONDARY_REFSET);
break;
case ATALK_FILE_TYPE_CONTROL :
AtalkDereferenceControlChannel("TdiReqChan", ((PCONTROLCHANNEL_FILE)Request->Owner), CCREF_REQUEST, SECONDARY_REFSET);
break;
default:
//
// BUGBUG:
// Should never happen; log error
//
DBGPRINT(ATALK_DEBUG_DISPATCH, DEBUG_LEVEL_SEVERE,
("ERROR: AtalkTdiDestroyRequest - Unknown object type when dereferencing request %ld-%lx\n", (INT)Request->OwnerType, Request));
DBGBRK(ATALK_DEBUG_DISPATCH, DEBUG_LEVEL_SEVERE);
break;
}
}
NdisFreeSpinLock(&Request->RequestLock);
AtalkFreeNonPagedMemory(Request);
return;
}
VOID
AtalkRefTdiRequest(
IN PATALK_TDI_REQUEST Request
)
/*++
Routine Description:
This routine increments the reference count on a request structure
Arguments:
Return Value:
none.
--*/
{
ULONG count;
count = NdisInterlockedAddUlong (
(PULONG)&Request->ReferenceCount,
(ULONG)1,
&AtalkGlobalRefLock);
ASSERT (count > 0);
return;
} /* AtalkRefTdiRequest */
VOID
AtalkDerefTdiRequest(
IN PATALK_TDI_REQUEST Request
)
/*++
Routine Description:
This routine dereferences a transport Request by decrementing the
reference count contained in the structure. If, after being
decremented, the reference count is zero, then this routine calls
AtalkDestroyRequest to remove it from the system.
Arguments:
Request - Pointer to a transport Request object.
Return Value:
none.
--*/
{
ULONG count;
count = NdisInterlockedAddUlong (
(PULONG)&Request->ReferenceCount,
(ULONG)-1,
&AtalkGlobalRefLock);
//
// If we have deleted all references to this Request, then we can
// destroy the object. It is okay to have already released the spin
// lock at this point because there is no possible way that another
// stream of execution has access to the Request any longer.
//
ASSERT (count >= 1);
if (count == 1) {
//
// Free the information buffer and then the atalkRequest buffer
//
DBGPRINT(ATALK_DEBUG_REFCOUNTS, DEBUG_LEVEL_INFOCLASS1,
("INFO1: AtalkDerefRequest - Destroying TDI request buffer %lx\n", Request));
AtalkDestroyTdiRequest(Request);
}
} /* AtalkDerefRequest */
VOID
AtalkCompleteTdiRequest (
PATALK_TDI_REQUEST Request,
NTSTATUS status
)
/*++
Routine Description:
Completes the ioRequest irp for the request, and then dereferences the
tdi request.
Arguments:
Request - request to complete
Status - status to use for io completion
Return Value:
None
--*/
{
USHORT i;
//
// Free the MDL's if they exist
//
for (i = 0; i < MAX_REQUESTMDLS; i++) {
if (Request->MdlChain[i] != NULL) {
FreeAnMdl(Request->MdlChain[i]);
} else
break; // Break upon first null mdl
}
//
// Complete the request and then dereference it
//
Request->IoStatus->Status = status;
DBGPRINT(ATALK_DEBUG_ALL, DEBUG_LEVEL_INFOCLASS1,
("INFO1: AtalkCompleteTdiRequest - status %lx info %lx pending %d\n",
status, Request->IoStatus->Information,
Request->IoRequestIrp->PendingReturned));
IoCompleteRequest(Request->IoRequestIrp, IO_NETWORK_INCREMENT );
AtalkDereferenceTdiRequest("TdiReqCmpl", Request, RQREF_MAKEREQ);
return;
}
#if DBG
VOID
DbgPrintPortInfo(
INT NumberOfPorts,
PPORT_INFO PortInformation
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
int i;
for (i=0; i < NumberOfPorts; i++) {
DBGPRINT(ATALK_DEBUG_INIT, DEBUG_LEVEL_ERROR, ("PORT INFORMATION STRUCTURE DUMP: Port %d\n", i));
DBGPRINT(ATALK_DEBUG_INIT, DEBUG_LEVEL_ERROR, ("DesiredPort -> %d\n", PortInformation[i].desiredPort));
DBGPRINT(ATALK_DEBUG_INIT, DEBUG_LEVEL_ERROR, ("PortType -> %d\n", PortInformation[i].portType));
DBGPRINT(ATALK_DEBUG_INIT, DEBUG_LEVEL_ERROR, ("A(ProtocolInfo)-> %lx\n",&PortInformation[i].protocolInfo));
if (PortInformation[i].portName != NULL) {
DBGPRINT(ATALK_DEBUG_INIT, DEBUG_LEVEL_ERROR, ("PortName -> %s\n", PortInformation[i].portName));
} else {
DBGPRINT(ATALK_DEBUG_INIT, DEBUG_LEVEL_ERROR, ("PortName -> (NULL)\n"));
}
DBGPRINT(ATALK_DEBUG_INIT, DEBUG_LEVEL_ERROR, ("AARP Probes -> %d\n", PortInformation[i].aarpProbes));
DBGPRINT(ATALK_DEBUG_INIT, DEBUG_LEVEL_ERROR, ("RoutingPort -> %d\n", PortInformation[i].routingPort));
DBGPRINT(ATALK_DEBUG_INIT, DEBUG_LEVEL_ERROR, ("SeedRouter -> %d\n", PortInformation[i].seedRouter));
DBGPRINT(ATALK_DEBUG_INIT, DEBUG_LEVEL_ERROR, ("networkRange -> %lx-%lx\n", \
PortInformation[i].networkRange.firstNetworkNumber, \
PortInformation[i].networkRange.lastNetworkNumber))
DbgPrintZoneList(PortInformation[i].zoneList);
if (PortInformation[i].defaultZone != NULL) {
DBGPRINT(ATALK_DEBUG_INIT, DEBUG_LEVEL_ERROR, ("DefaultZone -> %s\n", PortInformation[i].defaultZone));
} else {
DBGPRINT(ATALK_DEBUG_INIT, DEBUG_LEVEL_ERROR, ("DefaultZone -> NULL\n"));
}
if (PortInformation[i].desiredZone != NULL) {
DBGPRINT(ATALK_DEBUG_INIT, DEBUG_LEVEL_ERROR, ("DesiredZone -> %s\n", PortInformation[i].desiredZone));
} else {
DBGPRINT(ATALK_DEBUG_INIT, DEBUG_LEVEL_ERROR, ("DesiredZone -> NULL\n"));
}
DBGPRINT(ATALK_DEBUG_INIT, DEBUG_LEVEL_ERROR, ("defaultPort -> %d\n", PortInformation[i].defaultPort));
DBGPRINT(ATALK_DEBUG_INIT, DEBUG_LEVEL_ERROR, ("sendDdpChec -> %d\n", PortInformation[i].sendDdpChecksums));
DBGPRINT(ATALK_DEBUG_INIT, DEBUG_LEVEL_ERROR, ("startRouter -> %d\n", PortInformation[i].startRouter));
}
return;
}
VOID
DbgPrintZoneList(
PZONELIST Zlist
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
DBGPRINT(ATALK_DEBUG_INIT, DEBUG_LEVEL_ERROR, ("ZoneList:\n"));
while (Zlist != NULL) {
if (Zlist->zone != NULL) {
DBGPRINT(ATALK_DEBUG_INIT, DEBUG_LEVEL_ERROR, ("%s\n", Zlist->zone));
}
else
DBGPRINT(ATALK_DEBUG_INIT, DEBUG_LEVEL_ERROR, ("Zlist->zone = NULL!!\n"));
Zlist = Zlist->next;
}
return;
}
#endif