730 lines
17 KiB
C
730 lines
17 KiB
C
|
/*++
|
||
|
|
||
|
Copyright (c) 1992 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
atkact.c
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
This module contains the TDI action support code.
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Jameel Hyder (jameelh@microsoft.com)
|
||
|
Nikhil Kamkolkar (nikhilk@microsoft.com)
|
||
|
|
||
|
Revision History:
|
||
|
19 Jun 1992 Initial Version
|
||
|
|
||
|
Notes: Tab stop: 4
|
||
|
--*/
|
||
|
|
||
|
#include <atalk.h>
|
||
|
#pragma hdrstop
|
||
|
#define FILENUM ATKACT
|
||
|
|
||
|
#ifdef ALLOC_PRAGMA
|
||
|
#pragma alloc_text(PAGE_NZ, AtalkNbpTdiAction)
|
||
|
#pragma alloc_text(PAGE_NZ, AtalkZipTdiAction)
|
||
|
#pragma alloc_text(PAGE, AtalkAspTdiAction)
|
||
|
#pragma alloc_text(PAGE, AtalkAdspTdiAction)
|
||
|
#pragma alloc_text(PAGE_PAP, AtalkPapTdiAction)
|
||
|
#pragma alloc_text(PAGEASPC, AtalkAspCTdiAction)
|
||
|
#endif
|
||
|
|
||
|
ATALK_ERROR
|
||
|
AtalkStatTdiAction(
|
||
|
IN PVOID pObject, // Address or Connection object
|
||
|
IN struct _ActionReq * pActReq // Pointer to action request
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This is the entry for Statistics TdiAction call. There are no input parameters.
|
||
|
The statistics structure is returned.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
ATALK_ERROR Error = ATALK_NO_ERROR;
|
||
|
PPORT_DESCRIPTOR pPortDesc;
|
||
|
KIRQL OldIrql;
|
||
|
ULONG BytesCopied;
|
||
|
LONG Offset;
|
||
|
|
||
|
if (pActReq->ar_MdlSize < (SHORT)(sizeof(ATALK_STATS) +
|
||
|
sizeof(ATALK_PORT_STATS) * AtalkNumberOfPorts))
|
||
|
Error = ATALK_BUFFER_TOO_SMALL;
|
||
|
else
|
||
|
{
|
||
|
#ifdef PROFILING
|
||
|
// This is the only place where this is changed. And it always increases.
|
||
|
// Also the stats are changed using ExInterlocked calls. Acquiring a lock
|
||
|
// does little in terms of protection anyways.
|
||
|
AtalkStatistics.stat_ElapsedTime = AtalkTimerCurrentTick/ATALK_TIMER_FACTOR;
|
||
|
#endif
|
||
|
TdiCopyBufferToMdl(&AtalkStatistics,
|
||
|
0,
|
||
|
sizeof(ATALK_STATS),
|
||
|
pActReq->ar_pAMdl,
|
||
|
0,
|
||
|
&BytesCopied);
|
||
|
ASSERT(BytesCopied == sizeof(ATALK_STATS));
|
||
|
|
||
|
ACQUIRE_SPIN_LOCK(&AtalkPortLock, &OldIrql);
|
||
|
|
||
|
for (pPortDesc = AtalkPortList, Offset = sizeof(ATALK_STATS);
|
||
|
pPortDesc != NULL;
|
||
|
pPortDesc = pPortDesc->pd_Next)
|
||
|
{
|
||
|
TdiCopyBufferToMdl(&pPortDesc->pd_PortStats,
|
||
|
0,
|
||
|
sizeof(ATALK_PORT_STATS),
|
||
|
pActReq->ar_pAMdl,
|
||
|
Offset,
|
||
|
&BytesCopied);
|
||
|
Offset += sizeof(ATALK_PORT_STATS);
|
||
|
ASSERT(BytesCopied == sizeof(ATALK_PORT_STATS));
|
||
|
}
|
||
|
|
||
|
RELEASE_SPIN_LOCK(&AtalkPortLock, OldIrql);
|
||
|
}
|
||
|
|
||
|
(*pActReq->ar_Completion)(Error, pActReq);
|
||
|
return ATALK_PENDING;
|
||
|
}
|
||
|
|
||
|
|
||
|
ATALK_ERROR
|
||
|
AtalkNbpTdiAction(
|
||
|
IN PVOID pObject, // Address or Connection object
|
||
|
IN PACTREQ pActReq // Pointer to action request
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This is the entry for NBP TdiAction calls. The parameters are validated and
|
||
|
the calls are dispacthed to the appropriate NBP routines.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
ATALK_ERROR error = ATALK_NO_ERROR;
|
||
|
PDDP_ADDROBJ pDdpAddr;
|
||
|
PNBPTUPLE pNbpTuple;
|
||
|
|
||
|
PAGED_CODE ();
|
||
|
|
||
|
// Lock the Nbp stuff, if this is the first nbp action
|
||
|
AtalkLockNbpIfNecessary();
|
||
|
|
||
|
ASSERT (VALID_ACTREQ(pActReq));
|
||
|
// First get the Ddp address out of the pObject for the device
|
||
|
switch (pActReq->ar_DevType)
|
||
|
{
|
||
|
case ATALK_DEV_DDP:
|
||
|
pDdpAddr = (PDDP_ADDROBJ)pObject;
|
||
|
break;
|
||
|
|
||
|
case ATALK_DEV_ASPC:
|
||
|
pDdpAddr = AtalkAspCGetDdpAddress((PASPC_ADDROBJ)pObject);
|
||
|
break;
|
||
|
|
||
|
case ATALK_DEV_ASP:
|
||
|
pDdpAddr = AtalkAspGetDdpAddress((PASP_ADDROBJ)pObject);
|
||
|
break;
|
||
|
|
||
|
case ATALK_DEV_PAP:
|
||
|
pDdpAddr = AtalkPapGetDdpAddress((PPAP_ADDROBJ)pObject);
|
||
|
break;
|
||
|
|
||
|
case ATALK_DEV_ADSP:
|
||
|
pDdpAddr = AtalkAdspGetDdpAddress((PADSP_ADDROBJ)pObject);
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
DBGPRINT(DBG_COMP_ACTION, DBG_LEVEL_FATAL,
|
||
|
("AtalkNbpTdiAction: Invalid device type !!\n"));
|
||
|
error = ATALK_INVALID_REQUEST;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// reference the Ddp address.
|
||
|
if ((pActReq->ar_ActionCode == COMMON_ACTION_NBPREGISTER_BY_ADDR) ||
|
||
|
(pActReq->ar_ActionCode == COMMON_ACTION_NBPREMOVE_BY_ADDR))
|
||
|
{
|
||
|
// In this case, we don't want to access the object related to
|
||
|
// the filehandle in the IO request, we want to access the object
|
||
|
// related to a specific user socket address.
|
||
|
pNbpTuple = (PNBPTUPLE)(&((PNBP_REGDEREG_PARAMS)(pActReq->ar_pParms))->RegisterTuple);
|
||
|
AtalkDdpReferenceByAddr(AtalkDefaultPort,
|
||
|
&(pNbpTuple->tpl_Address),
|
||
|
&pDdpAddr,
|
||
|
&error);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
AtalkDdpReferenceByPtr(pDdpAddr, &error);
|
||
|
}
|
||
|
|
||
|
if (!ATALK_SUCCESS(error))
|
||
|
{
|
||
|
AtalkUnlockNbpIfNecessary();
|
||
|
return error;
|
||
|
}
|
||
|
|
||
|
// Call Nbp to do the right stuff
|
||
|
switch (pActReq->ar_ActionCode)
|
||
|
{
|
||
|
case COMMON_ACTION_NBPLOOKUP:
|
||
|
pNbpTuple = (PNBPTUPLE)(&((PNBP_LOOKUP_PARAMS)(pActReq->ar_pParms))->LookupTuple);
|
||
|
error = AtalkNbpAction(pDdpAddr,
|
||
|
FOR_LOOKUP,
|
||
|
pNbpTuple,
|
||
|
pActReq->ar_pAMdl,
|
||
|
(USHORT)(pActReq->ar_MdlSize/sizeof(NBPTUPLE)),
|
||
|
pActReq);
|
||
|
break;
|
||
|
|
||
|
case COMMON_ACTION_NBPCONFIRM:
|
||
|
pNbpTuple = (PNBPTUPLE)(&((PNBP_CONFIRM_PARAMS)(pActReq->ar_pParms))->ConfirmTuple);
|
||
|
error = AtalkNbpAction(pDdpAddr,
|
||
|
FOR_CONFIRM,
|
||
|
pNbpTuple,
|
||
|
NULL,
|
||
|
0,
|
||
|
pActReq);
|
||
|
break;
|
||
|
|
||
|
case COMMON_ACTION_NBPREGISTER:
|
||
|
pNbpTuple = (PNBPTUPLE)(&((PNBP_REGDEREG_PARAMS)(pActReq->ar_pParms))->RegisterTuple);
|
||
|
error = AtalkNbpAction(pDdpAddr,
|
||
|
FOR_REGISTER,
|
||
|
pNbpTuple,
|
||
|
NULL,
|
||
|
0,
|
||
|
pActReq);
|
||
|
break;
|
||
|
|
||
|
case COMMON_ACTION_NBPREMOVE:
|
||
|
pNbpTuple = (PNBPTUPLE)(&((PNBP_REGDEREG_PARAMS)(pActReq->ar_pParms))->RegisteredTuple);
|
||
|
error = AtalkNbpRemove(pDdpAddr,
|
||
|
pNbpTuple,
|
||
|
pActReq);
|
||
|
break;
|
||
|
|
||
|
case COMMON_ACTION_NBPREGISTER_BY_ADDR:
|
||
|
pNbpTuple = (PNBPTUPLE)(&((PNBP_REGDEREG_PARAMS)(pActReq->ar_pParms))->RegisterTuple);
|
||
|
error = AtalkNbpAction(pDdpAddr,
|
||
|
FOR_REGISTER,
|
||
|
pNbpTuple,
|
||
|
NULL,
|
||
|
0,
|
||
|
pActReq);
|
||
|
break;
|
||
|
|
||
|
case COMMON_ACTION_NBPREMOVE_BY_ADDR:
|
||
|
pNbpTuple = (PNBPTUPLE)(&((PNBP_REGDEREG_PARAMS)(pActReq->ar_pParms))->RegisteredTuple);
|
||
|
error = AtalkNbpRemove(pDdpAddr,
|
||
|
pNbpTuple,
|
||
|
pActReq);
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
DBGPRINT(DBG_COMP_ACTION, DBG_LEVEL_FATAL,
|
||
|
("AtalkNbpTdiAction: Invalid Nbp Action !!\n"));
|
||
|
error = ATALK_INVALID_REQUEST;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
AtalkDdpDereference(pDdpAddr);
|
||
|
|
||
|
if (error != ATALK_PENDING)
|
||
|
{
|
||
|
AtalkUnlockNbpIfNecessary();
|
||
|
}
|
||
|
|
||
|
return error;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
ATALK_ERROR
|
||
|
AtalkZipTdiAction(
|
||
|
IN PVOID pObject, // Address or Connection object
|
||
|
IN PACTREQ pActReq // Pointer to action request
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This is the entry for ZIP TdiAction calls. The parameters are validated and
|
||
|
the calls are dispacthed to the appropriate ZIP routines.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
ATALK_ERROR error = ATALK_INVALID_PARAMETER;
|
||
|
PPORT_DESCRIPTOR pPortDesc = AtalkDefaultPort;
|
||
|
PWCHAR PortName = NULL;
|
||
|
USHORT PortNameLen;
|
||
|
UNICODE_STRING AdapterName, UpcaseAdapterName;
|
||
|
WCHAR UpcaseBuffer[MAX_INTERNAL_PORTNAME_LEN];
|
||
|
KIRQL OldIrql;
|
||
|
int i;
|
||
|
|
||
|
PAGED_CODE ();
|
||
|
|
||
|
// Lock the Zip stuff, if this is the first zip action
|
||
|
AtalkLockZipIfNecessary();
|
||
|
|
||
|
ASSERT (VALID_ACTREQ(pActReq));
|
||
|
if ((pActReq->ar_ActionCode == COMMON_ACTION_ZIPGETLZONESONADAPTER) ||
|
||
|
(pActReq->ar_ActionCode == COMMON_ACTION_ZIPGETADAPTERDEFAULTS))
|
||
|
{
|
||
|
// Map the port name to the port descriptor
|
||
|
if ((pActReq->ar_pAMdl != NULL) && (pActReq->ar_MdlSize > 0))
|
||
|
{
|
||
|
PortName = (PWCHAR)AtalkGetAddressFromMdlSafe(
|
||
|
pActReq->ar_pAMdl,
|
||
|
NormalPagePriority);
|
||
|
|
||
|
}
|
||
|
|
||
|
if (PortName == NULL)
|
||
|
{
|
||
|
AtalkUnlockZipIfNecessary();
|
||
|
return ATALK_INVALID_PARAMETER;
|
||
|
}
|
||
|
|
||
|
PortNameLen = pActReq->ar_MdlSize/sizeof(WCHAR);
|
||
|
|
||
|
// make sure there is a NULL char in the buffer
|
||
|
for (i=0; i<PortNameLen; i++)
|
||
|
{
|
||
|
if (PortName[i] == UNICODE_NULL)
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// didn't find null char within limit? bad parameter..
|
||
|
if (i >= MAX_INTERNAL_PORTNAME_LEN)
|
||
|
{
|
||
|
DBGPRINT(DBG_COMP_ACTION, DBG_LEVEL_FATAL,
|
||
|
("AtalkZipTdiAction: port name too big (%d) for %lx\n",PortNameLen,PortName));
|
||
|
|
||
|
ASSERT(0);
|
||
|
return ATALK_INVALID_PARAMETER;
|
||
|
}
|
||
|
|
||
|
PortNameLen = (USHORT)i;
|
||
|
|
||
|
AdapterName.Buffer = PortName;
|
||
|
AdapterName.Length = (PortNameLen)*sizeof(WCHAR);
|
||
|
AdapterName.MaximumLength = (PortNameLen+1)*sizeof(WCHAR);
|
||
|
|
||
|
UpcaseAdapterName.Buffer = UpcaseBuffer;
|
||
|
UpcaseAdapterName.Length =
|
||
|
UpcaseAdapterName.MaximumLength = sizeof(UpcaseBuffer);
|
||
|
RtlUpcaseUnicodeString(&UpcaseAdapterName,
|
||
|
&AdapterName,
|
||
|
FALSE);
|
||
|
|
||
|
ACQUIRE_SPIN_LOCK(&AtalkPortLock, &OldIrql);
|
||
|
|
||
|
// Find the port corres. to the port descriptor
|
||
|
for (pPortDesc = AtalkPortList;
|
||
|
pPortDesc != NULL;
|
||
|
pPortDesc = pPortDesc->pd_Next)
|
||
|
{
|
||
|
if ((UpcaseAdapterName.Length == pPortDesc->pd_AdapterName.Length) &&
|
||
|
RtlEqualMemory(UpcaseAdapterName.Buffer,
|
||
|
pPortDesc->pd_AdapterName.Buffer,
|
||
|
UpcaseAdapterName.Length))
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
RELEASE_SPIN_LOCK(&AtalkPortLock, OldIrql);
|
||
|
|
||
|
if (pPortDesc == NULL)
|
||
|
{
|
||
|
AtalkUnlockZipIfNecessary();
|
||
|
return ATALK_INVALID_PARAMETER;
|
||
|
}
|
||
|
}
|
||
|
else if (pActReq->ar_ActionCode == COMMON_ACTION_ZIPGETZONELIST)
|
||
|
{
|
||
|
PPORT_DESCRIPTOR pTempPortDesc = NULL;
|
||
|
|
||
|
// This is to take care of cases when zone list is requested
|
||
|
// but the default adapter has gone away during PnP, and
|
||
|
// AtalkDefaultPort points to NULL
|
||
|
if (pPortDesc == NULL)
|
||
|
{
|
||
|
DBGPRINT(DBG_COMP_ACTION, DBG_LEVEL_ERR,
|
||
|
("COMMON_ACTION_ZIPGETZONELIST: PortDesc points to NULL\n"));
|
||
|
AtalkUnlockZipIfNecessary();
|
||
|
return ATALK_PORT_INVALID;
|
||
|
}
|
||
|
|
||
|
// Check if the AtalkDefaultPort is still in the list
|
||
|
// It is possible that AtalkDefaultPort holds a non-NULL value, but
|
||
|
// the adapter has gone away during a PnP
|
||
|
|
||
|
ACQUIRE_SPIN_LOCK(&AtalkPortLock, &OldIrql);
|
||
|
|
||
|
// Find the port corres. to the port descriptor
|
||
|
for (pTempPortDesc = AtalkPortList;
|
||
|
pTempPortDesc != NULL;
|
||
|
pTempPortDesc = pTempPortDesc->pd_Next)
|
||
|
{
|
||
|
if (pTempPortDesc == pPortDesc)
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
RELEASE_SPIN_LOCK(&AtalkPortLock, OldIrql);
|
||
|
|
||
|
if (pTempPortDesc == NULL)
|
||
|
{
|
||
|
DBGPRINT(DBG_COMP_ACTION, DBG_LEVEL_ERR,
|
||
|
("COMMON_ACTION_ZIPGETZONELIST: PortDesc structure has gone away during PnP\n"));
|
||
|
AtalkUnlockZipIfNecessary();
|
||
|
return ATALK_PORT_INVALID;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
switch (pActReq->ar_ActionCode)
|
||
|
{
|
||
|
case COMMON_ACTION_ZIPGETMYZONE:
|
||
|
error = AtalkZipGetMyZone( pPortDesc,
|
||
|
TRUE,
|
||
|
pActReq->ar_pAMdl,
|
||
|
pActReq->ar_MdlSize,
|
||
|
pActReq);
|
||
|
break;
|
||
|
|
||
|
case COMMON_ACTION_ZIPGETZONELIST:
|
||
|
error = AtalkZipGetZoneList(pPortDesc,
|
||
|
FALSE,
|
||
|
pActReq->ar_pAMdl,
|
||
|
pActReq->ar_MdlSize,
|
||
|
pActReq);
|
||
|
break;
|
||
|
|
||
|
case COMMON_ACTION_ZIPGETADAPTERDEFAULTS:
|
||
|
// Copy the network range from the port and fall through
|
||
|
((PZIP_GETPORTDEF_PARAMS)(pActReq->ar_pParms))->NwRangeLowEnd =
|
||
|
pPortDesc->pd_NetworkRange.anr_FirstNetwork;
|
||
|
((PZIP_GETPORTDEF_PARAMS)(pActReq->ar_pParms))->NwRangeHighEnd =
|
||
|
pPortDesc->pd_NetworkRange.anr_LastNetwork;
|
||
|
|
||
|
error = AtalkZipGetMyZone(pPortDesc,
|
||
|
FALSE,
|
||
|
pActReq->ar_pAMdl,
|
||
|
pActReq->ar_MdlSize,
|
||
|
pActReq);
|
||
|
break;
|
||
|
|
||
|
case COMMON_ACTION_ZIPGETLZONESONADAPTER:
|
||
|
case COMMON_ACTION_ZIPGETLZONES:
|
||
|
error = AtalkZipGetZoneList(pPortDesc,
|
||
|
TRUE,
|
||
|
pActReq->ar_pAMdl,
|
||
|
pActReq->ar_MdlSize,
|
||
|
pActReq);
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
DBGPRINT(DBG_COMP_ACTION, DBG_LEVEL_FATAL,
|
||
|
("AtalkZipTdiAction: Invalid Zip Action !!\n"));
|
||
|
error = ATALK_INVALID_REQUEST;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (error != ATALK_PENDING)
|
||
|
{
|
||
|
AtalkUnlockZipIfNecessary();
|
||
|
}
|
||
|
|
||
|
return error;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
ATALK_ERROR
|
||
|
AtalkAspTdiAction(
|
||
|
IN PVOID pObject, // Address or Connection object
|
||
|
IN PACTREQ pActReq // Pointer to action request
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This is the entry for ASP TdiAction calls. The parameters are validated and
|
||
|
the calls are dispacthed to the appropriate ASP routines.
|
||
|
|
||
|
The only ASP Action is: ASP_XCHG_ENTRIES
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
ATALK_ERROR error = ATALK_INVALID_REQUEST;
|
||
|
|
||
|
PAGED_CODE ();
|
||
|
|
||
|
ASSERT(VALID_ACTREQ(pActReq));
|
||
|
|
||
|
if (pActReq->ar_ActionCode == ACTION_ASP_BIND)
|
||
|
{
|
||
|
if (AtalkAspReferenceAddr((PASP_ADDROBJ)pObject) != NULL)
|
||
|
{
|
||
|
error = AtalkAspBind((PASP_ADDROBJ)pObject,
|
||
|
(PASP_BIND_PARAMS)(pActReq->ar_pParms),
|
||
|
pActReq);
|
||
|
AtalkAspDereferenceAddr((PASP_ADDROBJ)pObject);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return error;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
ATALK_ERROR
|
||
|
AtalkAdspTdiAction(
|
||
|
IN PVOID pObject, // Address or Connection object
|
||
|
IN PACTREQ pActReq // Pointer to action request
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This is the entry for ADSP TdiAction calls. The parameters are validated and
|
||
|
the calls are dispacthed to the appropriate ADSP routines.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
ATALK_ERROR error = ATALK_NO_ERROR;
|
||
|
|
||
|
PAGED_CODE ();
|
||
|
|
||
|
ASSERT (VALID_ACTREQ(pActReq));
|
||
|
|
||
|
return error;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
ATALK_ERROR
|
||
|
AtalkAspCTdiAction(
|
||
|
IN PVOID pObject, // Address or Connection object
|
||
|
IN PACTREQ pActReq // Pointer to action request
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This is the entry for ASP Client TdiAction calls. The parameters are validated
|
||
|
and the calls are dispatched to the appropriate ASP routines.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
ATALK_ERROR error = ATALK_NO_ERROR;
|
||
|
PAMDL pReplyMdl;
|
||
|
ATALK_ADDR atalkAddr;
|
||
|
BOOLEAN fWrite;
|
||
|
|
||
|
PAGED_CODE ();
|
||
|
|
||
|
ASSERT (VALID_ACTREQ(pActReq));
|
||
|
|
||
|
switch (pActReq->ar_ActionCode)
|
||
|
{
|
||
|
case ACTION_ASPCGETSTATUS:
|
||
|
AtalkAspCAddrReference((PASPC_ADDROBJ)pObject, &error);
|
||
|
if (ATALK_SUCCESS(error))
|
||
|
{
|
||
|
TDI_TO_ATALKADDR(&atalkAddr,
|
||
|
&(((PASPC_GETSTATUS_PARAMS)pActReq->ar_pParms)->ServerAddr));
|
||
|
|
||
|
error = AtalkAspCGetStatus((PASPC_ADDROBJ)pObject,
|
||
|
&atalkAddr,
|
||
|
pActReq->ar_pAMdl,
|
||
|
pActReq->ar_MdlSize,
|
||
|
pActReq);
|
||
|
|
||
|
AtalkAspCAddrDereference((PASPC_ADDROBJ)pObject);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case ACTION_ASPCCOMMAND:
|
||
|
case ACTION_ASPCWRITE:
|
||
|
// Split the mdl into command and reply/write mdls. The already constructed mdl
|
||
|
// serves as the command mdl
|
||
|
// First validate that the sizes are valid
|
||
|
if (pActReq->ar_MdlSize < (((PASPC_COMMAND_OR_WRITE_PARAMS)pActReq->ar_pParms)->CmdSize +
|
||
|
((PASPC_COMMAND_OR_WRITE_PARAMS)pActReq->ar_pParms)->WriteAndReplySize))
|
||
|
{
|
||
|
error = ATALK_BUFFER_TOO_SMALL;
|
||
|
break;
|
||
|
}
|
||
|
pReplyMdl = AtalkSubsetAmdl(pActReq->ar_pAMdl,
|
||
|
((PASPC_COMMAND_OR_WRITE_PARAMS)pActReq->ar_pParms)->CmdSize,
|
||
|
((PASPC_COMMAND_OR_WRITE_PARAMS)pActReq->ar_pParms)->WriteAndReplySize);
|
||
|
if (pReplyMdl == NULL)
|
||
|
{
|
||
|
error = ATALK_RESR_MEM;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
AtalkAspCConnReference((PASPC_CONNOBJ)pObject, &error);
|
||
|
if (ATALK_SUCCESS(error))
|
||
|
{
|
||
|
fWrite = (pActReq->ar_ActionCode == ACTION_ASPCWRITE) ? TRUE : FALSE;
|
||
|
error = AtalkAspCCmdOrWrite((PASPC_CONNOBJ)pObject,
|
||
|
pActReq->ar_pAMdl,
|
||
|
((PASPC_COMMAND_OR_WRITE_PARAMS)pActReq->ar_pParms)->CmdSize,
|
||
|
pReplyMdl,
|
||
|
((PASPC_COMMAND_OR_WRITE_PARAMS)pActReq->ar_pParms)->WriteAndReplySize,
|
||
|
fWrite,
|
||
|
pActReq);
|
||
|
AtalkAspCConnDereference((PASPC_CONNOBJ)pObject);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
DBGPRINT(DBG_COMP_ACTION, DBG_LEVEL_FATAL,
|
||
|
("AtalkAspCTdiAction: Invalid Asp Client Action !!\n"));
|
||
|
error = ATALK_INVALID_REQUEST;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return error;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
ATALK_ERROR
|
||
|
AtalkPapTdiAction(
|
||
|
IN PVOID pObject, // Address or Connection object
|
||
|
IN PACTREQ pActReq // Pointer to action request
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This is the entry for PAP TdiAction calls. The parameters are validated and
|
||
|
the calls are dispacthed to the appropriate PAP routines.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
ATALK_ERROR error;
|
||
|
ATALK_ADDR atalkAddr;
|
||
|
|
||
|
PAGED_CODE ();
|
||
|
|
||
|
ASSERT (VALID_ACTREQ(pActReq));
|
||
|
|
||
|
switch (pActReq->ar_ActionCode)
|
||
|
{
|
||
|
case ACTION_PAPGETSTATUSSRV:
|
||
|
AtalkPapAddrReference((PPAP_ADDROBJ)pObject, &error);
|
||
|
if (ATALK_SUCCESS(error))
|
||
|
{
|
||
|
TDI_TO_ATALKADDR(
|
||
|
&atalkAddr,
|
||
|
&(((PPAP_GETSTATUSSRV_PARAMS)pActReq->ar_pParms)->ServerAddr));
|
||
|
|
||
|
error = AtalkPapGetStatus((PPAP_ADDROBJ)pObject,
|
||
|
&atalkAddr,
|
||
|
pActReq->ar_pAMdl,
|
||
|
pActReq->ar_MdlSize,
|
||
|
pActReq);
|
||
|
|
||
|
AtalkPapAddrDereference((PPAP_ADDROBJ)pObject);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case ACTION_PAPSETSTATUS:
|
||
|
AtalkPapAddrReference((PPAP_ADDROBJ)pObject, &error);
|
||
|
if (ATALK_SUCCESS(error))
|
||
|
{
|
||
|
error = AtalkPapSetStatus((PPAP_ADDROBJ)pObject,
|
||
|
pActReq->ar_pAMdl,
|
||
|
pActReq);
|
||
|
AtalkPapAddrDereference((PPAP_ADDROBJ)pObject);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case ACTION_PAPPRIMEREAD:
|
||
|
AtalkPapConnReferenceByPtr((PPAP_CONNOBJ)pObject, &error);
|
||
|
if (ATALK_SUCCESS(error))
|
||
|
{
|
||
|
error = AtalkPapPrimeRead((PPAP_CONNOBJ)pObject, pActReq);
|
||
|
AtalkPapConnDereference((PPAP_CONNOBJ)pObject);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
DBGPRINT(DBG_COMP_ACTION, DBG_LEVEL_FATAL,
|
||
|
("AtalkPapTdiAction: Invalid Pap Action !!\n"));
|
||
|
error = ATALK_INVALID_REQUEST;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return error;
|
||
|
}
|
||
|
|