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.
4189 lines
124 KiB
4189 lines
124 KiB
/*++
|
|
|
|
Copyright (c) 1990 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
winsintf.c
|
|
|
|
Abstract:
|
|
This module contains the RPC interface to the WINS server
|
|
|
|
Functions:
|
|
R_WinsRecordAction
|
|
R_WinsStatus
|
|
R_WinsTrigger
|
|
R_WinsDoStaticInit
|
|
R_WinsGetDbRecs
|
|
R_WinsDelDbRecs
|
|
R_WinsSetProcPriority
|
|
WinsRecordAction
|
|
GetWinsStatus
|
|
WinsTrigger
|
|
WinsDoStaticInit
|
|
WinsDoScavenging
|
|
WinsGetDbRecs
|
|
WinsDelDbRecs
|
|
WinsSetProcPriority
|
|
sGetVersNo
|
|
GetConfig
|
|
GetStatistics
|
|
|
|
|
|
Portability:
|
|
|
|
This module is portable
|
|
|
|
|
|
Author:
|
|
|
|
Pradeep Bahl (PradeepB) Mar-1993
|
|
|
|
Revision History:
|
|
|
|
Modification date Person Description of modification
|
|
----------------- ------- ----------------------------
|
|
--*/
|
|
|
|
/*
|
|
* Includes
|
|
*/
|
|
#include <time.h>
|
|
#include "wins.h"
|
|
#include <lmerr.h>
|
|
#include <lmcons.h> //defines NET_API_STATUS
|
|
#include <secobj.h>
|
|
#include <rpcutil.h> //for NetpRevertToSelf
|
|
#include <rpcndr.h>
|
|
#include "winsif.h"
|
|
#include "winsi2.h"
|
|
#include "winsintf.h"
|
|
#include "comm.h"
|
|
#include "winsque.h"
|
|
#include "nms.h"
|
|
#include "nmsnmh.h"
|
|
#include "nmsmsgf.h"
|
|
#include "nmsdb.h"
|
|
#include "nmsscv.h"
|
|
#include "rpl.h"
|
|
#include "rplpull.h"
|
|
#include "winscnf.h"
|
|
#include "winsevt.h"
|
|
#include "winsmsc.h"
|
|
#include "winsprs.h"
|
|
#include "winstmm.h"
|
|
#ifdef WINSDBG
|
|
#include "winbasep.h"
|
|
#endif
|
|
|
|
/*
|
|
* Local Macro Declarations
|
|
*/
|
|
|
|
#if SECURITY > 0
|
|
#define CHK_ACCESS_LEVEL_M(_access) { \
|
|
if (!sfBS) \
|
|
{ \
|
|
NET_API_STATUS NetStatus; \
|
|
NetStatus = NetpAccessCheckAndAudit( \
|
|
WINS_SERVER, \
|
|
WINS_SERVER, \
|
|
pNmsSecurityDescriptor, \
|
|
_access, \
|
|
&NmsInfoMapping \
|
|
); \
|
|
if (NetStatus != NERR_Success) \
|
|
{ \
|
|
DBGPRINT1(ERR, "The Caller of the rpc function does not have the required permissions. NetSTatus is (%d)\n", NetStatus); \
|
|
WINSEVT_LOG_M(NetStatus, WINS_EVT_NO_PERM);\
|
|
return(NetStatus); \
|
|
} \
|
|
} \
|
|
}
|
|
|
|
#else
|
|
#define CHK_ACCESS_LEVEL_M()
|
|
#endif
|
|
|
|
#define INC_RPC_DB_COUNT_NCHK_M { \
|
|
EnterCriticalSection(&NmsTermCrtSec); \
|
|
NmsTotalTrmThdCnt++; \
|
|
LeaveCriticalSection(&NmsTermCrtSec); \
|
|
}
|
|
#define INC_RPC_DB_COUNT_M { \
|
|
if (WinsCnf.State_e != WINSCNF_E_TERMINATING) \
|
|
{ \
|
|
INC_RPC_DB_COUNT_NCHK_M; \
|
|
} \
|
|
else \
|
|
{ \
|
|
return(WINSINTF_FAILURE); \
|
|
} \
|
|
}
|
|
#define DEC_RPC_DB_COUNT_M { \
|
|
EnterCriticalSection(&NmsTermCrtSec); \
|
|
if (--NmsTotalTrmThdCnt == 1) \
|
|
{ \
|
|
DBGPRINT0(FLOW, "RPC thread: Signaling the main thread\n");\
|
|
SetEvent(NmsMainTermEvt); \
|
|
} \
|
|
LeaveCriticalSection(&NmsTermCrtSec); \
|
|
}
|
|
/*
|
|
* Local Typedef Declarations
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
* Global Variable Definitions
|
|
*/
|
|
WINSINTF_STAT_T WinsIntfStat = {0};
|
|
|
|
DWORD WinsIntfNoOfNbtThds;
|
|
DWORD WinsIntfNoCncrntStaticInits = 0;
|
|
//DWORD WinsIntfNoOfRpcThds = 0;
|
|
CRITICAL_SECTION WinsIntfCrtSec;
|
|
|
|
CRITICAL_SECTION WinsIntfPotentiallyLongCrtSec;
|
|
CRITICAL_SECTION WinsIntfNoOfUsersCrtSec; //extern in nms.h
|
|
|
|
/*
|
|
* Local Variable Definitions
|
|
*/
|
|
STATIC BOOL sfBS = FALSE;
|
|
|
|
//
|
|
// Time interval between reflushing of the 1B cache
|
|
//
|
|
#define THREE_MTS 180
|
|
|
|
//
|
|
// Used by WinsGetBrowserNames
|
|
//
|
|
DOM_CACHE_T sDomCache = { 0, NULL, 0, 0, NULL, FALSE};
|
|
|
|
/*
|
|
* Local Function Prototype Declarations
|
|
*/
|
|
DWORD
|
|
GetWinsStatus(
|
|
IN WINSINTF_CMD_E Cmd_e,
|
|
OUT LPVOID pResults,
|
|
BOOL fNew
|
|
);
|
|
|
|
STATIC
|
|
DWORD
|
|
sGetVersNo(
|
|
LPVOID pResults
|
|
);
|
|
|
|
STATIC
|
|
DWORD
|
|
GetStatistics(
|
|
LPVOID pResults,
|
|
BOOL fNew
|
|
);
|
|
|
|
STATIC
|
|
DWORD
|
|
GetConfig(
|
|
LPVOID pResults,
|
|
BOOL fNew,
|
|
BOOL fAllMaps
|
|
);
|
|
|
|
VOID
|
|
LogClientInfo(
|
|
RPC_BINDING_HANDLE ClientHdl,
|
|
BOOL fAbruptTerm
|
|
);
|
|
|
|
|
|
STATIC
|
|
STATUS
|
|
PackageRecs(
|
|
PRPL_REC_ENTRY2_T pBuff,
|
|
DWORD BuffLen,
|
|
DWORD NoOfRecs,
|
|
PWINSINTF_RECS_T pRecs
|
|
);
|
|
|
|
|
|
//
|
|
// Function definitions start here
|
|
//
|
|
|
|
DWORD
|
|
R_WinsCheckAccess(
|
|
WINSIF2_HANDLE ServerHdl,
|
|
DWORD *Access
|
|
)
|
|
{
|
|
NET_API_STATUS NetStatus;
|
|
*Access = WINS_NO_ACCESS;
|
|
NetStatus = NetpAccessCheckAndAudit(
|
|
WINS_SERVER,
|
|
WINS_SERVER,
|
|
pNmsSecurityDescriptor,
|
|
WINS_CONTROL_ACCESS,
|
|
&NmsInfoMapping
|
|
);
|
|
if (NERR_Success == NetStatus) {
|
|
*Access = WINS_CONTROL_ACCESS;
|
|
return WINSINTF_SUCCESS;
|
|
}
|
|
NetStatus = NetpAccessCheckAndAudit(
|
|
WINS_SERVER,
|
|
WINS_SERVER,
|
|
pNmsSecurityDescriptor,
|
|
WINS_QUERY_ACCESS,
|
|
&NmsInfoMapping
|
|
);
|
|
if (NERR_Success == NetStatus) {
|
|
*Access = WINS_QUERY_ACCESS;
|
|
return WINSINTF_SUCCESS;
|
|
}
|
|
return WINSINTF_SUCCESS;
|
|
}
|
|
|
|
DWORD
|
|
R_WinsRecordAction(
|
|
PWINSINTF_RECORD_ACTION_T *ppRecAction
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
This function is called to insert/update/delete a record
|
|
|
|
Arguments:
|
|
pRecAction - Record Information
|
|
|
|
Externals Used:
|
|
None
|
|
|
|
Return Value:
|
|
|
|
Success status codes --
|
|
Error status codes --
|
|
|
|
Error Handling:
|
|
|
|
Called by:
|
|
|
|
Side Effects:
|
|
|
|
Comments:
|
|
None
|
|
--*/
|
|
|
|
{
|
|
|
|
DWORD Status = WINSINTF_FAILURE;
|
|
|
|
PERF("Use & and || logic")
|
|
|
|
if (*ppRecAction == NULL)
|
|
{
|
|
return(Status);
|
|
}
|
|
if ((WinsCnf.State_e == WINSCNF_E_RUNNING) || (WinsCnf.State_e == WINSCNF_E_PAUSED))
|
|
{
|
|
if (WINSINTF_E_QUERY == (*ppRecAction)->Cmd_e) {
|
|
CHK_ACCESS_LEVEL_M(WINS_QUERY_ACCESS);
|
|
} else {
|
|
CHK_ACCESS_LEVEL_M(WINS_CONTROL_ACCESS);
|
|
}
|
|
INC_RPC_DB_COUNT_NCHK_M;
|
|
try {
|
|
Status = WinsRecordAction(ppRecAction);
|
|
}
|
|
finally {
|
|
DEC_RPC_DB_COUNT_M;
|
|
}
|
|
}
|
|
|
|
return(Status);
|
|
}
|
|
|
|
|
|
DWORD
|
|
R_WinsStatusWHdl (
|
|
WINSIF_HANDLE pWinsHdl,
|
|
WINSINTF_CMD_E Cmd_e,
|
|
PWINSINTF_RESULTS_NEW_T pResults
|
|
)
|
|
{
|
|
return(R_WinsStatusNew(Cmd_e, pResults));
|
|
|
|
}
|
|
|
|
DWORD
|
|
R_WinsStatus (
|
|
// LPTSTR pWinsAddStr,
|
|
WINSINTF_CMD_E Cmd_e,
|
|
PWINSINTF_RESULTS_T pResults
|
|
)
|
|
{
|
|
|
|
DWORD Status = WINSINTF_FAILURE;
|
|
|
|
//
|
|
// Make sure that the WINS is in steady state
|
|
//
|
|
PERF("Use & and || logic")
|
|
if ((WinsCnf.State_e == WINSCNF_E_RUNNING) || (WinsCnf.State_e == WINSCNF_E_PAUSED))
|
|
{
|
|
CHK_ACCESS_LEVEL_M(WINS_QUERY_ACCESS);
|
|
Status = GetWinsStatus(/*pWinsAddStr,*/Cmd_e, pResults, FALSE);
|
|
}
|
|
return(Status);
|
|
}
|
|
DWORD
|
|
R_WinsStatusNew (
|
|
WINSINTF_CMD_E Cmd_e,
|
|
PWINSINTF_RESULTS_NEW_T pResults
|
|
)
|
|
{
|
|
|
|
DWORD Status = WINSINTF_FAILURE;
|
|
|
|
//
|
|
// Make sure that the WINS is in steady state
|
|
//
|
|
PERF("Use & and || logic")
|
|
if ((WinsCnf.State_e == WINSCNF_E_RUNNING) || (WinsCnf.State_e == WINSCNF_E_PAUSED))
|
|
{
|
|
CHK_ACCESS_LEVEL_M(WINS_QUERY_ACCESS);
|
|
Status = GetWinsStatus(Cmd_e, pResults, TRUE);
|
|
}
|
|
return(Status);
|
|
}
|
|
|
|
DWORD
|
|
R_WinsTrigger (
|
|
PWINSINTF_ADD_T pWinsAdd,
|
|
WINSINTF_TRIG_TYPE_E TrigType_e
|
|
)
|
|
{
|
|
DWORD Status = WINSINTF_FAILURE;
|
|
PERF("Use & and || logic")
|
|
if ((WinsCnf.State_e == WINSCNF_E_RUNNING) || (WinsCnf.State_e == WINSCNF_E_PAUSED))
|
|
{
|
|
CHK_ACCESS_LEVEL_M(WINS_CONTROL_ACCESS);
|
|
Status = WinsTrigger(pWinsAdd, TrigType_e);
|
|
}
|
|
return(Status);
|
|
}
|
|
|
|
DWORD
|
|
R_WinsDoStaticInit (
|
|
LPWSTR pDataFilePath,
|
|
DWORD fDel
|
|
)
|
|
{
|
|
DWORD Status;
|
|
|
|
CHK_ACCESS_LEVEL_M(WINS_CONTROL_ACCESS);
|
|
EnterCriticalSection(&WinsIntfCrtSec);
|
|
|
|
//
|
|
// The admin tool can go haywire and create a lot of threads. Limit it
|
|
// to a certain max value. The value will be incremented and decremented
|
|
// by the thread doing the STATIC initialization.
|
|
//
|
|
if (WinsIntfNoCncrntStaticInits > WINSCNF_MAX_CNCRNT_STATIC_INITS)
|
|
{
|
|
LeaveCriticalSection(&WinsIntfCrtSec);
|
|
DBGPRINT1(ERR, "R_WinsDoStaticInit: Too many concurrent STATIC inits. No is (%d)\n", WinsIntfNoCncrntStaticInits);
|
|
WINSEVT_LOG_D_M(WinsIntfNoCncrntStaticInits, WINS_EVT_TOO_MANY_STATIC_INITS);
|
|
return(WINSINTF_TOO_MANY_STATIC_INITS);
|
|
}
|
|
LeaveCriticalSection(&WinsIntfCrtSec);
|
|
Status = WinsDoStaticInit(pDataFilePath, fDel);
|
|
return(Status);
|
|
}
|
|
|
|
DWORD
|
|
R_WinsDoScavenging (
|
|
VOID
|
|
)
|
|
{
|
|
DWORD Status;
|
|
CHK_ACCESS_LEVEL_M(WINS_CONTROL_ACCESS);
|
|
INC_RPC_DB_COUNT_M;
|
|
try {
|
|
Status = WinsDoScavenging();
|
|
}
|
|
finally {
|
|
DEC_RPC_DB_COUNT_M;
|
|
}
|
|
return(Status);
|
|
}
|
|
|
|
DWORD
|
|
R_WinsDoScavengingNew (
|
|
PWINSINTF_SCV_REQ_T pScvReq
|
|
)
|
|
{
|
|
DWORD Status;
|
|
CHK_ACCESS_LEVEL_M(WINS_CONTROL_ACCESS);
|
|
INC_RPC_DB_COUNT_M;
|
|
try {
|
|
Status = WinsDoScavengingNew(pScvReq);
|
|
}
|
|
finally {
|
|
DEC_RPC_DB_COUNT_M;
|
|
}
|
|
return(Status);
|
|
}
|
|
|
|
DWORD
|
|
R_WinsGetDbRecs (
|
|
PWINSINTF_ADD_T pWinsAdd,
|
|
WINSINTF_VERS_NO_T MinVersNo,
|
|
WINSINTF_VERS_NO_T MaxVersNo,
|
|
PWINSINTF_RECS_T pRecs
|
|
)
|
|
{
|
|
DWORD Status;
|
|
CHK_ACCESS_LEVEL_M(WINS_QUERY_ACCESS);
|
|
INC_RPC_DB_COUNT_M;
|
|
try {
|
|
#if 0
|
|
#ifdef WINSDBG
|
|
PVOID pCallersAdd, pCallersCaller;
|
|
RtlGetCallersAddress(&pCallersAdd, &pCallersCaller);
|
|
DbgPrint("Callers Address = (%x)\nCallersCaller = (%x)\n", pCallersAdd, pCallersCaller);
|
|
|
|
#endif
|
|
#endif
|
|
Status = WinsGetDbRecs(pWinsAdd, MinVersNo, MaxVersNo, pRecs);
|
|
}
|
|
finally {
|
|
DEC_RPC_DB_COUNT_M;
|
|
}
|
|
return(Status);
|
|
}
|
|
DWORD
|
|
R_WinsGetDbRecsByName (
|
|
PWINSINTF_ADD_T pWinsAdd,
|
|
DWORD Location,
|
|
LPBYTE pName,
|
|
DWORD NameLen,
|
|
DWORD NoOfRecsDesired,
|
|
DWORD fStaticOnly,
|
|
PWINSINTF_RECS_T pRecs
|
|
)
|
|
{
|
|
DWORD Status;
|
|
CHK_ACCESS_LEVEL_M(WINS_QUERY_ACCESS);
|
|
INC_RPC_DB_COUNT_M;
|
|
try {
|
|
#if 0
|
|
#ifdef WINSDBG
|
|
PVOID pCallersAdd, pCallersCaller;
|
|
RtlGetCallersAddress(&pCallersAdd, &pCallersCaller);
|
|
#endif
|
|
#endif
|
|
Status = WinsGetDbRecsByName(pWinsAdd, Location, pName, NameLen, NoOfRecsDesired,
|
|
fStaticOnly, pRecs);
|
|
}
|
|
finally {
|
|
DEC_RPC_DB_COUNT_M;
|
|
}
|
|
return(Status);
|
|
}
|
|
|
|
|
|
|
|
DWORD
|
|
R_WinsDeleteWins(
|
|
PWINSINTF_ADD_T pWinsAdd
|
|
)
|
|
{
|
|
DWORD Status;
|
|
//LogClientInfo();
|
|
CHK_ACCESS_LEVEL_M(WINS_CONTROL_ACCESS);
|
|
INC_RPC_DB_COUNT_M;
|
|
try {
|
|
Status = WinsDeleteWins(pWinsAdd);
|
|
}
|
|
finally {
|
|
DEC_RPC_DB_COUNT_M;
|
|
}
|
|
return(Status);
|
|
}
|
|
|
|
DWORD
|
|
R_WinsTerm (
|
|
handle_t ClientHdl,
|
|
short fAbruptTerm
|
|
)
|
|
{
|
|
DWORD Status;
|
|
CHK_ACCESS_LEVEL_M(WINS_CONTROL_ACCESS);
|
|
Status = WinsTerm(ClientHdl, fAbruptTerm);
|
|
LogClientInfo(ClientHdl, fAbruptTerm);
|
|
return(Status);
|
|
}
|
|
|
|
|
|
DWORD
|
|
R_WinsBackup (
|
|
LPBYTE pBackupPath,
|
|
short fIncremental
|
|
)
|
|
{
|
|
|
|
DWORD Status = WINSINTF_FAILURE;
|
|
BYTE BackupPath[WINS_MAX_FILENAME_SZ + sizeof(WINS_BACKUP_DIR_ASCII)];
|
|
#if 0
|
|
(VOID)WinsMscConvertUnicodeStringToAscii(pBackupPath, BackupPath, WINS_MAX_FILENAME_SZ);
|
|
#endif
|
|
FUTURES("expensive. Change idl prototype to pass length")
|
|
if (strlen(pBackupPath) > WINS_MAX_FILENAME_SZ)
|
|
{
|
|
return(Status);
|
|
}
|
|
//
|
|
// Make sure that the WINS is in steady state
|
|
//
|
|
PERF("Use & and || logic")
|
|
if ((WinsCnf.State_e == WINSCNF_E_RUNNING) || (WinsCnf.State_e == WINSCNF_E_PAUSED))
|
|
{
|
|
CHK_ACCESS_LEVEL_M(WINS_CONTROL_ACCESS);
|
|
INC_RPC_DB_COUNT_NCHK_M;
|
|
WinsLogAdminEvent( WINS_EVT_ADMIN_BACKUP_INITIATED, 0 );
|
|
try {
|
|
strcpy(BackupPath, pBackupPath);
|
|
strcat(BackupPath, WINS_BACKUP_DIR_ASCII);
|
|
if (CreateDirectoryA(BackupPath, NULL) || ((Status = GetLastError()) ==
|
|
ERROR_ALREADY_EXISTS))
|
|
{
|
|
Status = WinsBackup(BackupPath, fIncremental);
|
|
}
|
|
}
|
|
finally {
|
|
DEC_RPC_DB_COUNT_M;
|
|
}
|
|
}
|
|
return(Status);
|
|
}
|
|
|
|
DWORD
|
|
R_WinsDelDbRecs(
|
|
IN PWINSINTF_ADD_T pAdd,
|
|
IN WINSINTF_VERS_NO_T MinVersNo,
|
|
IN WINSINTF_VERS_NO_T MaxVersNo
|
|
)
|
|
{
|
|
|
|
DWORD Status = WINSINTF_FAILURE;
|
|
CHK_ACCESS_LEVEL_M(WINS_CONTROL_ACCESS);
|
|
INC_RPC_DB_COUNT_M;
|
|
try {
|
|
Status = WinsDelDbRecs(pAdd, MinVersNo, MaxVersNo);
|
|
}
|
|
finally {
|
|
DEC_RPC_DB_COUNT_M;
|
|
}
|
|
return(Status);
|
|
}
|
|
|
|
DWORD
|
|
R_WinsTombstoneDbRecs(
|
|
IN WINSIF2_HANDLE ServerHdl,
|
|
IN PWINSINTF_ADD_T pWinsAdd,
|
|
IN WINSINTF_VERS_NO_T MinVersNo,
|
|
IN WINSINTF_VERS_NO_T MaxVersNo
|
|
)
|
|
{
|
|
|
|
DWORD Status = WINSINTF_FAILURE;
|
|
CHK_ACCESS_LEVEL_M(WINS_CONTROL_ACCESS);
|
|
INC_RPC_DB_COUNT_M;
|
|
try {
|
|
Status = WinsTombstoneDbRecs(pWinsAdd, MinVersNo, MaxVersNo);
|
|
}
|
|
finally {
|
|
DEC_RPC_DB_COUNT_M;
|
|
}
|
|
return(Status);
|
|
}
|
|
|
|
DWORD
|
|
R_WinsPullRange(
|
|
IN PWINSINTF_ADD_T pAdd,
|
|
IN PWINSINTF_ADD_T pOwnerAdd,
|
|
IN WINSINTF_VERS_NO_T MinVersNo,
|
|
IN WINSINTF_VERS_NO_T MaxVersNo
|
|
)
|
|
{
|
|
|
|
DWORD Status = WINSINTF_FAILURE;
|
|
CHK_ACCESS_LEVEL_M(WINS_CONTROL_ACCESS);
|
|
Status = WinsPullRange(pAdd, pOwnerAdd, MinVersNo, MaxVersNo);
|
|
return(Status);
|
|
}
|
|
|
|
DWORD
|
|
R_WinsSetPriorityClass(
|
|
IN WINSINTF_PRIORITY_CLASS_E PriorityClass
|
|
)
|
|
{
|
|
|
|
DWORD Status = WINSINTF_FAILURE;
|
|
CHK_ACCESS_LEVEL_M(WINS_CONTROL_ACCESS);
|
|
Status = WinsSetPriorityClass(PriorityClass);
|
|
return(Status);
|
|
}
|
|
|
|
DWORD
|
|
R_WinsResetCounters(
|
|
VOID
|
|
)
|
|
{
|
|
|
|
DWORD Status = WINSINTF_FAILURE;
|
|
CHK_ACCESS_LEVEL_M(WINS_CONTROL_ACCESS);
|
|
Status = WinsResetCounters();
|
|
return(Status);
|
|
}
|
|
|
|
DWORD
|
|
R_WinsWorkerThdUpd(
|
|
DWORD NewNoOfNbtThds
|
|
)
|
|
{
|
|
DWORD Status = WINSINTF_FAILURE;
|
|
CHK_ACCESS_LEVEL_M(WINS_CONTROL_ACCESS);
|
|
Status = WinsWorkerThdUpd(NewNoOfNbtThds);
|
|
return(Status);
|
|
}
|
|
|
|
DWORD
|
|
R_WinsGetNameAndAdd(
|
|
PWINSINTF_ADD_T pWinsAdd,
|
|
LPBYTE pUncName
|
|
)
|
|
{
|
|
DWORD Status = WINSINTF_FAILURE;
|
|
CHK_ACCESS_LEVEL_M(WINS_QUERY_ACCESS);
|
|
Status = WinsGetNameAndAdd(pWinsAdd, pUncName);
|
|
return(Status);
|
|
}
|
|
|
|
DWORD
|
|
R_WinsGetBrowserNames_Old(
|
|
PWINSINTF_BROWSER_NAMES_T pNames
|
|
)
|
|
{
|
|
return(WINSINTF_FAILURE);
|
|
}
|
|
|
|
|
|
|
|
DWORD
|
|
R_WinsGetBrowserNames(
|
|
WINSIF_HANDLE pWinsHdl,
|
|
PWINSINTF_BROWSER_NAMES_T pNames
|
|
)
|
|
{
|
|
DWORD Status = WINSINTF_FAILURE;
|
|
|
|
static DWORD sNoOfReq = 0;
|
|
|
|
//
|
|
// Allow access to anybody. We don't check access here since
|
|
// browser running as a service has zero access when it goes
|
|
// on the network (It goes under the null account -- CliffVDyke 4/15/94)
|
|
//
|
|
INC_RPC_DB_COUNT_M;
|
|
EnterCriticalSection(&WinsIntfPotentiallyLongCrtSec);
|
|
try {
|
|
if (sNoOfReq++ < NMS_MAX_BROWSER_RPC_CALLS)
|
|
{
|
|
Status = WinsGetBrowserNames((PWINSINTF_BIND_DATA_T)pWinsHdl,pNames);
|
|
}
|
|
else
|
|
{
|
|
pNames->EntriesRead = 0;
|
|
pNames->pInfo = NULL;
|
|
Status = WINSINTF_FAILURE;
|
|
}
|
|
} // end of try
|
|
finally {
|
|
sNoOfReq--;
|
|
|
|
//
|
|
// increment the user count.
|
|
//
|
|
EnterCriticalSection(&WinsIntfNoOfUsersCrtSec);
|
|
sDomCache.NoOfUsers++;
|
|
LeaveCriticalSection(&WinsIntfNoOfUsersCrtSec);
|
|
|
|
LeaveCriticalSection(&WinsIntfPotentiallyLongCrtSec);
|
|
DEC_RPC_DB_COUNT_M;
|
|
|
|
}
|
|
return(Status);
|
|
}
|
|
|
|
|
|
DWORD
|
|
R_WinsSetFlags (
|
|
DWORD fFlags
|
|
)
|
|
{
|
|
DWORD Status = WINSINTF_SUCCESS;
|
|
|
|
Status = WinsSetFlags(fFlags);
|
|
return(Status);
|
|
}
|
|
|
|
DWORD
|
|
WinsSetFlags (
|
|
DWORD fFlags
|
|
)
|
|
{
|
|
DWORD Status = WINSINTF_SUCCESS;
|
|
#ifdef WINSDBG
|
|
DWORD DbgFlagsStore = WinsDbg;
|
|
SYSTEMTIME SystemTime;
|
|
BOOL sHaveProcessHeapHdl = FALSE;
|
|
HANDLE PrHeapHdl;
|
|
|
|
typedef struct _HEAP_INFO_T {
|
|
HANDLE HeapHdl;
|
|
LPBYTE cstrHeapType;
|
|
} HEAP_INFO_T, *PHEAP_INFO_T;
|
|
|
|
#define PRINT_TIME_OF_DUMP_M(SystemTime, Str) {DBGPRINT5(SPEC, "Activity: %s done on %d/%d at %d.%d \n", Str, SystemTime.wMonth, SystemTime.wDay, SystemTime.wHour, SystemTime.wMinute); }
|
|
|
|
#endif
|
|
|
|
//sfBS = fFlags & WINSINTF_BS;
|
|
|
|
DBGPRINT2(ERR, "WinsSetFlags: NmsDbDelDelDataRecs = (%d)\nNmsDbDelQueryNUpdRecs = (%d)\n", NmsDbDelDelDataRecs, NmsDbDelQueryNUpdRecs);
|
|
|
|
#ifdef WINSDBG
|
|
if (!sHaveProcessHeapHdl)
|
|
{
|
|
PrHeapHdl = GetProcessHeap();
|
|
}
|
|
GetSystemTime(&SystemTime);
|
|
WinsDbg |= DBG_SPEC;
|
|
if (fFlags & WINSINTF_MEMORY_INFO_DUMP)
|
|
{
|
|
MEMORYSTATUS Mem;
|
|
static SIZE_T sLTVmUsed = 0;
|
|
SIZE_T VmUsed;
|
|
|
|
DBGPRINT0(SPEC, "\n\n------------------MEMORY USAGE INFO-----------------\n\n");
|
|
GlobalMemoryStatus(&Mem);
|
|
|
|
VmUsed = Mem.dwTotalVirtual - Mem.dwAvailVirtual;
|
|
DBGPRINT2(SPEC, "VM used = (%d)\nDiff. from last time = (%d)\n", VmUsed,
|
|
VmUsed - sLTVmUsed);
|
|
sLTVmUsed = VmUsed;
|
|
|
|
}
|
|
EnterCriticalSection(&WinsCnfCnfCrtSec);
|
|
try {
|
|
if (fFlags & WINSINTF_HEAP_INFO_DUMP)
|
|
{
|
|
HEAP_INFO_T HeapHdls[] = {
|
|
CommUdpBuffHeapHdl, "Udp Buff Heap",
|
|
CommUdpDlgHeapHdl, "Udp Dlg Heap",
|
|
CommAssocDlgHeapHdl, "Tcp Dlg Heap",
|
|
CommAssocTcpMsgHeapHdl, "Tcp Msg Heap",
|
|
GenBuffHeapHdl, "General Heap",
|
|
QueBuffHeapHdl, "Que Wrk. Item Heap",
|
|
NmsChlHeapHdl, "Chl Req/Resp Heap",
|
|
CommAssocAssocHeapHdl, "Assoc. Msg Heap",
|
|
RplWrkItmHeapHdl, "Rpl Wrk Itm Heap",
|
|
NmsRpcHeapHdl, "Rpc Buff Heap",
|
|
WinsTmmHeapHdl, "Tmm Buff Heap",
|
|
(LPHANDLE)NULL, NULL
|
|
};
|
|
static SIZE_T sDiffLTHeapTotalANF[sizeof(HeapHdls)/sizeof(HEAP_INFO_T)] = {0};
|
|
static SIZE_T sHeapTotalANF[sizeof(HeapHdls)/sizeof(HEAP_INFO_T)] = {0};
|
|
SIZE_T Size2;
|
|
static SIZE_T sTotalAllocNFree = 0;
|
|
static SIZE_T LastTimeTotalAllocNFree = 0;
|
|
// NTSTATUS Status;
|
|
HANDLE HeapHdl;
|
|
DWORD i, n;
|
|
DWORD dwNumberOfHeaps;
|
|
PHANDLE pPrHeaps;
|
|
HEAP_SUMMARY heapSummary;
|
|
|
|
PRINT_TIME_OF_DUMP_M(SystemTime, "HEAP DUMP");
|
|
dwNumberOfHeaps = GetProcessHeaps(0, NULL);
|
|
Size2 = sizeof(*pPrHeaps) * dwNumberOfHeaps;
|
|
pPrHeaps = WinsMscHeapAlloc( NmsRpcHeapHdl, (ULONG)Size2);
|
|
dwNumberOfHeaps = GetProcessHeaps(dwNumberOfHeaps, pPrHeaps);
|
|
|
|
DBGPRINT1(SPEC, "No Of Heaps is (%d)\n", dwNumberOfHeaps);
|
|
DBGPRINT1(SPEC, "Process default heap handle is (%p)\n", PrHeapHdl);
|
|
LastTimeTotalAllocNFree = sTotalAllocNFree;
|
|
sTotalAllocNFree = 0;
|
|
heapSummary.cb = sizeof(HEAP_SUMMARY);
|
|
for (i=0; i< dwNumberOfHeaps; i++)
|
|
{
|
|
DBGPRINT0(SPEC, "----------Heap Info--------------------------\n");
|
|
DBGPRINT0(SPEC, "Heap -- ");
|
|
|
|
HeapHdl = pPrHeaps[i];
|
|
for (n = 0; HeapHdls[n].HeapHdl != NULL; n++)
|
|
{
|
|
if (HeapHdl == HeapHdls[n].HeapHdl)
|
|
{
|
|
DBGPRINT1(SPEC, "%s\n", HeapHdls[n].cstrHeapType);
|
|
break;
|
|
}
|
|
}
|
|
if (HeapHdls[n].HeapHdl == NULL)
|
|
{
|
|
|
|
DBGPRINT0(SPEC, "Catch all Heap\n");
|
|
}
|
|
|
|
DBGPRINT1(SPEC, "Heap Hdl = (%p)\n", HeapHdl);
|
|
if (HeapSummary(HeapHdl, 0, &heapSummary))
|
|
{
|
|
DBGPRINT2(SPEC,"Total Allocated = (%d)\nTotalFree = (%d)\n",
|
|
heapSummary.cbAllocated, heapSummary.cbCommitted - heapSummary.cbAllocated);
|
|
}
|
|
else
|
|
{
|
|
DBGPRINT0(SPEC,"COULD NOT GET HEAP INFO\n");
|
|
continue;
|
|
}
|
|
|
|
|
|
|
|
sDiffLTHeapTotalANF[n] = heapSummary.cbCommitted - sHeapTotalANF[n];
|
|
sHeapTotalANF[n] = heapSummary.cbCommitted;
|
|
sTotalAllocNFree += sHeapTotalANF[n];
|
|
DBGPRINT1(SPEC, "Size allocated from RpcHeap is (%d)\n", Size2);
|
|
} // end of for looping over process heaps
|
|
|
|
DBGPRINT0(SPEC, "\n----------Heap Info End --------------------------\n");
|
|
WinsMscHeapFree(NmsRpcHeapHdl, pPrHeaps);
|
|
|
|
for (n = 0; HeapHdls[n].HeapHdl != NULL; n++)
|
|
{
|
|
DBGPRINT3(SPEC, "%s -- Total AllocNFree = (%d); Diff from Last time = (%d)\n",
|
|
HeapHdls[n].cstrHeapType, sHeapTotalANF[n],
|
|
sDiffLTHeapTotalANF[n]
|
|
);
|
|
}
|
|
DBGPRINT2(SPEC, "\nTotal Process AllocNFree = (%d)\nDiff from last time = (%d)\n\n", sTotalAllocNFree, sTotalAllocNFree - LastTimeTotalAllocNFree);
|
|
|
|
if (WinsDbg & (DBG_HEAP_CNTRS | DBG_UPD_CNTRS))
|
|
{
|
|
NmsPrintCtrs();
|
|
}
|
|
}
|
|
if (fFlags & WINSINTF_QUE_ITEMS_DUMP)
|
|
{
|
|
typedef struct _QUE_INFO_T {
|
|
PQUE_HD_T pQueHd;
|
|
LPBYTE cstrQueType;
|
|
} QUE_INFO_T, *PQUE_INFO_T;
|
|
|
|
QUE_INFO_T Queues[] = {
|
|
&QueNbtWrkQueHd, "Nbt Query Que",
|
|
&QueOtherNbtWrkQueHd, "Nbt Reg. Que",
|
|
&QueRplPullQueHd, "Pull Thd Que", //Pull requests
|
|
&QueRplPushQueHd, "Push Thd Que", //Push requests
|
|
&QueNmsNrcqQueHd, "Chl Nbt Req. Msg Que", //Chl req fr nbt thds
|
|
&QueNmsRrcqQueHd, "Chl req. from Pull thd Que",
|
|
&QueNmsCrqQueHd, "Chl rsp from UDP thd Que",
|
|
&QueWinsTmmQueHd, "Timer Queue",
|
|
&QueInvalidQueHd, "Invalid Que"
|
|
};
|
|
PQUE_INFO_T pQueInfo = Queues;
|
|
PRINT_TIME_OF_DUMP_M(SystemTime, "WORK ITEM DUMP");
|
|
|
|
DBGPRINT0(SPEC, "----------Count of Wrk items-----------\n");
|
|
for (; pQueInfo->pQueHd != &QueInvalidQueHd; pQueInfo++)
|
|
{
|
|
PLIST_ENTRY pTmp;
|
|
DWORD NoOfWrkItms = 0;
|
|
pTmp = &pQueInfo->pQueHd->Head;
|
|
EnterCriticalSection(&pQueInfo->pQueHd->CrtSec);
|
|
// NoOfWrkItms = pQueInfo->pQueHd->NoOfEntries;
|
|
//#if 0
|
|
|
|
while (pTmp->Flink != &pQueInfo->pQueHd->Head)
|
|
{
|
|
|
|
NoOfWrkItms++;
|
|
pTmp = pTmp->Flink;
|
|
}
|
|
//#endif
|
|
LeaveCriticalSection(&pQueInfo->pQueHd->CrtSec);
|
|
DBGPRINT2(SPEC, "Que = (%s) has (%d) wrk items\n",
|
|
pQueInfo->cstrQueType,
|
|
NoOfWrkItms
|
|
);
|
|
}
|
|
|
|
DBGPRINT0(SPEC, "----------Count of Wrk items End-----------\n");
|
|
}
|
|
} // end of try
|
|
finally {
|
|
if (AbnormalTermination())
|
|
{
|
|
DBGPRINT0(SPEC, "WinsSetFlags terminated abnormally\n");
|
|
}
|
|
WinsDbg = DbgFlagsStore;
|
|
LeaveCriticalSection(&WinsCnfCnfCrtSec);
|
|
} //end of finally { }
|
|
#endif
|
|
return(Status);
|
|
}
|
|
|
|
DWORD
|
|
WinsBackup (
|
|
LPBYTE pBackupPath,
|
|
short fIncremental
|
|
)
|
|
{
|
|
DWORD RetVal = WINS_FAILURE;
|
|
try {
|
|
#if 0
|
|
RetVal = NmsDbBackup(pBackupPath, fIncremental ? NMSDB_INCREMENTAL_BACKUP :
|
|
NMSDB_FULL_BACKUP);
|
|
#endif
|
|
//
|
|
// Always do full backup until Jet is solid enough in doing incremental
|
|
// backups. Ian does not seem very sure about how robust it is currently.
|
|
// (7/6/94)
|
|
//
|
|
RetVal = NmsDbBackup(pBackupPath, NMSDB_FULL_BACKUP);
|
|
}
|
|
except(EXCEPTION_EXECUTE_HANDLER) {
|
|
DBGPRINTEXC("WinsBackup");
|
|
#if 0
|
|
DBGPRINT2(ERR, "WinsBackup: Could not do %s backup to dir (%s)\n", fIncremental ? "INCREMENTAL" : "FULL", pBackupPath);
|
|
|
|
DBGPRINT1(ERR, "WinsBackup: Could not do full backup to dir (%s)\n", pBackupPath);
|
|
#endif
|
|
WinsEvtLogDetEvt(FALSE, WINS_EVT_BACKUP_ERR, NULL, __LINE__, "s", pBackupPath);
|
|
}
|
|
if (RetVal != WINS_SUCCESS)
|
|
{
|
|
#if 0
|
|
RetVal = fIncremental ? WINSINTF_INC_BACKUP_FAILED : WINSINTF_FULL_BACKUP_FAILED;
|
|
#endif
|
|
RetVal = WINSINTF_FULL_BACKUP_FAILED;
|
|
}
|
|
else
|
|
{
|
|
RetVal = WINSINTF_SUCCESS;
|
|
}
|
|
return(RetVal);
|
|
}
|
|
|
|
|
|
DWORD
|
|
WinsTerm (
|
|
handle_t ClientHdl,
|
|
short fAbruptTerm
|
|
)
|
|
{
|
|
DBGPRINT1(FLOW, "WINS TERMINATED %s BY ADMINISTRATOR\n", fAbruptTerm ? "ABRUPTLY" : "GRACEFULLY");
|
|
|
|
UNREFERENCED_PARAMETER(ClientHdl);
|
|
|
|
if (fAbruptTerm)
|
|
{
|
|
fNmsAbruptTerm = TRUE;
|
|
WinsMscSignalHdl(NmsMainTermEvt);
|
|
ExitProcess(WINS_SUCCESS);
|
|
|
|
// EnterCriticalSection(&NmsTermCrtSec);
|
|
// NmsTotalTrmThdCnt = 0; //force the count to less than 0
|
|
// LeaveCriticalSection(&NmsTermCrtSec);
|
|
}
|
|
|
|
WinsMscSignalHdl(NmsMainTermEvt);
|
|
return(WINSINTF_SUCCESS);
|
|
}
|
|
|
|
DWORD
|
|
WinsRecordAction(
|
|
PWINSINTF_RECORD_ACTION_T *ppRecAction
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
This function is called to register, query, release a name
|
|
|
|
Arguments:
|
|
pRecAction - Info about the operation to do and the name to insert,
|
|
query or release
|
|
|
|
Externals Used:
|
|
None
|
|
|
|
|
|
Return Value:
|
|
|
|
Success status codes -- WINSINTF_SUCCESS
|
|
Error status codes -- WINSINTF_FAILURE
|
|
|
|
Error Handling:
|
|
|
|
Called by:
|
|
R_WinsRecordAction()
|
|
|
|
Side Effects:
|
|
|
|
Comments:
|
|
None
|
|
--*/
|
|
|
|
{
|
|
|
|
STATUS RetStat;
|
|
RPL_REC_ENTRY_T Rec;
|
|
NMSDB_STAT_INFO_T StatInfo;
|
|
NMSMSGF_CNT_ADD_T CntAdd;
|
|
DWORD i, n;
|
|
BOOL fSwapped = FALSE;
|
|
PWINSINTF_RECORD_ACTION_T pRecAction = *ppRecAction;
|
|
|
|
NmsDbThdInit(WINS_E_WINSRPC);
|
|
NmsDbOpenTables(WINS_E_WINSRPC);
|
|
DBGMYNAME("RPC-WinsRecordAction");
|
|
|
|
try {
|
|
CntAdd.NoOfAdds = 1;
|
|
CntAdd.Add[0].AddTyp_e = pRecAction->Add.Type;
|
|
CntAdd.Add[0].AddLen = pRecAction->Add.Len;
|
|
CntAdd.Add[0].Add.IPAdd = pRecAction->Add.IPAdd;
|
|
|
|
|
|
|
|
|
|
//
|
|
// Check to see if it is a PDC name (0x1B in the 16th byte). Do this only
|
|
// if the name is atleast 16 bytes long. Winscl or some other tool may
|
|
// send a shorter name. Netbt will never send a shorter name.
|
|
//
|
|
if ((pRecAction->NameLen >= (WINS_MAX_NS_NETBIOS_NAME_LEN - 1)) && (*(pRecAction->pName + 15) == 0x1B))
|
|
{
|
|
WINS_SWAP_BYTES_M(pRecAction->pName, pRecAction->pName + 15);
|
|
fSwapped = TRUE;
|
|
}
|
|
|
|
//
|
|
// just in case the admin. tool is screwing up and passing us an invalid
|
|
// name length, adjust the length.
|
|
//
|
|
if (pRecAction->NameLen > WINS_MAX_NAME_SZ)
|
|
{
|
|
pRecAction->NameLen = WINS_MAX_NAME_SZ - 1;
|
|
}
|
|
|
|
//
|
|
// Terminate name with NULL, just in case user didn't do it.
|
|
//
|
|
*(pRecAction->pName + pRecAction->NameLen) = (TCHAR)NULL;
|
|
|
|
switch(pRecAction->Cmd_e)
|
|
{
|
|
case(WINSINTF_E_INSERT):
|
|
|
|
if (pRecAction->TypOfRec_e == WINSINTF_E_UNIQUE)
|
|
{
|
|
|
|
RetStat = NmsNmhNamRegInd(
|
|
NULL, //no dialogue handle
|
|
(LPBYTE)pRecAction->pName,
|
|
pRecAction->NameLen + 1, //to include the ending //0 byte. See GetName()
|
|
//in nmsmsgf.c
|
|
CntAdd.Add,
|
|
pRecAction->NodeTyp,
|
|
NULL,
|
|
0,
|
|
0,
|
|
FALSE, //it is a name reg (nor a ref)
|
|
pRecAction->fStatic,
|
|
TRUE // administrative action
|
|
);
|
|
}
|
|
else // the record is a group or multihomed
|
|
{
|
|
|
|
if (
|
|
(pRecAction->TypOfRec_e == WINSINTF_E_MULTIHOMED )
|
|
||
|
|
(pRecAction->TypOfRec_e == WINSINTF_E_SPEC_GROUP )
|
|
)
|
|
{
|
|
for (i = 0; i < pRecAction->NoOfAdds; i++)
|
|
{
|
|
//
|
|
// pAdd is a unique pointer and so can be
|
|
// NULL. We however do not protect oureelves
|
|
// here for the following reasons
|
|
//
|
|
// - the call can only be executed by Admins
|
|
// on this machine and through tools
|
|
// that MS provides that do not pass pAdd as
|
|
// NULL. The rpc call is not published
|
|
//
|
|
// - AV will be caught and a failure returned.
|
|
// No harm done.
|
|
//
|
|
CntAdd.Add[i].AddTyp_e =
|
|
(pRecAction->pAdd + i)->Type;
|
|
CntAdd.Add[i].AddLen =
|
|
(pRecAction->pAdd + i)->Len;
|
|
CntAdd.Add[i].Add.IPAdd =
|
|
(pRecAction->pAdd + i)->IPAdd;
|
|
}
|
|
CntAdd.NoOfAdds = pRecAction->NoOfAdds;
|
|
|
|
}
|
|
RetStat= NmsNmhNamRegGrp(
|
|
NULL, //no dialogue handle
|
|
(LPBYTE)pRecAction->pName,
|
|
pRecAction->NameLen + 1,
|
|
&CntAdd,
|
|
0, //node type (not used)
|
|
NULL,
|
|
0,
|
|
0,
|
|
pRecAction->TypOfRec_e == WINSINTF_E_MULTIHOMED ? NMSDB_MULTIHOMED_ENTRY : (NMSDB_IS_IT_SPEC_GRP_NM_M(pRecAction->pName) || (pRecAction->TypOfRec_e == WINSINTF_E_NORM_GROUP) ? NMSDB_NORM_GRP_ENTRY : NMSDB_SPEC_GRP_ENTRY),
|
|
FALSE, //it is a name reg (nor a ref)
|
|
pRecAction->fStatic,
|
|
TRUE // administrative action
|
|
);
|
|
}
|
|
break;
|
|
|
|
case(WINSINTF_E_RELEASE):
|
|
|
|
if (
|
|
(pRecAction->TypOfRec_e == WINSINTF_E_MULTIHOMED)
|
|
||
|
|
(pRecAction->TypOfRec_e == WINSINTF_E_SPEC_GROUP)
|
|
)
|
|
{
|
|
if (pRecAction->pAdd != NULL)
|
|
{
|
|
CntAdd.Add[0].AddTyp_e = pRecAction->pAdd->Type;
|
|
CntAdd.Add[0].AddLen = pRecAction->pAdd->Len;
|
|
CntAdd.Add[0].Add.IPAdd = pRecAction->pAdd->IPAdd;
|
|
}
|
|
}
|
|
|
|
|
|
RetStat = NmsNmhNamRel(
|
|
NULL, //no dialogue handle
|
|
(LPBYTE)pRecAction->pName,
|
|
pRecAction->NameLen + 1,
|
|
CntAdd.Add,
|
|
pRecAction->TypOfRec_e ==
|
|
WINSINTF_E_UNIQUE ? FALSE : TRUE,
|
|
NULL,
|
|
0,
|
|
0,
|
|
TRUE // administrative action
|
|
);
|
|
|
|
break;
|
|
|
|
case(WINSINTF_E_QUERY):
|
|
|
|
//
|
|
// Anybody can query a record. We don't have any security
|
|
// for plain queries. Therefore somebody can cause a leak
|
|
// by making calls with pAdd pointing to allocated memory.
|
|
// Let us free that memory and proceed. We can return
|
|
// failure also but let us cover for our legit caller's
|
|
// mistakes. Currently, the only known callers of this
|
|
// function are winsmon, winscl, winsadmn (NT 4 and before)
|
|
// and wins snapin.
|
|
//
|
|
if (pRecAction->pAdd != NULL)
|
|
{
|
|
midl_user_free(pRecAction->pAdd);
|
|
}
|
|
RetStat = NmsNmhNamQuery(
|
|
NULL, //no dialogue handle
|
|
(LPBYTE)pRecAction->pName,
|
|
pRecAction->NameLen + 1,
|
|
NULL,
|
|
0,
|
|
0,
|
|
TRUE, // administrative action
|
|
&StatInfo
|
|
);
|
|
|
|
if (RetStat == WINS_SUCCESS)
|
|
{
|
|
pRecAction->TypOfRec_e = StatInfo.EntTyp;
|
|
pRecAction->OwnerId = StatInfo.OwnerId;
|
|
pRecAction->State_e =
|
|
(WINSINTF_STATE_E)StatInfo.EntryState_e;
|
|
pRecAction->TimeStamp = StatInfo.TimeStamp;
|
|
if (
|
|
NMSDB_ENTRY_UNIQUE_M(StatInfo.EntTyp)
|
|
||
|
|
NMSDB_ENTRY_NORM_GRP_M(StatInfo.EntTyp)
|
|
)
|
|
{
|
|
pRecAction->NoOfAdds = 0;
|
|
pRecAction->pAdd = NULL;
|
|
pRecAction->Add.IPAdd =
|
|
StatInfo.NodeAdds.Mem[0].Add.Add.IPAdd;
|
|
pRecAction->Add.Type =
|
|
(UCHAR) StatInfo.NodeAdds.Mem[0].Add.AddTyp_e;
|
|
pRecAction->Add.Len =
|
|
StatInfo.NodeAdds.Mem[0].Add.AddLen;
|
|
}
|
|
else
|
|
{
|
|
|
|
PNMSDB_WINS_STATE_E pWinsState_e;
|
|
PCOMM_ADD_T pAdd;
|
|
PVERS_NO_T pStartVersNo;
|
|
|
|
EnterCriticalSection(&NmsDbOwnAddTblCrtSec);
|
|
try {
|
|
if (StatInfo.NodeAdds.NoOfMems > 0)
|
|
{
|
|
pRecAction->NoOfAdds = StatInfo.NodeAdds.NoOfMems * 2;
|
|
pRecAction->pAdd = midl_user_allocate(pRecAction->NoOfAdds * sizeof(WINSINTF_ADD_T));
|
|
}
|
|
else
|
|
{
|
|
pRecAction->NoOfAdds = 0;
|
|
pRecAction->pAdd = NULL;
|
|
}
|
|
for (
|
|
n = 0, i = 0;
|
|
n < (StatInfo.NodeAdds.NoOfMems) && n < WINSINTF_MAX_MEM; n++
|
|
)
|
|
{
|
|
RPL_FIND_ADD_BY_OWNER_ID_M(
|
|
StatInfo.NodeAdds.Mem[n].OwnerId,
|
|
pAdd,
|
|
pWinsState_e,
|
|
pStartVersNo
|
|
);
|
|
(pRecAction->pAdd + i++)->IPAdd = pAdd->Add.IPAdd;
|
|
|
|
(pRecAction->pAdd + i++)->IPAdd =
|
|
StatInfo.NodeAdds.Mem[n].Add.Add.IPAdd;
|
|
|
|
|
|
}
|
|
}
|
|
except(EXCEPTION_EXECUTE_HANDLER) {
|
|
DWORD ExcCode = GetExceptionCode();
|
|
WINSEVT_LOG_M(ExcCode, WINS_EVT_RPC_EXC);
|
|
DBGPRINT1(EXC, "WinsRecordAction: Got Exception (%x)\n", ExcCode);
|
|
}
|
|
LeaveCriticalSection(&NmsDbOwnAddTblCrtSec);
|
|
}
|
|
|
|
pRecAction->NodeTyp = StatInfo.NodeTyp;
|
|
pRecAction->VersNo = StatInfo.VersNo;
|
|
pRecAction->fStatic = StatInfo.fStatic;
|
|
}
|
|
else
|
|
{
|
|
pRecAction->NoOfAdds = 0;
|
|
pRecAction->pAdd = NULL;
|
|
}
|
|
break;
|
|
|
|
case(WINSINTF_E_MODIFY):
|
|
|
|
//
|
|
// Note: Currently, the administrator can not change the
|
|
// address in the record
|
|
//
|
|
time((time_t *)&Rec.NewTimeStamp);
|
|
|
|
//
|
|
// If the record type is wrong, return a failure
|
|
//
|
|
if (pRecAction->TypOfRec_e > WINSINTF_E_MULTIHOMED)
|
|
{
|
|
RetStat = WINS_FAILURE;
|
|
break;
|
|
}
|
|
//
|
|
// If the state specified is wrong, return a failure
|
|
//
|
|
if (pRecAction->State_e > WINSINTF_E_DELETED)
|
|
{
|
|
RetStat = WINS_FAILURE;
|
|
break;
|
|
}
|
|
NMSDB_SET_ENTRY_TYPE_M(Rec.Flag, pRecAction->TypOfRec_e);
|
|
NMSDB_SET_NODE_TYPE_M(Rec.Flag, pRecAction->NodeTyp);
|
|
NMSDB_SET_STDYN_M(Rec.Flag, pRecAction->fStatic);
|
|
|
|
//
|
|
// Fall through
|
|
//
|
|
|
|
case(WINSINTF_E_DELETE):
|
|
NMSDB_SET_STATE_M(Rec.Flag, pRecAction->State_e)
|
|
|
|
Rec.pName = pRecAction->pName;
|
|
Rec.NameLen = pRecAction->NameLen + 1;
|
|
|
|
//
|
|
// NOTE:
|
|
// The index on the name address table was set to
|
|
// the clustered index column (as required by this function)
|
|
// in NmsDbThdInit()
|
|
//
|
|
|
|
RetStat = NmsDbQueryNUpdIfMatch(
|
|
&Rec,
|
|
THREAD_PRIORITY_NORMAL,
|
|
FALSE, //don't change priority to
|
|
//normal
|
|
WINS_E_WINSRPC //ensures no matching
|
|
//of timestamps
|
|
);
|
|
if (RetStat == WINS_SUCCESS)
|
|
{
|
|
DBGPRINT1(DET, "WinsRecordAction: Record (%s) deleted\n",
|
|
Rec.pName);
|
|
FUTURES("use macros defined in winsevt.h. Change to warning")
|
|
if (WinsCnf.LogDetailedEvts > 0)
|
|
{
|
|
WinsEvtLogDetEvt(TRUE, WINS_EVT_REC_DELETED, NULL, __LINE__, "s", Rec.pName);
|
|
}
|
|
}
|
|
break;
|
|
|
|
|
|
default:
|
|
RetStat = WINS_FAILURE;
|
|
break;
|
|
|
|
}
|
|
} // end of try
|
|
except(EXCEPTION_EXECUTE_HANDLER) {
|
|
DWORD ExcCode = GetExceptionCode();
|
|
WINSEVT_LOG_M(ExcCode, WINS_EVT_RPC_EXC);
|
|
DBGPRINT1(EXC, "WinsRecordAction: Got Exception (%x)\n", ExcCode);
|
|
}
|
|
if (fSwapped)
|
|
{
|
|
WINS_SWAP_BYTES_M(pRecAction->pName, pRecAction->pName + 15);
|
|
}
|
|
//
|
|
// Let us end the session
|
|
//
|
|
NmsDbCloseTables();
|
|
NmsDbEndSession();
|
|
if (RetStat == WINS_SUCCESS)
|
|
{
|
|
RetStat = WINSINTF_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
if (pRecAction->Cmd_e == WINSINTF_E_QUERY)
|
|
{
|
|
RetStat = WINSINTF_REC_NOT_FOUND;
|
|
}
|
|
else
|
|
{
|
|
RetStat = WINSINTF_FAILURE;
|
|
}
|
|
}
|
|
return(RetStat);
|
|
}
|
|
|
|
DWORD
|
|
GetWinsStatus(
|
|
IN WINSINTF_CMD_E Cmd_e,
|
|
OUT LPVOID pResults,
|
|
BOOL fNew
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
This function is called to get the information pertaining to WINS
|
|
Refer WINSINTF_RESULTS_T data structure to see what information
|
|
is retrieved
|
|
|
|
Arguments:
|
|
Cmd_e - Command to execute
|
|
pResults - Info. retrieved
|
|
|
|
Externals Used:
|
|
None
|
|
|
|
|
|
Return Value:
|
|
|
|
Success status codes -- WINSINTF_SUCCESS
|
|
Error status codes -- WINSINTF_FAILURE
|
|
|
|
Error Handling:
|
|
|
|
Called by:
|
|
R_WinsStatus()
|
|
|
|
Side Effects:
|
|
|
|
Comments:
|
|
None
|
|
--*/
|
|
|
|
{
|
|
|
|
DWORD RetVal = WINSINTF_FAILURE;
|
|
|
|
switch(Cmd_e)
|
|
{
|
|
|
|
case(WINSINTF_E_ADDVERSMAP):
|
|
if (fNew)
|
|
{
|
|
break;
|
|
}
|
|
RetVal = sGetVersNo(pResults);
|
|
break;
|
|
case(WINSINTF_E_CONFIG):
|
|
RetVal = GetConfig(pResults, fNew, FALSE);
|
|
break;
|
|
case(WINSINTF_E_CONFIG_ALL_MAPS):
|
|
RetVal = GetConfig(pResults, fNew, TRUE);
|
|
break;
|
|
case(WINSINTF_E_STAT):
|
|
RetVal = GetStatistics(pResults, fNew);
|
|
break;
|
|
default:
|
|
DBGPRINT1(ERR, "WinsStatus: Weird: Bad RPC Status command = (%D) \n", Cmd_e);
|
|
WINSEVT_LOG_D_M(WINS_FAILURE, WINS_EVT_BAD_RPC_STATUS_CMD);
|
|
break;
|
|
|
|
}
|
|
return(RetVal);
|
|
|
|
}
|
|
|
|
DWORD
|
|
WinsTrigger(
|
|
PWINSINTF_ADD_T pWinsAdd,
|
|
WINSINTF_TRIG_TYPE_E TrigType_e
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
This function is called to send a trigger to a remote WINS so that
|
|
it may pull the latest information from it
|
|
|
|
Arguments:
|
|
|
|
pWinsAdd - Address of WINS to send a Push update notification to
|
|
|
|
Externals Used:
|
|
None
|
|
|
|
|
|
Return Value:
|
|
|
|
Success status codes -- WINSINTF_SUCCESS
|
|
Error status codes -- WINSINTF_FAILURE
|
|
|
|
Error Handling:
|
|
|
|
Called by:
|
|
R_WinsTrigger
|
|
|
|
Side Effects:
|
|
|
|
Comments:
|
|
A Trigger is sent to a remote WINS only if it is specified
|
|
under the PULL/PUSH subkey of the PARTNERS key in the registry
|
|
--*/
|
|
|
|
{
|
|
|
|
PRPL_CONFIG_REC_T pPnr;
|
|
DWORD RetCode = WINSINTF_SUCCESS;
|
|
BOOL fRplPnr = FALSE;
|
|
QUE_CMD_TYP_E CmdType_e;
|
|
|
|
DBGENTER("WinsTrigger\n");
|
|
//
|
|
// Enter the critical sections guarded by WinsCnfCnfCrtSec and
|
|
// NmsNmhNamRegCrtSec. There is no danger of deadlock because we
|
|
// always enter the two critical sections in the following sequence
|
|
//
|
|
EnterCriticalSection(&WinsCnfCnfCrtSec);
|
|
|
|
PERF("Do we need to enter the following critical section")
|
|
// EnterCriticalSection(&NmsNmhNamRegCrtSec);
|
|
try {
|
|
if (
|
|
(TrigType_e == WINSINTF_E_PUSH)
|
|
||
|
|
(TrigType_e == WINSINTF_E_PUSH_PROP)
|
|
)
|
|
{
|
|
DBGPRINT1(DET, "WinsTrigger. Send Push trigger to (%x)\n",
|
|
pWinsAdd->IPAdd);
|
|
|
|
CmdType_e = (TrigType_e == WINSINTF_E_PUSH ?
|
|
QUE_E_CMD_SND_PUSH_NTF :
|
|
QUE_E_CMD_SND_PUSH_NTF_PROP);
|
|
|
|
pPnr = WinsCnf.PushInfo.pPushCnfRecs;
|
|
}
|
|
else // it is a pull trigger
|
|
{
|
|
DBGPRINT1(DET, "WinsTrigger. Send Pull trigger to (%x)\n",
|
|
pWinsAdd->IPAdd);
|
|
|
|
CmdType_e = QUE_E_CMD_REPLICATE;
|
|
pPnr = WinsCnf.PullInfo.pPullCnfRecs;
|
|
|
|
}
|
|
|
|
if (WinsCnf.fRplOnlyWCnfPnrs)
|
|
{
|
|
if (pPnr != NULL)
|
|
{
|
|
//
|
|
// Search for the Cnf record for the WINS we want to
|
|
// send the PUSH notification to/Replicate with.
|
|
//
|
|
for (
|
|
;
|
|
(pPnr->WinsAdd.Add.IPAdd != INADDR_NONE)
|
|
&&
|
|
!fRplPnr;
|
|
// no third expression
|
|
)
|
|
{
|
|
|
|
|
|
DBGPRINT1(DET, "WinsTrigger. Comparing with (%x)\n",
|
|
pPnr->WinsAdd.Add.IPAdd);
|
|
//
|
|
// Check if this is the one we want
|
|
//
|
|
if (pPnr->WinsAdd.Add.IPAdd == pWinsAdd->IPAdd)
|
|
{
|
|
//
|
|
// We are done. Set the fRplPnr flag to TRUE so that
|
|
// we break out of the loop.
|
|
//
|
|
// Note: Don't use break since that would cause
|
|
// a search for a 'finally' block
|
|
//
|
|
fRplPnr = TRUE;
|
|
|
|
//
|
|
// Make it 0, so that we always try to establish
|
|
// a connection. Otherwise, pull thread may not
|
|
// try if it has already exhausted the number of
|
|
// retries
|
|
//
|
|
pPnr->RetryCount = 0;
|
|
continue; //so that we can break out
|
|
|
|
}
|
|
//
|
|
// Get the next record that follows this one sequentially
|
|
//
|
|
pPnr = WinsCnfGetNextRplCnfRec(
|
|
pPnr,
|
|
RPL_E_IN_SEQ //seq. traversal
|
|
);
|
|
} // end of for
|
|
} // end of if (pPnr != 0)
|
|
} // end of if (fRplOnlyWCnfPnrs)
|
|
else
|
|
{
|
|
//
|
|
// Allocate from the general heap because that is what
|
|
// is used by the replicator.
|
|
//
|
|
WinsMscAlloc(RPL_CONFIG_REC_SIZE, &pPnr);
|
|
COMM_INIT_ADD_M(&pPnr->WinsAdd, pWinsAdd->IPAdd);
|
|
pPnr->MagicNo = 0;
|
|
pPnr->RetryCount = 0;
|
|
pPnr->LastCommFailTime = 0;
|
|
pPnr->PushNtfTries = 0;
|
|
fRplPnr = TRUE;
|
|
|
|
//
|
|
// We want the buffer to be deallocated by the PULL thread
|
|
//
|
|
pPnr->fTemp = TRUE;
|
|
}
|
|
|
|
//
|
|
// If replication needs to be done
|
|
//
|
|
if (fRplPnr)
|
|
{
|
|
//
|
|
// Call RplInsertQue to insert the push request to
|
|
// the Pull Thread
|
|
//
|
|
ERplInsertQue(
|
|
WINS_E_WINSRPC,
|
|
CmdType_e,
|
|
NULL, //no Dlg Hdl
|
|
NULL, //no msg is there
|
|
0, //msg length
|
|
pPnr, //client context
|
|
pPnr->MagicNo
|
|
);
|
|
|
|
}
|
|
} // end of try block
|
|
|
|
except (EXCEPTION_EXECUTE_HANDLER) {
|
|
DWORD ExcCode = GetExceptionCode();
|
|
DBGPRINT1(EXC, "WinsTrigger: Got Exception (%x)\n", ExcCode);
|
|
WINSEVT_LOG_D_M(ExcCode, WINS_EVT_PUSH_TRIGGER_EXC);
|
|
RetCode = WINSINTF_FAILURE;
|
|
}
|
|
|
|
//
|
|
// Leave the critical section guarded by NmsNmhNamRegCrtSec.
|
|
//
|
|
// LeaveCriticalSection(&NmsNmhNamRegCrtSec);
|
|
LeaveCriticalSection(&WinsCnfCnfCrtSec);
|
|
|
|
//
|
|
// if replication was allowed only with configured partners and
|
|
// there was no WINS with the address specified by the client,
|
|
// return failure
|
|
//
|
|
if (!fRplPnr)
|
|
{
|
|
RetCode = WINSINTF_RPL_NOT_ALLOWED;
|
|
}
|
|
|
|
DBGLEAVE("WinsTrigger\n");
|
|
return(RetCode);
|
|
}
|
|
|
|
DWORD
|
|
sGetVersNo(
|
|
LPVOID pResultsA
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function returns with the highest version number of records
|
|
owned by a particular WINS
|
|
|
|
Arguments:
|
|
|
|
|
|
Externals Used:
|
|
None
|
|
|
|
|
|
Return Value:
|
|
|
|
Success status codes -- WINSINTF_SUCCESS
|
|
Error status codes -- WINSINTF_FAILURE
|
|
|
|
Error Handling:
|
|
|
|
Called by:
|
|
|
|
Side Effects:
|
|
|
|
Comments:
|
|
None
|
|
--*/
|
|
|
|
{
|
|
COMM_ADD_T WinsAdd;
|
|
DWORD OwnerId;
|
|
STATUS RetStat;
|
|
VERS_NO_T VersNo;
|
|
BOOL fAllocNew = FALSE;
|
|
PWINSINTF_RESULTS_T pResults = pResultsA;
|
|
|
|
WinsAdd.AddLen = sizeof(COMM_IP_ADD_T);
|
|
WinsAdd.AddTyp_e = COMM_ADD_E_TCPUDPIP;
|
|
WinsAdd.Add.IPAdd = pResults->AddVersMaps[0].Add.IPAdd;
|
|
RetStat = RplFindOwnerId(
|
|
&WinsAdd,
|
|
&fAllocNew, //don't assign if not there
|
|
&OwnerId,
|
|
WINSCNF_E_IGNORE_PREC,
|
|
WINSCNF_LOW_PREC
|
|
);
|
|
if(RetStat != WINS_SUCCESS)
|
|
{
|
|
return(WINSINTF_FAILURE);
|
|
}
|
|
|
|
if (OwnerId == 0)
|
|
{
|
|
EnterCriticalSection(&NmsNmhNamRegCrtSec);
|
|
NMSNMH_DEC_VERS_NO_M(NmsNmhMyMaxVersNo, VersNo);
|
|
LeaveCriticalSection(&NmsNmhNamRegCrtSec);
|
|
pResults->AddVersMaps[0].VersNo = VersNo;
|
|
}
|
|
else
|
|
{
|
|
EnterCriticalSection(&RplVersNoStoreCrtSec);
|
|
try {
|
|
pResults->AddVersMaps[0].VersNo =
|
|
(pRplPullOwnerVersNo+OwnerId)->VersNo;
|
|
}
|
|
except(EXCEPTION_EXECUTE_HANDLER) {
|
|
DBGPRINTEXC("sGetVersNo");
|
|
}
|
|
LeaveCriticalSection(&RplVersNoStoreCrtSec);
|
|
}
|
|
return(WINSINTF_SUCCESS);
|
|
|
|
}
|
|
|
|
DWORD
|
|
GetConfig(
|
|
OUT LPVOID pResultsA,
|
|
IN BOOL fNew,
|
|
IN BOOL fAllMaps
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
This function returns with configuration information
|
|
and counter info related to replication
|
|
|
|
Arguments:
|
|
pResults - has the information retrieved
|
|
|
|
Externals Used:
|
|
None
|
|
|
|
|
|
Return Value:
|
|
|
|
Success status codes -- WINSINTF_SUCCESS
|
|
Error status codes -- WINSINTF_FAILURE
|
|
|
|
Error Handling:
|
|
|
|
Called by:
|
|
GetWinsStatus()
|
|
|
|
Side Effects:
|
|
|
|
Comments:
|
|
None
|
|
--*/
|
|
|
|
{
|
|
|
|
PNMSDB_WINS_STATE_E pWinsState_e;
|
|
PCOMM_ADD_T pWinsAdd;
|
|
PVERS_NO_T pStartVersNo;
|
|
DWORD i, n;
|
|
VERS_NO_T MyMaxVersNo;
|
|
PWINSINTF_ADD_VERS_MAP_T pAddVersMaps, pAddVersMapsStore;
|
|
PWINSINTF_RESULTS_T pResults = pResultsA;
|
|
PWINSINTF_RESULTS_NEW_T pResultsN = pResultsA;
|
|
BOOL fDel;
|
|
VERS_NO_T VersNoForDelRec;
|
|
|
|
|
|
if (fAllMaps)
|
|
{
|
|
fDel = FALSE;
|
|
VersNoForDelRec.HighPart = MAXLONG;
|
|
VersNoForDelRec.LowPart = MAXULONG;
|
|
}
|
|
EnterCriticalSection(&NmsNmhNamRegCrtSec);
|
|
MyMaxVersNo = NmsNmhMyMaxVersNo;
|
|
LeaveCriticalSection(&NmsNmhNamRegCrtSec);
|
|
|
|
if (fNew)
|
|
{
|
|
|
|
pResultsN->pAddVersMaps =
|
|
midl_user_allocate(NmsDbNoOfOwners * sizeof(WINSINTF_ADD_VERS_MAP_T));
|
|
if (pResultsN->pAddVersMaps == NULL)
|
|
return WINSINTF_FAILURE;
|
|
|
|
pAddVersMaps = pResultsN->pAddVersMaps;
|
|
|
|
}
|
|
else
|
|
{
|
|
pAddVersMaps = pResults->AddVersMaps;
|
|
}
|
|
pAddVersMapsStore = pAddVersMaps;
|
|
//
|
|
// First extract the timeouts and Non-remote WINS information
|
|
// from the WinsCnf global var. We enter the WinsCnfCnfCrtSec
|
|
// since we need to synchronize with the thread doing the
|
|
// reinitialization (Main thread)
|
|
//
|
|
EnterCriticalSection(&WinsCnfCnfCrtSec);
|
|
if (!fNew)
|
|
{
|
|
pResults->RefreshInterval = WinsCnf.RefreshInterval;
|
|
pResults->TombstoneInterval = WinsCnf.TombstoneInterval;
|
|
pResults->TombstoneTimeout = WinsCnf.TombstoneTimeout;
|
|
pResults->VerifyInterval = WinsCnf.VerifyInterval;
|
|
pResults->WinsPriorityClass = WinsCnf.WinsPriorityClass == (DWORD)WINSINTF_E_NORMAL ? NORMAL_PRIORITY_CLASS : HIGH_PRIORITY_CLASS;
|
|
pResults->NoOfWorkerThds = NmsNoOfNbtThds;
|
|
}
|
|
else
|
|
{
|
|
pResultsN->RefreshInterval = WinsCnf.RefreshInterval;
|
|
pResultsN->TombstoneInterval = WinsCnf.TombstoneInterval;
|
|
pResultsN->TombstoneTimeout = WinsCnf.TombstoneTimeout;
|
|
pResultsN->VerifyInterval = WinsCnf.VerifyInterval;
|
|
pResultsN->WinsPriorityClass = WinsCnf.WinsPriorityClass == (DWORD)WINSINTF_E_NORMAL ? NORMAL_PRIORITY_CLASS : HIGH_PRIORITY_CLASS;
|
|
pResultsN->NoOfWorkerThds = NmsNoOfNbtThds;
|
|
|
|
}
|
|
LeaveCriticalSection(&WinsCnfCnfCrtSec);
|
|
|
|
//
|
|
// Enter two critical sections in sequence. No danger of deadlock
|
|
// here. The only other thread that takes both these critical section
|
|
// is the RplPush thread. It takes these in the same order (See
|
|
// HandleVersMapReq())
|
|
//
|
|
EnterCriticalSection(&NmsDbOwnAddTblCrtSec);
|
|
EnterCriticalSection(&RplVersNoStoreCrtSec);
|
|
try {
|
|
NONPORT("Change when using different address family")
|
|
|
|
for (
|
|
i=0, n = 0;
|
|
i < NmsDbNoOfOwners;
|
|
i++
|
|
)
|
|
{
|
|
|
|
if (!fNew && (i == WINSINTF_MAX_NO_RPL_PNRS))
|
|
{
|
|
break;
|
|
}
|
|
//
|
|
// if the record is deleted in the in-memory table, it
|
|
// means that there are no records for it in the
|
|
// database
|
|
//
|
|
if ((pNmsDbOwnAddTbl+i)->WinsState_e == NMSDB_E_WINS_DELETED)
|
|
{
|
|
//
|
|
// if only active mappings are sought, skip this
|
|
// entry
|
|
//
|
|
if (!fAllMaps)
|
|
{
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
fDel = TRUE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Find address corresponding to the owner id.
|
|
//
|
|
RPL_FIND_ADD_BY_OWNER_ID_M(i, pWinsAdd, pWinsState_e,
|
|
pStartVersNo);
|
|
|
|
//
|
|
// It is possible for NmsDbNoOfOwners to be more than the
|
|
// number of initialized RplPullVersNoTbl entries. When
|
|
// we reach a NULL entry, we break out of the loop.
|
|
//
|
|
if (pWinsAdd != NULL)
|
|
{
|
|
pAddVersMaps->Add.Type = WINSINTF_TCP_IP;
|
|
pAddVersMaps->Add.Len = pWinsAdd->AddLen;
|
|
pAddVersMaps->Add.IPAdd = pWinsAdd->Add.IPAdd;
|
|
|
|
pAddVersMaps++->VersNo = (fDel == FALSE) ? (pRplPullOwnerVersNo+i)->VersNo : VersNoForDelRec;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
if (fDel)
|
|
{
|
|
fDel = FALSE;
|
|
}
|
|
n++;
|
|
} // end of for ..
|
|
|
|
//
|
|
// Since RplPullOwnerVersNo[0] may be out of date, let us get
|
|
// get the uptodate value
|
|
//
|
|
NMSNMH_DEC_VERS_NO_M(MyMaxVersNo,
|
|
pAddVersMapsStore->VersNo
|
|
);
|
|
if (fNew)
|
|
{
|
|
pResultsN->NoOfOwners = n;
|
|
}
|
|
else
|
|
{
|
|
pResults->NoOfOwners = n;
|
|
|
|
}
|
|
NOTE("Wins Mib agent relies on the first entry being that of the local WINS")
|
|
NOTE("See WinsMib.c -- EnumAddKeys")
|
|
#if 0
|
|
//
|
|
// Since RplPullOwnerVersNo[0] may be out of date, let us get
|
|
// get the uptodate value
|
|
//
|
|
NMSNMH_DEC_VERS_NO_M(MyMaxVersNo,
|
|
pResults->AddVersMaps[0].VersNo
|
|
);
|
|
#endif
|
|
}
|
|
except(EXCEPTION_EXECUTE_HANDLER) {
|
|
DBGPRINTEXC("GetConfig");
|
|
//
|
|
// log a message
|
|
//
|
|
}
|
|
LeaveCriticalSection(&RplVersNoStoreCrtSec);
|
|
LeaveCriticalSection(&NmsDbOwnAddTblCrtSec);
|
|
|
|
return(WINSINTF_SUCCESS);
|
|
}
|
|
|
|
DWORD
|
|
GetStatistics(
|
|
LPVOID pResultsA,
|
|
BOOL fNew
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function returns with the highest version number of records
|
|
owned by a particular WINS
|
|
|
|
Arguments:
|
|
|
|
|
|
Externals Used:
|
|
None
|
|
|
|
|
|
Return Value:
|
|
|
|
Success status codes -- WINSINTF_SUCCESS
|
|
Error status codes -- WINSINTF_FAILURE
|
|
|
|
Error Handling:
|
|
|
|
Called by:
|
|
|
|
Side Effects:
|
|
|
|
Comments:
|
|
None
|
|
--*/
|
|
|
|
{
|
|
|
|
PRPL_CONFIG_REC_T pPnr;
|
|
PWINSINTF_RPL_COUNTERS_T pPnrData;
|
|
DWORD i;
|
|
PWINSINTF_RESULTS_T pResults = pResultsA;
|
|
PWINSINTF_RESULTS_NEW_T pResultsN = pResultsA;
|
|
|
|
|
|
ASSERT(pResults != NULL);
|
|
|
|
|
|
//
|
|
// If client passed us a non-null pRplPnr, then we return failure
|
|
// so as to avoid a memory leak.
|
|
//
|
|
if (!fNew)
|
|
{
|
|
if (pResults->WinsStat.pRplPnrs != NULL)
|
|
{
|
|
return(WINSINTF_FAILURE);
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
|
|
if (pResultsN->WinsStat.pRplPnrs != NULL)
|
|
{
|
|
return(WINSINTF_FAILURE);
|
|
}
|
|
}
|
|
//
|
|
// Copy the counters
|
|
//
|
|
EnterCriticalSection(&NmsNmhNamRegCrtSec);
|
|
if (!fNew)
|
|
{
|
|
pResults->WinsStat.Counters = WinsIntfStat.Counters;
|
|
FUTURES("Get rid of of the following two fields")
|
|
pResults->WinsStat.Counters.NoOfQueries =
|
|
WinsIntfStat.Counters.NoOfSuccQueries +
|
|
WinsIntfStat.Counters.NoOfFailQueries;
|
|
pResults->WinsStat.Counters.NoOfRel = WinsIntfStat.Counters.NoOfSuccRel
|
|
+ WinsIntfStat.Counters.NoOfFailRel;
|
|
}
|
|
else
|
|
{
|
|
pResultsN->WinsStat.Counters = WinsIntfStat.Counters;
|
|
FUTURES("Get rid of of the following two fields")
|
|
pResultsN->WinsStat.Counters.NoOfQueries =
|
|
WinsIntfStat.Counters.NoOfSuccQueries +
|
|
WinsIntfStat.Counters.NoOfFailQueries;
|
|
pResultsN->WinsStat.Counters.NoOfRel = WinsIntfStat.Counters.NoOfSuccRel
|
|
+ WinsIntfStat.Counters.NoOfFailRel;
|
|
|
|
}
|
|
LeaveCriticalSection(&NmsNmhNamRegCrtSec);
|
|
|
|
//
|
|
// Copy the TimeStamps and replication specific counters
|
|
//
|
|
EnterCriticalSection(&WinsIntfCrtSec);
|
|
{
|
|
PWINSINTF_STAT_T pWinsStat = (fNew) ? &(pResultsN->WinsStat) : &(pResults->WinsStat);
|
|
TIME_ZONE_INFORMATION tzInfo;
|
|
|
|
GetTimeZoneInformation(&tzInfo);
|
|
SystemTimeToTzSpecificLocalTime(&tzInfo, &(WinsIntfStat.TimeStamps.WinsStartTime), &(pWinsStat->TimeStamps.WinsStartTime));
|
|
SystemTimeToTzSpecificLocalTime(&tzInfo, &(WinsIntfStat.TimeStamps.LastPScvTime), &(pWinsStat->TimeStamps.LastPScvTime));
|
|
SystemTimeToTzSpecificLocalTime(&tzInfo, &(WinsIntfStat.TimeStamps.LastATScvTime), &(pWinsStat->TimeStamps.LastATScvTime));
|
|
SystemTimeToTzSpecificLocalTime(&tzInfo, &(WinsIntfStat.TimeStamps.LastTombScvTime), &(pWinsStat->TimeStamps.LastTombScvTime));
|
|
SystemTimeToTzSpecificLocalTime(&tzInfo, &(WinsIntfStat.TimeStamps.LastVerifyScvTime), &(pWinsStat->TimeStamps.LastVerifyScvTime));
|
|
SystemTimeToTzSpecificLocalTime(&tzInfo, &(WinsIntfStat.TimeStamps.LastInitDbTime), &(pWinsStat->TimeStamps.LastInitDbTime));
|
|
SystemTimeToTzSpecificLocalTime(&tzInfo, &(WinsIntfStat.TimeStamps.LastPRplTime), &(pWinsStat->TimeStamps.LastPRplTime));
|
|
SystemTimeToTzSpecificLocalTime(&tzInfo, &(WinsIntfStat.TimeStamps.LastATRplTime), &(pWinsStat->TimeStamps.LastATRplTime));
|
|
SystemTimeToTzSpecificLocalTime(&tzInfo, &(WinsIntfStat.TimeStamps.LastNTRplTime), &(pWinsStat->TimeStamps.LastNTRplTime));
|
|
SystemTimeToTzSpecificLocalTime(&tzInfo, &(WinsIntfStat.TimeStamps.LastACTRplTime), &(pWinsStat->TimeStamps.LastACTRplTime));
|
|
SystemTimeToTzSpecificLocalTime(&tzInfo, &(WinsIntfStat.TimeStamps.CounterResetTime), &(pWinsStat->TimeStamps.CounterResetTime));
|
|
}
|
|
LeaveCriticalSection(&WinsIntfCrtSec);
|
|
EnterCriticalSection(&WinsCnfCnfCrtSec);
|
|
try {
|
|
DWORD NoOfPnrs;
|
|
pPnr = WinsCnf.PullInfo.pPullCnfRecs;
|
|
if (!fNew)
|
|
{
|
|
NoOfPnrs = pResults->WinsStat.NoOfPnrs = WinsCnf.PullInfo.NoOfPushPnrs;
|
|
|
|
}
|
|
else
|
|
{
|
|
NoOfPnrs = pResultsN->WinsStat.NoOfPnrs = WinsCnf.PullInfo.NoOfPushPnrs;
|
|
}
|
|
|
|
//
|
|
// If no. of push pnrs (pnrs under the pull key) is > 0
|
|
//
|
|
if (NoOfPnrs > 0)
|
|
{
|
|
if (!fNew)
|
|
{
|
|
pPnrData = pResults->WinsStat.pRplPnrs =
|
|
midl_user_allocate(pResults->WinsStat.NoOfPnrs *
|
|
sizeof(WINSINTF_RPL_COUNTERS_T));
|
|
}
|
|
else
|
|
{
|
|
pPnrData = pResultsN->WinsStat.pRplPnrs =
|
|
midl_user_allocate(pResultsN->WinsStat.NoOfPnrs *
|
|
sizeof(WINSINTF_RPL_COUNTERS_T));
|
|
|
|
}
|
|
PERF("remove one of the expressions in the test condition of the if statement")
|
|
for (
|
|
i = 0;
|
|
(pPnr->WinsAdd.Add.IPAdd != INADDR_NONE)
|
|
&&
|
|
i < NoOfPnrs;
|
|
pPnrData++, i++
|
|
)
|
|
{
|
|
|
|
pPnrData->Add.IPAdd = pPnr->WinsAdd.Add.IPAdd;
|
|
(VOID)InterlockedExchange(
|
|
&pPnrData->NoOfRpls, pPnr->NoOfRpls);
|
|
(VOID)InterlockedExchange(
|
|
&pPnrData->NoOfCommFails,
|
|
pPnr->NoOfCommFails
|
|
);
|
|
//
|
|
// Get the next record that follows this one sequentially
|
|
//
|
|
pPnr = WinsCnfGetNextRplCnfRec(
|
|
pPnr,
|
|
RPL_E_IN_SEQ //seq. traversal
|
|
);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!fNew)
|
|
{
|
|
pResults->WinsStat.pRplPnrs = NULL;
|
|
}
|
|
else
|
|
{
|
|
pResultsN->WinsStat.pRplPnrs = NULL;
|
|
}
|
|
}
|
|
}
|
|
except(EXCEPTION_EXECUTE_HANDLER) {
|
|
DBGPRINTEXC("GetStatistics");
|
|
//
|
|
// log a message
|
|
//
|
|
}
|
|
|
|
LeaveCriticalSection(&WinsCnfCnfCrtSec);
|
|
|
|
GetConfig(pResultsA, fNew, FALSE);
|
|
return(WINSINTF_SUCCESS);
|
|
} // GetStatistics
|
|
|
|
|
|
DWORD
|
|
WinsDoStaticInit(
|
|
LPWSTR pDataFilePath,
|
|
DWORD fDel
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
This function does the STATIC initialization of WINS
|
|
|
|
Arguments:
|
|
pDataFilePath - Path to the data file or NULL
|
|
|
|
Externals Used:
|
|
None
|
|
|
|
|
|
Return Value:
|
|
|
|
Success status codes -- WINSINTF_SUCCESS
|
|
Error status codes -- WINSINTF_FAILURE
|
|
|
|
Error Handling:
|
|
|
|
Called by:
|
|
R_WinsDoStaticInit
|
|
Side Effects:
|
|
|
|
Comments:
|
|
None
|
|
--*/
|
|
|
|
{
|
|
|
|
WINSCNF_CNF_T WinsCnf;
|
|
STATUS RetStat = WINS_SUCCESS;
|
|
|
|
//
|
|
// If no path has been specified, take the values from the registry
|
|
//
|
|
if (pDataFilePath == NULL)
|
|
{
|
|
//
|
|
// Read the DataFiles info information
|
|
//
|
|
// This function will return with either the name of the default
|
|
// file to read or one or more files specified under the
|
|
// Parameters\Datafiles key of WINS
|
|
//
|
|
(VOID)WinsCnfGetNamesOfDataFiles(&WinsCnf);
|
|
}
|
|
else
|
|
{
|
|
FUTURES("expensive. Change idl prototype to pass length")
|
|
if (lstrlen(pDataFilePath) >= WINS_MAX_FILENAME_SZ)
|
|
{
|
|
|
|
return(WINSINTF_STATIC_INIT_FAILED);
|
|
}
|
|
//
|
|
// Set time of data initialization
|
|
//
|
|
WinsIntfSetTime(NULL, WINSINTF_E_INIT_DB);
|
|
WinsMscAlloc(WINSCNF_FILE_INFO_SZ, &WinsCnf.pStaticDataFile);
|
|
|
|
lstrcpy(WinsCnf.pStaticDataFile->FileNm, pDataFilePath);
|
|
WinsCnf.pStaticDataFile->StrType = REG_EXPAND_SZ;
|
|
WinsCnf.NoOfDataFiles = 1;
|
|
}
|
|
|
|
//
|
|
// If Static initialization fails, it will be logged.
|
|
// This function does not return an error code
|
|
//
|
|
if ((RetStat = WinsPrsDoStaticInit(
|
|
WinsCnf.pStaticDataFile,
|
|
WinsCnf.NoOfDataFiles,
|
|
FALSE //do it synchronously
|
|
)) == WINS_SUCCESS)
|
|
{
|
|
if ((pDataFilePath != NULL) && fDel)
|
|
{
|
|
if (!DeleteFile(pDataFilePath))
|
|
{
|
|
DWORD Error;
|
|
Error = GetLastError();
|
|
if (Error != ERROR_FILE_NOT_FOUND)
|
|
{
|
|
DBGPRINT1(ERR, "DbgOpenFile: Could not delete the data file. Error = (%d). Dbg file will not be truncated\n", Error);
|
|
WinsEvtLogDetEvt(FALSE, WINS_EVT_COULD_NOT_DELETE_FILE,
|
|
TEXT("winsintf.c"), __LINE__, "ud", pDataFilePath, Error);
|
|
RetStat = Error;
|
|
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
return (RetStat == WINS_SUCCESS ? WINSINTF_SUCCESS : WINSINTF_STATIC_INIT_FAILED);
|
|
}
|
|
DWORD
|
|
WinsDoScavenging(
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
This function starts the scavenging cycle
|
|
|
|
Arguments:
|
|
None
|
|
|
|
Externals Used:
|
|
None
|
|
|
|
|
|
Return Value:
|
|
|
|
Success status codes -- WINSINTF_SUCCESS
|
|
Error status codes -- exception from WinsMscSignalHdl
|
|
|
|
Error Handling:
|
|
|
|
Called by:
|
|
R_WinsDoScavenging
|
|
Side Effects:
|
|
|
|
Comments:
|
|
None
|
|
--*/
|
|
|
|
{
|
|
PQUE_SCV_REQ_WRK_ITM_T pWrkItm;
|
|
|
|
pWrkItm = WinsMscHeapAlloc( NmsRpcHeapHdl, sizeof(QUE_SCV_REQ_WRK_ITM_T));
|
|
pWrkItm->Opcode_e = WINSINTF_E_SCV_GENERAL;
|
|
pWrkItm->CmdTyp_e = QUE_E_CMD_SCV_ADMIN;
|
|
pWrkItm->fForce = 0;
|
|
pWrkItm->Age = 1; //should not be zero since zero implies
|
|
//consistency check on all replicas.
|
|
WinsLogAdminEvent( WINS_EVT_ADMIN_SCVENGING_INITIATED, 0 );
|
|
QueInsertScvWrkItm((PLIST_ENTRY)pWrkItm);
|
|
return (WINSINTF_SUCCESS);
|
|
}
|
|
|
|
DWORD
|
|
WinsDoScavengingNew(
|
|
PWINSINTF_SCV_REQ_T pScvReq
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
This function starts the scavenging cycle
|
|
|
|
Arguments:
|
|
None
|
|
|
|
Externals Used:
|
|
None
|
|
|
|
|
|
Return Value:
|
|
|
|
Success status codes -- WINSINTF_SUCCESS
|
|
Error status codes -- exception from WinsMscSignalHdl
|
|
|
|
Error Handling:
|
|
|
|
Called by:
|
|
R_WinsDoScavenging
|
|
Side Effects:
|
|
|
|
Comments:
|
|
None
|
|
--*/
|
|
|
|
{
|
|
PQUE_SCV_REQ_WRK_ITM_T pWrkItm;
|
|
pWrkItm = WinsMscHeapAlloc( NmsRpcHeapHdl, sizeof(QUE_SCV_REQ_WRK_ITM_T));
|
|
pWrkItm->Opcode_e = pScvReq->Opcode_e;
|
|
pWrkItm->Age = pScvReq->Age;
|
|
pWrkItm->fForce = pScvReq->fForce;
|
|
if (WINSINTF_E_SCV_GENERAL == pWrkItm->Opcode_e ) {
|
|
WinsLogAdminEvent( WINS_EVT_ADMIN_SCVENGING_INITIATED, 0 );
|
|
} else {
|
|
WinsLogAdminEvent( WINS_EVT_ADMIN_CCCHECK_INITIATED, 0);
|
|
}
|
|
QueInsertScvWrkItm((PLIST_ENTRY)pWrkItm);
|
|
return (WINSINTF_SUCCESS);
|
|
}
|
|
|
|
DWORD
|
|
WinsGetDbRecs (
|
|
PWINSINTF_ADD_T pWinsAdd,
|
|
WINSINTF_VERS_NO_T MinVersNo,
|
|
WINSINTF_VERS_NO_T MaxVersNo,
|
|
PWINSINTF_RECS_T pRecs
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
This function returns with all the records (that can fit into the
|
|
buffer passed) owned by a WINS in the local db of this WINS.
|
|
|
|
Arguments:
|
|
|
|
|
|
Externals Used:
|
|
None
|
|
|
|
|
|
Return Value:
|
|
|
|
Success status codes --
|
|
Error status codes --
|
|
|
|
Error Handling:
|
|
|
|
Called by:
|
|
|
|
Side Effects:
|
|
|
|
Comments:
|
|
None
|
|
--*/
|
|
|
|
{
|
|
COMM_ADD_T Address;
|
|
PRPL_REC_ENTRY_T pBuff = NULL;
|
|
LPVOID pStartBuff;
|
|
DWORD BuffLen;
|
|
DWORD NoOfRecs;
|
|
PWINSINTF_RECORD_ACTION_T pRow;
|
|
DWORD i;
|
|
DWORD ind;
|
|
//VERS_NO_T MinVersNo = {0,0};
|
|
DWORD EntType;
|
|
PWINSTHD_TLS_T pTls;
|
|
//ULONG Status;
|
|
BOOL fExcRaised = FALSE;
|
|
|
|
|
|
// PVOID pCallersAdd, pCallersCaller;
|
|
// RtlGetCallersAddress(&pCallersAdd, &pCallersCaller);
|
|
DBGENTER("WinsGetDbRecs\n");
|
|
|
|
if (LiLtr(MaxVersNo, MinVersNo))
|
|
{
|
|
return(WINSINTF_FAILURE);
|
|
}
|
|
|
|
Address.AddTyp_e = pWinsAdd->Type;
|
|
Address.AddLen = pWinsAdd->Len;
|
|
|
|
//
|
|
// snmp agent can pass a 0 for the address to ask for all records
|
|
// owned by the local wins.
|
|
//
|
|
if (pWinsAdd->IPAdd == 0)
|
|
{
|
|
Address.AddTyp_e = NmsLocalAdd.AddTyp_e;
|
|
Address.AddLen = NmsLocalAdd.AddLen;
|
|
Address.Add.IPAdd = NmsLocalAdd.Add.IPAdd;
|
|
}
|
|
else
|
|
{
|
|
Address.AddTyp_e = pWinsAdd->Type;
|
|
Address.AddLen = pWinsAdd->Len;
|
|
Address.Add.IPAdd = pWinsAdd->IPAdd;
|
|
}
|
|
//
|
|
// initialize this thread with the db engine
|
|
//
|
|
NmsDbThdInit(WINS_E_WINSRPC);
|
|
NmsDbOpenTables(WINS_E_WINSRPC);
|
|
DBGMYNAME("RPC-WinsGetDbRecs");
|
|
|
|
PERF("The caller can pass the number of records for which space has been")
|
|
PERF("allocated in buffer pointed to by pRec in the NoOfRecs field. We should")
|
|
PERF("We should pass this argument to NmsDbGetDataRecs so that it does not get")
|
|
PERF("more records than are necessary")
|
|
|
|
GET_TLS_M(pTls);
|
|
try {
|
|
NmsDbGetDataRecs(
|
|
WINS_E_WINSRPC,
|
|
0, //not used
|
|
MinVersNo,
|
|
MaxVersNo,
|
|
0, //not used
|
|
LiEqlZero(MinVersNo) && LiEqlZero(MaxVersNo) ? TRUE : FALSE,
|
|
FALSE, //not used
|
|
NULL, //must be NULL since we are not doing
|
|
//scavenging of clutter
|
|
&Address,
|
|
FALSE, //dynamic + static records are wanted
|
|
//#if RPL_TYPE
|
|
WINSCNF_RPL_DEFAULT_TYPE,
|
|
//#endif
|
|
&pBuff,
|
|
&BuffLen,
|
|
&NoOfRecs
|
|
);
|
|
|
|
i = 0;
|
|
pStartBuff = pBuff;
|
|
|
|
//
|
|
// If there are records to send back and the client has specified
|
|
// a buffer for them, insert the records
|
|
//
|
|
if (NoOfRecs > 0)
|
|
{
|
|
|
|
//
|
|
// Allocate memory for the no of records
|
|
//
|
|
pRecs->BuffSize = sizeof(WINSINTF_RECORD_ACTION_T) * NoOfRecs;
|
|
|
|
//
|
|
// If memory can not be allocate, an exception will be returned
|
|
// by midl_user_alloc
|
|
//
|
|
pRecs->pRow = midl_user_allocate(pRecs->BuffSize);
|
|
// DBGPRINT1(DET, "WinsGetDbRecs: Address of memory for records is (%d)\n", pRecs->pRow);
|
|
|
|
#if 0
|
|
pRecs->pRow = RpcSmAllocate(pRecs->BuffSize, &Status);
|
|
if (Status != RPC_S_OK)
|
|
{
|
|
DBGPRINT1(ERR, "WinsGetDbRecs: RpcSmAllocate returned error = (%x)\n", Status);
|
|
}
|
|
#endif
|
|
pRow = pRecs->pRow;
|
|
|
|
|
|
for (; i<NoOfRecs; i++)
|
|
{
|
|
|
|
//
|
|
// Initialize so that we don't get "enum wrong" error.
|
|
//
|
|
pRow->Cmd_e = WINSINTF_E_QUERY;
|
|
|
|
//
|
|
// the name retrieved has NULL as the last character. This
|
|
// We need to pass a name without this NULL.
|
|
//
|
|
pRow->NameLen = pBuff->NameLen;
|
|
if (*pBuff->pName == 0x1B)
|
|
{
|
|
WINS_SWAP_BYTES_M(pBuff->pName, pBuff->pName + 15);
|
|
}
|
|
|
|
pRow->pName = midl_user_allocate(pRow->NameLen + 1);
|
|
//DBGPRINT2(DET, "WinsGetDbRecs: Address of name = (%s) is (%d) \n", pBuff->pName, pRow->pName);
|
|
#if 0
|
|
pRow->pName = RpcSmAllocate(pRow->NameLen, &Status);
|
|
if (Status != RPC_S_OK)
|
|
{
|
|
DBGPRINT1(ERR, "WinsGetDbRecs: RpcSmAllocate returned error = (%x)\n", Status);
|
|
}
|
|
#endif
|
|
WINSMSC_COPY_MEMORY_M(pRow->pName, pBuff->pName,
|
|
pRow->NameLen);
|
|
|
|
|
|
WinsMscHeapFree(pTls->HeapHdl, pBuff->pName);
|
|
EntType = NMSDB_ENTRY_TYPE_M(pBuff->Flag);
|
|
pRow->TypOfRec_e = NMSDB_ENTRY_UNIQUE_M(EntType)
|
|
? WINSINTF_E_UNIQUE :
|
|
(NMSDB_ENTRY_NORM_GRP_M(EntType) ?
|
|
WINSINTF_E_NORM_GROUP :
|
|
(NMSDB_ENTRY_SPEC_GRP_M(EntType) ?
|
|
WINSINTF_E_SPEC_GROUP :
|
|
WINSINTF_E_MULTIHOMED));
|
|
|
|
|
|
if (
|
|
(pRow->TypOfRec_e == WINSINTF_E_SPEC_GROUP) ||
|
|
(pRow->TypOfRec_e == WINSINTF_E_MULTIHOMED)
|
|
)
|
|
{
|
|
PWINSINTF_ADD_T pAdd;
|
|
DWORD No;
|
|
if (pBuff->NoOfAdds > 0)
|
|
{
|
|
pRow->NoOfAdds = pBuff->NoOfAdds * 2;
|
|
|
|
//
|
|
// Each member is comprised of two addresses,
|
|
// first address is that of the owner WINS, second
|
|
// address is that of the node registered
|
|
//
|
|
pRow->pAdd =
|
|
// RpcSmAllocate(
|
|
midl_user_allocate(
|
|
(unsigned int)(pRow->NoOfAdds)
|
|
*
|
|
sizeof(WINSINTF_ADD_T)//,
|
|
// &Status
|
|
);
|
|
//DBGPRINT2(DET, "WinsGetDbRecs: Address of ip address for name = (%s) is (%d) \n", pRow->pName, pRow->pAdd);
|
|
#if 0
|
|
if (Status != RPC_S_OK)
|
|
{
|
|
DBGPRINT1(ERR, "WinsGetDbRecs: RpcSmAllocate returned error = (%x)\n", Status);
|
|
}
|
|
#endif
|
|
for (
|
|
No= 0, ind= 0, pAdd = pRow->pAdd;
|
|
No < (pRow->NoOfAdds/2);
|
|
No++
|
|
)
|
|
{
|
|
pAdd->Type = (UCHAR)(pBuff->pNodeAdd + ind)->AddTyp_e;
|
|
pAdd->Len = (pBuff->pNodeAdd + ind)->AddLen;
|
|
pAdd++->IPAdd = (pBuff->pNodeAdd + ind)->Add.IPAdd;
|
|
|
|
pAdd->Type = (UCHAR)(pBuff->pNodeAdd + ++ind)->AddTyp_e;
|
|
pAdd->Len = (pBuff->pNodeAdd + ind)->AddLen;
|
|
pAdd++->IPAdd = (pBuff->pNodeAdd + ind++)->Add.IPAdd;
|
|
}
|
|
WinsMscHeapFree(pTls->HeapHdl, pBuff->pNodeAdd);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pRow->NoOfAdds = 0;
|
|
pRow->pAdd = NULL;
|
|
pRow->Add.Type = (UCHAR)pBuff->NodeAdd[0].AddTyp_e;
|
|
pRow->Add.Len = pBuff->NodeAdd[0].AddLen;
|
|
pRow->Add.IPAdd = pBuff->NodeAdd[0].Add.IPAdd;
|
|
}
|
|
pRow->NodeTyp = (BYTE)NMSDB_NODE_TYPE_M(pBuff->Flag);
|
|
pRow->fStatic = NMSDB_IS_ENTRY_STATIC_M(pBuff->Flag);
|
|
pRow->State_e = NMSDB_ENTRY_STATE_M(pBuff->Flag);
|
|
pRow->VersNo = pBuff->VersNo;
|
|
pRow->TimeStamp = pBuff->TimeStamp;
|
|
|
|
pRow++;
|
|
|
|
|
|
pBuff = (PRPL_REC_ENTRY_T)((LPBYTE)pBuff + RPL_REC_ENTRY_SIZE);
|
|
PERF("Do the addition above the for loop and store in a var. Use var. here")
|
|
|
|
} // end of for loop
|
|
} //end of if block
|
|
else
|
|
{
|
|
pRecs->pRow = NULL;
|
|
}
|
|
|
|
} // end of try
|
|
except(EXCEPTION_EXECUTE_HANDLER) {
|
|
DBGPRINTEXC("WinsGetDbRecs");
|
|
WINSEVT_LOG_M(GetExceptionCode(), WINS_EVT_RPC_EXC);
|
|
fExcRaised = TRUE;
|
|
}
|
|
|
|
pRecs->TotalNoOfRecs = NoOfRecs;
|
|
|
|
//
|
|
// Deallocate the buffer allocated by NmsDbGetDataRecs
|
|
//
|
|
|
|
|
|
WinsMscHeapFree(pTls->HeapHdl, pStartBuff);
|
|
WinsMscHeapDestroy(pTls->HeapHdl);
|
|
|
|
if (!fExcRaised)
|
|
{
|
|
pRecs->NoOfRecs = i;
|
|
}
|
|
else
|
|
{
|
|
// RpcSmFree(pRecs->pRow);
|
|
midl_user_free(pRecs->pRow);
|
|
pRecs->NoOfRecs = 0;
|
|
}
|
|
|
|
//
|
|
// Let us end the session
|
|
//
|
|
NmsDbCloseTables();
|
|
NmsDbEndSession();
|
|
|
|
DBGLEAVE("WinsGetDbRecs\n");
|
|
return (WINSINTF_SUCCESS);
|
|
}
|
|
|
|
VOID
|
|
WinsIntfSetTime(
|
|
OUT PSYSTEMTIME pTime,
|
|
IN WINSINTF_TIME_TYPE_E TimeType_e
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
This function is called to set the the time in the WINSINTF_STAT_T
|
|
structure
|
|
|
|
Arguments:
|
|
pTime - Local Time (returned)
|
|
TimeType_e - The activity for which the time has to be stored
|
|
|
|
Externals Used:
|
|
None
|
|
|
|
Return Value:
|
|
|
|
NONE
|
|
|
|
Error Handling:
|
|
|
|
Called by:
|
|
|
|
Side Effects:
|
|
|
|
Comments:
|
|
None
|
|
--*/
|
|
{
|
|
SYSTEMTIME SysTime;
|
|
PSYSTEMTIME pSysTime = &SysTime;
|
|
|
|
GetSystemTime(pSysTime);
|
|
|
|
EnterCriticalSection(&WinsIntfCrtSec);
|
|
|
|
switch(TimeType_e)
|
|
{
|
|
case(WINSINTF_E_WINS_START):
|
|
WinsIntfStat.TimeStamps.WinsStartTime = *pSysTime;
|
|
break;
|
|
case(WINSINTF_E_PLANNED_SCV):
|
|
WinsIntfStat.TimeStamps.LastPScvTime = *pSysTime;
|
|
break;
|
|
case(WINSINTF_E_ADMIN_TRIG_SCV):
|
|
WinsIntfStat.TimeStamps.LastATScvTime = *pSysTime;
|
|
break;
|
|
case(WINSINTF_E_TOMBSTONES_SCV):
|
|
WinsIntfStat.TimeStamps.LastTombScvTime = *pSysTime;
|
|
break;
|
|
case(WINSINTF_E_VERIFY_SCV):
|
|
WinsIntfStat.TimeStamps.LastVerifyScvTime = *pSysTime;
|
|
break;
|
|
case(WINSINTF_E_INIT_DB):
|
|
WinsIntfStat.TimeStamps.LastInitDbTime = *pSysTime;
|
|
break;
|
|
case(WINSINTF_E_PLANNED_PULL):
|
|
WinsIntfStat.TimeStamps.LastPRplTime = *pSysTime;
|
|
break;
|
|
case(WINSINTF_E_ADMIN_TRIG_PULL):
|
|
WinsIntfStat.TimeStamps.LastATRplTime = *pSysTime;
|
|
break;
|
|
case(WINSINTF_E_NTWRK_TRIG_PULL):
|
|
WinsIntfStat.TimeStamps.LastNTRplTime = *pSysTime;
|
|
break;
|
|
case(WINSINTF_E_UPDCNT_TRIG_PULL):
|
|
WinsIntfStat.TimeStamps.LastNTRplTime = *pSysTime;
|
|
break;
|
|
case(WINSINTF_E_ADDCHG_TRIG_PULL):
|
|
WinsIntfStat.TimeStamps.LastACTRplTime = *pSysTime;
|
|
break;
|
|
case(WINSINTF_E_COUNTER_RESET):
|
|
WinsIntfStat.TimeStamps.CounterResetTime = *pSysTime;
|
|
break;
|
|
default:
|
|
DBGPRINT1(EXC, "WinsIntfSetTime: Weird Timestamp type = (%d)\n", TimeType_e);
|
|
WINSEVT_LOG_M(WINS_FAILURE, WINS_EVT_SFT_ERR);
|
|
break;
|
|
}
|
|
LeaveCriticalSection(&WinsIntfCrtSec);
|
|
|
|
if (pTime)
|
|
{
|
|
TIME_ZONE_INFORMATION tzInfo;
|
|
GetTimeZoneInformation(&tzInfo);
|
|
SystemTimeToTzSpecificLocalTime(&tzInfo, pSysTime, pTime);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
DWORD
|
|
WinsDelDbRecs(
|
|
IN PWINSINTF_ADD_T pAdd,
|
|
IN WINSINTF_VERS_NO_T MinVersNo,
|
|
IN WINSINTF_VERS_NO_T MaxVersNo
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
This func. deletes a specified range of records belonging to a
|
|
particular owner
|
|
|
|
Arguments:
|
|
|
|
|
|
Externals Used:
|
|
None
|
|
|
|
|
|
Return Value:
|
|
|
|
Success status codes -- WINSINTF_SUCCESS
|
|
Error status codes -- WINSINTF_FAILURE
|
|
|
|
Error Handling:
|
|
|
|
Called by:
|
|
R_WinsDelDbRecs
|
|
|
|
Side Effects:
|
|
|
|
Comments:
|
|
None
|
|
--*/
|
|
|
|
{
|
|
|
|
COMM_ADD_T Address;
|
|
DWORD RetVal = WINSINTF_SUCCESS;
|
|
DWORD dwOwnerId;
|
|
BOOL fAllocNew = FALSE;
|
|
|
|
Address.AddTyp_e = pAdd->Type;
|
|
Address.AddLen = pAdd->Len;
|
|
Address.Add.IPAdd = pAdd->IPAdd;
|
|
|
|
//
|
|
// initialize this thread with the db engine
|
|
//
|
|
NmsDbThdInit(WINS_E_WINSRPC);
|
|
NmsDbOpenTables(WINS_E_WINSRPC);
|
|
DBGMYNAME("RPC-WinsDelDbRecs");
|
|
|
|
|
|
if (RplFindOwnerId(
|
|
&Address,
|
|
&fAllocNew, //do not allocate an entry if not
|
|
//present
|
|
&dwOwnerId,
|
|
WINSCNF_E_IGNORE_PREC,
|
|
WINSCNF_LOW_PREC
|
|
) != WINS_SUCCESS)
|
|
|
|
{
|
|
DBGPRINT0(DET, "WinsDelDataRecs: WINS is not in the owner-add mapping table\n");
|
|
RetVal = WINSINTF_FAILURE;
|
|
}
|
|
else
|
|
{
|
|
if (NmsDbDelDataRecs(
|
|
dwOwnerId,
|
|
MinVersNo,
|
|
MaxVersNo,
|
|
TRUE, //enter critical section
|
|
FALSE //no fragmented deletion
|
|
) != WINS_SUCCESS)
|
|
{
|
|
RetVal = WINSINTF_FAILURE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Let us end the session
|
|
//
|
|
NmsDbCloseTables();
|
|
NmsDbEndSession();
|
|
return(RetVal);
|
|
}
|
|
|
|
DWORD
|
|
WinsTombstoneDbRecs(
|
|
IN PWINSINTF_ADD_T pAdd,
|
|
IN WINSINTF_VERS_NO_T MinVersNo,
|
|
IN WINSINTF_VERS_NO_T MaxVersNo
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
This func. tombstones a specified range of records belonging to a
|
|
particular owner
|
|
|
|
Arguments:
|
|
|
|
|
|
Externals Used:
|
|
None
|
|
|
|
|
|
Return Value:
|
|
|
|
Success status codes -- WINSINTF_SUCCESS
|
|
Error status codes -- WINSINTF_FAILURE
|
|
|
|
Error Handling:
|
|
|
|
Called by:
|
|
R_WinsTombstoneDbRecs
|
|
|
|
Side Effects:
|
|
|
|
|
|
Comments:
|
|
None
|
|
--*/
|
|
|
|
{
|
|
|
|
DWORD RetVal = WINSINTF_SUCCESS;
|
|
COMM_ADD_T Address;
|
|
DWORD dwOwnerId;
|
|
BOOL fAllocNew = FALSE;
|
|
|
|
Address.AddTyp_e = pAdd->Type;
|
|
Address.AddLen = pAdd->Len;
|
|
Address.Add.IPAdd = pAdd->IPAdd;
|
|
|
|
|
|
//
|
|
// initialize this thread with the db engine
|
|
//
|
|
NmsDbThdInit(WINS_E_WINSRPC);
|
|
NmsDbOpenTables(WINS_E_WINSRPC);
|
|
DBGMYNAME("RPC-WinsTombstoneDbRecs");
|
|
|
|
if (RplFindOwnerId(
|
|
&Address,
|
|
&fAllocNew, //do not allocate an entry if not
|
|
//present
|
|
&dwOwnerId,
|
|
WINSCNF_E_IGNORE_PREC,
|
|
WINSCNF_LOW_PREC
|
|
) != WINS_SUCCESS)
|
|
|
|
{
|
|
DBGPRINT0(DET, "WinsTombstoneDataRecs: WINS is not in the owner-add mapping table\n");
|
|
RetVal = WINSINTF_FAILURE;
|
|
}else if(NmsDbTombstoneDataRecs(
|
|
dwOwnerId,
|
|
MinVersNo,
|
|
MaxVersNo
|
|
) != WINS_SUCCESS)
|
|
{
|
|
RetVal = WINSINTF_FAILURE;
|
|
}
|
|
// Let us end the session
|
|
NmsDbCloseTables();
|
|
NmsDbEndSession();
|
|
return(RetVal);
|
|
}
|
|
|
|
DWORD
|
|
WinsPullRange(
|
|
IN PWINSINTF_ADD_T pWinsAdd,
|
|
IN PWINSINTF_ADD_T pOwnerAdd,
|
|
IN WINSINTF_VERS_NO_T MinVersNo,
|
|
IN WINSINTF_VERS_NO_T MaxVersNo
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
This function is called to pull a range of records owned by a particular
|
|
WINS server from another WINS server.
|
|
|
|
Arguments:
|
|
|
|
|
|
Externals Used:
|
|
None
|
|
|
|
|
|
Return Value:
|
|
|
|
Success status codes --
|
|
Error status codes --
|
|
|
|
Error Handling:
|
|
|
|
Called by:
|
|
|
|
Side Effects:
|
|
|
|
Comments:
|
|
None
|
|
--*/
|
|
|
|
{
|
|
PWINSINTF_PULL_RANGE_INFO_T pPullRangeInfo;
|
|
PRPL_CONFIG_REC_T pPnr;
|
|
BOOL fRplPnr = FALSE;
|
|
DWORD RetCode = WINSINTF_SUCCESS;
|
|
|
|
|
|
//
|
|
// if the minimum version number is > than the max version number
|
|
// return a failure code
|
|
//
|
|
if (LiGtr(MinVersNo, MaxVersNo))
|
|
{
|
|
return(WINSINTF_FAILURE);
|
|
|
|
}
|
|
//
|
|
// Enter the critical sections guarded by WinsCnfCnfCrtSec and
|
|
// NmsNmhNamRegCrtSec. There is no danger of deadlock because we
|
|
// always enter the two critical sections in the following sequence
|
|
//
|
|
EnterCriticalSection(&WinsCnfCnfCrtSec);
|
|
|
|
PERF("Do we need to enter the following critical section")
|
|
EnterCriticalSection(&NmsNmhNamRegCrtSec);
|
|
try {
|
|
pPnr = WinsCnf.PullInfo.pPullCnfRecs;
|
|
|
|
//
|
|
// If we are allowed to pull only from configured partners,
|
|
// let us try to find the config record of the partner
|
|
//
|
|
if (WinsCnf.fRplOnlyWCnfPnrs)
|
|
{
|
|
if (pPnr != NULL)
|
|
{
|
|
//
|
|
// Search for the Cnf record for the WINS we want to
|
|
// send the PULL RANGE request to.
|
|
//
|
|
for (
|
|
;
|
|
(pPnr->WinsAdd.Add.IPAdd != INADDR_NONE)
|
|
&&
|
|
!fRplPnr;
|
|
// no third expression
|
|
)
|
|
{
|
|
|
|
|
|
//
|
|
// Check if this is the one we want
|
|
//
|
|
if (pPnr->WinsAdd.Add.IPAdd == pWinsAdd->IPAdd)
|
|
{
|
|
//
|
|
// We are done. Set the fRplPnr flag to TRUE so that
|
|
// we break out of the loop.
|
|
//
|
|
fRplPnr = TRUE;
|
|
|
|
//
|
|
// Make it 0, so that we always try to establish
|
|
// a connection. Otherwise, pull thread may not
|
|
// try if it has already exhausted the number of
|
|
// retries
|
|
//
|
|
pPnr->RetryCount = 0;
|
|
continue; //so that we can break out
|
|
|
|
}
|
|
//
|
|
// Get the next record that follows this one sequentially
|
|
//
|
|
pPnr = WinsCnfGetNextRplCnfRec(
|
|
pPnr,
|
|
RPL_E_IN_SEQ //seq. traversal
|
|
);
|
|
} // end of for
|
|
} // end of if (pPnr != 0)
|
|
} // end of if (fRplOnlyWCnfPnrs)
|
|
else
|
|
{
|
|
pPnr = WinsMscHeapAlloc( NmsRpcHeapHdl, RPL_CONFIG_REC_SIZE);
|
|
COMM_INIT_ADD_M(&pPnr->WinsAdd, pWinsAdd->IPAdd);
|
|
pPnr->MagicNo = 0;
|
|
pPnr->RetryCount = 0;
|
|
pPnr->LastCommFailTime = 0;
|
|
pPnr->PushNtfTries = 0;
|
|
fRplPnr = TRUE;
|
|
|
|
//
|
|
// We want the buffer to be deallocated by the PULL thread
|
|
//
|
|
pPnr->fTemp = TRUE;
|
|
|
|
//#if RPL_TYPE
|
|
//
|
|
// We need to pull according to the RplType for the pull pnrs
|
|
//
|
|
pPnr->RplType = WinsCnf.PullInfo.RplType;
|
|
//#endif
|
|
|
|
}
|
|
|
|
|
|
if (fRplPnr)
|
|
{
|
|
pPullRangeInfo = WinsMscHeapAlloc(
|
|
NmsRpcHeapHdl,
|
|
sizeof(WINSINTF_PULL_RANGE_INFO_T)
|
|
);
|
|
#if 0
|
|
WinsMscAlloc(sizeof(WINSINTF_PULL_RANGE_INFO_T),
|
|
&pPullRangeInfo);
|
|
#endif
|
|
pPullRangeInfo->pPnr = pPnr;
|
|
pPullRangeInfo->OwnAdd = *pOwnerAdd;
|
|
pPullRangeInfo->MinVersNo = MinVersNo;
|
|
pPullRangeInfo->MaxVersNo = MaxVersNo;
|
|
|
|
|
|
//
|
|
// Call RplInsertQue to insert the push request to
|
|
// the Pull Thread
|
|
//
|
|
ERplInsertQue(
|
|
WINS_E_WINSRPC,
|
|
QUE_E_CMD_PULL_RANGE,
|
|
NULL, //no Dlg Hdl
|
|
NULL, //no msg is there
|
|
0, //msg length
|
|
pPullRangeInfo, //client context
|
|
pPnr->MagicNo
|
|
);
|
|
}
|
|
}
|
|
except (EXCEPTION_EXECUTE_HANDLER) {
|
|
DBGPRINTEXC("WinsPullRange");
|
|
WINSEVT_LOG_D_M(WINS_FAILURE, WINS_EVT_PUSH_TRIGGER_EXC);
|
|
RetCode = WINSINTF_FAILURE;
|
|
}
|
|
|
|
//
|
|
// Leave the critical section guarded by NmsNmhNamRegCrtSec.
|
|
//
|
|
LeaveCriticalSection(&NmsNmhNamRegCrtSec);
|
|
LeaveCriticalSection(&WinsCnfCnfCrtSec);
|
|
|
|
//
|
|
// if replication was allowed only with configured partners and
|
|
// there was no WINS with the address specified by the client,
|
|
// return failure
|
|
//
|
|
if (!fRplPnr)
|
|
{
|
|
RetCode = WINSINTF_FAILURE;
|
|
}
|
|
|
|
return(RetCode);
|
|
}
|
|
|
|
DWORD
|
|
WinsSetPriorityClass(
|
|
IN WINSINTF_PRIORITY_CLASS_E PriorityClass_e
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
This function sets the priority class of the Wins process.
|
|
|
|
Arguments:
|
|
PriorityClass -- Priority Class of the WINS process
|
|
|
|
Externals Used:
|
|
WinsCnf
|
|
|
|
|
|
Return Value:
|
|
|
|
Success status codes --
|
|
Error status codes --
|
|
|
|
Error Handling:
|
|
|
|
Called by:
|
|
|
|
Side Effects:
|
|
|
|
Comments:
|
|
None
|
|
--*/
|
|
{
|
|
|
|
//DWORD OldPrCls;
|
|
DWORD NewPrCls;
|
|
HANDLE ProcHdl;
|
|
DWORD RetVal = WINSINTF_SUCCESS;
|
|
|
|
switch(PriorityClass_e)
|
|
{
|
|
case(WINSINTF_E_NORMAL):
|
|
NewPrCls = NORMAL_PRIORITY_CLASS;
|
|
break;
|
|
case(WINSINTF_E_HIGH):
|
|
NewPrCls = HIGH_PRIORITY_CLASS;
|
|
break;
|
|
default:
|
|
DBGPRINT0(DET, "WinsSetPriorityClass: Invalid Priority Class\n");
|
|
return(WINSINTF_FAILURE);
|
|
break;
|
|
}
|
|
|
|
|
|
ProcHdl = GetCurrentProcess();
|
|
|
|
EnterCriticalSection(&WinsCnfCnfCrtSec);
|
|
#if 0
|
|
try {
|
|
FUTURES("Use a WinsMsc functions here for consistency")
|
|
|
|
if ((OldPrCls = GetPriorityClass(ProcHdl)) == 0)
|
|
{
|
|
DBGPRINT1(ERR, "WinsSetPriorityClass: Can not Proc Priority. Error = (%d)\n", GetLastError());
|
|
RetVal = WINSINTF_FAILURE;
|
|
}
|
|
else
|
|
{
|
|
if (OldPrCls == NewPrCls)
|
|
{
|
|
DBGPRINT1(ERR, "WinsSetPriorityClass: Process already has this Priority Class = (%d)\n", NewPrCls);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
if (SetPriorityClass(ProcHdl, NewPrCls) == FALSE)
|
|
{
|
|
DBGPRINT1(ERR, "WinsSetPriorityClass: SetPriorityClass() Failed. Error = (%d)\n", GetLastError());
|
|
}
|
|
else
|
|
{
|
|
WinsCnf.WinsPriorityClass = (DWORD)PriorityClass_e;
|
|
}
|
|
#if 0
|
|
}
|
|
}
|
|
}
|
|
except(EXCEPTION_EXECUTE_HANDLER) {
|
|
DBGPRINTEXC("WinsSetPriorityCls");
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// ProcHdl is a pseudo-handle and does not need to be closed
|
|
//
|
|
LeaveCriticalSection(&WinsCnfCnfCrtSec);
|
|
return(WINSINTF_SUCCESS);
|
|
}
|
|
|
|
DWORD
|
|
WinsResetCounters(
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
This function resets/clears the counters
|
|
|
|
Arguments:
|
|
None
|
|
|
|
Externals Used:
|
|
NmsNmhNamRegCrtSec
|
|
|
|
Return Value:
|
|
|
|
Success status codes --
|
|
Error status codes --
|
|
|
|
Error Handling:
|
|
|
|
Called by:
|
|
R_WinsResetCounters
|
|
|
|
Side Effects:
|
|
|
|
Comments:
|
|
None
|
|
--*/
|
|
|
|
{
|
|
DWORD i;
|
|
PRPL_CONFIG_REC_T pPnr;
|
|
//
|
|
// Copy the counters
|
|
//
|
|
EnterCriticalSection(&NmsNmhNamRegCrtSec);
|
|
(VOID)RtlFillMemory(&WinsIntfStat.Counters, sizeof(WinsIntfStat.Counters), 0);
|
|
LeaveCriticalSection(&NmsNmhNamRegCrtSec);
|
|
// now clear the per partner info.
|
|
EnterCriticalSection(&WinsCnfCnfCrtSec);
|
|
pPnr = WinsCnf.PullInfo.pPullCnfRecs;
|
|
for (i = 0; (i<WinsCnf.PullInfo.NoOfPushPnrs) && (pPnr->WinsAdd.Add.IPAdd != INADDR_NONE) ; i++) {
|
|
pPnr->NoOfRpls = 0;
|
|
pPnr->NoOfCommFails = 0;
|
|
pPnr = WinsCnfGetNextRplCnfRec(pPnr,RPL_E_IN_SEQ);
|
|
}
|
|
LeaveCriticalSection(&WinsCnfCnfCrtSec);
|
|
|
|
//
|
|
// Even if we have multiple threads doing resets (unlikely occurence),
|
|
// the window between the above critical section and the one entered
|
|
// by the following function does not cause any problem.
|
|
//
|
|
WinsIntfSetTime(NULL, WINSINTF_E_COUNTER_RESET);
|
|
|
|
return(WINSINTF_SUCCESS);
|
|
}
|
|
|
|
DWORD
|
|
WinsWorkerThdUpd(
|
|
DWORD NewNoOfNbtThds
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
This function is called to change the count of the NBT threads in
|
|
the WINS process.
|
|
|
|
Arguments:
|
|
NewNoOfNbtThds - The new count of the Nbt threads
|
|
|
|
Externals Used:
|
|
None
|
|
|
|
|
|
Return Value:
|
|
|
|
Success status codes -- WINSINTF_SUCCESS
|
|
Error status codes -- WINSINTF_FAILURE
|
|
|
|
Error Handling:
|
|
|
|
Called by:
|
|
|
|
Side Effects:
|
|
|
|
Comments:
|
|
None
|
|
--*/
|
|
{
|
|
|
|
//
|
|
// If the WINS server is not in steady state or if the new count
|
|
// of Nbt threads requested is outside the allowed range, return
|
|
// failure
|
|
//
|
|
CHECK("Somehow, if the number of threads is equal to the max. number allowed")
|
|
CHECK("pTls comes out as NULL for all NBT threads (seen at termination)")
|
|
if (
|
|
|
|
((WinsCnf.State_e != WINSCNF_E_RUNNING)
|
|
&&
|
|
(WinsCnf.State_e != WINSCNF_E_PAUSED))
|
|
||
|
|
(NewNoOfNbtThds >= WINSTHD_MAX_NO_NBT_THDS)
|
|
||
|
|
(NewNoOfNbtThds < WINSTHD_MIN_NO_NBT_THDS)
|
|
)
|
|
{
|
|
return(WINSINTF_FAILURE);
|
|
}
|
|
|
|
EnterCriticalSection(&WinsCnfCnfCrtSec);
|
|
WinsIntfNoOfNbtThds = NewNoOfNbtThds;
|
|
|
|
try {
|
|
//
|
|
// If the new count is more than the existing count, store the new
|
|
// count in a global and signal an Nbt thread. The signaled
|
|
// Nbt thread will create all the extra threads needed
|
|
//
|
|
if (NewNoOfNbtThds > NmsNoOfNbtThds)
|
|
{
|
|
WinsMscSignalHdl(NmsCrDelNbtThdEvt);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// if the new count is same as the existing count, return
|
|
// success
|
|
//
|
|
if (NewNoOfNbtThds == NmsNoOfNbtThds)
|
|
{
|
|
DBGPRINT1(FLOW, "WinsWorkerThdUpd: Wins server already has %d threads\n", NewNoOfNbtThds);
|
|
}
|
|
else // NewNoOfNbtThds < NmsNoOfNbtThds
|
|
{
|
|
//
|
|
// Signal a thread to delete self. The signaled thread will
|
|
// signal the event again if more than one thread has to be
|
|
// deleted
|
|
//
|
|
WinsMscSignalHdl(NmsCrDelNbtThdEvt);
|
|
}
|
|
}
|
|
}
|
|
except (EXCEPTION_EXECUTE_HANDLER) {
|
|
DBGPRINTEXC("WinsWorkerThdUpd");
|
|
}
|
|
|
|
LeaveCriticalSection(&WinsCnfCnfCrtSec);
|
|
|
|
return(WINSINTF_SUCCESS);
|
|
}
|
|
|
|
|
|
|
|
DWORD
|
|
WinsGetNameAndAdd(
|
|
PWINSINTF_ADD_T pWinsAdd,
|
|
LPBYTE pUncName
|
|
)
|
|
{
|
|
DWORD RetStat = WINSINTF_SUCCESS;
|
|
|
|
// TCHAR UncName[MAX_COMPUTERNAME_LENGTH + 1];
|
|
// DWORD LenOfBuff = WINSINTF_MAX_COMPUTERNAME_LENGTH;
|
|
DWORD LenOfBuff = MAX_COMPUTERNAME_LENGTH + 1;
|
|
pWinsAdd->IPAdd = NmsLocalAdd.Add.IPAdd;
|
|
FUTURES("Change this to GetComputerName when winsadmn is made unicode compliant")
|
|
if (GetComputerNameA(pUncName, &LenOfBuff) == FALSE)
|
|
{
|
|
DBGPRINT1(ERR, "WinsGetNameAndAdd: Name error. Error=(%x)\n", GetLastError());
|
|
RetStat = GetLastError();
|
|
}
|
|
return(RetStat);
|
|
}
|
|
|
|
|
|
|
|
#define INITIAL_RAMPUP_NO 3
|
|
|
|
DWORD
|
|
WinsGetBrowserNames(
|
|
PWINSINTF_BIND_DATA_T pWinsHdl,
|
|
PWINSINTF_BROWSER_NAMES_T pNames
|
|
)
|
|
{
|
|
|
|
DWORD RetVal = WINSINTF_SUCCESS;
|
|
time_t CurrentTime;
|
|
static DWORD sNoOfTimes = 0;
|
|
static time_t sLastTime = 0;
|
|
BOOL fPopCache = FALSE;
|
|
|
|
|
|
UNREFERENCED_PARAMETER(pWinsHdl);
|
|
|
|
//
|
|
// If this the initial ramp up period, populate the cache
|
|
//
|
|
if (sNoOfTimes++ < INITIAL_RAMPUP_NO)
|
|
{
|
|
//
|
|
// if this is the first call, create the dom. cache event.
|
|
//
|
|
if (sNoOfTimes == 1)
|
|
{
|
|
WinsMscCreateEvt(L"WinsDomCachEvt", FALSE, &sDomCache.EvtHdl);
|
|
}
|
|
DBGPRINT1(SPEC, "WinsGetBrowserNames: sNoOfTimes = (%d)\n", sNoOfTimes);
|
|
fPopCache = TRUE;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Initial ramp up period is past. Populate the cache if 3 mts
|
|
// have expired since it was last populated
|
|
//
|
|
if ((time(&CurrentTime) - sLastTime) > THREE_MTS || sDomCache.bRefresh)
|
|
{
|
|
DBGPRINT0(SPEC, "WinsGetBrowserNames: Pop Cache due to timeout\n");
|
|
sDomCache.bRefresh = FALSE;
|
|
sLastTime = CurrentTime;
|
|
fPopCache = TRUE;
|
|
}
|
|
}
|
|
try {
|
|
//
|
|
// Populate the cache if fPopCache is set or if the number of entries
|
|
// in the current cache are 0
|
|
//
|
|
if (fPopCache || (sDomCache.SzOfBlock == 0))
|
|
{
|
|
//
|
|
// if our cache has some data, deallocate it first.
|
|
//
|
|
// Note: There could be an rpc thread in the rpc code accessing
|
|
// this buffer. I can't free this buffer until it is done.
|
|
//
|
|
if (sDomCache.SzOfBlock > 0)
|
|
{
|
|
DWORD i;
|
|
PWINSINTF_BROWSER_INFO_T pBrInfo = sDomCache.pInfo;
|
|
DWORD NoOfUsers;
|
|
|
|
//
|
|
// Wait until all users are done. We won't iterate more than
|
|
//
|
|
// We can iterate a max. of INITIAL_RAMPUP_NO of times and
|
|
// that too only at initial ramp up time. If a thread is
|
|
// waiting on the event, another thread will also wait
|
|
// on it (except during initial rampup time)
|
|
//
|
|
do {
|
|
EnterCriticalSection(&WinsIntfNoOfUsersCrtSec);
|
|
NoOfUsers = sDomCache.NoOfUsers;
|
|
LeaveCriticalSection(&WinsIntfNoOfUsersCrtSec);
|
|
if (NoOfUsers > 0)
|
|
{
|
|
WinsMscWaitInfinite(sDomCache.EvtHdl);
|
|
}
|
|
} while (NoOfUsers > 0);
|
|
//
|
|
// Free all memory allocated for names
|
|
//
|
|
for (i=0; i< sDomCache.EntriesRead; i++, pBrInfo++)
|
|
{
|
|
midl_user_free(pBrInfo->pName);
|
|
}
|
|
|
|
//
|
|
// Free the main block
|
|
//
|
|
midl_user_free(sDomCache.pInfo);
|
|
sDomCache.SzOfBlock = 0;
|
|
pNames->EntriesRead = 0;
|
|
pNames->pInfo = NULL;
|
|
}
|
|
|
|
NmsDbThdInit(WINS_E_WINSRPC);
|
|
NmsDbOpenTables(WINS_E_WINSRPC);
|
|
DBGMYNAME("RPC-WinsGetBrowserNames");
|
|
|
|
//
|
|
// Get all records starting with 1B Names
|
|
//
|
|
RetVal = NmsDbGetNamesWPrefixChar(
|
|
0x1B,
|
|
&pNames->pInfo,
|
|
&pNames->EntriesRead
|
|
);
|
|
NmsDbCloseTables();
|
|
NmsDbEndSession();
|
|
|
|
//
|
|
// Store the info. only if there is something to be stored.
|
|
//
|
|
if (
|
|
(RetVal == WINS_SUCCESS)
|
|
&&
|
|
(pNames->EntriesRead > 0)
|
|
)
|
|
{
|
|
sDomCache.SzOfBlock =
|
|
pNames->EntriesRead * sizeof(WINSINTF_BROWSER_INFO_T);
|
|
// sDomCache.pInfo = midl_user_allocate(sDomCache.SzOfBlock);
|
|
// WINSMSC_COPY_MEMORY_M(sDomCache.pInfo, pNames->pInfo,
|
|
// sDomCache.SzOfBlock);
|
|
sDomCache.pInfo = pNames->pInfo;
|
|
sDomCache.EntriesRead = pNames->EntriesRead;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// We did not get anything from the db
|
|
//
|
|
sDomCache.SzOfBlock = 0;
|
|
pNames->EntriesRead = 0;
|
|
pNames->pInfo = NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Use the cached info.
|
|
//
|
|
//pNames->pInfo = midl_user_allocate(sDomCache.SzOfBlock);
|
|
//WINSMSC_COPY_MEMORY_M(pNames->pInfo, sDomCache.pInfo,
|
|
// sDomCache.SzOfBlock);
|
|
pNames->pInfo = sDomCache.pInfo;
|
|
pNames->EntriesRead = sDomCache.EntriesRead;
|
|
}
|
|
}
|
|
except(EXCEPTION_EXECUTE_HANDLER) {
|
|
DBGPRINTEXC("WinsGetBrowserNames");
|
|
WINSEVT_LOG_M(GetExceptionCode(), WINS_EVT_BROWSER_NAME_EXC);
|
|
pNames->EntriesRead = 0;
|
|
pNames->pInfo = NULL;
|
|
RetVal = WINSINTF_FAILURE;
|
|
}
|
|
return(RetVal);
|
|
}
|
|
|
|
VOID
|
|
R_WinsGetBrowserNames_notify_flag(boolean __MIDL_NotifyFlag
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Called by rpc to indicate that it is done with the buffer returned by
|
|
WinsGetBrowserNames
|
|
|
|
Arguments:
|
|
|
|
Externals Used:
|
|
None
|
|
|
|
|
|
Return Value:
|
|
|
|
Success status codes --
|
|
Error status codes --
|
|
|
|
Error Handling:
|
|
|
|
Called by:
|
|
|
|
Side Effects:
|
|
|
|
Comments:
|
|
None
|
|
--*/
|
|
|
|
{
|
|
//
|
|
// Decrement the user count. If equal to 0, signal the event to let
|
|
// another thread go on.
|
|
//
|
|
EnterCriticalSection(&WinsIntfNoOfUsersCrtSec);
|
|
|
|
//
|
|
// workaround an rpc bug (18627) where it may call notify without calling
|
|
// R_WinsGetBrowserNames (checkout winsif_s.c)
|
|
//
|
|
if (
|
|
(sDomCache.NoOfUsers > 0) &&
|
|
(--sDomCache.NoOfUsers == 0) &&
|
|
sDomCache.EvtHdl != NULL
|
|
)
|
|
{
|
|
WinsMscSignalHdl(sDomCache.EvtHdl);
|
|
}
|
|
LeaveCriticalSection(&WinsIntfNoOfUsersCrtSec);
|
|
return;
|
|
}
|
|
|
|
DWORD
|
|
WinsDeleteWins(
|
|
PWINSINTF_ADD_T pWinsAdd
|
|
)
|
|
{
|
|
PCOMM_ADD_T pAdd;
|
|
DWORD RetVal = WINSINTF_FAILURE;
|
|
|
|
|
|
if (pWinsAdd->IPAdd == NmsLocalAdd.Add.IPAdd)
|
|
{
|
|
WINSINTF_VERS_NO_T MinVersNo = {0};
|
|
WINSINTF_VERS_NO_T MaxVersNo = {0};
|
|
RetVal = WinsDelDbRecs(pWinsAdd, MinVersNo, MaxVersNo);
|
|
#if 0
|
|
//
|
|
// We always keep the entry for the local WINS. For any
|
|
//
|
|
DBGPRINT0(ERR, "WinsDeleteWins: Sorry, you can not delete the entry for the local WINS\n");
|
|
WINSEVT_LOG_M(WINS_FAILURE, WINS_EVT_DELETE_LOCAL_WINS_DISALLOWED);
|
|
RetVal = WINSINTF_CAN_NOT_DEL_LOCAL_WINS;
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
WCHAR String[WINS_MAX_NAME_SZ];
|
|
struct in_addr InAddr;
|
|
|
|
InAddr.s_addr = htonl(pWinsAdd->IPAdd);
|
|
(VOID)WinsMscConvertAsciiStringToUnicode(
|
|
inet_ntoa( InAddr),
|
|
(LPBYTE)String,
|
|
WINS_MAX_NAME_SZ);
|
|
|
|
WinsLogAdminEvent(WINS_EVT_ADMIN_DEL_OWNER_INITIATED,1,String);
|
|
|
|
//
|
|
// Allocate from the general heap (not from the rpc heap)
|
|
// since this memory will be deallocated by DeleteWins in
|
|
// rplpull.c which I don't want to tie to just rpc work.
|
|
//
|
|
WinsMscAlloc(sizeof(COMM_ADD_T), &pAdd);
|
|
pAdd->AddTyp_e = pWinsAdd->Type;
|
|
pAdd->AddLen = pWinsAdd->Len;
|
|
pAdd->Add.IPAdd = pWinsAdd->IPAdd;
|
|
|
|
//
|
|
// Call RplInsertQue to insert the push request to
|
|
// the Pull Thread
|
|
//
|
|
ERplInsertQue(
|
|
WINS_E_WINSRPC,
|
|
QUE_E_CMD_DELETE_WINS,
|
|
NULL, //no Dlg Hdl
|
|
NULL, //no msg is there
|
|
0, //msg length
|
|
pAdd, //client context,
|
|
0 //no magic no
|
|
);
|
|
RetVal = WINSINTF_SUCCESS;
|
|
}
|
|
return(RetVal);
|
|
}
|
|
|
|
#define MAX_RECS_TO_RETURN 5000
|
|
DWORD
|
|
WinsGetDbRecsByName (
|
|
PWINSINTF_ADD_T pWinsAdd,
|
|
DWORD Location,
|
|
LPBYTE pName,
|
|
DWORD NameLen,
|
|
DWORD NoOfRecsDesired,
|
|
DWORD TypeOfRecs,
|
|
PWINSINTF_RECS_T pRecs
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
This function returns with all the records (that can fit into the
|
|
buffer passed) owned by a WINS in the local db of this WINS.
|
|
|
|
Arguments:
|
|
|
|
|
|
Externals Used:
|
|
None
|
|
|
|
|
|
Return Value:
|
|
|
|
Success status codes --
|
|
Error status codes --
|
|
|
|
Error Handling:
|
|
|
|
Called by:
|
|
|
|
Side Effects:
|
|
|
|
Comments:
|
|
None
|
|
--*/
|
|
|
|
{
|
|
COMM_ADD_T Address;
|
|
LPVOID pBuff = NULL;
|
|
DWORD BuffLen;
|
|
DWORD NoOfRecs = 0;
|
|
DWORD Status;
|
|
PWINSTHD_TLS_T pTls;
|
|
|
|
DBGENTER("WinsGetDbRecsByName\n");
|
|
|
|
|
|
if ((NoOfRecsDesired == 0) || (NoOfRecsDesired > MAX_RECS_TO_RETURN))
|
|
{
|
|
NoOfRecsDesired = MAX_RECS_TO_RETURN;
|
|
}
|
|
|
|
|
|
if ((pWinsAdd != NULL) && (pWinsAdd->IPAdd != 0))
|
|
{
|
|
Address.AddTyp_e = pWinsAdd->Type;
|
|
Address.AddLen = pWinsAdd->Len;
|
|
Address.Add.IPAdd = pWinsAdd->IPAdd;
|
|
}
|
|
//
|
|
// initialize this thread with the db engine
|
|
//
|
|
NmsDbThdInit(WINS_E_WINSRPC);
|
|
NmsDbOpenTables(WINS_E_WINSRPC);
|
|
DBGMYNAME("RPC-WinsGetDbRecsByName");
|
|
try {
|
|
if ((pName != NULL) && (NameLen != 0))
|
|
{
|
|
//
|
|
// Terminate name with NULL, just in case user didn't do it.
|
|
//
|
|
*(pName + NameLen) = (BYTE)NULL;
|
|
}
|
|
if ((pName == NULL) && (NameLen > 0))
|
|
{
|
|
NameLen = 0;
|
|
}
|
|
|
|
PERF("The caller can pass the number of records for which space has been")
|
|
PERF("allocated in buffer pointed to by pRec in the NoOfRecs field. We should")
|
|
PERF("We should pass this argument to NmsDbGetDataRecs so that it does not get")
|
|
PERF("more records than are necessary")
|
|
|
|
Status = NmsDbGetDataRecsByName(
|
|
pName,
|
|
NameLen != 0 ? NameLen + 1 : 0,
|
|
Location,
|
|
NoOfRecsDesired,
|
|
pWinsAdd != NULL ? &Address : NULL,
|
|
TypeOfRecs,
|
|
&pBuff,
|
|
&BuffLen,
|
|
&NoOfRecs
|
|
);
|
|
|
|
|
|
if (Status == WINS_SUCCESS)
|
|
{
|
|
Status = PackageRecs( pBuff, BuffLen, NoOfRecs, pRecs);
|
|
}
|
|
|
|
}
|
|
except(EXCEPTION_EXECUTE_HANDLER) {
|
|
DBGPRINTEXC("WinsGetDbRecsByName");
|
|
WINSEVT_LOG_M(GetExceptionCode(), WINS_EVT_RPC_EXC);
|
|
Status = WINS_FAILURE;
|
|
}
|
|
//
|
|
// Free the buffer and destroy the heap.
|
|
//
|
|
GET_TLS_M(pTls);
|
|
if (pTls->HeapHdl != NULL)
|
|
{
|
|
if (pBuff != NULL)
|
|
{
|
|
WinsMscHeapFree(pTls->HeapHdl, pBuff);
|
|
}
|
|
WinsMscHeapDestroy(pTls->HeapHdl);
|
|
// pTls->HeapHdl = NULL;
|
|
}
|
|
|
|
//
|
|
// Let us end the session
|
|
//
|
|
NmsDbCloseTables();
|
|
NmsDbEndSession();
|
|
|
|
if (Status != WINS_SUCCESS)
|
|
{
|
|
pRecs->pRow = NULL;
|
|
pRecs->NoOfRecs = 0;
|
|
Status = WINSINTF_FAILURE;
|
|
}
|
|
else
|
|
{
|
|
if (pRecs->NoOfRecs == 0)
|
|
{
|
|
pRecs->pRow = NULL;
|
|
pRecs->NoOfRecs = 0;
|
|
Status = WINSINTF_REC_NOT_FOUND;
|
|
}
|
|
}
|
|
DBGLEAVE("WinsGetDbRecsByName\n");
|
|
return (Status);
|
|
}
|
|
|
|
STATUS
|
|
PackageRecs(
|
|
PRPL_REC_ENTRY2_T pBuff,
|
|
DWORD BuffLen,
|
|
DWORD NoOfRecs,
|
|
PWINSINTF_RECS_T pRecs
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Externals Used:
|
|
None
|
|
|
|
|
|
Return Value:
|
|
|
|
Success status codes --
|
|
Error status codes --
|
|
|
|
Error Handling:
|
|
|
|
Called by:
|
|
|
|
Side Effects:
|
|
|
|
Comments:
|
|
None
|
|
--*/
|
|
|
|
{
|
|
// ULONG Status;
|
|
BOOL fExcRaised = FALSE;
|
|
PWINSINTF_RECORD_ACTION_T pRow;
|
|
DWORD i;
|
|
DWORD ind;
|
|
DWORD EntType;
|
|
// DWORD MaxAdds;
|
|
PWINSTHD_TLS_T pTls;
|
|
|
|
DBGENTER("PackageRecs\n");
|
|
|
|
i = 0;
|
|
GET_TLS_M(pTls);
|
|
try {
|
|
|
|
//
|
|
// If there are records to send back and the client has specified
|
|
// a buffer for them, insert the records
|
|
//
|
|
if (NoOfRecs > 0)
|
|
{
|
|
|
|
//
|
|
// Allocate memory for the no of records
|
|
//
|
|
pRecs->BuffSize = sizeof(WINSINTF_RECORD_ACTION_T) * NoOfRecs;
|
|
|
|
//
|
|
// If memory can not be allocate, an exception will be returned
|
|
// by midl_user_alloc
|
|
//
|
|
pRecs->pRow = midl_user_allocate(pRecs->BuffSize);
|
|
|
|
#if 0
|
|
pRecs->pRow = RpcSmAllocate(pRecs->BuffSize, &Status);
|
|
|
|
if (Status != RPC_S_OK)
|
|
{
|
|
DBGPRINT1(ERR, "PackageRecs: RpcSmAllocate returned error = (%x)\n", Status);
|
|
}
|
|
#endif
|
|
pRow = pRecs->pRow;
|
|
|
|
|
|
for (; i<NoOfRecs; i++)
|
|
{
|
|
|
|
//
|
|
// Initialize so that we don't get "enum wrong" error.
|
|
//
|
|
pRow->Cmd_e = WINSINTF_E_QUERY;
|
|
|
|
//
|
|
// the name retrieved has NULL as the last character. This
|
|
// We need to pass a name without this NULL.
|
|
//
|
|
pRow->NameLen = pBuff->NameLen;
|
|
if (*pBuff->pName == 0x1B)
|
|
{
|
|
WINS_SWAP_BYTES_M(pBuff->pName, pBuff->pName + 15);
|
|
}
|
|
|
|
// +1 added to fix #390830
|
|
pRow->pName = midl_user_allocate(pRow->NameLen + 1);
|
|
#if 0
|
|
pRow->pName = RpcSmAllocate(pRow->NameLen, &Status);
|
|
if (Status != RPC_S_OK)
|
|
{
|
|
DBGPRINT1(ERR, "PackageRecs: RpcSmAllocate returned error = (%x)\n", Status);
|
|
}
|
|
#endif
|
|
WINSMSC_COPY_MEMORY_M(pRow->pName, pBuff->pName,pRow->NameLen);
|
|
WinsMscHeapFree(pTls->HeapHdl, pBuff->pName);
|
|
|
|
EntType = NMSDB_ENTRY_TYPE_M(pBuff->Flag);
|
|
pRow->TypOfRec_e = NMSDB_ENTRY_UNIQUE_M(EntType)
|
|
? WINSINTF_E_UNIQUE :
|
|
(NMSDB_ENTRY_NORM_GRP_M(EntType) ?
|
|
WINSINTF_E_NORM_GROUP :
|
|
(NMSDB_ENTRY_SPEC_GRP_M(EntType) ?
|
|
WINSINTF_E_SPEC_GROUP :
|
|
WINSINTF_E_MULTIHOMED));
|
|
|
|
|
|
if (
|
|
(pRow->TypOfRec_e == WINSINTF_E_SPEC_GROUP) ||
|
|
(pRow->TypOfRec_e == WINSINTF_E_MULTIHOMED)
|
|
)
|
|
{
|
|
PWINSINTF_ADD_T pAdd;
|
|
DWORD No;
|
|
|
|
if (pBuff->NoOfAdds > 0)
|
|
{
|
|
pRow->NoOfAdds = pBuff->NoOfAdds * 2;
|
|
|
|
|
|
//
|
|
// Each member is comprised of two addresses,
|
|
// first address is that of the owner WINS, second
|
|
// address is that of the node registered
|
|
//
|
|
pRow->pAdd =
|
|
// RpcSmAllocate(
|
|
midl_user_allocate(
|
|
(unsigned int)(pRow->NoOfAdds)
|
|
*
|
|
sizeof(WINSINTF_ADD_T)//,
|
|
// &Status
|
|
);
|
|
|
|
#if 0
|
|
if (Status != RPC_S_OK)
|
|
{
|
|
DBGPRINT1(ERR, "WinsGetDbRecs: RpcSmAllocate returned error = (%x)\n", Status);
|
|
}
|
|
#endif
|
|
|
|
for (
|
|
No= 0, ind= 0, pAdd = pRow->pAdd;
|
|
No < (pRow->NoOfAdds/2);
|
|
No++
|
|
)
|
|
{
|
|
pAdd->Type = (UCHAR)(pBuff->pNodeAdd + ind)->AddTyp_e;
|
|
pAdd->Len = (pBuff->pNodeAdd + ind)->AddLen;
|
|
pAdd++->IPAdd = (pBuff->pNodeAdd + ind)->Add.IPAdd;
|
|
|
|
pAdd->Type = (UCHAR)(pBuff->pNodeAdd + ++ind)->AddTyp_e;
|
|
pAdd->Len = (pBuff->pNodeAdd + ind)->AddLen;
|
|
pAdd++->IPAdd = (pBuff->pNodeAdd + ind++)->Add.IPAdd;
|
|
}
|
|
WinsMscHeapFree(pTls->HeapHdl, pBuff->pNodeAdd);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pRow->NoOfAdds = 0;
|
|
pRow->pAdd = NULL;
|
|
pRow->Add.Type = (UCHAR)pBuff->NodeAdd[0].AddTyp_e;
|
|
pRow->Add.Len = pBuff->NodeAdd[0].AddLen;
|
|
pRow->Add.IPAdd = pBuff->NodeAdd[0].Add.IPAdd;
|
|
}
|
|
pRow->NodeTyp = (BYTE)NMSDB_NODE_TYPE_M(pBuff->Flag);
|
|
pRow->fStatic = NMSDB_IS_ENTRY_STATIC_M(pBuff->Flag);
|
|
pRow->State_e = NMSDB_ENTRY_STATE_M(pBuff->Flag);
|
|
pRow->VersNo = pBuff->VersNo;
|
|
pRow->TimeStamp = pBuff->TimeStamp;
|
|
pRow->OwnerId = pBuff->OwnerId;
|
|
pRow++;
|
|
|
|
|
|
pBuff = (PRPL_REC_ENTRY2_T)((LPBYTE)pBuff + RPL_REC_ENTRY2_SIZE);
|
|
PERF("Do the addition above the for loop and store in a var. Use var. here")
|
|
|
|
} // end of for loop
|
|
} //end of if block
|
|
else
|
|
{
|
|
pRecs->pRow = NULL;
|
|
}
|
|
|
|
} // end of try
|
|
except(EXCEPTION_EXECUTE_HANDLER) {
|
|
DBGPRINTEXC("WinsGetDbRecs");
|
|
WINSEVT_LOG_M(GetExceptionCode(), WINS_EVT_RPC_EXC);
|
|
fExcRaised = TRUE;
|
|
}
|
|
|
|
pRecs->TotalNoOfRecs = NoOfRecs;
|
|
|
|
if (!fExcRaised)
|
|
{
|
|
pRecs->NoOfRecs = i;
|
|
}
|
|
else
|
|
{
|
|
// RpcSmFree(pRecs->pRow);
|
|
midl_user_free(pRecs->pRow);
|
|
pRecs->NoOfRecs = 0;
|
|
}
|
|
|
|
DBGENTER("PackageRecs\n");
|
|
return (WINSINTF_SUCCESS);
|
|
}
|
|
|
|
|
|
|
|
|
|
//void __RPC_FAR * __RPC_API
|
|
void *
|
|
midl_user_allocate(size_t cBytes)
|
|
{
|
|
#if 0
|
|
//#ifdef WINSDBG
|
|
LPVOID pMem = WinsMscHeapAlloc(NmsRpcHeapHdl, cBytes);
|
|
DBGPRINT1(DET, "midl_user_alloc: Memory allocated is (%d)\n", pMem);
|
|
return(pMem);
|
|
//#else
|
|
#endif
|
|
return(WinsMscHeapAlloc(NmsRpcHeapHdl, cBytes));
|
|
}
|
|
|
|
//void __RPC_FAR __RPC_API
|
|
void
|
|
//midl_user_free(void __RPC_FAR *pMem)
|
|
midl_user_free(void *pMem)
|
|
{
|
|
if (pMem != NULL)
|
|
{
|
|
// DBGPRINT1(DET, "midl_user_free: Memory to free is (%d)\n", pMem);
|
|
WinsMscHeapFree(NmsRpcHeapHdl, pMem);
|
|
}
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
LogClientInfo(
|
|
RPC_BINDING_HANDLE ClientHdl,
|
|
BOOL fAbruptTerm
|
|
)
|
|
{
|
|
RPC_STATUS RpcRet;
|
|
RPC_BINDING_HANDLE Binding;
|
|
PTUCHAR pStringBinding;
|
|
PTUCHAR pProtSeq;
|
|
PTUCHAR pNetworkAddress;
|
|
WINSEVT_STRS_T EvtStrs;
|
|
|
|
NOTE("remove #if 0 when we go to 540 or above")
|
|
#if 0
|
|
RpcRet = RpcBindingServerFromClient(ClientHdl, &Binding);
|
|
|
|
if (RpcRet != RPC_S_OK)
|
|
{
|
|
DBGPRINT1(ERR, "LogClientInfo: Can not get binding handle. Rpc Error = (%d)\nThis could be because named pipe protocol is being used\n", RpcRet);
|
|
Binding = ClientHdl;
|
|
}
|
|
#endif
|
|
NOTE("remove when we go to 540 or above")
|
|
Binding = ClientHdl;
|
|
|
|
|
|
RpcRet = RpcBindingToStringBinding(Binding, &pStringBinding);
|
|
if (RpcRet != RPC_S_OK)
|
|
{
|
|
DBGPRINT1(ERR, "LogClientInfo: RpcBindingToStringBinding returned error = (%d)\n", RpcRet);
|
|
return;
|
|
}
|
|
RpcRet = RpcStringBindingParse(
|
|
pStringBinding,
|
|
NULL, //don't want uuid
|
|
&pProtSeq,
|
|
&pNetworkAddress,
|
|
NULL, //end point
|
|
NULL //network options
|
|
);
|
|
if (RpcRet != RPC_S_OK)
|
|
{
|
|
DBGPRINT1(ERR, "LogClientInfo: RpcStringBindingParse returned error = (%d)\n", RpcRet);
|
|
RpcStringFree(&pStringBinding);
|
|
return;
|
|
}
|
|
|
|
#ifndef UNICODE
|
|
DBGPRINT2(FLOW, "LogClientInfo: The protocol sequence and address used by client are (%s) and (%s)\n", pProtSeq, pNetworkAddress);
|
|
#else
|
|
#ifdef WINSDBG
|
|
IF_DBG(FLOW)
|
|
{
|
|
wprintf(L"LogClientInfo: The protocol sequence and address used by client are (%s) and (%s)\n", pProtSeq, pNetworkAddress);
|
|
}
|
|
#endif
|
|
#endif
|
|
RpcStringFree(&pProtSeq);
|
|
RpcStringFree(&pNetworkAddress);
|
|
|
|
EvtStrs.NoOfStrs = 1;
|
|
EvtStrs.pStr[0] = (LPTSTR)pNetworkAddress;
|
|
if (fAbruptTerm)
|
|
{
|
|
WINSEVT_LOG_STR_D_M(WINS_EVT_ADMIN_ABRUPT_SHUTDOWN, &EvtStrs);
|
|
}
|
|
else
|
|
{
|
|
WINSEVT_LOG_STR_D_M(WINS_EVT_ADMIN_ORDERLY_SHUTDOWN, &EvtStrs);
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
|