1727 lines
37 KiB
C
1727 lines
37 KiB
C
/*++
|
|
|
|
Copyright (c) 1990 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
queue.c
|
|
|
|
Abstract:
|
|
|
|
Contains functions for queuing and dequeuing to/from the various
|
|
work queues
|
|
|
|
|
|
Functions:
|
|
QueInsertNbtWrkItm
|
|
QueRemoveNbtWrkItm
|
|
QueInsertChlReqWrkItm
|
|
QueRemoveChlReqWrkItm
|
|
QueInsertChlRspWrkItm
|
|
QueRemoveChlRspWrkItm
|
|
QueInsertWrkItm
|
|
QueGetWrkItm
|
|
QueAllocWrkItm
|
|
QueDeallocWrkItm
|
|
QueInsertWrkItmAtHdOfList
|
|
|
|
Portability:
|
|
|
|
This module is portable
|
|
Author:
|
|
|
|
Pradeep Bahl (pradeepb) 18-Nov-1992
|
|
|
|
|
|
Revision History:
|
|
|
|
Modification date Person Description of modification
|
|
----------------- ------- ----------------------------
|
|
--*/
|
|
|
|
/*
|
|
* Includes
|
|
*/
|
|
#include "wins.h"
|
|
#include "comm.h"
|
|
//#include "winsque.h"
|
|
#include "nms.h"
|
|
#include "nmsdb.h"
|
|
#include "nmschl.h"
|
|
#include "winsmsc.h"
|
|
#include "winsevt.h"
|
|
#include "rplpush.h"
|
|
#include "rplmsgf.h"
|
|
#include "winsque.h"
|
|
|
|
/*
|
|
* Local Macro Declarations
|
|
*/
|
|
|
|
|
|
/*
|
|
* Local Typedef Declarations
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
* Global Variable Definitions
|
|
*/
|
|
//
|
|
// The various queue heads
|
|
//
|
|
QUE_HD_T QueNbtWrkQueHd; //head for nbt req queue
|
|
|
|
#if REG_N_QUERY_SEP > 0
|
|
QUE_HD_T QueOtherNbtWrkQueHd; //head for nbt req queue
|
|
#endif
|
|
DWORD QueOtherNbtWrkQueMaxLen;
|
|
|
|
QUE_HD_T QueRplPullQueHd; //head for rpl pull thread's queue
|
|
QUE_HD_T QueRplPushQueHd; //head for rpl push thread's queue
|
|
QUE_HD_T QueNmsNrcqQueHd; //head for challenge queue used by NBT
|
|
QUE_HD_T QueNmsRrcqQueHd; //head for challenge queue used by Replicator
|
|
QUE_HD_T QueNmsCrqQueHd; //head for response queue to challenges sent
|
|
QUE_HD_T QueWinsTmmQueHd; //head for timer manager's queue
|
|
QUE_HD_T QueWinsScvQueHd; //head for Scavenger's queue
|
|
QUE_HD_T QueInvalidQueHd; //head for an invalid queue
|
|
|
|
|
|
HANDLE QueBuffHeapHdl; //handle to heap for use for nbt queue items
|
|
/*
|
|
* Local Variable Definitions
|
|
*/
|
|
/*
|
|
pWinsQueQueHd
|
|
|
|
Array indexed by the enumerator QUE_TYP_E values. This array
|
|
maps the QUE_TYP_E to the address of the queue head
|
|
|
|
*/
|
|
PQUE_HD_T pWinsQueQueHd[QUE_E_TOTAL_NO_QS] = {
|
|
&QueNbtWrkQueHd, //nbt requests
|
|
#if REG_N_QUERY_SEP > 0
|
|
&QueOtherNbtWrkQueHd, //nbt requests
|
|
#endif
|
|
&QueRplPullQueHd, //Pull requests
|
|
&QueRplPushQueHd, //Push requests
|
|
&QueNmsNrcqQueHd, //Chl request from nbt thds
|
|
&QueNmsRrcqQueHd, //Chl req. from Pull thd
|
|
&QueNmsCrqQueHd, //Chl rsp from UDP thd
|
|
&QueWinsTmmQueHd, //timer queue
|
|
&QueWinsScvQueHd, //Scavenger queue
|
|
&QueInvalidQueHd
|
|
};
|
|
|
|
STATIC fsChlWaitForRsp = FALSE;
|
|
|
|
CHECK("The timer queue may not be a PLIST_ENTRY queue. We may not")
|
|
CHECK("just insert the work item at the end")
|
|
|
|
/*
|
|
* Local Function Prototype Declarations
|
|
*/
|
|
|
|
STATIC
|
|
BOOL
|
|
ChlRspDropped(
|
|
MSG_T pMsg
|
|
);
|
|
|
|
|
|
|
|
//
|
|
// Function definitions start here
|
|
//
|
|
|
|
STATUS
|
|
QueInsertNbtWrkItm(
|
|
IN PCOMM_HDL_T pDlgHdl,
|
|
IN MSG_T pMsg,
|
|
IN MSG_LEN_T MsgLen
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
This function inserts a work item on the nbt request queue
|
|
|
|
|
|
Arguments:
|
|
pDlgHdl - Handle to dialogue under which the nbt request was received
|
|
pMsg - Nbt work item
|
|
MsgLen - Size of work item
|
|
|
|
Externals Used:
|
|
None
|
|
|
|
|
|
Return Value:
|
|
|
|
Success status codes -- WINS_SUCCESS
|
|
Error status codes -- WINS_FAILURE
|
|
|
|
Error Handling:
|
|
|
|
Called by:
|
|
QueNbtReq in nms.c
|
|
|
|
Side Effects:
|
|
|
|
Comments:
|
|
None
|
|
--*/
|
|
|
|
|
|
{
|
|
|
|
|
|
PNBT_REQ_WRK_ITM_T pNbtWrkItm = NULL;
|
|
STATUS RetStat;
|
|
|
|
QueAllocWrkItm(
|
|
QueBuffHeapHdl,
|
|
sizeof(NBT_REQ_WRK_ITM_T),
|
|
(LPVOID *)&pNbtWrkItm
|
|
);
|
|
|
|
pNbtWrkItm->DlgHdl = *pDlgHdl;
|
|
pNbtWrkItm->pMsg = pMsg;
|
|
pNbtWrkItm->MsgLen = MsgLen;
|
|
|
|
RetStat = QueInsertWrkItm(
|
|
(PLIST_ENTRY)pNbtWrkItm,
|
|
QUE_E_NBT_REQ,
|
|
NULL /*ptr to que head*/
|
|
);
|
|
|
|
return(RetStat);
|
|
}
|
|
|
|
|
|
|
|
STATUS
|
|
QueRemoveNbtWrkItm(
|
|
OUT PCOMM_HDL_T pDlgHdl,
|
|
OUT PMSG_T ppMsg,
|
|
OUT PMSG_LEN_T pMsgLen
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function removes a work item from the nbt queue.
|
|
Arguments:
|
|
|
|
pDlgHdl - Handle to dialogue of nbt request dequeued
|
|
pMsg - Nbt work item
|
|
MsgLen - Size of work item
|
|
|
|
|
|
Externals Used:
|
|
None
|
|
|
|
|
|
Return Value:
|
|
|
|
Success status codes -- WINS_SUCCESS
|
|
Error status codes -- WINS_FAILURE
|
|
|
|
Error Handling:
|
|
|
|
Called by:
|
|
NbtThdInitFn() in nms.c
|
|
|
|
Side Effects:
|
|
|
|
Comments:
|
|
None
|
|
--*/
|
|
|
|
{
|
|
|
|
PNBT_REQ_WRK_ITM_T pNbtWrkItm = NULL;
|
|
STATUS RetStat;
|
|
|
|
RetStat = QueGetWrkItm(QUE_E_NBT_REQ, &pNbtWrkItm);
|
|
|
|
if (RetStat != WINS_SUCCESS)
|
|
{
|
|
*ppMsg = NULL;
|
|
}
|
|
else
|
|
{
|
|
|
|
*ppMsg = pNbtWrkItm->pMsg;
|
|
*pMsgLen = pNbtWrkItm->MsgLen;
|
|
*pDlgHdl = pNbtWrkItm->DlgHdl;
|
|
|
|
|
|
QueDeallocWrkItm( QueBuffHeapHdl, pNbtWrkItm );
|
|
}
|
|
|
|
return(RetStat);
|
|
|
|
}
|
|
#if REG_N_QUERY_SEP > 0
|
|
STATUS
|
|
QueInsertOtherNbtWrkItm(
|
|
IN PCOMM_HDL_T pDlgHdl,
|
|
IN MSG_T pMsg,
|
|
IN MSG_LEN_T MsgLen
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
This function inserts a work item on the nbt request queue
|
|
|
|
|
|
Arguments:
|
|
pDlgHdl - Handle to dialogue under which the nbt request was received
|
|
pMsg - Nbt work item
|
|
MsgLen - Size of work item
|
|
|
|
Externals Used:
|
|
None
|
|
|
|
|
|
Return Value:
|
|
|
|
Success status codes -- WINS_SUCCESS
|
|
Error status codes -- WINS_FAILURE
|
|
|
|
Error Handling:
|
|
|
|
Called by:
|
|
QueNbtReq in nms.c
|
|
|
|
Side Effects:
|
|
|
|
Comments:
|
|
None
|
|
--*/
|
|
|
|
|
|
{
|
|
|
|
|
|
PNBT_REQ_WRK_ITM_T pNbtWrkItm = NULL;
|
|
STATUS RetStat;
|
|
static BOOL SpoofingStarted = FALSE;
|
|
|
|
QueAllocWrkItm(
|
|
QueBuffHeapHdl,
|
|
sizeof(NBT_REQ_WRK_ITM_T),
|
|
(LPVOID *)&pNbtWrkItm
|
|
);
|
|
|
|
pNbtWrkItm->DlgHdl = *pDlgHdl;
|
|
pNbtWrkItm->pMsg = pMsg;
|
|
pNbtWrkItm->MsgLen = MsgLen;
|
|
|
|
RetStat = QueInsertWrkItm(
|
|
(PLIST_ENTRY)pNbtWrkItm,
|
|
QUE_E_OTHER_NBT_REQ,
|
|
NULL /*ptr to que head*/
|
|
);
|
|
//
|
|
// If the queue is full, the request was not inserted, so
|
|
// drop it. Log an event after every 100 requests have
|
|
// been dropped
|
|
//
|
|
if (RetStat == WINS_QUEUE_FULL)
|
|
{
|
|
static DWORD sNoOfReqSpoofed = 0;
|
|
static DWORD sBlockOfReq = 1;
|
|
|
|
#if DBG
|
|
static DWORD sNoOfReqDropped = 0;
|
|
#endif
|
|
if (!WinsCnf.fDoSpoofing)
|
|
{
|
|
#if DBG
|
|
NmsRegReqQDropped++;
|
|
if (sNoOfReqDropped++ == 5000)
|
|
{
|
|
sNoOfReqDropped = 0;
|
|
DBGPRINT1(ERR, "ENmsHandleMsg: REG QUEUE FULL. REQUESTS DROPPED = (%d\n", NmsRegReqQDropped);
|
|
}
|
|
|
|
#endif
|
|
//
|
|
// NOTE : freeing the buffers here takes away from modularity aspects
|
|
// of code but saves us cycles on the critical path
|
|
//
|
|
ECommFreeBuff(pMsg);
|
|
ECommEndDlg(pDlgHdl);
|
|
}
|
|
else
|
|
{
|
|
|
|
//
|
|
// we respond to groups of 300
|
|
// refresh/reg requests with a refresh interval of a multiple of
|
|
// 5 mts. The multiple is based on the group #. The refresh interval
|
|
// is not allowed to go over 1-2 hrs .
|
|
//
|
|
if (sNoOfReqSpoofed > 100)
|
|
{
|
|
if (sBlockOfReq == 10)
|
|
{
|
|
sBlockOfReq = 1;
|
|
}
|
|
else
|
|
{
|
|
sBlockOfReq++;
|
|
}
|
|
sNoOfReqSpoofed = 0;
|
|
}
|
|
else
|
|
{
|
|
sNoOfReqSpoofed++;
|
|
}
|
|
|
|
if (!SpoofingStarted)
|
|
{
|
|
WINSEVT_LOG_INFO_D_M(WINS_SUCCESS, WINS_EVT_SPOOFING_STARTED);
|
|
SpoofingStarted = TRUE;
|
|
}
|
|
DBGPRINT1(DET, "QueInsertOtherNbtWrkItm: Spoofing - SpoofBlockNum %d\n", sBlockOfReq);
|
|
NmsMsgfSndNamRsp(pDlgHdl, pMsg, MsgLen, sBlockOfReq);
|
|
}
|
|
QueDeallocWrkItm( QueBuffHeapHdl, pNbtWrkItm );
|
|
}
|
|
|
|
if ((WINS_SUCCESS == RetStat) && SpoofingStarted && QueOtherNbtWrkQueHd.NoOfEntries < (QueOtherNbtWrkQueMaxLen >> 2))
|
|
{
|
|
WINSEVT_LOG_INFO_D_M(WINS_SUCCESS, WINS_EVT_SPOOFING_COMPLETED);
|
|
SpoofingStarted = FALSE;
|
|
|
|
}
|
|
return(RetStat);
|
|
}
|
|
|
|
|
|
|
|
STATUS
|
|
QueRemoveOtherNbtWrkItm(
|
|
OUT PCOMM_HDL_T pDlgHdl,
|
|
OUT PMSG_T ppMsg,
|
|
OUT PMSG_LEN_T pMsgLen
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function removes a work item from the nbt queue.
|
|
Arguments:
|
|
|
|
pDlgHdl - Handle to dialogue of nbt request dequeued
|
|
pMsg - Nbt work item
|
|
MsgLen - Size of work item
|
|
|
|
|
|
Externals Used:
|
|
None
|
|
|
|
|
|
Return Value:
|
|
|
|
Success status codes -- WINS_SUCCESS
|
|
Error status codes -- WINS_FAILURE
|
|
|
|
Error Handling:
|
|
|
|
Called by:
|
|
NbtThdInitFn() in nms.c
|
|
|
|
Side Effects:
|
|
|
|
Comments:
|
|
None
|
|
--*/
|
|
|
|
{
|
|
|
|
PNBT_REQ_WRK_ITM_T pNbtWrkItm = NULL;
|
|
STATUS RetStat;
|
|
|
|
RetStat = QueGetWrkItm(QUE_E_OTHER_NBT_REQ, &pNbtWrkItm);
|
|
|
|
if (RetStat != WINS_SUCCESS)
|
|
{
|
|
*ppMsg = NULL;
|
|
}
|
|
else
|
|
{
|
|
|
|
*ppMsg = pNbtWrkItm->pMsg;
|
|
*pMsgLen = pNbtWrkItm->MsgLen;
|
|
*pDlgHdl = pNbtWrkItm->DlgHdl;
|
|
|
|
|
|
QueDeallocWrkItm( QueBuffHeapHdl, pNbtWrkItm );
|
|
}
|
|
|
|
return(RetStat);
|
|
|
|
}
|
|
#endif
|
|
|
|
STATUS
|
|
QueInsertChlReqWrkItm(
|
|
IN NMSCHL_CMD_TYP_E CmdTyp_e,
|
|
IN WINS_CLIENT_E Client_e,
|
|
IN PCOMM_HDL_T pDlgHdl,
|
|
IN MSG_T pMsg,
|
|
IN MSG_LEN_T MsgLen,
|
|
IN DWORD QuesNamSecLen,
|
|
IN PNMSDB_ROW_INFO_T pNodeToReg,
|
|
IN PNMSDB_STAT_INFO_T pNodeInCnf,
|
|
//IN PCOMM_ADD_T pAddOfNodeInCnf,
|
|
IN PCOMM_ADD_T pAddOfRemWins
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
This function inserts a work item on the nbt request queue
|
|
|
|
Arguments:
|
|
pDlgHdl - Handle to dialogue under which the nbt request was received
|
|
pMsg - Nbt work item
|
|
MsgLen - Size of work item
|
|
|
|
Externals Used:
|
|
None
|
|
|
|
|
|
Return Value:
|
|
|
|
Success status codes -- WINS_SUCCESS
|
|
Error status codes -- WINS_FAILURE
|
|
|
|
Error Handling:
|
|
|
|
Called by:
|
|
NmsChlHdlNamReg
|
|
|
|
Side Effects:
|
|
|
|
Comments:
|
|
None
|
|
--*/
|
|
|
|
|
|
{
|
|
|
|
|
|
PCHL_REQ_WRK_ITM_T pWrkItm = NULL;
|
|
STATUS RetStat = WINS_SUCCESS;
|
|
DWORD Error = 0;
|
|
BOOL fLvCrtSec = FALSE;
|
|
DWORD i;
|
|
|
|
QueAllocWrkItm(
|
|
NmsChlHeapHdl,
|
|
sizeof(CHL_REQ_WRK_ITM_T),
|
|
(LPVOID *)&pWrkItm
|
|
);
|
|
|
|
pWrkItm->CmdTyp_e = CmdTyp_e;
|
|
pWrkItm->Client_e = Client_e;
|
|
if (pDlgHdl != NULL)
|
|
{
|
|
pWrkItm->DlgHdl = *pDlgHdl;
|
|
}
|
|
pWrkItm->pMsg = pMsg;
|
|
pWrkItm->MsgLen = MsgLen;
|
|
pWrkItm->QuesNamSecLen = QuesNamSecLen;
|
|
pWrkItm->NodeToReg = *pNodeToReg;
|
|
|
|
pWrkItm->NodeAddsInCnf.NoOfMems = pNodeInCnf->NodeAdds.NoOfMems;
|
|
for (i=0; i < pNodeInCnf->NodeAdds.NoOfMems; i++)
|
|
{
|
|
pWrkItm->NodeAddsInCnf.Mem[i] = pNodeInCnf->NodeAdds.Mem[i];
|
|
}
|
|
pWrkItm->NoOfAddsToUse = pNodeInCnf->NodeAdds.NoOfMems;
|
|
pWrkItm->NoOfAddsToUseSv = pNodeInCnf->NodeAdds.NoOfMems;
|
|
|
|
pWrkItm->OwnerIdInCnf = pNodeInCnf->OwnerId;
|
|
pWrkItm->fGroupInCnf = NMSDB_ENTRY_GRP_M(pNodeInCnf->EntTyp);
|
|
|
|
// pWrkItm->NodeTypInCnf = pNodeInCnf->NodeTyp;
|
|
// pWrkItm->EntTypInCnf = pNodeInCnf->EntTyp;
|
|
|
|
|
|
if (pNodeToReg->pNodeAdd != NULL)
|
|
{
|
|
pWrkItm->AddToReg = *(pNodeToReg->pNodeAdd);
|
|
}
|
|
if (pAddOfRemWins != NULL)
|
|
{
|
|
pWrkItm->AddOfRemWins = *pAddOfRemWins;
|
|
}
|
|
|
|
switch(Client_e)
|
|
{
|
|
case(WINS_E_NMSNMH):
|
|
pWrkItm->QueTyp_e = QUE_E_NMSNRCQ;
|
|
break;
|
|
|
|
case(WINS_E_RPLPULL):
|
|
pWrkItm->QueTyp_e = QUE_E_NMSRRCQ;
|
|
break;
|
|
|
|
default:
|
|
DBGPRINT0(ERR, "QueInsertChlWrkItm: Invalid Client\n");
|
|
WINSEVT_LOG_M(WINS_FAILURE, WINS_EVT_SFT_ERR);
|
|
break;
|
|
|
|
}
|
|
|
|
RetStat = QueInsertWrkItm(
|
|
(PLIST_ENTRY)pWrkItm,
|
|
pWrkItm->QueTyp_e,
|
|
NULL /*ptr to que head*/
|
|
);
|
|
|
|
return(RetStat);
|
|
}
|
|
|
|
|
|
|
|
STATUS
|
|
QueRemoveChlReqWrkItm(
|
|
IN HANDLE EvtHdl,
|
|
IN OUT LPVOID *ppaWrkItm,
|
|
OUT LPDWORD pNoOfReqs
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function removes a work item from the nbt queue.
|
|
Arguments:
|
|
|
|
EvtHdl - handle of event signaled (not used currently)
|
|
ppaWrkItm - pointer to array of pointers (to work items) to
|
|
initialize
|
|
pNoOfReqs - No of Requests acquired (in the array pointed by
|
|
the ppaWrkItm arg
|
|
|
|
|
|
Externals Used:
|
|
None
|
|
|
|
|
|
Return Value:
|
|
|
|
Success status codes -- WINS_SUCCESS
|
|
Error status codes -- WINS_FAILURE
|
|
|
|
Error Handling:
|
|
|
|
Called by:
|
|
ChlThdInitFn() in nmschl.c
|
|
|
|
Side Effects:
|
|
|
|
Comments:
|
|
None
|
|
--*/
|
|
|
|
{
|
|
|
|
STATUS RetStat = WINS_SUCCESS;
|
|
PQUE_HD_T pQueHd;
|
|
|
|
UNREFERENCED_PARAMETER(EvtHdl);
|
|
*pNoOfReqs = 0;
|
|
|
|
//
|
|
// EvtHdl is the handle of the event signaled. We don't use
|
|
// it since we always need to check the queues in the sequence
|
|
// Nrcq, Rrcq, Srcq irrespective of the event that got signaled.
|
|
//
|
|
// EvtHdl is passed as an input argument for future extensibility
|
|
|
|
//
|
|
// We could have had one critical section for both the queues but that
|
|
// could slow NBT threads due to replication. We don't
|
|
// want that.
|
|
//
|
|
|
|
|
|
//
|
|
// First check the NBT Request challenge queue
|
|
//
|
|
pQueHd = &QueNmsNrcqQueHd;
|
|
EnterCriticalSection(&pQueHd->CrtSec);
|
|
try {
|
|
|
|
//
|
|
// We have a limit to the number of nodes
|
|
// we will challenge at any one time
|
|
//
|
|
while (
|
|
(!IsListEmpty(&pQueHd->Head)) &&
|
|
(*pNoOfReqs < NMSCHL_MAX_CHL_REQ_AT_ONE_TIME)
|
|
)
|
|
{
|
|
*ppaWrkItm++ = RemoveHeadList(&pQueHd->Head);
|
|
(*pNoOfReqs)++;
|
|
}
|
|
}
|
|
finally {
|
|
LeaveCriticalSection(&pQueHd->CrtSec);
|
|
}
|
|
//
|
|
// if we have reached the limit return
|
|
//
|
|
if (*pNoOfReqs == NMSCHL_MAX_CHL_REQ_AT_ONE_TIME)
|
|
{
|
|
DBGPRINT0(CHL, "QueRemoveChlReqWrkItm: Limit reached with just nbt requests\n");
|
|
*ppaWrkItm = NULL; //delimiter to the list
|
|
return(WINS_SUCCESS);
|
|
}
|
|
|
|
//
|
|
// Now check the Replicator request challenge queue (populated
|
|
// by the Pull handler
|
|
//
|
|
pQueHd = &QueNmsRrcqQueHd;
|
|
EnterCriticalSection(&pQueHd->CrtSec);
|
|
try {
|
|
while(
|
|
(!IsListEmpty(&pQueHd->Head)) &&
|
|
(*pNoOfReqs < NMSCHL_MAX_CHL_REQ_AT_ONE_TIME)
|
|
)
|
|
{
|
|
*ppaWrkItm++ = RemoveHeadList(&pQueHd->Head);
|
|
(*pNoOfReqs)++;
|
|
}
|
|
}
|
|
finally {
|
|
LeaveCriticalSection(&pQueHd->CrtSec);
|
|
}
|
|
|
|
if (*pNoOfReqs == 0)
|
|
{
|
|
RetStat = WINS_NO_REQ;
|
|
}
|
|
else
|
|
{
|
|
*ppaWrkItm = NULL; //delimiter to the list
|
|
}
|
|
|
|
return(RetStat);
|
|
}
|
|
|
|
|
|
|
|
|
|
STATUS
|
|
QueInsertChlRspWrkItm(
|
|
IN PCOMM_HDL_T pDlgHdl,
|
|
IN MSG_T pMsg,
|
|
IN MSG_LEN_T MsgLen
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
This function inserts a work item on the challenge response queue
|
|
|
|
|
|
Arguments:
|
|
|
|
pDlgHdl - Handle to dialogue under which the nbt response was received
|
|
pMsg - response message
|
|
MsgLen - response msg length
|
|
|
|
Externals Used:
|
|
None
|
|
|
|
|
|
Return Value:
|
|
|
|
Success status codes -- WINS_SUCCESS
|
|
Error status codes -- WINS_FAILURE
|
|
|
|
Error Handling:
|
|
|
|
Called by:
|
|
ENmsHdlMsg in nms.c
|
|
|
|
Side Effects:
|
|
|
|
Comments:
|
|
None
|
|
--*/
|
|
|
|
|
|
{
|
|
|
|
|
|
PCHL_REQ_WRK_ITM_T pWrkItm = NULL;
|
|
STATUS RetStat = WINS_SUCCESS;
|
|
DWORD Error = 0;
|
|
|
|
if (!ChlRspDropped(pMsg))
|
|
{
|
|
QueAllocWrkItm(
|
|
NmsChlHeapHdl,
|
|
sizeof(CHL_RSP_WRK_ITM_T),
|
|
(LPVOID *)&pWrkItm
|
|
);
|
|
|
|
pWrkItm->DlgHdl = *pDlgHdl;
|
|
pWrkItm->pMsg = pMsg;
|
|
pWrkItm->MsgLen = MsgLen;
|
|
|
|
RetStat = QueInsertWrkItm(
|
|
(PLIST_ENTRY)pWrkItm,
|
|
QUE_E_NMSCRQ,
|
|
NULL /*ptr to que head*/
|
|
);
|
|
|
|
}
|
|
return(RetStat);
|
|
}
|
|
|
|
STATUS
|
|
QueRemoveChlRspWrkItm(
|
|
IN LPVOID *ppWrkItm
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function removes a work item from the nbt queue.
|
|
Arguments:
|
|
|
|
ppaWrkItm - address of an array of pointers to chl request work items
|
|
|
|
Externals Used:
|
|
None
|
|
|
|
Return Value:
|
|
|
|
Success status codes -- WINS_SUCCESS
|
|
Error status codes -- WINS_FAILURE
|
|
|
|
Error Handling:
|
|
|
|
Called by:
|
|
ChlThdInitFn() in nmschl.c
|
|
|
|
Side Effects:
|
|
|
|
Comments:
|
|
None
|
|
--*/
|
|
|
|
{
|
|
|
|
STATUS RetStat;
|
|
RetStat = QueGetWrkItm(QUE_E_NMSCRQ, ppWrkItm);
|
|
return(RetStat);
|
|
}
|
|
|
|
|
|
STATUS
|
|
QueInsertWrkItm (
|
|
IN PLIST_ENTRY pWrkItm,
|
|
IN OPTIONAL QUE_TYP_E QueTyp_e,
|
|
IN OPTIONAL PQUE_HD_T pQueHdPassed
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
This function is called to queue a work item on
|
|
a queue. If the pQueHdPassed is Non NULL, the work item is queued
|
|
on that queue, else, it is queued on the queue specified by
|
|
QueTyp_e.
|
|
|
|
TMM will use pQueHdPassed to specify the queue while other clients
|
|
of the queue services will specify QueTyp_e
|
|
|
|
Arguments:
|
|
pWrkItm - Work Item to queue
|
|
QueTyp_e - Type of queue to queue it on (may or may not have valid value)
|
|
pQueHdPassed - Head of queue (may or may not be passed)
|
|
|
|
Externals Used:
|
|
None
|
|
|
|
Return Value:
|
|
|
|
Success status codes -- WINS_SUCCESS
|
|
Error status codes -- WINS_FAILURE
|
|
|
|
Error Handling:
|
|
|
|
Called by:
|
|
ERplInsertQue, QueInsertNbtWrkItm
|
|
|
|
Side Effects:
|
|
|
|
Comments:
|
|
None
|
|
--*/
|
|
{
|
|
|
|
STATUS RetStat = WINS_SUCCESS;
|
|
PQUE_HD_T pQueHd = NULL;
|
|
// DWORD Error;
|
|
|
|
if (pQueHdPassed == NULL)
|
|
{
|
|
|
|
pQueHd = pWinsQueQueHd[QueTyp_e];
|
|
}
|
|
else
|
|
{
|
|
pQueHd = pQueHdPassed;
|
|
}
|
|
|
|
EnterCriticalSection(&pQueHd->CrtSec);
|
|
try {
|
|
|
|
//
|
|
// If we are surpassing the limit in the Reg/Ref/Rel queue,
|
|
// don't insert the wrk. item.
|
|
//
|
|
if ((pQueHd == &QueOtherNbtWrkQueHd) &&
|
|
(pQueHd->NoOfEntries > QueOtherNbtWrkQueMaxLen))
|
|
{
|
|
RetStat = WINS_QUEUE_FULL;
|
|
}
|
|
else
|
|
{
|
|
InsertTailList(&pQueHd->Head, pWrkItm);
|
|
pQueHd->NoOfEntries++;
|
|
if (!SetEvent(pQueHd->EvtHdl))
|
|
{
|
|
// Error = GetLastError();
|
|
RetStat = WINS_FAILURE;
|
|
}
|
|
}
|
|
}
|
|
finally {
|
|
LeaveCriticalSection(&pQueHd->CrtSec);
|
|
}
|
|
|
|
return(RetStat);
|
|
|
|
}
|
|
|
|
STATUS
|
|
QueGetWrkItm (
|
|
IN QUE_TYP_E QueTyp_e,
|
|
OUT LPVOID *ppWrkItm
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
This function is called to dequeue a work item from
|
|
a queue
|
|
|
|
Arguments:
|
|
|
|
QueTyp_e - Type of queue to get the wrk item from
|
|
ppWrkItm - Work Item
|
|
|
|
Externals Used:
|
|
None
|
|
|
|
|
|
Return Value:
|
|
|
|
Success status codes -- WINS_SUCCESS or WINS_NO_REQ
|
|
Error status codes -- None at present
|
|
|
|
Error Handling:
|
|
|
|
Called by:
|
|
RplPullInit, QueNbtRemoveWrkItm
|
|
|
|
Side Effects:
|
|
|
|
Comments:
|
|
None
|
|
--*/
|
|
{
|
|
|
|
STATUS RetStat = WINS_SUCCESS;
|
|
PQUE_HD_T pQueHd;
|
|
|
|
pQueHd = pWinsQueQueHd[QueTyp_e];
|
|
|
|
EnterCriticalSection(&pQueHd->CrtSec);
|
|
try {
|
|
if (IsListEmpty(&pQueHd->Head))
|
|
{
|
|
*ppWrkItm = NULL;
|
|
RetStat = WINS_NO_REQ;
|
|
}
|
|
else
|
|
{
|
|
*ppWrkItm = RemoveHeadList(&pQueHd->Head);
|
|
pQueHd->NoOfEntries--;
|
|
}
|
|
}
|
|
finally {
|
|
LeaveCriticalSection(&pQueHd->CrtSec);
|
|
}
|
|
return(RetStat);
|
|
}
|
|
|
|
|
|
|
|
|
|
__inline
|
|
VOID
|
|
QueAllocWrkItm(
|
|
IN HANDLE HeapHdl,
|
|
IN DWORD Size,
|
|
OUT LPVOID *ppBuf
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function allocates a work item. The work item is allocated
|
|
from a heap
|
|
|
|
Arguments:
|
|
|
|
ppBuf - Buffer (work item) allocated
|
|
|
|
Externals Used:
|
|
None
|
|
|
|
|
|
Return Value:
|
|
|
|
None
|
|
Error Handling:
|
|
|
|
Called by:
|
|
QueInsertNbtWrkItm
|
|
|
|
Side Effects:
|
|
|
|
Comments:
|
|
None
|
|
--*/
|
|
{
|
|
|
|
|
|
|
|
//
|
|
// WinsMscHeapAlloc will return an exception if it is not able to
|
|
// allocate a buffer. So there is no need to check the return value
|
|
// for NULL.
|
|
//
|
|
*ppBuf = WinsMscHeapAlloc(HeapHdl, Size );
|
|
return;
|
|
}
|
|
|
|
|
|
__inline
|
|
VOID
|
|
QueDeallocWrkItm(
|
|
IN HANDLE HeapHdl,
|
|
IN PVOID pBuff
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
This function deallcoated a nbt request work item
|
|
|
|
Arguments:
|
|
pBuff - Nbt req. work item to deallocate
|
|
|
|
Externals Used:
|
|
None
|
|
|
|
|
|
Return Value:
|
|
|
|
Success status codes -- WINS_SUCCESS
|
|
Error status codes -- none currently
|
|
|
|
Error Handling:
|
|
|
|
Called by:
|
|
QueRemoveNbtWrkItm
|
|
Side Effects:
|
|
|
|
Comments:
|
|
None
|
|
--*/
|
|
{
|
|
|
|
|
|
WinsMscHeapFree(
|
|
HeapHdl,
|
|
pBuff
|
|
);
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
STATUS
|
|
QueInsertWrkItmAtHdOfList (
|
|
IN PLIST_ENTRY pWrkItm,
|
|
IN QUE_TYP_E QueTyp_e,
|
|
IN PQUE_HD_T pQueHdPassed
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
This function is called to queue a work item
|
|
at the head of a queue. If the pQueHdPassed is Non NULL,
|
|
the work item is queued on that queue, else, it is queued on
|
|
the queue specified by QueTyp_e.
|
|
|
|
TMM will use pQueHdPassed to specify the queue while other clients
|
|
of the queue services will specify QueTyp_e
|
|
|
|
Arguments:
|
|
pWrlItm - Work Item to queue
|
|
QueTyp_e - Type of queue to queue it on (may or may not have valid value)
|
|
pQueHdPassed - ListHead of queue (may or may not be passed)
|
|
|
|
Externals Used:
|
|
None
|
|
|
|
|
|
Return Value:
|
|
|
|
Success status codes -- WINS_SUCCESS
|
|
Error status codes -- WINS_FAILURE
|
|
|
|
Error Handling:
|
|
|
|
Called by:
|
|
ProcRsp in nmschl.c
|
|
|
|
Side Effects:
|
|
|
|
Comments:
|
|
This function differs from QueInsertWrkItm in that it inserts
|
|
the work item at the head of a queue versus at the tail. I
|
|
prefered to create this function rather than have an extra
|
|
argument to QueInsertWrkItm to save an if test. QueInsertWrkItm
|
|
is used by the UDP listener thread and I want to do the minimum
|
|
work I can in that thread.
|
|
|
|
|
|
--*/
|
|
{
|
|
FUTURES("I may get rid of this function since it is very similar to QueInsertWrkItm")
|
|
STATUS RetStat = WINS_SUCCESS;
|
|
PQUE_HD_T pQueHd = NULL;
|
|
DWORD Error;
|
|
|
|
if (pQueHdPassed == NULL)
|
|
{
|
|
|
|
pQueHd = pWinsQueQueHd[QueTyp_e];
|
|
}
|
|
else
|
|
{
|
|
pQueHd = pQueHdPassed;
|
|
}
|
|
|
|
EnterCriticalSection(&pQueHd->CrtSec);
|
|
try {
|
|
InsertHeadList(&pQueHd->Head, pWrkItm);
|
|
if (!SetEvent(pQueHd->EvtHdl))
|
|
{
|
|
Error = GetLastError();
|
|
RetStat = WINS_FAILURE;
|
|
}
|
|
}
|
|
finally {
|
|
LeaveCriticalSection(&pQueHd->CrtSec);
|
|
}
|
|
|
|
#ifdef WINSDBG
|
|
NmsChlNoReqAtHdOfList++;
|
|
#endif
|
|
return(RetStat);
|
|
|
|
}
|
|
|
|
|
|
|
|
STATUS
|
|
QueInsertRplPushWrkItm (
|
|
IN PLIST_ENTRY pWrkItm,
|
|
IN BOOL fAlreadyInCrtSec
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
This function is called to queue a work item on
|
|
the Push thread's queue.
|
|
|
|
Arguments:
|
|
pWrkItm - Work Item to queue
|
|
|
|
Externals Used:
|
|
None
|
|
|
|
Return Value:
|
|
|
|
Success status codes -- WINS_SUCCESS
|
|
Error status codes -- WINS_FAILURE
|
|
|
|
Error Handling:
|
|
|
|
Called by:
|
|
ERplInsertQue
|
|
|
|
Side Effects:
|
|
|
|
Comments:
|
|
None
|
|
--*/
|
|
{
|
|
|
|
STATUS RetStat = WINS_SUCCESS;
|
|
PQUE_HD_T pQueHd = pWinsQueQueHd[QUE_E_RPLPUSH];
|
|
|
|
//
|
|
// if we are already in the critical section, no need to enter it
|
|
// again
|
|
//
|
|
if (!fAlreadyInCrtSec)
|
|
{
|
|
EnterCriticalSection(&pQueHd->CrtSec);
|
|
}
|
|
try {
|
|
//
|
|
// if the push thread does not exist, create it.
|
|
//
|
|
if (!fRplPushThdExists)
|
|
{
|
|
WinsThdPool.RplThds[WINSTHD_RPL_PUSH_INDEX].ThdHdl =
|
|
WinsMscCreateThd(
|
|
RplPushInit,
|
|
NULL,
|
|
&WinsThdPool.RplThds[WINSTHD_RPL_PUSH_INDEX].ThdId
|
|
);
|
|
fRplPushThdExists = TRUE;
|
|
WinsThdPool.RplThds[WINSTHD_RPL_PUSH_INDEX].fTaken = TRUE;
|
|
WinsThdPool.ThdCount++;
|
|
}
|
|
|
|
//
|
|
// Insert the work item and signal the thread.
|
|
//
|
|
InsertTailList(&pQueHd->Head, pWrkItm);
|
|
if (!SetEvent(pQueHd->EvtHdl))
|
|
{
|
|
WINSEVT_LOG_M(WINS_EVT_SFT_ERR, GetLastError());
|
|
RetStat = WINS_FAILURE;
|
|
}
|
|
}
|
|
except(EXCEPTION_EXECUTE_HANDLER) {
|
|
DWORD ExcCode = GetExceptionCode();
|
|
DBGPRINT1(EXC, "QueInsertRplPushWrkItm: Got exception (%d)\n",ExcCode);
|
|
//
|
|
// no need to log an event. WinsMscCreateThd logs it
|
|
//
|
|
|
|
}
|
|
//
|
|
// If we entered the critical section, we should get out of it
|
|
//
|
|
if (!fAlreadyInCrtSec)
|
|
{
|
|
LeaveCriticalSection(&pQueHd->CrtSec);
|
|
}
|
|
|
|
return(RetStat);
|
|
|
|
}
|
|
|
|
VOID
|
|
QueChlWaitForRsp(
|
|
VOID
|
|
)
|
|
{
|
|
EnterCriticalSection(&QueNmsCrqQueHd.CrtSec);
|
|
fsChlWaitForRsp = TRUE;
|
|
LeaveCriticalSection(&QueNmsCrqQueHd.CrtSec);
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
QueChlNoWaitForRsp(
|
|
VOID
|
|
)
|
|
{
|
|
EnterCriticalSection(&QueNmsCrqQueHd.CrtSec);
|
|
fsChlWaitForRsp = FALSE;
|
|
LeaveCriticalSection(&QueNmsCrqQueHd.CrtSec);
|
|
return;
|
|
}
|
|
|
|
BOOL
|
|
ChlRspDropped(
|
|
MSG_T pMsg
|
|
)
|
|
{
|
|
BOOL fFreeBuff = FALSE;
|
|
EnterCriticalSection(&QueNmsCrqQueHd.CrtSec);
|
|
|
|
//
|
|
// If the challenge thread is not wait for responses, drop the
|
|
// datagram
|
|
//
|
|
if (!fsChlWaitForRsp)
|
|
{
|
|
fFreeBuff = TRUE;
|
|
|
|
}
|
|
LeaveCriticalSection(&QueNmsCrqQueHd.CrtSec);
|
|
if (fFreeBuff)
|
|
{
|
|
#ifdef WINSDBG
|
|
NmsChlNoRspDropped++;
|
|
#endif
|
|
ECommFreeBuff(pMsg);
|
|
return(TRUE);
|
|
}
|
|
return(FALSE);
|
|
}
|
|
|
|
STATUS
|
|
QueInsertNetNtfWrkItm (
|
|
IN PLIST_ENTRY pWrkItm
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
This function is called to queue a push ntf work item on
|
|
the RPLPULL queue. It checks if there is another push ntf
|
|
work item from the same WINS on the queue. If there is, it is replaced
|
|
with this new one. This is done because the new one has more information
|
|
than the previous one. The old one is terminated to free up the connection.
|
|
|
|
|
|
Arguments:
|
|
pWrkItm - Work Item to queue
|
|
|
|
Externals Used:
|
|
None
|
|
|
|
Return Value:
|
|
|
|
Success status codes -- WINS_SUCCESS
|
|
Error status codes -- WINS_FAILURE
|
|
|
|
Error Handling:
|
|
|
|
Called by:
|
|
ERplInsertQue, QueInsertNbtWrkItm
|
|
|
|
Side Effects:
|
|
|
|
Comments:
|
|
None
|
|
--*/
|
|
{
|
|
|
|
STATUS RetStat = WINS_SUCCESS;
|
|
PQUE_HD_T pQueHd = NULL;
|
|
PQUE_RPL_REQ_WRK_ITM_T pTmp;
|
|
COMM_IP_ADD_T IpAddNew;
|
|
COMM_IP_ADD_T IpAddInList;
|
|
BOOL fBreak = FALSE;
|
|
PRPL_CONFIG_REC_T pCnfRec;
|
|
|
|
|
|
//
|
|
// Get address of the WINS sending the notfication
|
|
//
|
|
pTmp = (PQUE_RPL_REQ_WRK_ITM_T)pWrkItm;
|
|
pCnfRec = pTmp->pClientCtx;
|
|
COMM_GET_IPADD_M(&pTmp->DlgHdl, &IpAddNew);
|
|
pQueHd = pWinsQueQueHd[QUE_E_RPLPULL];
|
|
|
|
EnterCriticalSection(&pQueHd->CrtSec);
|
|
try {
|
|
for(pTmp = (PQUE_RPL_REQ_WRK_ITM_T)pQueHd->Head.Flink;
|
|
pTmp != (PQUE_RPL_REQ_WRK_ITM_T)pQueHd;
|
|
pTmp = (PQUE_RPL_REQ_WRK_ITM_T)pTmp->Head.Flink)
|
|
{
|
|
|
|
|
|
if ( pTmp->CmdTyp_e == QUE_E_CMD_HDL_PUSH_NTF )
|
|
{
|
|
//
|
|
// Get address of the WINS that sent this notification
|
|
//
|
|
COMM_GET_IPADD_M(&pTmp->DlgHdl, &IpAddInList);
|
|
if (IpAddInList == IpAddNew)
|
|
{
|
|
DBGPRINT1(DET, "QueInsertNetNtfWrkItm: Found an earlier Net Ntf work item. Replacing it. WINS address = (%x)\n", IpAddInList);
|
|
//
|
|
// switch the work items since the new one takes precedence
|
|
// over the old one.
|
|
//
|
|
pWrkItm->Flink = pTmp->Head.Flink;
|
|
pWrkItm->Blink = pTmp->Head.Blink;
|
|
pTmp->Head.Blink->Flink = pWrkItm;
|
|
pTmp->Head.Flink->Blink = pWrkItm;
|
|
fBreak = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
//
|
|
// If there was no match, insert at tail end of list
|
|
//
|
|
if (!fBreak)
|
|
{
|
|
InsertTailList(&pQueHd->Head, pWrkItm);
|
|
}
|
|
if (!SetEvent(pQueHd->EvtHdl))
|
|
{
|
|
// Error = GetLastError();
|
|
RetStat = WINS_FAILURE;
|
|
}
|
|
} // end of try
|
|
finally {
|
|
LeaveCriticalSection(&pQueHd->CrtSec);
|
|
}
|
|
//
|
|
// If we found a match, terminate the old work item
|
|
//
|
|
// Do this outside the critical section
|
|
//
|
|
if (fBreak)
|
|
{
|
|
CHECK("Can we avoid the try block")
|
|
try {
|
|
#if PRSCONN
|
|
RPLMSGF_MSG_OPCODE_E Opcode_e;
|
|
BOOL fPrsDlg;
|
|
#endif
|
|
|
|
|
|
#if PRSCONN
|
|
//
|
|
// If the ntf was sent on a persistent dlg, we do not terminate it since
|
|
// it will be terminated by the remote WINS when it so chooses. This
|
|
// dlg is used for multiple such notifications. If
|
|
// it was sent on a non-persistent dlg, we will terminate it since the
|
|
// remote WINS create a dlg for each such notification
|
|
//
|
|
RPLMSGF_GET_OPC_FROM_MSG_M(pTmp->pMsg, Opcode_e);
|
|
|
|
fPrsDlg = ((Opcode_e == RPLMSGF_E_UPDATE_NTF_PRS) || (Opcode_e == RPLMSGF_E_UPDATE_NTF_PROP_PRS));
|
|
if (!fPrsDlg)
|
|
{
|
|
ECommEndDlg(&pTmp->DlgHdl);
|
|
}
|
|
#else
|
|
ECommEndDlg(&pTmp->DlgHdl);
|
|
#endif
|
|
//
|
|
// Terminate the dequeued request.
|
|
//
|
|
ECommFreeBuff(pTmp->pMsg - COMM_HEADER_SIZE);
|
|
QueDeallocWrkItm(RplWrkItmHeapHdl, pTmp);
|
|
|
|
}
|
|
except (EXCEPTION_EXECUTE_HANDLER) {
|
|
DBGPRINTEXC("QueInsertNtfWrkItm");
|
|
}
|
|
}
|
|
|
|
return(RetStat);
|
|
|
|
}
|
|
STATUS
|
|
QueInsertSndNtfWrkItm (
|
|
IN PLIST_ENTRY pWrkItmp
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
This function is called to queue a send push ntf work item on
|
|
the RPLPULL queue. It checks if there is another send push ntf
|
|
work item from the same WINS on the queue. If there is, it is replaced
|
|
with this new one. This is done because the new one has more information
|
|
than the previous one. The old one is terminated to free up the connection.
|
|
|
|
|
|
Arguments:
|
|
pWrkItm - Work Item to queue
|
|
|
|
Externals Used:
|
|
None
|
|
|
|
Return Value:
|
|
|
|
Success status codes -- WINS_SUCCESS
|
|
Error status codes -- WINS_FAILURE
|
|
|
|
Error Handling:
|
|
|
|
Called by:
|
|
ERplInsertQue, QueInsertNbtWrkItm
|
|
|
|
Side Effects:
|
|
|
|
Comments:
|
|
None
|
|
--*/
|
|
{
|
|
|
|
STATUS RetStat = WINS_SUCCESS;
|
|
PQUE_HD_T pQueHd = NULL;
|
|
PQUE_RPL_REQ_WRK_ITM_T pTmp;
|
|
PQUE_RPL_REQ_WRK_ITM_T pWrkItm = (PQUE_RPL_REQ_WRK_ITM_T)pWrkItmp;
|
|
COMM_IP_ADD_T IpAddNew;
|
|
COMM_IP_ADD_T IpAddInList;
|
|
BOOL fBreak = FALSE;
|
|
PRPL_CONFIG_REC_T pCnfRec;
|
|
|
|
|
|
pTmp = (PQUE_RPL_REQ_WRK_ITM_T)pWrkItm;
|
|
pCnfRec = pTmp->pClientCtx;
|
|
IpAddNew = pCnfRec->WinsAdd.Add.IPAdd;
|
|
pQueHd = pWinsQueQueHd[QUE_E_RPLPULL];
|
|
|
|
EnterCriticalSection(&pQueHd->CrtSec);
|
|
try {
|
|
for(
|
|
pTmp = (PQUE_RPL_REQ_WRK_ITM_T)pQueHd->Head.Flink;
|
|
pTmp != (PQUE_RPL_REQ_WRK_ITM_T)pQueHd;
|
|
// no 3rd expression
|
|
)
|
|
{
|
|
|
|
//
|
|
// If this is a push ntf item, then go on to the next if test
|
|
//
|
|
if (( pTmp->CmdTyp_e == QUE_E_CMD_SND_PUSH_NTF ) ||
|
|
(pTmp->CmdTyp_e == QUE_E_CMD_SND_PUSH_NTF_PROP))
|
|
{
|
|
IpAddInList = ((PRPL_CONFIG_REC_T)(pTmp->pClientCtx))->WinsAdd.Add.IPAdd;
|
|
//
|
|
// If the push is to the same WINS, replace the work item
|
|
//
|
|
if (IpAddInList == IpAddNew)
|
|
{
|
|
if (pTmp->CmdTyp_e == QUE_E_CMD_SND_PUSH_NTF_PROP)
|
|
{
|
|
pWrkItm->CmdTyp_e = pTmp->CmdTyp_e;
|
|
}
|
|
|
|
DBGPRINT1(DET, "QueInsertSndNtfWrkItm: Found an earlier Snd Ntf work item. Replacing it. WINS address = (%x)\n", IpAddInList);
|
|
|
|
//
|
|
// switch the work items since the new one takes precedence
|
|
// over the old one.
|
|
//
|
|
pWrkItmp->Flink = pTmp->Head.Flink;
|
|
pWrkItmp->Blink = pTmp->Head.Blink;
|
|
pTmp->Head.Blink->Flink = pWrkItmp;
|
|
pTmp->Head.Flink->Blink = pWrkItmp;
|
|
fBreak = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
pTmp = (PQUE_RPL_REQ_WRK_ITM_T)pTmp->Head.Flink;
|
|
}
|
|
if (!fBreak)
|
|
{
|
|
InsertTailList(&pQueHd->Head, pWrkItmp);
|
|
}
|
|
if (!SetEvent(pQueHd->EvtHdl))
|
|
{
|
|
// Error = GetLastError();
|
|
RetStat = WINS_FAILURE;
|
|
}
|
|
}
|
|
finally {
|
|
LeaveCriticalSection(&pQueHd->CrtSec);
|
|
|
|
//
|
|
// if we replaced an item, we need to deallocate it here.
|
|
//
|
|
if (fBreak)
|
|
{
|
|
QueDeallocWrkItm(RplWrkItmHeapHdl, pTmp);
|
|
}
|
|
}
|
|
return(RetStat);
|
|
|
|
}
|
|
|
|
__inline
|
|
STATUS
|
|
QueInsertScvWrkItm (
|
|
IN PLIST_ENTRY pWrkItm
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
This function is called to queue a work item on
|
|
the Push thread's queue.
|
|
|
|
Arguments:
|
|
pWrkItm - Work Item to queue
|
|
|
|
Externals Used:
|
|
None
|
|
|
|
Return Value:
|
|
|
|
Success status codes -- WINS_SUCCESS
|
|
Error status codes -- WINS_FAILURE
|
|
|
|
Error Handling:
|
|
|
|
Called by:
|
|
ERplInsertQue
|
|
|
|
Side Effects:
|
|
|
|
Comments:
|
|
None
|
|
--*/
|
|
{
|
|
return(QueInsertWrkItm ( pWrkItm, QUE_E_WINSSCVQ, NULL));
|
|
}
|
|
__inline
|
|
STATUS
|
|
QueRemoveScvWrkItm(
|
|
IN OUT LPVOID *ppWrkItm
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function removes a work item from the nbt queue.
|
|
Arguments:
|
|
|
|
ppWrkItm - pointer to array of pointers (to work items) to
|
|
initialize
|
|
|
|
|
|
Externals Used:
|
|
None
|
|
|
|
|
|
Return Value:
|
|
|
|
Success status codes -- WINS_SUCCESS
|
|
Error status codes -- WINS_FAILURE
|
|
|
|
Error Handling:
|
|
|
|
Called by:
|
|
|
|
Side Effects:
|
|
|
|
Comments:
|
|
None
|
|
--*/
|
|
|
|
{
|
|
return(QueGetWrkItm(QUE_E_WINSSCVQ, ppWrkItm));
|
|
}
|
|
|
|
|
|
VOID
|
|
WinsQueInit(
|
|
LPTSTR pName,
|
|
PQUE_HD_T pQueHd
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
Function to init a queue
|
|
|
|
Arguments:
|
|
|
|
|
|
Externals Used:
|
|
None
|
|
|
|
|
|
Return Value:
|
|
|
|
Success status codes --
|
|
Error status codes --
|
|
|
|
Error Handling:
|
|
|
|
Called by:
|
|
|
|
Side Effects:
|
|
|
|
Comments:
|
|
None
|
|
--*/
|
|
|
|
{
|
|
//
|
|
// Create the response event handle. This event is signaled
|
|
// by the UDP listener thread when it stores a response
|
|
// in the spReqWrkItmArr array
|
|
//
|
|
WinsMscCreateEvt(
|
|
pName,
|
|
FALSE, //auto-reset
|
|
&pQueHd->EvtHdl
|
|
);
|
|
|
|
|
|
//
|
|
// Initialize the critical section for the response queue
|
|
//
|
|
InitializeCriticalSection(&pQueHd->CrtSec);
|
|
|
|
//
|
|
//Initialize the queue head for the response queue
|
|
//
|
|
InitializeListHead(&pQueHd->Head);
|
|
pQueHd->NoOfEntries = 0; //not required really since QueHd structures
|
|
//are externs
|
|
return;
|
|
}
|
|
|