1683 lines
30 KiB
C
1683 lines
30 KiB
C
/*++
|
|
|
|
Copyright (c) 1990 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
assoc.c
|
|
|
|
Abstract:
|
|
THis module contains the functions that deal with associations and
|
|
dialogues
|
|
|
|
Functions:
|
|
CommAssocSetUpAssoc
|
|
CommAssocFrmStartAssocReq
|
|
CommAssocUfmStartAssocReq
|
|
CommAssocFrmStopAssocReq
|
|
CommAssocUfmStopAssocReq
|
|
CommAssocFrmStartAssocRsp
|
|
CommAssocUfmStartAssocRsp
|
|
CommAssocAllocAssoc
|
|
CommAssocAllocDlg
|
|
AllocEnt
|
|
DeallocEnt
|
|
CommAssocDeallocAssoc
|
|
CommAssocDeallocDlg
|
|
CommAssocInit
|
|
CommAssocInsertUdpDlgInTbl
|
|
CommAssocDeleteUdpDlgInTbl
|
|
CommAssocCreateAssocInTbl
|
|
CommAssocDeleteAssocInTbl
|
|
CommAssocLookupAssoc
|
|
CommAssocInsertAssocInTbl
|
|
|
|
|
|
Portability:
|
|
|
|
This module is portable
|
|
|
|
Author:
|
|
|
|
Pradeep Bahl (PradeepB) 7-Dec-1992
|
|
|
|
Revision History:
|
|
|
|
Modification date Person Description of modification
|
|
----------------- ------- ----------------------------
|
|
--*/
|
|
|
|
/*
|
|
* Includes
|
|
*/
|
|
#include "wins.h"
|
|
#include "nms.h"
|
|
#include "comm.h"
|
|
#include "assoc.h"
|
|
#include "winsque.h"
|
|
#include "winsmsc.h"
|
|
#include "winsevt.h"
|
|
|
|
/*
|
|
* Local Macro Declarations
|
|
*/
|
|
|
|
|
|
/*
|
|
* Local Typedef Declarations
|
|
*/
|
|
|
|
#if PRSCONN
|
|
STATIC DWORD sAssocSeqNo = 0;
|
|
#else
|
|
STATIC DWORD sAssocSeqNo = 1;
|
|
#endif
|
|
|
|
STATIC QUE_HD_T sAssocQueHd;
|
|
STATIC CRITICAL_SECTION sAssocListCrtSec;
|
|
|
|
#if PRSCONN
|
|
STATIC DWORD sDlgSeqNo = 0;
|
|
#else
|
|
STATIC DWORD sDlgSeqNo = 1;
|
|
#endif
|
|
|
|
STATIC QUE_HD_T sDlgQueHd;
|
|
STATIC DWORD sNoOfDlgCrtSec; //no of crt. secs in dlgs
|
|
STATIC DWORD sNoOfAssocCrtSec; //no of crt. secs in assocs.
|
|
STATIC CRITICAL_SECTION sDlgListCrtSec;
|
|
|
|
STATIC LIST_ENTRY sUdpDlgHead;
|
|
|
|
COMMASSOC_TAG_POOL_T sTagAssoc; //32bit ULONG -> LPVOID mapping
|
|
|
|
/*
|
|
* Global Variable Definitions
|
|
*/
|
|
|
|
|
|
/*
|
|
Handles to the heaps to be used for assoc. and dlg. allocation
|
|
*/
|
|
HANDLE CommAssocAssocHeapHdl;
|
|
HANDLE CommAssocDlgHeapHdl;
|
|
HANDLE CommAssocTcpMsgHeapHdl;
|
|
|
|
/*
|
|
Size of the memory for one assoc.
|
|
*/
|
|
DWORD CommAssocAssocSize = 0;
|
|
|
|
/*
|
|
Size of
|
|
DWORD CommAssocMaxAssoc = 0;
|
|
|
|
|
|
/*
|
|
* Local Variable Definitions
|
|
*/
|
|
|
|
STATIC CRITICAL_SECTION sUdpDlgTblCrtSec;
|
|
|
|
//
|
|
// This is the start of the Responder Assoc Table. This table holds the list of
|
|
// active Responder associations. Currently, the table is implemented
|
|
// as a linked list using the Rtl Linked list functions.
|
|
//
|
|
QUE_HD_T sRspAssocQueHd;
|
|
|
|
/*
|
|
* Local Function Prototype Declarations
|
|
*/
|
|
|
|
/* prototypes for functions local to this module go here */
|
|
STATIC
|
|
LPVOID
|
|
AllocEnt(
|
|
HANDLE HeapHdl,
|
|
PQUE_HD_T pQueHd,
|
|
LPCRITICAL_SECTION pCrtSec,
|
|
LPDWORD pSeqNoCntr,
|
|
DWORD Size,
|
|
LPDWORD pCntCrtSec
|
|
);
|
|
|
|
STATIC
|
|
VOID
|
|
DeallocEnt(
|
|
HANDLE HeapHdl,
|
|
PQUE_HD_T pQueHd,
|
|
LPCRITICAL_SECTION pCrtSec,
|
|
LPDWORD pSeqNoCntr,
|
|
LPVOID pHdl,
|
|
LPDWORD pCntCrtSec
|
|
);
|
|
|
|
|
|
//
|
|
// Function definitions start here
|
|
//
|
|
|
|
VOID
|
|
CommAssocSetUpAssoc(
|
|
IN PCOMM_HDL_T pDlgHdl,
|
|
IN PCOMM_ADD_T pAdd,
|
|
IN COMM_TYP_E CommTyp_e,
|
|
OUT PCOMMASSOC_ASSOC_CTX_T *ppAssocCtx
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function sets up an association
|
|
Arguments:
|
|
pDlghdl - Handle to dlg under which an association has to be set up
|
|
pAdd - Address of node with which the association has to be set up
|
|
CommTyp_e - TYpe of association
|
|
ppAssocCtx - Association Context block allocated by the function
|
|
|
|
|
|
Externals Used:
|
|
None
|
|
|
|
Called by:
|
|
ECommStartDlg
|
|
Comments:
|
|
None
|
|
|
|
Return Value:
|
|
|
|
Success status codes -- WINS_SUCCESS
|
|
Error status codes --
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
SOCKET SockNo = INVALID_SOCKET;
|
|
PCOMMASSOC_ASSOC_CTX_T pAssocCtx = NULL; //v. imp to init this to NULL
|
|
INT BytesRead = -1;
|
|
MSG_T pTcpMsg;
|
|
STATUS RetStat;
|
|
WINS_MEM_T WinsMem[2];
|
|
PWINS_MEM_T pWinsMem = WinsMem;
|
|
#if SUPPORT612WINS > 0
|
|
BYTE AssocMsg[COMMASSOC_POST_BETA1_ASSOC_MSG_SIZE];
|
|
DWORD MsgLen = COMMASSOC_POST_BETA1_ASSOC_MSG_SIZE;
|
|
#else
|
|
BYTE AssocMsg[COMMASSOC_ASSOC_MSG_SIZE];
|
|
DWORD MsgLen = COMMASSOC_ASSOC_MSG_SIZE;
|
|
#endif
|
|
PCOMMASSOC_DLG_CTX_T pDlgCtx = pDlgHdl->pEnt;
|
|
pWinsMem->pMem = NULL;
|
|
|
|
try {
|
|
|
|
/*
|
|
* Create a TCP connection to the WINS at the other node
|
|
*/
|
|
CommConnect(
|
|
pAdd,
|
|
CommWinsTcpPortNo, // WINS_TCP_PORT,
|
|
&SockNo
|
|
);
|
|
|
|
/*
|
|
* Allocate the assoc context block
|
|
*/
|
|
pAssocCtx = CommAssocAllocAssoc();
|
|
|
|
pAssocCtx->SockNo = SockNo;
|
|
pAssocCtx->uRemAssocCtx = 0;
|
|
pAssocCtx->State_e = COMMASSOC_ASSOC_E_NON_EXISTENT;
|
|
pAssocCtx->Role_e = COMMASSOC_ASSOC_E_INITIATOR;
|
|
pAssocCtx->Typ_e = CommTyp_e;
|
|
pAssocCtx->DlgHdl = *pDlgHdl;
|
|
pAssocCtx->RemoteAdd.sin_addr.s_addr = pAdd->Add.IPAdd;
|
|
pAssocCtx->nTag = CommAssocTagAlloc(&sTagAssoc,pAssocCtx);
|
|
|
|
|
|
/*
|
|
Format the start association message.
|
|
|
|
The address passed to the formatting function is offset
|
|
from the address of the buffer by a LONG so that CommSendAssoc
|
|
can store the length of the message in it.
|
|
*/
|
|
CommAssocFrmStartAssocReq(
|
|
pAssocCtx,
|
|
AssocMsg + sizeof(LONG),
|
|
MsgLen - sizeof(LONG)
|
|
);
|
|
|
|
|
|
pDlgCtx->AssocHdl.pEnt = pAssocCtx;
|
|
pDlgCtx->AssocHdl.SeqNo = pAssocCtx->Top.SeqNo;
|
|
|
|
/*
|
|
* send the message on the TCP connection
|
|
*/
|
|
CommSendAssoc(
|
|
pAssocCtx->SockNo,
|
|
AssocMsg + sizeof(LONG),
|
|
MsgLen - sizeof(LONG)
|
|
);
|
|
|
|
/*
|
|
Read in the response message
|
|
*/
|
|
RetStat = CommReadStream(
|
|
pAssocCtx->SockNo,
|
|
TRUE, // do timed wait
|
|
&pTcpMsg,
|
|
&BytesRead
|
|
);
|
|
|
|
|
|
/*
|
|
If the return status is not WINS_SUCCESS or bytes read are 0, then
|
|
either it is a disconnect or the read timed out. Raise an exception.
|
|
(We should have gotten either a start or a stop assoc. message.
|
|
*/
|
|
if ((BytesRead != 0) && (RetStat == WINS_SUCCESS))
|
|
{
|
|
|
|
DWORD Opc;
|
|
DWORD MsgTyp;
|
|
ULONG uNoNeed;
|
|
|
|
pWinsMem->pMem = pTcpMsg - sizeof(LONG) - COMM_BUFF_HEADER_SIZE;
|
|
(++pWinsMem)->pMem = NULL;
|
|
|
|
/*
|
|
* unformat the response
|
|
*/
|
|
COMM_GET_HEADER_M(pTcpMsg, Opc, uNoNeed, MsgTyp);
|
|
|
|
|
|
/*
|
|
* if MsgTyp indicates that it is a start assoc. response
|
|
* message, change state of association to Active; return
|
|
* success
|
|
*/
|
|
if (MsgTyp == COMM_START_RSP_ASSOC_MSG)
|
|
{
|
|
CommAssocUfmStartAssocRsp(
|
|
pTcpMsg,
|
|
&pAssocCtx->MajVersNo,
|
|
&pAssocCtx->MinVersNo,
|
|
&pAssocCtx->uRemAssocCtx
|
|
);
|
|
|
|
pAssocCtx->State_e = COMMASSOC_ASSOC_E_ACTIVE;
|
|
#if SUPPORT612WINS > 0
|
|
//
|
|
// If bytes read are less than what a post-beta1
|
|
// WINS sends us, it means that it must be a beta1 WINS.
|
|
//
|
|
if (BytesRead >= (COMMASSOC_POST_BETA1_ASSOC_MSG_SIZE - sizeof(LONG)))
|
|
{
|
|
#if 0
|
|
pAssocCtx->MajVersNo = WINS_BETA2_MAJOR_VERS_NO;
|
|
pAssocCtx->MinVersNo = 1; //not used currently
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
pAssocCtx->MajVersNo = WINS_BETA1_MAJOR_VERS_NO;
|
|
pAssocCtx->MinVersNo = 1; //not used currently
|
|
|
|
}
|
|
#endif
|
|
}
|
|
|
|
//
|
|
// Let us free the message that we received
|
|
//
|
|
ECommFreeBuff(pTcpMsg);
|
|
|
|
/*
|
|
* if opcode indicates that it is a stop assoc. message, do
|
|
* cleanup; return failure
|
|
*/
|
|
if (MsgTyp == COMM_STOP_REQ_ASSOC_MSG)
|
|
{
|
|
//
|
|
// Decrement conn. count
|
|
//
|
|
CommDecConnCount();
|
|
WINS_RAISE_EXC_M(WINS_EXC_COMM_FAIL);
|
|
}
|
|
}
|
|
else // Either Bytes Read are 0 or select timed out or some other error
|
|
// occurred
|
|
{
|
|
WINS_RAISE_EXC_M(WINS_EXC_COMM_FAIL);
|
|
}
|
|
}
|
|
except (EXCEPTION_EXECUTE_HANDLER) {
|
|
|
|
DWORD ExcCode = GetExceptionCode();
|
|
DBGPRINTEXC("CommAssocSetUpAssoc");
|
|
|
|
|
|
//
|
|
// If the exception occurred after the socket was opened, close it
|
|
//
|
|
if (SockNo != INVALID_SOCKET)
|
|
{
|
|
CommDisc(SockNo, TRUE); // close the socket
|
|
}
|
|
|
|
//
|
|
// if an assoc. ctx block was allocated, free it now
|
|
//
|
|
if (pAssocCtx != NULL)
|
|
{
|
|
CommAssocTagFree(&sTagAssoc, pAssocCtx->nTag);
|
|
CommAssocDeallocAssoc(pAssocCtx);
|
|
}
|
|
|
|
//
|
|
// reraise the exception
|
|
//
|
|
WINS_HDL_EXC_N_RERAISE_M(WinsMem);
|
|
} //end of except {..}
|
|
|
|
*ppAssocCtx = pAssocCtx;
|
|
return;
|
|
} //CommAssocSetUpAssoc()
|
|
|
|
|
|
VOID
|
|
CommAssocFrmStartAssocReq(
|
|
IN PCOMMASSOC_ASSOC_CTX_T pAssocCtx,
|
|
IN MSG_T pMsg,
|
|
IN MSG_LEN_T MsgLen
|
|
)
|
|
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function is called to format a start association message
|
|
|
|
Arguments:
|
|
pAssocCtx - Association Context block
|
|
pMsg - Buffer containing the formatted start assoc. req. msg.
|
|
MsgLen - Size of the above buffer
|
|
|
|
|
|
Externals Used:
|
|
None
|
|
|
|
Return Value:
|
|
None
|
|
|
|
Error Handling:
|
|
|
|
Called by:
|
|
CommAssocSetUpAssoc
|
|
|
|
Side Effects:
|
|
|
|
Comments:
|
|
None
|
|
--*/
|
|
|
|
{
|
|
|
|
ULONG *pLong = NULL;
|
|
|
|
/*
|
|
|
|
The start assoc. message contains the following fields
|
|
|
|
the assoc handle (ptr field)
|
|
Version Number (major and minor) both are 16 bits
|
|
Authentication Info (currently nothing)
|
|
Association Type (an integer)
|
|
|
|
*/
|
|
pLong = (LPLONG)pMsg;
|
|
|
|
COMM_SET_HEADER_M(
|
|
pLong,
|
|
WINS_IS_NOT_NBT, //opcode
|
|
0, /*We don't have the remote guy's assoc. ptr yet*/
|
|
COMM_START_REQ_ASSOC_MSG //msg type
|
|
);
|
|
|
|
*pLong++ = htonl(pAssocCtx->nTag);
|
|
*pLong++ = htonl((WINS_MAJOR_VERS << 16 ) | WINS_MINOR_VERS);
|
|
*pLong = htonl(pAssocCtx->Typ_e); //assoc type
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VOID
|
|
CommAssocUfmStartAssocReq(
|
|
IN MSG_T pMsg,
|
|
OUT PCOMM_TYP_E pAssocTyp_e,
|
|
OUT LPDWORD pMajorVer,
|
|
OUT LPDWORD pMinorVer,
|
|
OUT ULONG *puRemAssocCtx
|
|
)
|
|
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function parses the start association message that arrives on
|
|
a TCP connection and returns with the relevant information
|
|
|
|
Arguments:
|
|
pMsg -- Message to be unformatted
|
|
pAssocTyp_e -- Type of assoc (i.e from who -- replicator, COMSYS, etc)
|
|
pMajorVer -- Major version no.
|
|
pMinorVer -- Minor version no.
|
|
puRemAssocCtx -- ptr to assoc. ctx block of remote WINS
|
|
|
|
|
|
Externals Used:
|
|
None
|
|
|
|
|
|
Return Value:
|
|
None
|
|
|
|
Error Handling:
|
|
|
|
Called by:
|
|
ProcTcpMsg
|
|
|
|
Side Effects:
|
|
|
|
Comments:
|
|
None
|
|
--*/
|
|
|
|
{
|
|
|
|
|
|
|
|
/*
|
|
Increment pLong past the comm header
|
|
*/
|
|
LPLONG pLong = (LPLONG)(pMsg + COMM_HEADER_SIZE);
|
|
LONG lTmp;
|
|
|
|
*puRemAssocCtx = ntohl(*pLong++);
|
|
//ptr to assoc. ctx at remote WINS
|
|
/*
|
|
* Get the long that contains the major and minor version numbers
|
|
*/
|
|
lTmp = ntohl(*pLong++);
|
|
|
|
*pMajorVer = lTmp >> 16; //Major vers. no.
|
|
*pMinorVer = lTmp & 0x0ff; //Minor vers. no.
|
|
|
|
*pAssocTyp_e = ntohl(*pLong); /*Msg type (from who -- COMSYS,
|
|
Replicator
|
|
*/
|
|
return;
|
|
|
|
}
|
|
|
|
VOID
|
|
CommAssocFrmStopAssocReq(
|
|
IN PCOMMASSOC_ASSOC_CTX_T pAssocCtx,
|
|
IN MSG_T pMsg,
|
|
IN MSG_LEN_T MsgLen,
|
|
IN COMMASSOC_STP_RSN_E StopRsn_e
|
|
)
|
|
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
This function formats a stop association message
|
|
|
|
|
|
Arguments:
|
|
pAssocCtx -- Assoc. Ctx block.
|
|
pMsg -- Buffer containing the formatted stop assoc. req. msg.
|
|
MsgLen -- Length of above buffer
|
|
StopRsn_e -- Reason why the association is being stopped
|
|
|
|
Externals Used:
|
|
None
|
|
|
|
|
|
Return Value:
|
|
None
|
|
|
|
Error Handling:
|
|
|
|
Called by:
|
|
CommAssocSetUpAssoc
|
|
|
|
Side Effects:
|
|
|
|
Comments:
|
|
None
|
|
--*/
|
|
{
|
|
|
|
|
|
|
|
unsigned long *pLong = NULL;
|
|
|
|
|
|
/*
|
|
The stop assoc. message contains the following fields
|
|
|
|
the reason for the stop/abort.
|
|
|
|
*/
|
|
|
|
|
|
pLong = (LPLONG)pMsg;
|
|
|
|
|
|
COMM_SET_HEADER_M(
|
|
pLong,
|
|
WINS_IS_NOT_NBT,
|
|
pAssocCtx->uRemAssocCtx,
|
|
COMM_STOP_REQ_ASSOC_MSG
|
|
);
|
|
|
|
*pLong = htonl(StopRsn_e);
|
|
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
CommUfmStopAssocReq(
|
|
IN MSG_T pMsg,
|
|
OUT PCOMMASSOC_STP_RSN_E pStopRsn_e
|
|
)
|
|
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
This function formats a stop association message
|
|
|
|
|
|
Arguments:
|
|
pMsg - Message containing the stop assoc. req.
|
|
pStopRsn_e - reason why the association was stopped
|
|
|
|
|
|
Externals Used:
|
|
None
|
|
|
|
|
|
Return Value:
|
|
None
|
|
|
|
Error Handling:
|
|
|
|
Called by:
|
|
ProcTcpMsg
|
|
|
|
Side Effects:
|
|
|
|
Comments:
|
|
None
|
|
--*/
|
|
{
|
|
|
|
/*
|
|
Increment pLong past the comm header
|
|
*/
|
|
LPLONG pLong = (LPLONG)(pMsg + COMM_HEADER_SIZE);
|
|
|
|
*pStopRsn_e = ntohl(*pLong);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VOID
|
|
CommAssocFrmStartAssocRsp(
|
|
IN PCOMMASSOC_ASSOC_CTX_T pAssocCtx,
|
|
IN MSG_T pMsg,
|
|
IN MSG_LEN_T MsgLen
|
|
)
|
|
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function is called to format a start association response message
|
|
|
|
Arguments:
|
|
pAssocCtx -- Assoc. ctx block
|
|
pMsg -- Buffer containing the formatted start assoc. rsp. msg.
|
|
MsgLen -- Length of above buffer
|
|
|
|
Externals Used:
|
|
None
|
|
|
|
|
|
Return Value:
|
|
None
|
|
|
|
Error Handling:
|
|
|
|
Called by:
|
|
ProcTcpMsg
|
|
|
|
Side Effects:
|
|
|
|
Comments:
|
|
None
|
|
--*/
|
|
|
|
{
|
|
LPLONG pLong = NULL;
|
|
|
|
|
|
/*
|
|
|
|
The start assoc. message contains the following fields
|
|
|
|
the assoc handle (ptr field)
|
|
Authentication Info (currently nothing)
|
|
|
|
*/
|
|
|
|
|
|
pLong = (unsigned long *)pMsg;
|
|
|
|
COMM_SET_HEADER_M(
|
|
pLong,
|
|
WINS_IS_NOT_NBT,
|
|
pAssocCtx->uRemAssocCtx,
|
|
COMM_START_RSP_ASSOC_MSG
|
|
);
|
|
|
|
*pLong++ = htonl(pAssocCtx->nTag);
|
|
*pLong = htonl((WINS_MAJOR_VERS << 16 ) | WINS_MINOR_VERS);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
VOID
|
|
CommAssocUfmStartAssocRsp(
|
|
IN MSG_T pMsg,
|
|
OUT LPDWORD pMajorVer,
|
|
OUT LPDWORD pMinorVer,
|
|
OUT ULONG *puRemAssocCtx
|
|
)
|
|
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
This function formats a stop association message
|
|
|
|
|
|
Arguments:
|
|
pMsg - Buffer containing the Start Assoc. rsp. message
|
|
puRemAssocCtx - ptr to remote assoc. ctx block.
|
|
|
|
Externals Used:
|
|
None
|
|
|
|
Return Value:
|
|
None
|
|
|
|
Error Handling:
|
|
|
|
Called by:
|
|
CommAssocSetUpAssoc
|
|
|
|
Side Effects:
|
|
|
|
Comments:
|
|
None
|
|
--*/
|
|
{
|
|
/*
|
|
Increment pLong past the comm header
|
|
*/
|
|
LPLONG pLong = (LPLONG)(pMsg + COMM_HEADER_SIZE);
|
|
LONG lTmp;
|
|
|
|
*puRemAssocCtx = ntohl(*pLong++);
|
|
|
|
/*
|
|
* Get the long that contains the major and minor version numbers
|
|
*/
|
|
lTmp = ntohl(*pLong);
|
|
|
|
*pMajorVer = lTmp >> 16; //Major vers. no.
|
|
*pMinorVer = lTmp & 0xff; //Minor vers. no.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
LPVOID
|
|
CommAssocAllocAssoc(
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
This function allocates an association
|
|
|
|
|
|
Arguments:
|
|
None
|
|
|
|
Externals Used:
|
|
None
|
|
|
|
|
|
Return Value:
|
|
|
|
Success status codes --
|
|
Error status codes --
|
|
|
|
Error Handling:
|
|
|
|
Called by:
|
|
ECommAssocAllocAssoc
|
|
|
|
Side Effects:
|
|
|
|
Comments:
|
|
None
|
|
--*/
|
|
|
|
{
|
|
|
|
return(
|
|
AllocEnt(
|
|
CommAssocAssocHeapHdl,
|
|
&sAssocQueHd,
|
|
&sAssocListCrtSec,
|
|
&sAssocSeqNo,
|
|
COMMASSOC_ASSOC_DS_SZ,
|
|
&sNoOfAssocCrtSec
|
|
)
|
|
);
|
|
|
|
}
|
|
|
|
LPVOID
|
|
CommAssocAllocDlg(
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
This function allocates a dialogue context block
|
|
|
|
Arguments:
|
|
None
|
|
|
|
Externals Used:
|
|
None
|
|
|
|
|
|
Return Value:
|
|
None
|
|
|
|
Error Handling:
|
|
|
|
Called by:
|
|
ECommStartDlg, ProcTcpMsg
|
|
|
|
Side Effects:
|
|
|
|
Comments:
|
|
None
|
|
--*/
|
|
|
|
{
|
|
|
|
return(
|
|
AllocEnt(
|
|
CommAssocDlgHeapHdl,
|
|
&sDlgQueHd,
|
|
&sDlgListCrtSec,
|
|
&sDlgSeqNo,
|
|
COMMASSOC_DLG_DS_SZ,
|
|
&sNoOfDlgCrtSec
|
|
)
|
|
);
|
|
|
|
}
|
|
|
|
LPVOID
|
|
AllocEnt(
|
|
IN HANDLE HeapHdl,
|
|
IN PQUE_HD_T pQueHd,
|
|
IN LPCRITICAL_SECTION pCrtSec,
|
|
IN LPDWORD pSeqNoCntr,
|
|
IN DWORD Size,
|
|
IN LPDWORD pCntOfCrtSec
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
This function is used to allocate a ctx. block (association or dlg).
|
|
|
|
Arguments:
|
|
HeapHdl - Heap from where the alloc. muxt be done
|
|
pQueHd - Head of free list queue
|
|
pCrtSec - Critical section protecting the above queue
|
|
pSeqNoCtr - Counter value used to stamp the buffer if it is allocated
|
|
as versus when it is taken from the free list
|
|
Size - Size of buffer to allocate
|
|
|
|
Externals Used:
|
|
None
|
|
|
|
|
|
Return Value:
|
|
Ptr to the block allocated
|
|
|
|
Error Handling:
|
|
|
|
Called by:
|
|
CommAssocAllocAssoc, CommAssocAllocDlg
|
|
|
|
Side Effects:
|
|
|
|
Comments:
|
|
--*/
|
|
|
|
{
|
|
PCOMM_TOP_T pTop;
|
|
// DWORD Error;
|
|
PLIST_ENTRY pHead = &pQueHd->Head;
|
|
|
|
|
|
EnterCriticalSection(pCrtSec);
|
|
try {
|
|
|
|
if (IsListEmpty(pHead))
|
|
{
|
|
|
|
pTop = WinsMscHeapAlloc(
|
|
HeapHdl,
|
|
Size
|
|
);
|
|
#ifdef WINSDBG
|
|
IF_DBG(HEAP_CNTRS)
|
|
{
|
|
EnterCriticalSection(&NmsHeapCrtSec);
|
|
NmsHeapAllocForList++;
|
|
LeaveCriticalSection(&NmsHeapCrtSec);
|
|
}
|
|
#endif
|
|
//
|
|
// Init the critical section in the block we just allocated.
|
|
//
|
|
InitializeCriticalSection(&pTop->CrtSec);
|
|
pTop->fCrtSecInited = TRUE;
|
|
(*pCntOfCrtSec)++;
|
|
pTop->SeqNo = (*pSeqNoCntr)++;
|
|
}
|
|
else
|
|
{
|
|
pTop = (PCOMM_TOP_T)RemoveTailList(pHead);
|
|
|
|
//
|
|
// Just took a free entry. Decrement count
|
|
//
|
|
if (!pTop->fCrtSecInited)
|
|
{
|
|
InitializeCriticalSection(&pTop->CrtSec);
|
|
pTop->fCrtSecInited = TRUE;
|
|
(*pCntOfCrtSec)++;
|
|
}
|
|
}
|
|
|
|
}
|
|
finally {
|
|
LeaveCriticalSection(pCrtSec);
|
|
}
|
|
return(pTop);
|
|
}
|
|
|
|
|
|
VOID
|
|
DeallocEnt(
|
|
IN HANDLE HeapHdl,
|
|
IN PQUE_HD_T pQueHd,
|
|
IN LPCRITICAL_SECTION pCrtSec,
|
|
IN LPDWORD pSeqNoCntr,
|
|
IN LPVOID pEnt,
|
|
IN LPDWORD pCntOfCrtSec
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
The function deallocates a context block
|
|
|
|
|
|
Arguments:
|
|
pQueHd - Head of free list queue
|
|
pCrtSec - Critical section protecting the above queue
|
|
pSeqNoCtr - Counter value used to stamp the buffer before putting
|
|
it in the queue.
|
|
heap
|
|
pEnt - entity to be deallocated
|
|
|
|
Externals Used:
|
|
None
|
|
|
|
|
|
Return Value:
|
|
None
|
|
|
|
Error Handling:
|
|
|
|
Called by:
|
|
CommAssocDeallocDlg, CommAssocDeallocAssoc
|
|
|
|
Side Effects:
|
|
|
|
Comments:
|
|
None
|
|
--*/
|
|
|
|
{
|
|
PCOMM_TOP_T pTop;
|
|
PLIST_ENTRY pHead = &pQueHd->Head;
|
|
|
|
UNREFERENCED_PARAMETER(HeapHdl);
|
|
pTop = pEnt;
|
|
EnterCriticalSection(pCrtSec);
|
|
try {
|
|
(*pSeqNoCntr)++;
|
|
pTop->SeqNo = *pSeqNoCntr;
|
|
InsertTailList(pHead, &pTop->Head);
|
|
//
|
|
// Delete critical section if necessary to save on non-paged pool
|
|
//
|
|
if (*pCntOfCrtSec > COMM_FREE_COMM_HDL_THRESHOLD)
|
|
{
|
|
//
|
|
//
|
|
// We want to keep the non-paged pool within a limit.
|
|
// Deallocate this block. This ensures that we will never
|
|
// have more than COMM_FREE_COMM_HDL_THRESHOLD no of dlgs and
|
|
// assocs in the free list.
|
|
//
|
|
DeleteCriticalSection(&pTop->CrtSec);
|
|
(*pCntOfCrtSec)--;
|
|
pTop->fCrtSecInited = FALSE;
|
|
}
|
|
} //end of try
|
|
finally {
|
|
LeaveCriticalSection(pCrtSec);
|
|
}
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
CommAssocDeallocAssoc(
|
|
IN LPVOID pAssocCtx
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
The function deallocates an association context block
|
|
|
|
|
|
Arguments:
|
|
pAssocCtx - Buffer (assoc. ctx block) to deallocate
|
|
|
|
|
|
Externals Used:
|
|
None
|
|
|
|
|
|
Return Value:
|
|
None
|
|
|
|
Error Handling:
|
|
|
|
Called by:
|
|
CommAssocDeleteAssocInTbl, CommAssocSetUpAssoc, CommEndAssoc
|
|
|
|
Side Effects:
|
|
|
|
Comments:
|
|
None
|
|
--*/
|
|
|
|
{
|
|
DeallocEnt(
|
|
CommAssocAssocHeapHdl,
|
|
&sAssocQueHd,
|
|
&sAssocListCrtSec,
|
|
&sAssocSeqNo,
|
|
pAssocCtx,
|
|
&sNoOfAssocCrtSec
|
|
);
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
CommAssocDeallocDlg(
|
|
IN LPVOID pDlgCtx
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
The function deallocates a dialogue context block
|
|
|
|
|
|
Arguments:
|
|
pDlgCtx - Buffer (dlg. ctx block) to deallocate
|
|
|
|
|
|
Externals Used:
|
|
None
|
|
|
|
|
|
Return Value:
|
|
None
|
|
|
|
Error Handling:
|
|
|
|
Called by:
|
|
RtlDeleteElementGenericTable
|
|
|
|
Side Effects:
|
|
|
|
Comments:
|
|
None
|
|
--*/
|
|
|
|
{
|
|
DeallocEnt(
|
|
CommAssocDlgHeapHdl,
|
|
&sDlgQueHd,
|
|
&sDlgListCrtSec,
|
|
&sDlgSeqNo,
|
|
pDlgCtx,
|
|
&sNoOfDlgCrtSec
|
|
);
|
|
return;
|
|
}
|
|
|
|
|
|
VOID
|
|
CommAssocInit(
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
The function is called at init time to initialize the critical sections
|
|
and queues for RESPONDER associations and dialogues pertaining to
|
|
incoming request datagrams.
|
|
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Externals Used:
|
|
None
|
|
|
|
|
|
Return Value:
|
|
None
|
|
|
|
Error Handling:
|
|
|
|
Called by:
|
|
CommInit
|
|
|
|
Side Effects:
|
|
|
|
Comments:
|
|
None
|
|
--*/
|
|
|
|
{
|
|
|
|
//
|
|
// Initialize the critical sections that guard the lists of
|
|
// associations and non-udp dialogues
|
|
//
|
|
InitializeCriticalSection(&sAssocListCrtSec);
|
|
InitializeCriticalSection(&sDlgListCrtSec);
|
|
|
|
//
|
|
// Initialize the critical section for the UDP table
|
|
//
|
|
InitializeCriticalSection(&sUdpDlgTblCrtSec);
|
|
|
|
|
|
//
|
|
// Initialize the list heads for the lists of associations
|
|
// and non-udp dialogues
|
|
//
|
|
InitializeListHead(&sAssocQueHd.Head);
|
|
InitializeListHead(&sDlgQueHd.Head);
|
|
|
|
//
|
|
// Initialize the list head for the list of active responder
|
|
// associations
|
|
//
|
|
InitializeListHead(&sRspAssocQueHd.Head);
|
|
|
|
InitializeListHead(&sUdpDlgHead);
|
|
|
|
// Initialize the tag variable
|
|
InitializeCriticalSection(&sTagAssoc.crtSection);
|
|
sTagAssoc.nIdxLimit = 0;
|
|
sTagAssoc.nMaxIdx = 0;
|
|
sTagAssoc.ppStorage = NULL;
|
|
sTagAssoc.pTagPool = NULL;
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
PCOMMASSOC_DLG_CTX_T
|
|
CommAssocInsertUdpDlgInTbl(
|
|
IN PCOMMASSOC_DLG_CTX_T pCtx,
|
|
OUT LPBOOL pfNewElem
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
This function is called to insert a UDP dlg into the CommUdpNbtDlgTable.
|
|
|
|
|
|
Arguments:
|
|
|
|
pDlgCtx - Dlg Ctx Block
|
|
pfNewElem - flag indicating whether it is a new element
|
|
|
|
|
|
Externals Used:
|
|
None
|
|
|
|
|
|
Return Value:
|
|
Ptr to the dlg ctx block
|
|
|
|
Error Handling:
|
|
|
|
Called by:
|
|
|
|
Side Effects:
|
|
|
|
Comments:
|
|
None
|
|
--*/
|
|
{
|
|
|
|
PCOMMASSOC_DLG_CTX_T pDlgCtx;
|
|
|
|
|
|
EnterCriticalSection(&sUdpDlgTblCrtSec);
|
|
try {
|
|
pDlgCtx = WINSMSC_INSERT_IN_TBL_M(
|
|
&CommUdpNbtDlgTable,
|
|
pCtx,
|
|
sizeof(COMMASSOC_DLG_CTX_T),
|
|
(PBOOLEAN)pfNewElem
|
|
);
|
|
}
|
|
finally {
|
|
LeaveCriticalSection(&sUdpDlgTblCrtSec);
|
|
}
|
|
return(pDlgCtx);
|
|
}
|
|
|
|
VOID
|
|
CommAssocDeleteUdpDlgInTbl(
|
|
IN PCOMMASSOC_DLG_CTX_T pDlgCtx
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
This function is called to insert a UDP dlg into the CommUdpNbtDlgTable.
|
|
|
|
|
|
Arguments:
|
|
pDlgCtx - Dlg Ctx Block
|
|
|
|
Externals Used:
|
|
None
|
|
|
|
Return Value:
|
|
|
|
Ptr to the dlg ctx block
|
|
Error Handling:
|
|
|
|
Called by:
|
|
|
|
Side Effects:
|
|
|
|
Comments:
|
|
None
|
|
--*/
|
|
{
|
|
|
|
|
|
BOOLEAN fRetVal;
|
|
|
|
EnterCriticalSection(&sUdpDlgTblCrtSec);
|
|
try {
|
|
DBGPRINT0(FLOW, "CommAssocDeleteUdpDlgInTbl:Deleting dlg from table\n");
|
|
fRetVal = WINSMSC_DELETE_FRM_TBL_M(
|
|
&CommUdpNbtDlgTable,
|
|
pDlgCtx
|
|
);
|
|
|
|
if (fRetVal == (BOOLEAN)FALSE)
|
|
{
|
|
DBGPRINT0(ERR, "CommAssocDeleteUdpDlgInTbl:Could not delete dlg in table\n");
|
|
}
|
|
}
|
|
finally {
|
|
|
|
LeaveCriticalSection(&sUdpDlgTblCrtSec);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
LPVOID
|
|
CommAssocCreateAssocInTbl(
|
|
SOCKET SockNo
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
This function is called to create an association ctx block for
|
|
a tcp connection
|
|
|
|
Arguments:
|
|
SockNo - Socket # of socket mapped to the TCP connection
|
|
|
|
Externals Used:
|
|
sRspAssocQueHd
|
|
|
|
|
|
Return Value:
|
|
ptr to the associaton context block created for the TCP connection
|
|
|
|
Error Handling:
|
|
|
|
Called by:
|
|
MonTcp (TCP listener thread)
|
|
|
|
Side Effects:
|
|
|
|
Comments:
|
|
None
|
|
--*/
|
|
|
|
{
|
|
PCOMMASSOC_ASSOC_CTX_T pAssocCtx;
|
|
|
|
//
|
|
// Allocate/(grab from free list) an association
|
|
//
|
|
pAssocCtx = CommAssocAllocAssoc();
|
|
pAssocCtx->SockNo = SockNo;
|
|
pAssocCtx->nTag = CommAssocTagAlloc(&sTagAssoc,pAssocCtx);
|
|
|
|
CommAssocInsertAssocInTbl(pAssocCtx);
|
|
return(pAssocCtx);
|
|
}
|
|
|
|
|
|
VOID
|
|
CommAssocDeleteAssocInTbl(
|
|
PCOMMASSOC_ASSOC_CTX_T pAssocCtx
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
This function is called to delete an association context block from
|
|
the table of active responder associations. The association ctx.
|
|
block is deleted from the table and also deallocated (i.e. put
|
|
in the free list)
|
|
|
|
Arguments:
|
|
pAssocCtx - Association context block to delete from a table
|
|
|
|
Externals Used:
|
|
sRspAssocQueHd
|
|
|
|
Return Value:
|
|
None
|
|
|
|
Error Handling:
|
|
|
|
Called by:
|
|
DelAssoc
|
|
|
|
Side Effects:
|
|
|
|
Comments:
|
|
None
|
|
--*/
|
|
|
|
{
|
|
|
|
//
|
|
// Unlink the association
|
|
//
|
|
COMMASSOC_UNLINK_RSP_ASSOC_M(pAssocCtx);
|
|
|
|
//
|
|
// Dealloc the assoc. so that it can be reused for some other
|
|
// TCP connection
|
|
//
|
|
CommAssocTagFree(&sTagAssoc, pAssocCtx->nTag);
|
|
CommAssocDeallocAssoc(pAssocCtx);
|
|
return;
|
|
}
|
|
|
|
LPVOID
|
|
CommAssocLookupAssoc(
|
|
SOCKET SockNo
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
This function is called to lookup an association context block
|
|
corresponding to a socket.
|
|
|
|
Arguments:
|
|
SockNo - Socket # of socket whose association context block is
|
|
desired
|
|
|
|
Externals Used:
|
|
sRspAssocQueHd
|
|
|
|
Return Value:
|
|
|
|
ptr to assoc ctx block or NULL if there is no assoc. mapped to the
|
|
socket
|
|
|
|
Error Handling:
|
|
|
|
Called by:
|
|
DelAssoc
|
|
|
|
Side Effects:
|
|
|
|
Comments:
|
|
None
|
|
--*/
|
|
|
|
{
|
|
PCOMMASSOC_ASSOC_CTX_T pTmp =
|
|
(PCOMMASSOC_ASSOC_CTX_T)sRspAssocQueHd.Head.Flink;
|
|
|
|
//
|
|
// If list is empty, return NULL
|
|
//
|
|
if (IsListEmpty(&sRspAssocQueHd.Head))
|
|
{
|
|
return(NULL);
|
|
}
|
|
//
|
|
// Search for the assoc. mapped to socket
|
|
//
|
|
for(
|
|
;
|
|
pTmp != (PCOMMASSOC_ASSOC_CTX_T)&sRspAssocQueHd ;
|
|
pTmp = NEXT_ASSOC_M(pTmp)
|
|
)
|
|
{
|
|
if (pTmp->SockNo == SockNo)
|
|
{
|
|
return(pTmp);
|
|
}
|
|
}
|
|
|
|
//
|
|
// There is no assoc. mapped to socket SockNo. Return NULL
|
|
//
|
|
return(NULL);
|
|
}
|
|
|
|
|
|
VOID
|
|
CommAssocInsertAssocInTbl(
|
|
PCOMMASSOC_ASSOC_CTX_T pAssocCtx
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
This function is called to insert an association at the head
|
|
of the list of associations currently being monitored
|
|
|
|
Arguments:
|
|
pAssocCtx - Assoc. Ctx. Block
|
|
|
|
Externals Used:
|
|
None
|
|
|
|
|
|
Return Value:
|
|
None
|
|
Error Handling:
|
|
|
|
Called by:
|
|
CommAssocCreateAssocInTbl, ECommMonDlg
|
|
Side Effects:
|
|
|
|
Comments:
|
|
Change to a macro
|
|
--*/
|
|
|
|
{
|
|
|
|
//
|
|
// Insert at the head of the list of active responder associations
|
|
//
|
|
// Insertion is done at the head of the list in order to optimize
|
|
// the lookup of the association when the first message comes on
|
|
// it from a remote WINS. Since the first message follows on the
|
|
// heels of the connection set up, the search for the association
|
|
// which starts from the head is optimized.
|
|
//
|
|
InsertHeadList(&sRspAssocQueHd.Head, &pAssocCtx->Top.Head);
|
|
return;
|
|
}
|
|
|
|
ULONG
|
|
CommAssocTagAlloc(
|
|
PCOMMASSOC_TAG_POOL_T pTag,
|
|
LPVOID pPtrValue
|
|
)
|
|
/*++
|
|
Routine Description:
|
|
This function is used to create a mapping between a generic pointer (32bit/64bit)
|
|
and a 32bit tag.
|
|
Arguments:
|
|
pPtrValue - generic pointer value
|
|
Externals Used:
|
|
TBD
|
|
Return Value:
|
|
None
|
|
--*/
|
|
{
|
|
// a try..finally block is needed just in case the memory reallocation would raise.
|
|
// an exception. In this case, before leaving the try block and the function, the finally
|
|
// block gets executed and leaves cleanly the tag critical section. If this happens
|
|
// the exception will still be passed up the chain (since there is no except block present).
|
|
try
|
|
{
|
|
ULONG newTag;
|
|
|
|
DBGPRINT0(FLOW, "Entering CommAssocTagAlloc.\n");
|
|
|
|
EnterCriticalSection(&(pTag->crtSection));
|
|
|
|
// if nMaxIdx is 0 this means there is no entry available in the Tag pool
|
|
if (pTag->nMaxIdx == 0)
|
|
{
|
|
UINT i;
|
|
|
|
// tag pool needs to be enlarged. We might want to check if the buffers have not reached
|
|
// 2^32 entries (highly unlikely)
|
|
ULONG nNewLimit = pTag->nIdxLimit + COMMASSOC_TAG_CHUNK;
|
|
// realloc failures raise exceptions.
|
|
if (pTag->nIdxLimit == 0)
|
|
{
|
|
pTag->ppStorage = (LPVOID*)WinsMscHeapAlloc(CommAssocAssocHeapHdl, nNewLimit*sizeof(LPVOID));
|
|
pTag->pTagPool = (ULONG*)WinsMscHeapAlloc(CommAssocAssocHeapHdl, nNewLimit*sizeof(ULONG));
|
|
}
|
|
else
|
|
{
|
|
WinsMscHeapReAlloc(CommAssocAssocHeapHdl, nNewLimit*sizeof(LPVOID), (LPVOID)&(pTag->ppStorage));
|
|
WinsMscHeapReAlloc(CommAssocAssocHeapHdl, nNewLimit*sizeof(ULONG), &(pTag->pTagPool));
|
|
}
|
|
|
|
// mark the newly allocated entries as being free for use
|
|
pTag->nMaxIdx = COMMASSOC_TAG_CHUNK;
|
|
for (i = 0; i < pTag->nMaxIdx; i++)
|
|
{
|
|
// tags should be in the range 1... hence the pre-increment op here.
|
|
pTag->pTagPool[i] = ++pTag->nIdxLimit;
|
|
}
|
|
}
|
|
// at this point pTag->nMaxIdx entries are free for use and pTag->nMaxIdx is guaranteed
|
|
// to be greater than 0. The entries free for use have the indices in pTag->pTagPool[0..pTag->nMaxIdx-1]
|
|
|
|
// get the newly allocated tag
|
|
newTag = pTag->pTagPool[--pTag->nMaxIdx];
|
|
// map the pointer to this tag into the pointer storage
|
|
pTag->ppStorage[newTag-1] = pPtrValue;
|
|
|
|
#ifdef WINSDBG
|
|
// robust programming
|
|
pTag->pTagPool[pTag->nMaxIdx] = 0;
|
|
#endif
|
|
DBGPRINT2(REPL, "TagAlloc: tag for %p is %08x.\n", pPtrValue, newTag);
|
|
|
|
// return the newly allocated tag
|
|
return newTag;
|
|
}
|
|
finally
|
|
{
|
|
LeaveCriticalSection(&(pTag->crtSection));
|
|
DBGPRINT0(FLOW, "Leaving CommAssocTagAlloc.\n");
|
|
}
|
|
}
|
|
|
|
VOID
|
|
CommAssocTagFree(
|
|
PCOMMASSOC_TAG_POOL_T pTag,
|
|
ULONG nTag
|
|
)
|
|
/*++
|
|
Routine Description:
|
|
This function is used to free a mapping between a generic pointer (32bit/64bit)
|
|
and a 32bit tag.
|
|
Arguments:
|
|
nTag - tag value to be freed.
|
|
Externals Used:
|
|
TBD
|
|
Return Value:
|
|
None
|
|
--*/
|
|
{
|
|
DBGPRINT0(FLOW, "Entering CommAssocTagFree.\n");
|
|
EnterCriticalSection(&(pTag->crtSection));
|
|
|
|
#ifdef WINSDBG
|
|
// robust programming - just set the corresponding pointer from the storage to NULL
|
|
pTag->ppStorage[nTag-1] = NULL;
|
|
#endif
|
|
|
|
// just mark the nTag index as being free for use
|
|
pTag->pTagPool[pTag->nMaxIdx++] = nTag;
|
|
|
|
DBGPRINT1(REPL, "TagFree for tag %08x.\n", nTag);
|
|
|
|
// 'Free' has to match with 'Alloc' so nMaxIdx can't exceed under no circumstances nIdxLimit
|
|
ASSERT (pTag->nMaxIdx <= pTag->nIdxLimit);
|
|
|
|
LeaveCriticalSection(&(pTag->crtSection));
|
|
DBGPRINT0(FLOW, "Leaving CommAssocTagFree.\n");
|
|
}
|
|
|
|
LPVOID
|
|
CommAssocTagMap(
|
|
PCOMMASSOC_TAG_POOL_T pTag,
|
|
ULONG nTag
|
|
)
|
|
/*++
|
|
Routine Description:
|
|
This function is used to retrieve a generic pointer (32bit/64bit) that
|
|
is uniquely identified through a 32bit tag.
|
|
Arguments:
|
|
nTag - tag value that identifies the generic pointer.
|
|
Externals Used:
|
|
TBD
|
|
Return Value:
|
|
None
|
|
--*/
|
|
{
|
|
DBGPRINT0(FLOW, "Entering CommAssocTagMap.\n");
|
|
|
|
DBGPRINT2(REPL, "TagMap for tag %08x is %p.\n",
|
|
nTag,
|
|
nTag == 0 ? NULL : pTag->ppStorage[nTag-1]);
|
|
|
|
// the indices that were given have to fall in the range 0..pTag->nIdxLimit
|
|
ASSERT (nTag <= pTag->nIdxLimit);
|
|
|
|
DBGPRINT0(FLOW, "Leaving CommAssocTagMap.\n");
|
|
// return the (64bit) value from pStorage, associated with the nTag provided
|
|
return nTag == 0 ? NULL : pTag->ppStorage[nTag-1];
|
|
}
|