mirror of https://github.com/lianthony/NT4.0
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.
1902 lines
60 KiB
1902 lines
60 KiB
/*++
|
|
|
|
Copyright (c) 1993 Micorsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
bchk.c
|
|
|
|
Abstract:
|
|
|
|
Browser Monitor main program.
|
|
|
|
Author:
|
|
|
|
Congpa You (CongpaY) 10-Feb-1993
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include <nt.h>
|
|
#include <ntrtl.h>
|
|
#include <nturtl.h>
|
|
#include <sys\types.h>
|
|
#include <sys\stat.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <windows.h>
|
|
#include <lm.h>
|
|
#include <ntddbrow.h>
|
|
#include <brcommon.h> // svcdll\browser
|
|
#include <rap.h>
|
|
#include <rxserver.h>
|
|
#include <winerror.h> // inc
|
|
#include <rpcutil.h> // for MIDL_user_free. net\inc
|
|
#include "bchk.h"
|
|
|
|
// global data for counting.
|
|
INT nCountFail[ERRORTYPENUM];
|
|
INT nCountSuccess[ERRORTYPENUM];
|
|
INT nTimes;
|
|
PERRORLIST pErrorList[ERRORTYPENUM];
|
|
FILE * pLOGFILE;
|
|
|
|
void _CRTAPI1 main()
|
|
{
|
|
DWORD dwVal; // The value returned from function calls.
|
|
PWSTR * BrowserList = NULL; // The browser list returned from Master Browser.
|
|
ULONG BrowserListLength = 0;
|
|
INITPARAM InitParam;
|
|
struct _stat buf;
|
|
PLMDR_TRANSPORT_LIST TransportList = NULL;
|
|
PLMDR_TRANSPORT_LIST TransportEntry = NULL;
|
|
|
|
// Set trap on ctrl-c.
|
|
if (!SetConsoleCtrlHandler (ConvertFile, TRUE))
|
|
{
|
|
printf("Error %lu occured in SetConsoleCtrlHandler", GetLastError());
|
|
return;
|
|
}
|
|
|
|
try
|
|
{
|
|
// Get nTolerance, nSleepTime, lpUser, lpDomain from bchk.ini.
|
|
if (!Init (&InitParam))
|
|
return;
|
|
|
|
// Create a logfile for writing all the errors and other information to.
|
|
pLOGFILE = fopen (szBCHKLOG, "w+");
|
|
|
|
// Set all count to 0.
|
|
InitAllCount();
|
|
|
|
do // This runs forever.
|
|
{
|
|
fprintf(stdout, "BCHK is running.\n") ;
|
|
|
|
// Print the header in the bchklog file.
|
|
PrintHeader (pLOGFILE);
|
|
|
|
// Count the times of the check.
|
|
nTimes++;
|
|
|
|
// Find all transports that we have.
|
|
dwVal = GetBrowserTransportList (&TransportList);
|
|
if (dwVal != NERR_Success)
|
|
{
|
|
if (TransportList != NULL)
|
|
{
|
|
MIDL_user_free (TransportList);
|
|
}
|
|
MyMessageBox (dwVal);
|
|
return;
|
|
}
|
|
|
|
TransportEntry = TransportList;
|
|
|
|
// Enumerate on the transports.
|
|
while (TransportEntry != NULL)
|
|
{
|
|
TCHAR lpDomain[STRINGLEN]; // The array of domain names.
|
|
LPTSTR lpDomainName; // One domain's name.
|
|
UNICODE_STRING TransportName;
|
|
|
|
TransportName.Buffer = TransportEntry->TransportName;
|
|
TransportName.Length = (USHORT) TransportEntry->TransportNameLength;
|
|
TransportName.MaximumLength = (USHORT) TransportEntry->TransportNameLength;
|
|
|
|
// Enumerate all the Domains that we want. All domains are in one string.
|
|
// They are separated by space.
|
|
lstrcpy (lpDomain, InitParam.lpDomain);
|
|
lpDomainName = strtokf (lpDomain, szSeps);
|
|
|
|
while (lpDomainName != NULL)
|
|
{
|
|
BOOL fFoundMaster = FALSE; // See if we have master browser's name.
|
|
TCHAR lpMasterName[UNCLEN+1];
|
|
{
|
|
SYSTEMTIME systime;
|
|
|
|
GetLocalTime(&systime);
|
|
|
|
fprintf(pLOGFILE, "Run %ws %ws started at %2.2d/%2.2d/%4.4d %2.2d:%2.2d:%2.2d:%4.4d\n",
|
|
lpDomainName,
|
|
TransportName.Buffer,
|
|
systime.wMonth,
|
|
systime.wDay,
|
|
systime.wYear,
|
|
systime.wHour,
|
|
systime.wMinute,
|
|
systime.wSecond,
|
|
systime.wMilliseconds);
|
|
|
|
}
|
|
|
|
|
|
// Check for error type 1: Browser master is not returning
|
|
// backup browser list.
|
|
|
|
dwVal = GetBrowserServerList (&TransportName,
|
|
lpDomainName,
|
|
&BrowserList,
|
|
&BrowserListLength,
|
|
TRUE);
|
|
|
|
if (dwVal != NERR_Success) // Type 1 error occured.
|
|
{
|
|
//
|
|
// Send a magic bullet on this failure.
|
|
//
|
|
|
|
SendMagicBullet();
|
|
|
|
ReportError (InitParam.lpUser,
|
|
TransportName.Buffer,
|
|
lpDomainName,
|
|
lpMasterName,
|
|
NULL,
|
|
dwVal,
|
|
NO_MASTER_RUNNING); //Error type number.
|
|
|
|
// Try to get Domain Master's name.
|
|
if (GetMasterName (lpMasterName,
|
|
TransportName.Buffer,
|
|
lpDomainName) == NERR_Success)
|
|
{
|
|
ReportError (InitParam.lpUser,
|
|
TransportName.Buffer,
|
|
lpDomainName,
|
|
NULL,
|
|
lpMasterName,
|
|
dwVal,
|
|
INVALID_MASTER); //Error type number.
|
|
}
|
|
else
|
|
{
|
|
nCountSuccess[INVALID_MASTER]++;
|
|
}
|
|
}
|
|
else if (BrowserListLength == 1) //Type 1 error didnot occur but there is only one browser on the domain.
|
|
{
|
|
nCountSuccess[NO_MASTER_RUNNING]++;
|
|
ReportError (InitParam.lpUser,
|
|
TransportName.Buffer,
|
|
lpDomainName,
|
|
BrowserList[0],
|
|
NULL,
|
|
0,
|
|
NO_BACKUP);
|
|
}
|
|
else // Type 1 error didn't occur and there are backup browsers.
|
|
{
|
|
WriteBrowserList (pLOGFILE, BrowserList, BrowserListLength);
|
|
|
|
nCountSuccess[NO_MASTER_RUNNING]++;
|
|
nCountSuccess[NO_BACKUP]++;
|
|
|
|
// Try to get Domain Master's name.
|
|
dwVal = GetMasterName (lpMasterName,
|
|
TransportName.Buffer,
|
|
lpDomainName);
|
|
if (dwVal == NERR_Success)
|
|
{
|
|
nCountSuccess[NO_MASTER_NAME]++;
|
|
fFoundMaster = TRUE;
|
|
}
|
|
else // Try other ways to find the master browser's name.
|
|
{
|
|
ReportError (InitParam.lpUser,
|
|
TransportName.Buffer,
|
|
lpDomainName,
|
|
NULL,
|
|
NULL,
|
|
dwVal,
|
|
NO_MASTER_NAME); //Error type number.
|
|
|
|
fFoundMaster = RxGetMasterName (InitParam.lpUser,
|
|
lpMasterName,
|
|
TransportName.Buffer,
|
|
lpDomainName,
|
|
BrowserList,
|
|
BrowserListLength,
|
|
InitParam.nTimeLimit);
|
|
}
|
|
|
|
if (fFoundMaster) // Report error if we donot have master name
|
|
{
|
|
// Log the master browser's name.
|
|
LogMaster (pLOGFILE,
|
|
TransportName.Buffer,
|
|
lpDomainName,
|
|
lpMasterName);
|
|
|
|
// Check for error type 2: Incorrect server lists returned by
|
|
// backup browsers (and master browsers). This includes stale
|
|
// servers in the list.
|
|
CheckErrorType2 (InitParam.lpUser,
|
|
TransportName.Buffer,
|
|
lpDomainName,
|
|
lpMasterName,
|
|
BrowserList,
|
|
BrowserListLength,
|
|
InitParam.nTolerance,
|
|
InitParam.nTimeLimit);
|
|
|
|
// Check for error type 3: Incorrect number of browser servers.
|
|
CheckErrorType3 (InitParam.lpUser,
|
|
TransportName.Buffer,
|
|
lpDomainName,
|
|
lpMasterName);
|
|
|
|
// Check for error type 4: Master is not PDC.
|
|
CheckErrorType4 (InitParam.lpUser,
|
|
TransportName.Buffer,
|
|
lpDomainName,
|
|
lpMasterName);
|
|
|
|
} // End of else when we have the master name.
|
|
|
|
} // End of else when type 1 error didnot occur and there are backup browsers.
|
|
|
|
if (BrowserList != NULL)
|
|
{
|
|
MIDL_user_free(BrowserList);
|
|
}
|
|
|
|
{
|
|
SYSTEMTIME systime;
|
|
|
|
GetLocalTime(&systime);
|
|
|
|
fprintf(pLOGFILE, "Run %ws %ws completed at %2.2d/%2.2d/%4.4d %2.2d:%2.2d:%2.2d:%4.4d\n",
|
|
lpDomainName,
|
|
TransportName.Buffer,
|
|
systime.wMonth,
|
|
systime.wDay,
|
|
systime.wYear,
|
|
systime.wHour,
|
|
systime.wMinute,
|
|
systime.wSecond,
|
|
systime.wMilliseconds);
|
|
|
|
}
|
|
|
|
// print out == between domains.
|
|
|
|
PrintSeparation (pLOGFILE);
|
|
|
|
lpDomainName = strtokf (NULL, szSeps);
|
|
|
|
} // End of the enumeration of domains.
|
|
|
|
if (TransportEntry->NextEntryOffset == 0)
|
|
TransportEntry = NULL;
|
|
else
|
|
{
|
|
TransportEntry = (PLMDR_TRANSPORT_LIST) ((PCHAR) TransportEntry
|
|
+TransportEntry->NextEntryOffset);
|
|
}
|
|
|
|
} // End of the enumeration of transports.
|
|
|
|
// Free memory.
|
|
MIDL_user_free (TransportList);
|
|
|
|
// Write the result to the summory file.
|
|
WriteSummory();
|
|
|
|
// Make sure alert is writen to the disk.
|
|
fflush (pLOGFILE);
|
|
|
|
// Check if the file size is too big. Reopen it if it's so.
|
|
if (_fstat (_fileno(pLOGFILE), &buf) != -1)
|
|
{
|
|
printf("File size = %ld, Limit = %d\n", buf.st_size, InitParam.nFileSizeLimit);
|
|
|
|
if (buf.st_size > InitParam.nFileSizeLimit)
|
|
{
|
|
fclose (pLOGFILE);
|
|
|
|
if (!MoveFileEx (szLBCHKLOG, szLBACKUP, MOVEFILE_REPLACE_EXISTING))
|
|
{
|
|
pLOGFILE = fopen (szBCHKLOG, "w+");
|
|
LogError (pLOGFILE, GetError(GetLastError()));
|
|
}
|
|
else
|
|
pLOGFILE = fopen (szBCHKLOG, "w+");
|
|
}
|
|
}
|
|
|
|
// Wait for a while before start again.
|
|
fprintf(stdout, "bchk is sleeping for %d secs\n", InitParam.nSleepTime/1000) ;
|
|
Sleep (InitParam.nSleepTime);
|
|
|
|
} while (TRUE);
|
|
}
|
|
finally
|
|
{
|
|
ConvertFile(0);
|
|
LocalFree (InitParam.lpUser);
|
|
LocalFree (InitParam.lpDomain);
|
|
}
|
|
return;
|
|
}
|
|
|
|
// Get nTolerance, nSleepTime, lpUser, lpDomain from bchk.ini.
|
|
BOOL Init (INITPARAM * pInitParam)
|
|
{
|
|
DWORD dwVal;
|
|
DWORD dwComputerNameLength = STRINGLEN;
|
|
LPTSTR lpUser;
|
|
LPTSTR lpTemp;
|
|
|
|
pInitParam->lpUser = (LPTSTR) LocalAlloc (LPTR, STRINGLEN);
|
|
pInitParam->lpDomain = (LPTSTR) LocalAlloc (LPTR, STRINGLEN);
|
|
lpUser = (LPTSTR) LocalAlloc (LPTR, STRINGLEN);
|
|
lpTemp = (LPTSTR) LocalAlloc (LPTR, INTLEN);
|
|
|
|
if ((pInitParam->lpUser == NULL) ||
|
|
(pInitParam->lpDomain == NULL) ||
|
|
(lpUser == NULL) ||
|
|
(lpTemp == NULL))
|
|
{
|
|
MyMessageBox (ERROR_NOT_ENOUGH_MEMORY);
|
|
return(FALSE);
|
|
}
|
|
|
|
// Get the current computer name. We will always notify the current user
|
|
// when an error occurs. This computer name is for sending message.
|
|
if (!GetComputerName (pInitParam->lpUser, &dwComputerNameLength))
|
|
{
|
|
MyMessageBox (GetLastError());
|
|
return(FALSE);
|
|
}
|
|
|
|
// Read nTolerance from bchk.ini. We allow backup browser return
|
|
// nTolerance different entries from those from master browser.
|
|
GetPrivateProfileString (szAPPNAME,
|
|
szTOLERANCE,
|
|
szDefaultTolerance,
|
|
lpTemp,
|
|
INTLEN,
|
|
szFILENAME);
|
|
|
|
pInitParam->nTolerance = atoi(toansi(lpTemp));
|
|
|
|
// Read nTolerance from bchk.ini. We allow backup browser return
|
|
// nTolerance different entries from those from master browser.
|
|
GetPrivateProfileString (szAPPNAME,
|
|
szTIMELIMIT,
|
|
szDefaultTimeLimit,
|
|
lpTemp,
|
|
INTLEN,
|
|
szFILENAME);
|
|
|
|
pInitParam->nTimeLimit = atoi(toansi(lpTemp));
|
|
|
|
// Get the sleep time from bchk.ini.
|
|
GetPrivateProfileString (szAPPNAME,
|
|
szSLEEPTIME,
|
|
szDefaultSleepTime, //millisecond.
|
|
lpTemp,
|
|
INTLEN,
|
|
szFILENAME);
|
|
|
|
pInitParam->nSleepTime = atoi(toansi(lpTemp));
|
|
|
|
// Get the file size limit from bchk.ini.
|
|
GetPrivateProfileString (szAPPNAME,
|
|
szFILESIZE,
|
|
szDefaultFileSize, //millisecond.
|
|
lpTemp,
|
|
INTLEN,
|
|
szFILENAME);
|
|
|
|
pInitParam->nFileSizeLimit = atoi(toansi(lpTemp));
|
|
|
|
// Read the people we want to notify when an browser error occurs from bchk.ini.
|
|
dwVal = GetPrivateProfileString (szAPPNAME,
|
|
szOTHERUSERS,
|
|
szDefaultOtherUser,
|
|
lpUser,
|
|
STRINGLEN,
|
|
szFILENAME);
|
|
|
|
if (dwVal >= (STRINGLEN-2)) // The memory assigned to lpUser is not big enough.
|
|
{
|
|
MyMessageBox (ERROR_NOT_ENOUGH_MEMORY);
|
|
return(FALSE);
|
|
}
|
|
else
|
|
{
|
|
lstrcat (pInitParam->lpUser, L" ");
|
|
lstrcat (pInitParam->lpUser, lpUser);
|
|
}
|
|
|
|
// Read all the domains that we want to check from bchk.ini
|
|
dwVal = GetPrivateProfileString (szAPPNAME,
|
|
szDOMAINS,
|
|
szDefaultDomain,
|
|
pInitParam->lpDomain,
|
|
STRINGLEN,
|
|
szFILENAME);
|
|
|
|
if (dwVal >= (STRINGLEN-2)) // The memory assigned to lpDomainList is not big enough.
|
|
{
|
|
MyMessageBox (ERROR_NOT_ENOUGH_MEMORY);
|
|
return(FALSE);
|
|
}
|
|
|
|
//
|
|
// Make sure that the domain name is upper cased.
|
|
//
|
|
|
|
_wcsupr(pInitParam->lpDomain);
|
|
|
|
LocalFree (lpUser);
|
|
LocalFree (lpTemp);
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
void InitAllCount ()
|
|
{
|
|
INT i;
|
|
|
|
nTimes = 0;
|
|
|
|
for (i = 0; i< ERRORTYPENUM ; i++)
|
|
{
|
|
nCountFail[i] = 0;
|
|
nCountSuccess[i] = 0;
|
|
}
|
|
}
|
|
|
|
// Try to get the Domain Master's name using GetNetBiosMasterName.
|
|
NET_API_STATUS GetMasterName (LPTSTR lpMasterName,
|
|
LPTSTR lpTransportName,
|
|
LPTSTR lpDomainName)
|
|
{
|
|
TCHAR lpTempMaster[UNCLEN+1];
|
|
DWORD dwStartTime;
|
|
DWORD dwEndTime;
|
|
NET_API_STATUS dwVal;
|
|
|
|
dwStartTime = GetTickCount();
|
|
|
|
dwVal = GetNetBiosMasterName (lpTransportName,
|
|
lpDomainName,
|
|
lpTempMaster,
|
|
NULL );
|
|
|
|
dwEndTime = GetTickCount();
|
|
|
|
if (dwVal == NERR_Success)
|
|
{
|
|
// lpTempMaster has lots of space following
|
|
// the characters. We want to make a null terminated
|
|
// string, and add \\ in front of master name.
|
|
lstrcpy (lpMasterName, L"\\\\");
|
|
KillSpace (lpTempMaster);
|
|
lstrcat (lpMasterName, lpTempMaster);
|
|
}
|
|
else
|
|
{
|
|
fprintf (pLOGFILE, "GetNetBiosMasterName failed after %d milliseconds.\n",
|
|
dwEndTime-dwStartTime);
|
|
|
|
wsprintf (lpMasterName, L"unknown");
|
|
}
|
|
return(dwVal);
|
|
}
|
|
|
|
// Use RxNetServerEnum call to get Domain Master's name.
|
|
BOOL RxGetMasterName (LPTSTR lpUser,
|
|
LPTSTR lpMasterName,
|
|
LPTSTR lpTransportName,
|
|
LPTSTR lpDomainName,
|
|
PWSTR * BrowserList,
|
|
DWORD BrowserListLength,
|
|
DWORD nTimeLimit)
|
|
{
|
|
INT i = 0;
|
|
DWORD dwVal;
|
|
DWORD dwTotalEntries; // Total servers returned from Backup Browser.
|
|
DWORD dwEntriesRead; // Total servers read from Backup Browser.
|
|
LPVOID lpBrowserList;
|
|
// TCHAR lpErrorMessage[STRINGLEN];
|
|
PSERVER_INFO_101 pBrowserServerInfo101;
|
|
DWORD dwStartTime;
|
|
DWORD dwEndTime;
|
|
|
|
for (i = 0 ; i < (INT) BrowserListLength ; i++)
|
|
{
|
|
dwStartTime = GetTickCount();
|
|
|
|
dwVal = MyRxNetServerEnum (BrowserList[i],
|
|
lpTransportName,
|
|
101,
|
|
(LPBYTE *) &lpBrowserList,
|
|
0xffffffff,
|
|
&dwEntriesRead,
|
|
&dwTotalEntries,
|
|
SV_TYPE_MASTER_BROWSER,
|
|
lpDomainName,
|
|
NULL);
|
|
|
|
dwEndTime = GetTickCount();
|
|
|
|
if (dwVal == NERR_Success) // Get the master browser list.
|
|
{
|
|
nCountSuccess[FAIL_RETURN_MASTER]++;
|
|
|
|
if ((dwEndTime - dwStartTime) > nTimeLimit) {
|
|
|
|
dwVal = dwEndTime - dwStartTime;
|
|
|
|
//
|
|
// If this took "too long", log it as an error.
|
|
//
|
|
|
|
ReportError (lpUser,
|
|
lpTransportName,
|
|
lpDomainName,
|
|
NULL,
|
|
BrowserList[i],
|
|
dwVal,
|
|
BROWSE_TOO_LONG);
|
|
|
|
if ((dwEndTime - dwStartTime) > 2*nTimeLimit) {
|
|
SendMagicBullet();
|
|
}
|
|
|
|
|
|
} else {
|
|
nCountSuccess[BROWSE_TOO_LONG] += 1;
|
|
}
|
|
|
|
if (dwEntriesRead != 1) // Wrong master browser list
|
|
{
|
|
WriteList (pLOGFILE, lpBrowserList, dwEntriesRead);
|
|
|
|
MIDL_user_free (lpBrowserList);
|
|
|
|
ReportError (lpUser,
|
|
lpTransportName,
|
|
lpDomainName,
|
|
NULL,
|
|
BrowserList[i],
|
|
dwEntriesRead,
|
|
WRONG_NUM_MASTER); //Error type number.
|
|
|
|
}
|
|
else //Found the master.
|
|
{
|
|
nCountSuccess[WRONG_NUM_MASTER]++;
|
|
nCountSuccess[UNKNOWN_MASTER]++;
|
|
|
|
pBrowserServerInfo101 = lpBrowserList;
|
|
wsprintf(lpMasterName, L"\\\\%s", pBrowserServerInfo101[0].sv101_name);
|
|
MIDL_user_free (lpBrowserList);
|
|
return(TRUE);
|
|
}
|
|
|
|
} // End of if when we get the master browser list.
|
|
else
|
|
{
|
|
if (lpBrowserList != NULL)
|
|
{
|
|
MIDL_user_free (lpBrowserList);
|
|
}
|
|
|
|
ReportError (NULL,
|
|
lpTransportName,
|
|
lpDomainName,
|
|
NULL,
|
|
BrowserList[i],
|
|
dwVal,
|
|
FAIL_RETURN_MASTER);
|
|
}
|
|
|
|
} // End of the for loop
|
|
|
|
ReportError (lpUser,
|
|
lpTransportName,
|
|
lpDomainName,
|
|
NULL,
|
|
NULL,
|
|
0,
|
|
UNKNOWN_MASTER); //Error type number.
|
|
|
|
return(FALSE);
|
|
}
|
|
|
|
// Generate an error message, write to the logfile and send to all the users.
|
|
void ReportError (LPTSTR lpUser,
|
|
LPTSTR lpTransportName,
|
|
LPTSTR lpDomainName,
|
|
LPTSTR lpMasterName,
|
|
LPTSTR lpBrowserName,
|
|
DWORD dwError,
|
|
INT nErrorType)
|
|
{
|
|
TCHAR lpErrorMessage[STRINGLEN];
|
|
DWORD dwNSGI = 0;
|
|
PSERVER_INFO_101 pSV101 = NULL;
|
|
|
|
static BOOL fError[ERRORTYPENUM] = {FALSE, FALSE, FALSE, FALSE, FALSE,
|
|
FALSE, FALSE, FALSE, FALSE, FALSE,
|
|
FALSE, FALSE, FALSE, FALSE, FALSE,
|
|
FALSE, FALSE, FALSE, FALSE};
|
|
|
|
nCountFail[nErrorType]++;
|
|
|
|
switch (nErrorType)
|
|
{
|
|
case NO_MASTER_RUNNING:
|
|
GetMasterName (lpMasterName,
|
|
lpTransportName,
|
|
lpDomainName);
|
|
|
|
wsprintf (lpErrorMessage,
|
|
L"No browser master is running on domain %s, transport %s. \nThe browser master's name is %ws.\n",
|
|
lpDomainName,
|
|
lpTransportName,
|
|
lpMasterName);
|
|
lstrcat (lpErrorMessage, GetError (dwError));
|
|
|
|
break;
|
|
|
|
case INVALID_MASTER:
|
|
wsprintf (lpErrorMessage,
|
|
L"Browser added a not-running master %s on domain %s transport %s.\n",
|
|
lpBrowserName,
|
|
lpDomainName,
|
|
lpTransportName);
|
|
break;
|
|
|
|
case NO_BACKUP:
|
|
wsprintf (lpErrorMessage,
|
|
L"There are no backup browsers on domain %s transport %s.\nThe domain master is owned by %s.\n",
|
|
lpDomainName,
|
|
lpTransportName,
|
|
lpMasterName);
|
|
break;
|
|
|
|
case NO_MASTER_NAME:
|
|
wsprintf (lpErrorMessage,
|
|
L"GetNetBiosMasterName failed on domain %s transport %s.\n",
|
|
lpDomainName,
|
|
lpTransportName);
|
|
lstrcat (lpErrorMessage, GetError (dwError));
|
|
break;
|
|
|
|
case WRONG_NUM_MASTER:
|
|
wsprintf (lpErrorMessage,
|
|
L"%lu browser masters are returned from %s.\nCannot determine the master browser on domain %s, transport%s through %s.\n",
|
|
dwError, // = dwEntriesRead
|
|
lpBrowserName,
|
|
lpDomainName,
|
|
lpTransportName,
|
|
lpBrowserName);
|
|
break;
|
|
|
|
case FAIL_RETURN_MASTER:
|
|
wsprintf (lpErrorMessage,
|
|
L"Browser %s on domain %s, transport %s failed to return its master.\n",
|
|
lpBrowserName,
|
|
lpDomainName,
|
|
lpTransportName);
|
|
lstrcat (lpErrorMessage, GetError (dwError));
|
|
break;
|
|
|
|
case UNKNOWN_MASTER:
|
|
wsprintf (lpErrorMessage,
|
|
L"Cannot determine the master browser on domain %s, transport %s.\n",
|
|
lpDomainName,
|
|
lpTransportName);
|
|
break;
|
|
|
|
case MASTER_NO_SERVER_LIST:
|
|
wsprintf (lpErrorMessage,
|
|
L"The master browser %s on domain %s transport %s failed to return the server list.\n",
|
|
lpMasterName,
|
|
lpDomainName,
|
|
lpTransportName);
|
|
|
|
lstrcat (lpErrorMessage, GetError (dwError));
|
|
break;
|
|
|
|
case BROWSER_NO_SERVER_LIST:
|
|
wsprintf (lpErrorMessage,
|
|
L"Browser %s on domain %s transport %s failed to return the server list.\nThe domain master is owned by %s.\n",
|
|
lpBrowserName,
|
|
lpDomainName,
|
|
lpTransportName,
|
|
lpMasterName);
|
|
|
|
lstrcat (lpErrorMessage, GetError (dwError));
|
|
break;
|
|
|
|
case MASTER_NO_DOMAIN_LIST:
|
|
wsprintf (lpErrorMessage,
|
|
L"The master browser %s on domain %s transport %s failed to return the domain list.\n",
|
|
lpMasterName,
|
|
lpDomainName,
|
|
lpTransportName);
|
|
|
|
lstrcat (lpErrorMessage, GetError (dwError));
|
|
break;
|
|
|
|
case BROWSER_NO_DOMAIN_LIST:
|
|
wsprintf (lpErrorMessage,
|
|
L"Browser %s on domain %s transport %s failed to return the domain list.\nThe domain master is owned by %s.\n",
|
|
lpBrowserName,
|
|
lpDomainName,
|
|
lpTransportName,
|
|
lpMasterName);
|
|
|
|
lstrcat (lpErrorMessage, GetError (dwError));
|
|
break;
|
|
|
|
case STALE_SERVER:
|
|
wsprintf (lpErrorMessage,
|
|
L"Browser %s on domain %s,transport %s returned an incorrect number of servers. \nThe domain master is owned by %s.\n",
|
|
lpBrowserName,
|
|
lpDomainName,
|
|
lpTransportName,
|
|
lpMasterName);
|
|
break;
|
|
|
|
case STALE_DOMAIN:
|
|
wsprintf (lpErrorMessage,
|
|
L"Browser %s on domain %s,transport %s returned an incorrect number of domains. \nThe domain master is owned by %s.\n",
|
|
lpBrowserName,
|
|
lpDomainName,
|
|
lpTransportName,
|
|
lpMasterName);
|
|
break;
|
|
|
|
case MASTER_NO_LOCAL_LIST:
|
|
wsprintf (lpErrorMessage,
|
|
L"The master browser %s on domain %s transport %s failed to return the local list.\n",
|
|
lpMasterName,
|
|
lpDomainName,
|
|
lpTransportName);
|
|
|
|
lstrcat (lpErrorMessage, GetError (dwError));
|
|
break;
|
|
|
|
case WRONG_NUM_BACKUP:
|
|
wsprintf (lpErrorMessage,
|
|
L"Incorrect number of Backup Browsers on domain %s transport %s \n nNTMachine = %d \n nBackupBrowser = %d \n nServer = %d \n Expected %d backups \n",
|
|
lpDomainName,
|
|
lpTransportName,
|
|
((INT *)dwError)[0],
|
|
((INT *)dwError)[1],
|
|
((INT *)dwError)[2],
|
|
((INT *)dwError)[3]);
|
|
|
|
break;
|
|
|
|
case NO_PDC:
|
|
wsprintf (lpErrorMessage,
|
|
L"There are no PDC on domain %s transport %s.\nThe domain master is owned by %s.\n",
|
|
lpDomainName,
|
|
lpTransportName,
|
|
lpMasterName);
|
|
|
|
lstrcat (lpErrorMessage, GetError (dwError));
|
|
break;
|
|
|
|
case MASTER_NOT_PDC:
|
|
wsprintf (lpErrorMessage,
|
|
L"The master browser %s on domain %s transport %s is not a PDC.\nPDC is owned by %s.\n",
|
|
lpBrowserName,
|
|
lpDomainName,
|
|
lpTransportName,
|
|
lpMasterName);
|
|
|
|
break;
|
|
case BROWSE_TOO_LONG:
|
|
wsprintf (lpErrorMessage,
|
|
L"Browse request to %ws (domain %ws, transport %ws), took %ld milliseconds.\n",
|
|
lpBrowserName,
|
|
lpDomainName,
|
|
lpTransportName,
|
|
dwError);
|
|
|
|
break;
|
|
|
|
default:
|
|
return;
|
|
}
|
|
|
|
if (lpBrowserName != NULL)
|
|
{
|
|
lstrcat (lpErrorMessage, ServerInfo(lpBrowserName));
|
|
|
|
if ((dwError != 0) && ((nErrorType == MASTER_NO_SERVER_LIST) ||
|
|
(nErrorType == MASTER_NO_DOMAIN_LIST) ||
|
|
(nErrorType == MASTER_NO_LOCAL_LIST) ||
|
|
(nErrorType == BROWSER_NO_SERVER_LIST)||
|
|
(nErrorType == BROWSER_NO_DOMAIN_LIST)))
|
|
|
|
{
|
|
WCHAR ShareName[UNCLEN+1];
|
|
|
|
wcscpy(ShareName, lpBrowserName);
|
|
wcscat(ShareName, L"\\Ipc$");
|
|
|
|
NetUseDel(NULL, ShareName, USE_LOTS_OF_FORCE);
|
|
|
|
dwNSGI = NetServerGetInfo (lpBrowserName,
|
|
101,
|
|
(LPBYTE *)&pSV101);
|
|
|
|
if (dwNSGI == NERR_Success &&
|
|
!(pSV101->sv101_type & SV_TYPE_POTENTIAL_BROWSER))
|
|
{
|
|
if (dwError == ERROR_BAD_NETPATH && dwNSGI == NERR_Success) {
|
|
DbgPrint("Sending magic bullet\n");
|
|
SendMagicBullet();
|
|
}
|
|
|
|
CheckErrorType5(lpBrowserName,
|
|
lpTransportName,
|
|
lpDomainName,
|
|
lpUser);
|
|
} else {
|
|
#if 0
|
|
|
|
if (dwError == ERROR_VC_DISCONNECTED &&
|
|
dwNSGI == ERROR_VC_DISCONNECTED) {
|
|
DbgPrint("Sending magic bullet\n");
|
|
SendMagicBullet();
|
|
}
|
|
#endif
|
|
|
|
}
|
|
|
|
if (pSV101 != NULL)
|
|
{
|
|
MIDL_user_free (pSV101);
|
|
}
|
|
}
|
|
}
|
|
|
|
RecordError (&fError[nErrorType],
|
|
lpBrowserName,
|
|
lpTransportName,
|
|
lpDomainName,
|
|
lpUser,
|
|
lpErrorMessage,
|
|
dwError,
|
|
dwNSGI,
|
|
nErrorType);
|
|
}
|
|
|
|
void RecordError (BOOL * pfError,
|
|
LPTSTR lpBrowserName,
|
|
LPTSTR lpTransportName,
|
|
LPTSTR lpDomainName,
|
|
LPTSTR lpUser,
|
|
LPTSTR lpErrorMessage,
|
|
DWORD dwError,
|
|
DWORD dwNSGI,
|
|
INT nErrorType)
|
|
{
|
|
SYSTEMTIME systime;
|
|
|
|
GetLocalTime (&systime);
|
|
|
|
if ((nErrorType != BROWSER_NO_SERVER_LIST) &&
|
|
(nErrorType != BROWSER_NO_DOMAIN_LIST) &&
|
|
(nErrorType != NO_PDC))
|
|
{
|
|
LogError (pLOGFILE, lpErrorMessage);
|
|
}
|
|
else
|
|
{
|
|
LogWarning (pLOGFILE, lpErrorMessage);
|
|
}
|
|
|
|
//
|
|
// Notify that the error occurred.
|
|
//
|
|
|
|
if ((nErrorType != BROWSER_NO_SERVER_LIST) &&
|
|
(nErrorType != BROWSER_NO_DOMAIN_LIST) &&
|
|
(nErrorType != MASTER_NOT_PDC) &&
|
|
(nErrorType != WRONG_NUM_BACKUP) &&
|
|
(nErrorType != NO_PDC)) {
|
|
NotifyUser (lpUser, lpErrorMessage);
|
|
}
|
|
|
|
if (*pfError) // A known error.
|
|
{
|
|
ERRORLIST * pErrorEntry = pErrorList[nErrorType];
|
|
|
|
do
|
|
{
|
|
if (!lstrcmp (pErrorEntry->lpTransport, lpTransportName) &&
|
|
!lstrcmp (pErrorEntry->lpDomain, lpDomainName) &&
|
|
((lpBrowserName == NULL) ||
|
|
((lpBrowserName != NULL) &&
|
|
(!lstrcmp (pErrorEntry->lpServer, lpBrowserName)))) &&
|
|
((nErrorType == WRONG_NUM_BACKUP) ||
|
|
(nErrorType == STALE_SERVER) ||
|
|
(nErrorType == STALE_DOMAIN) ||
|
|
((pErrorEntry->nVal1 == dwError) &&
|
|
(pErrorEntry->nVal2 == dwNSGI))))
|
|
{
|
|
if ((nErrorType != STALE_SERVER) &&
|
|
(nErrorType != STALE_DOMAIN))
|
|
{
|
|
// record the last time the error occurred.
|
|
pErrorEntry->wHour = systime.wHour;
|
|
pErrorEntry->wMinute = systime.wMinute;
|
|
}
|
|
else
|
|
{
|
|
AddStaleEntry (pErrorEntry,
|
|
((DWORD *) dwError)[1],
|
|
((DWORD *) dwError)[0],
|
|
systime.wHour,
|
|
systime.wMinute);
|
|
}
|
|
(pErrorEntry->nCount)++;
|
|
return;
|
|
}
|
|
|
|
if (pErrorEntry->pNextEntry != NULL)
|
|
{
|
|
pErrorEntry = pErrorEntry->pNextEntry;
|
|
}
|
|
else
|
|
{
|
|
pErrorEntry->pNextEntry = NewEntry (lpBrowserName,
|
|
lpTransportName,
|
|
lpDomainName,
|
|
dwError,
|
|
dwNSGI,
|
|
systime.wHour,
|
|
systime.wMinute,
|
|
nErrorType);
|
|
return;
|
|
}
|
|
} while (TRUE);
|
|
}
|
|
else // Error never occur before.
|
|
{
|
|
pErrorList[nErrorType] = NewEntry(lpBrowserName,
|
|
lpTransportName,
|
|
lpDomainName,
|
|
dwError,
|
|
dwNSGI,
|
|
systime.wHour,
|
|
systime.wMinute,
|
|
nErrorType);
|
|
if (pErrorList[nErrorType] != NULL)
|
|
{
|
|
(*pfError) = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
PERRORLIST NewEntry (LPTSTR lpServer,
|
|
LPTSTR lpTransport,
|
|
LPTSTR lpDomain,
|
|
DWORD dwError,
|
|
DWORD dwNSGI,
|
|
WORD wHour,
|
|
WORD wMinute,
|
|
INT nErrorType)
|
|
{
|
|
PERRORLIST pNewEntry;
|
|
|
|
// Added for reduce the logfile size, ie not report error caused
|
|
// by machine crash.
|
|
if ((dwError == 53) &&
|
|
(dwNSGI == 53) &&
|
|
!IsOurMachine (lpServer))
|
|
{
|
|
return(NULL);
|
|
}
|
|
|
|
pNewEntry = (PERRORLIST) LocalAlloc (LPTR, sizeof(ERRORLIST));
|
|
if (pNewEntry == NULL)
|
|
{
|
|
fprintf(stdout, "Not enough memory");
|
|
return(NULL);
|
|
}
|
|
|
|
pNewEntry->lpTransport = (LPTSTR) LocalAlloc (LPTR, (2*lstrlen(lpTransport)+2));
|
|
pNewEntry->lpDomain = (LPTSTR) LocalAlloc (LPTR, (2*lstrlen(lpDomain)+2));
|
|
if ((pNewEntry->lpTransport == NULL) ||
|
|
(pNewEntry->lpDomain == NULL))
|
|
{
|
|
fprintf(stdout, "Not enough memory");
|
|
return(NULL);
|
|
}
|
|
|
|
if (lpServer != NULL)
|
|
{
|
|
pNewEntry->lpServer = (LPTSTR) LocalAlloc (LPTR, (2*lstrlen(lpServer)+2));
|
|
if (pNewEntry->lpServer == NULL)
|
|
{
|
|
fprintf(stdout, "Not enough memory");
|
|
return(NULL);
|
|
}
|
|
lstrcpy (pNewEntry->lpServer, lpServer);
|
|
}
|
|
|
|
lstrcpy (pNewEntry->lpTransport, lpTransport);
|
|
lstrcpy (pNewEntry->lpDomain, lpDomain);
|
|
pNewEntry->nCount = 1;
|
|
pNewEntry->wHour = wHour;
|
|
pNewEntry->wMinute = wMinute;
|
|
pNewEntry->pNextEntry = NULL;
|
|
|
|
if (nErrorType == WRONG_NUM_BACKUP)
|
|
{
|
|
pNewEntry->nVal1 = ((INT *)dwError)[0];
|
|
pNewEntry->nVal2 = ((INT *)dwError)[1];
|
|
pNewEntry->nVal3 = ((INT *)dwError)[2];
|
|
pNewEntry->nVal4 = ((INT *)dwError)[3];
|
|
}
|
|
else if ((nErrorType == STALE_SERVER)||
|
|
(nErrorType == STALE_DOMAIN))
|
|
|
|
{
|
|
AddStaleEntry (pNewEntry,
|
|
((DWORD *)dwError)[1],
|
|
((DWORD *)dwError)[0],
|
|
wHour,
|
|
wMinute);
|
|
}
|
|
else
|
|
{
|
|
pNewEntry->nVal1 = dwError;
|
|
pNewEntry->nVal2 = dwNSGI;
|
|
}
|
|
|
|
return(pNewEntry);
|
|
}
|
|
|
|
void AddStaleEntry (PERRORLIST pErrorList,
|
|
DWORD dwBackupEntry,
|
|
DWORD dwMasterEntry,
|
|
WORD wHour,
|
|
WORD wMinute)
|
|
{
|
|
PENTRYLIST pNewEntry;
|
|
|
|
pNewEntry = (PENTRYLIST) LocalAlloc (LPTR, sizeof(ENTRYLIST));
|
|
if (pNewEntry == NULL)
|
|
{
|
|
fprintf(stdout, "Not enough memory");
|
|
return;
|
|
}
|
|
|
|
pNewEntry->dwBackupEntry = dwBackupEntry;
|
|
pNewEntry->dwMasterEntry = dwMasterEntry;
|
|
pNewEntry->wHour = wHour;
|
|
pNewEntry->wMinute = wMinute;
|
|
pNewEntry->pNextEntry = (PENTRYLIST) pErrorList->nVal1;
|
|
|
|
*((PENTRYLIST *)(&pErrorList->nVal1)) = pNewEntry;
|
|
}
|
|
|
|
// Get all the servers in lpBrowserName.
|
|
BOOL MyGetList (LPTSTR lpUser,
|
|
LPTSTR lpBrowserName,
|
|
LPTSTR lpTransportName,
|
|
LPTSTR lpDomainName,
|
|
LPTSTR lpMasterName,
|
|
DWORD * pdwEntriesRead,
|
|
DWORD * pdwTotalEntries,
|
|
LPVOID * lppBrowserList,
|
|
BOOL fBrowserNotDomain,
|
|
DWORD nTimeLimit)
|
|
{
|
|
DWORD dwVal;
|
|
INT nErrorType;
|
|
DWORD dwStartTime;
|
|
DWORD dwEndTime;
|
|
|
|
nErrorType = lstrcmp(lpBrowserName, lpMasterName)?
|
|
(fBrowserNotDomain? BROWSER_NO_SERVER_LIST : BROWSER_NO_DOMAIN_LIST) :
|
|
(fBrowserNotDomain? MASTER_NO_SERVER_LIST : MASTER_NO_DOMAIN_LIST);
|
|
|
|
|
|
dwStartTime = GetTickCount();
|
|
|
|
dwVal = MyRxNetServerEnum (lpBrowserName,
|
|
lpTransportName,
|
|
101,
|
|
(LPBYTE *) lppBrowserList,
|
|
0xffffffff,
|
|
pdwEntriesRead,
|
|
pdwTotalEntries,
|
|
fBrowserNotDomain? SV_TYPE_ALL : SV_TYPE_DOMAIN_ENUM,
|
|
lpDomainName,
|
|
NULL);
|
|
|
|
dwEndTime = GetTickCount();
|
|
|
|
if (dwVal != NERR_Success) // Failed to return backup browser list.
|
|
{
|
|
ReportError (lpUser,
|
|
lpTransportName,
|
|
lpDomainName,
|
|
lpMasterName,
|
|
lpBrowserName,
|
|
dwVal,
|
|
nErrorType);
|
|
|
|
return(FALSE);
|
|
}
|
|
else // Continue if we got a backup list from the backup browser.
|
|
{
|
|
nCountSuccess[nErrorType]++;
|
|
|
|
if ((dwEndTime - dwStartTime) > nTimeLimit) {
|
|
|
|
dwVal = dwEndTime - dwStartTime;
|
|
|
|
//
|
|
// If this took "too long", log it as an error.
|
|
//
|
|
|
|
ReportError (lpUser,
|
|
lpTransportName,
|
|
lpDomainName,
|
|
lpMasterName,
|
|
lpBrowserName,
|
|
dwVal,
|
|
BROWSE_TOO_LONG);
|
|
|
|
if ((dwEndTime - dwStartTime) > 2*nTimeLimit) {
|
|
SendMagicBullet();
|
|
}
|
|
|
|
} else {
|
|
nCountSuccess[BROWSE_TOO_LONG] += 1;
|
|
}
|
|
|
|
// Log the number of backups etc.
|
|
fprintf (pLOGFILE,
|
|
"There are %lu %s on browser %s\nEntriesRead = %lu. TotalEntries = %lu. Time = %lu milliseconds\n",
|
|
*pdwTotalEntries,
|
|
fBrowserNotDomain? "server" : "domain",
|
|
toansi (lpBrowserName),
|
|
*pdwEntriesRead,
|
|
*pdwTotalEntries,
|
|
dwEndTime - dwStartTime);
|
|
|
|
WriteList (pLOGFILE, *lppBrowserList, *pdwEntriesRead);
|
|
return(TRUE);
|
|
}
|
|
}
|
|
|
|
// Check for error type 2: Incorrect server lists returned by
|
|
// backup browsers (and master browsers). This includes stale
|
|
// servers in the list. Same for the domain list.
|
|
void CheckErrorType2 (LPTSTR lpUser,
|
|
LPTSTR lpTransportName,
|
|
LPTSTR lpDomainName,
|
|
LPTSTR lpMasterName,
|
|
PWSTR * lpList,
|
|
DWORD dwEntries,
|
|
INT nTolerancePercent,
|
|
DWORD nTimeLimit)
|
|
{
|
|
// Check if the server list returned from backup browser is the same
|
|
// as that from the master browser.
|
|
|
|
CheckList (lpUser,
|
|
lpTransportName,
|
|
lpDomainName,
|
|
lpMasterName,
|
|
lpList,
|
|
dwEntries,
|
|
nTolerancePercent,
|
|
TRUE,
|
|
nTimeLimit);
|
|
|
|
// Check if the domain list returned from backup browser is the same
|
|
// as that from the master browser.
|
|
|
|
CheckList (lpUser,
|
|
lpTransportName,
|
|
lpDomainName,
|
|
lpMasterName,
|
|
lpList,
|
|
dwEntries,
|
|
nTolerancePercent,
|
|
FALSE,
|
|
nTimeLimit);
|
|
}
|
|
|
|
void CheckList (LPTSTR lpUser,
|
|
LPTSTR lpTransportName,
|
|
LPTSTR lpDomainName,
|
|
LPTSTR lpMasterName,
|
|
PWSTR * lpList,
|
|
DWORD dwEntries,
|
|
INT nTolerancePercent,
|
|
BOOL fBrowserNotDomain,
|
|
DWORD nTimeLimit)
|
|
{
|
|
INT i;
|
|
INT nTolerance;
|
|
INT nErrorType = fBrowserNotDomain? STALE_SERVER : STALE_DOMAIN;
|
|
BOOL fError = FALSE;
|
|
DWORD dwTotalEntries; // Total Backup Browsers
|
|
DWORD dwEntriesRead; // Total Backup Browsers Read.
|
|
DWORD dwBackupTotalEntries; // Total Backup Browsers
|
|
DWORD dwBackupEntriesRead; // Total Backup Browsers Read.
|
|
LPVOID lpBrowserList;
|
|
LPVOID lpBackupBrowserList;
|
|
|
|
if (!MyGetList(lpUser,
|
|
lpMasterName,
|
|
lpTransportName,
|
|
lpDomainName,
|
|
lpMasterName,
|
|
&dwEntriesRead,
|
|
&dwTotalEntries,
|
|
&lpBrowserList,
|
|
fBrowserNotDomain,
|
|
nTimeLimit))
|
|
{
|
|
if (lpBrowserList != NULL)
|
|
{
|
|
MIDL_user_free (lpBrowserList);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
nTolerance = nTolerancePercent*dwEntriesRead/100;
|
|
|
|
for (i = 0; i < (INT) dwEntries ; i++) // Enumerate on backups.
|
|
{
|
|
if (lstrcmp (lpMasterName, lpList[i])) // When they are different it returns true.
|
|
{
|
|
if (MyGetList (lpUser,
|
|
lpList[i],
|
|
lpTransportName,
|
|
lpDomainName,
|
|
lpMasterName,
|
|
&dwBackupEntriesRead,
|
|
&dwBackupTotalEntries,
|
|
&lpBackupBrowserList,
|
|
fBrowserNotDomain,
|
|
nTimeLimit))
|
|
{
|
|
// Compare the number of browserlist from the backup with the one
|
|
// from the master.
|
|
|
|
if ((abs(dwBackupEntriesRead - dwEntriesRead) > 10) &&
|
|
((dwEntriesRead > dwBackupEntriesRead + nTolerance) ||
|
|
(dwEntriesRead < dwBackupEntriesRead - nTolerance)))
|
|
{
|
|
fError = TRUE;
|
|
}
|
|
else
|
|
{
|
|
// Compare the servers returned from backups with those from master.
|
|
// When the list are too different, CompareList returns false.
|
|
fError = !CompareList (lpBrowserList,
|
|
lpBackupBrowserList,
|
|
dwEntriesRead,
|
|
dwBackupEntriesRead,
|
|
nTolerance);
|
|
}
|
|
|
|
if (fError) // Type 2 error occured.
|
|
{
|
|
DWORD dwEntries[2] = {dwEntriesRead, dwBackupEntriesRead};
|
|
|
|
ReportError (lpUser,
|
|
lpTransportName,
|
|
lpDomainName,
|
|
lpMasterName,
|
|
lpList[i],
|
|
(DWORD)dwEntries,
|
|
nErrorType);
|
|
} // End of if type 2 error occured.
|
|
else
|
|
{
|
|
nCountSuccess[nErrorType]++;
|
|
}
|
|
|
|
} //End of if we get a browser list from the backup browser.
|
|
|
|
if (lpBackupBrowserList != NULL)
|
|
{
|
|
MIDL_user_free (lpBackupBrowserList);
|
|
}
|
|
|
|
} // End of if when we get a backup browser.
|
|
|
|
} // End of for statement.
|
|
|
|
MIDL_user_free (lpBrowserList);
|
|
}
|
|
|
|
// Check for error type 3: Incorrect number of browser servers.
|
|
void CheckErrorType3 (LPTSTR lpUser,
|
|
LPTSTR lpTransportName,
|
|
LPTSTR lpDomainName,
|
|
LPTSTR lpMasterName)
|
|
{
|
|
INT i;
|
|
INT nNTMachine = 0;
|
|
DWORD nBackup = 0;
|
|
INT nServer;
|
|
DWORD dwVal;
|
|
DWORD dwEntriesRead;
|
|
DWORD dwTotalEntries;
|
|
// TCHAR lpErrorMessage[STRINGLEN];
|
|
LPVOID lpServerList;
|
|
PSERVER_INFO_101 pServerInfo101;
|
|
|
|
// Get the number of servers.
|
|
dwVal = MyRxNetServerEnum (lpMasterName,
|
|
lpTransportName,
|
|
101,
|
|
(LPBYTE *) &lpServerList,
|
|
0xffffffff,
|
|
&dwEntriesRead,
|
|
&dwTotalEntries,
|
|
SV_TYPE_LOCAL_LIST_ONLY,
|
|
lpDomainName,
|
|
NULL);
|
|
|
|
if (dwVal != NERR_Success) {
|
|
if (lpServerList != NULL) {
|
|
MIDL_user_free (lpServerList);
|
|
}
|
|
|
|
ReportError (lpUser,
|
|
lpTransportName,
|
|
lpDomainName,
|
|
lpMasterName,
|
|
lpMasterName,
|
|
dwVal,
|
|
MASTER_NO_LOCAL_LIST); //Error type number.
|
|
return;
|
|
} else { // Got the server list.
|
|
DWORD nExpected;
|
|
nCountSuccess[MASTER_NO_LOCAL_LIST]++;
|
|
|
|
nServer = dwEntriesRead;
|
|
|
|
pServerInfo101 = lpServerList;
|
|
|
|
for (i = 0; i < (INT) dwEntriesRead; i++ ) {
|
|
if (pServerInfo101[i].sv101_type & SV_TYPE_BACKUP_BROWSER) {
|
|
nBackup++;
|
|
}
|
|
|
|
if ( (pServerInfo101[i].sv101_type & SV_TYPE_BACKUP_BROWSER) &&
|
|
!(pServerInfo101[i].sv101_type & SV_TYPE_POTENTIAL_BROWSER)) {
|
|
|
|
nNTMachine++;
|
|
}
|
|
}
|
|
|
|
//Check for error type 3: Incorrect number of browser server.
|
|
|
|
if (nNTMachine > 1) {
|
|
nExpected = nNTMachine;
|
|
} else {
|
|
nExpected = (nServer+31)/32;
|
|
}
|
|
|
|
if ((nNTMachine > 1 && (nBackup != nExpected)) ||
|
|
((nNTMachine <= 1) && (nBackup < nExpected))) {
|
|
|
|
INT nMachine[4] = {nNTMachine, nBackup, nServer, nExpected};
|
|
|
|
ReportError(lpUser,
|
|
lpTransportName,
|
|
lpDomainName,
|
|
NULL,
|
|
NULL,
|
|
(DWORD) nMachine,
|
|
WRONG_NUM_BACKUP);
|
|
} else { // No type 3 error. Write info to the logfile.
|
|
nCountSuccess[WRONG_NUM_BACKUP]++;
|
|
}
|
|
|
|
MIDL_user_free (lpServerList);
|
|
}
|
|
}
|
|
|
|
// Check for error type 4: Master is not a PDC.
|
|
void CheckErrorType4 (LPTSTR lpUser,
|
|
LPTSTR lpTransportName,
|
|
LPTSTR lpDomainName,
|
|
LPTSTR lpMasterName)
|
|
{
|
|
LPTSTR lpPDCName = NULL;
|
|
DWORD dwVal;
|
|
|
|
dwVal = NetGetDCName (NULL,
|
|
lpDomainName,
|
|
(LPBYTE *)&lpPDCName);
|
|
if (dwVal != NERR_Success)
|
|
{
|
|
ReportError (lpUser,
|
|
lpTransportName,
|
|
lpDomainName,
|
|
lpMasterName,
|
|
lpMasterName,
|
|
dwVal,
|
|
NO_PDC);
|
|
}
|
|
else
|
|
{
|
|
nCountSuccess[NO_PDC]++;
|
|
|
|
if (lstrcmp (lpMasterName, lpPDCName))
|
|
{
|
|
ReportError (lpUser,
|
|
lpTransportName,
|
|
lpDomainName,
|
|
lpPDCName,
|
|
lpMasterName,
|
|
0,
|
|
MASTER_NOT_PDC);
|
|
}
|
|
else
|
|
{
|
|
nCountSuccess[MASTER_NOT_PDC]++;
|
|
}
|
|
}
|
|
|
|
if (lpPDCName != NULL)
|
|
{
|
|
LocalFree(lpPDCName);
|
|
}
|
|
}
|
|
|
|
void CheckErrorType5 (LPTSTR lpBrowserName,
|
|
LPTSTR lpTransportName,
|
|
LPTSTR lpDomainName,
|
|
LPTSTR lpUser)
|
|
{
|
|
PLMDR_TRANSPORT_LIST TransportList = NULL;
|
|
PLMDR_TRANSPORT_LIST TransportEntry = NULL;
|
|
NET_API_STATUS Status;
|
|
|
|
Status = GetBrowserTransportList(&TransportList);
|
|
if (Status != NERR_Success)
|
|
{
|
|
return;
|
|
}
|
|
|
|
TransportEntry = TransportList;
|
|
|
|
while (TransportEntry != NULL)
|
|
{
|
|
UNICODE_STRING TransportName;
|
|
LPBYTE lpBrowserList;
|
|
ULONG dwEntriesRead, dwTotalEntries;
|
|
|
|
TransportName.Buffer = TransportEntry->TransportName;
|
|
TransportName.Length = (USHORT) TransportEntry->TransportNameLength;
|
|
TransportName.MaximumLength = (USHORT) TransportEntry->TransportNameLength;
|
|
|
|
Status = RxNetServerEnum(lpBrowserName,
|
|
TransportName.Buffer,
|
|
101,
|
|
&lpBrowserList,
|
|
0xffffffff,
|
|
&dwEntriesRead,
|
|
&dwTotalEntries,
|
|
SV_TYPE_ALL,
|
|
NULL,
|
|
NULL);
|
|
|
|
if (lpBrowserList != NULL)
|
|
{
|
|
NetApiBufferFree(lpBrowserList);
|
|
}
|
|
|
|
if (Status == NERR_Success)
|
|
{
|
|
break;
|
|
}
|
|
|
|
if (TransportEntry->NextEntryOffset == 0)
|
|
TransportEntry = NULL;
|
|
else
|
|
{
|
|
TransportEntry = (PLMDR_TRANSPORT_LIST) ((PCHAR) TransportEntry
|
|
+TransportEntry->NextEntryOffset);
|
|
}
|
|
}
|
|
|
|
NetApiBufferFree(TransportList);
|
|
|
|
if (Status != NERR_Success)
|
|
{
|
|
static BOOL fError = FALSE;
|
|
TCHAR lpErrorMessage[STRINGLEN];
|
|
|
|
nCountFail[TRANSPORT_FAILURE]++;
|
|
wsprintf (lpErrorMessage, L"Browser %ws failed on all transports.\n", lpBrowserName);
|
|
|
|
RecordError (&fError,
|
|
lpBrowserName,
|
|
lpTransportName,
|
|
lpDomainName,
|
|
lpUser,
|
|
lpErrorMessage,
|
|
0,
|
|
0,
|
|
TRANSPORT_FAILURE);
|
|
}
|
|
else
|
|
nCountSuccess[TRANSPORT_FAILURE]++;
|
|
}
|
|
|
|
LPTSTR ServerInfo (LPTSTR lpServer)
|
|
{
|
|
PSERVER_INFO_101 psvInfo = NULL;
|
|
static TCHAR lpTemp[STRINGLEN/2];
|
|
|
|
WCHAR ShareName[STRINGLEN/2];
|
|
|
|
wcscpy(ShareName, lpServer);
|
|
wcscat(ShareName, L"\\Ipc$");
|
|
|
|
NetUseDel(NULL, ShareName, USE_LOTS_OF_FORCE);
|
|
|
|
if (NetServerGetInfo (lpServer,
|
|
101,
|
|
(LPBYTE *)&psvInfo) == NERR_Success)
|
|
{
|
|
wsprintf (lpTemp,
|
|
L"\\\\%ws: version=%ld.%ld type=",
|
|
psvInfo->sv101_name,
|
|
psvInfo->sv101_version_major,
|
|
psvInfo->sv101_version_minor);
|
|
|
|
if (psvInfo->sv101_type&SV_TYPE_WORKSTATION)
|
|
{
|
|
lstrcat (lpTemp, L"WORKSTATION");
|
|
}
|
|
|
|
if (psvInfo->sv101_type&SV_TYPE_SERVER)
|
|
{
|
|
lstrcat (lpTemp, L" | SERVER");
|
|
}
|
|
|
|
if (psvInfo->sv101_type&SV_TYPE_SQLSERVER)
|
|
{
|
|
lstrcat (lpTemp, L" | SQLSERVER");
|
|
}
|
|
|
|
if (psvInfo->sv101_type&SV_TYPE_DOMAIN_CTRL)
|
|
{
|
|
lstrcat (lpTemp, L" | DOMAIN_CTRL");
|
|
}
|
|
|
|
if (psvInfo->sv101_type&SV_TYPE_DOMAIN_BAKCTRL)
|
|
{
|
|
lstrcat (lpTemp, L" | DOMAIN_BAKCTRL");
|
|
}
|
|
|
|
if (psvInfo->sv101_type&SV_TYPE_TIME_SOURCE)
|
|
{
|
|
lstrcat (lpTemp, L" | TIME_SOURCE");
|
|
}
|
|
|
|
if (psvInfo->sv101_type&SV_TYPE_AFP)
|
|
{
|
|
lstrcat (lpTemp, L" | AFP");
|
|
}
|
|
|
|
if (psvInfo->sv101_type&SV_TYPE_NOVELL)
|
|
{
|
|
lstrcat (lpTemp, L" | NOVELL");
|
|
}
|
|
|
|
if (psvInfo->sv101_type&SV_TYPE_DOMAIN_MEMBER)
|
|
{
|
|
lstrcat (lpTemp, L" | DOMAIN_MEMEBER");
|
|
}
|
|
|
|
if (psvInfo->sv101_type&SV_TYPE_PRINTQ_SERVER)
|
|
{
|
|
lstrcat (lpTemp, L" | PRINTQ_SERVER");
|
|
}
|
|
|
|
if (psvInfo->sv101_type&SV_TYPE_DIALIN_SERVER)
|
|
{
|
|
lstrcat (lpTemp, L" | DIALIN_SERVER");
|
|
}
|
|
|
|
if (psvInfo->sv101_type&SV_TYPE_XENIX_SERVER)
|
|
{
|
|
lstrcat (lpTemp, L" | XENIX_SERVER");
|
|
}
|
|
|
|
if (psvInfo->sv101_type&SV_TYPE_NT)
|
|
{
|
|
lstrcat (lpTemp, L" | NT");
|
|
}
|
|
|
|
if (psvInfo->sv101_type&SV_TYPE_WFW)
|
|
{
|
|
lstrcat (lpTemp, L" | WFW");
|
|
}
|
|
|
|
if (psvInfo->sv101_type&SV_TYPE_POTENTIAL_BROWSER)
|
|
{
|
|
lstrcat (lpTemp, L" | POTNETIAL_BROWSER");
|
|
}
|
|
|
|
if (psvInfo->sv101_type&SV_TYPE_BACKUP_BROWSER)
|
|
{
|
|
lstrcat (lpTemp, L" | BACKUP_BROWSER");
|
|
}
|
|
|
|
if (psvInfo->sv101_type&SV_TYPE_MASTER_BROWSER)
|
|
{
|
|
lstrcat (lpTemp, L" | MASTER_BROWSER");
|
|
}
|
|
|
|
if (psvInfo->sv101_type&SV_TYPE_DOMAIN_MASTER)
|
|
{
|
|
lstrcat (lpTemp, L" | DOMAIN_MASTER");
|
|
}
|
|
|
|
lstrcat (lpTemp, L"\n");
|
|
MIDL_user_free (psvInfo);
|
|
|
|
return(lpTemp);
|
|
}
|
|
else
|
|
return(L"\0");
|
|
}
|
|
|
|
BOOL
|
|
ConvertFile(
|
|
DWORD CtrlType
|
|
)
|
|
{
|
|
WriteSummory();
|
|
MyFreeList();
|
|
fclose (pLOGFILE);
|
|
|
|
CtrlType;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
void WriteSummory()
|
|
{
|
|
FILE * pFile;
|
|
INT i;
|
|
LPSTR lpText[ERRORTYPENUM];
|
|
|
|
lpText[0] = szText0;
|
|
lpText[1] = szText1;
|
|
lpText[2] = szText2;
|
|
lpText[3] = szText3;
|
|
lpText[4] = szText4;
|
|
lpText[5] = szText5;
|
|
lpText[6] = szText6;
|
|
lpText[7] = szText7;
|
|
lpText[8] = szText8;
|
|
lpText[9] = szText9;
|
|
lpText[10] = szText10;
|
|
lpText[11] = szText11;
|
|
lpText[12] = szText12;
|
|
lpText[13] = szText13;
|
|
lpText[14] = szText14;
|
|
lpText[15] = szText15;
|
|
lpText[16] = szText16;
|
|
lpText[17] = szText17;
|
|
lpText[18] = szText18;
|
|
|
|
pFile = fopen (szLOGFILE, "w+");
|
|
|
|
if (pFile == NULL) {
|
|
fprintf (stderr, "The browser checker was unable to open the log file.\n");
|
|
return;
|
|
}
|
|
|
|
fprintf (pFile, "The browser check has run %d times.\n", nTimes);
|
|
|
|
for (i=0 ; i < ERRORTYPENUM ; i++)
|
|
{
|
|
fprintf (pFile,
|
|
"%d : %d -- %s\n",
|
|
nCountFail[i],
|
|
nCountSuccess[i],
|
|
lpText[i]);
|
|
|
|
PrintEntries(pFile, i, pErrorList[i]);
|
|
|
|
fprintf (pFile, "\n");
|
|
}
|
|
|
|
fclose(pFile);
|
|
}
|
|
|
|
void PrintEntries (FILE * pFile,
|
|
INT nErrorType,
|
|
PERRORLIST pErrorList)
|
|
{
|
|
PERRORLIST pErrorEntry;
|
|
|
|
pErrorEntry = pErrorList;
|
|
|
|
while (pErrorEntry != NULL)
|
|
{
|
|
if ((nErrorType == STALE_SERVER) ||
|
|
(nErrorType == STALE_DOMAIN))
|
|
{
|
|
PENTRYLIST pEntryList;
|
|
pEntryList = (PENTRYLIST) pErrorEntry->nVal1;
|
|
|
|
fprintf (pFile,
|
|
toansi(L" %ws %ws %ws occurred %d times.\n"),
|
|
pErrorEntry->lpTransport,
|
|
pErrorEntry->lpDomain,
|
|
pErrorEntry->lpServer,
|
|
pErrorEntry->nCount);
|
|
|
|
while (pEntryList != NULL)
|
|
{
|
|
fprintf (pFile,
|
|
" BackupEntries = %lu, MasterEntries = %lu, time = %d:%d\n",
|
|
pEntryList->dwBackupEntry,
|
|
pEntryList->dwMasterEntry,
|
|
pEntryList->wHour,
|
|
pEntryList->wMinute);
|
|
|
|
pEntryList = pEntryList->pNextEntry;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (pErrorEntry->lpServer != NULL) {
|
|
fprintf (pFile,
|
|
toansi(L" %ws %ws %ws occurred %d times. Last time at %d:%d\n"),
|
|
pErrorEntry->lpTransport,
|
|
pErrorEntry->lpDomain,
|
|
pErrorEntry->lpServer,
|
|
pErrorEntry->nCount,
|
|
pErrorEntry->wHour,
|
|
pErrorEntry->wMinute);
|
|
} else {
|
|
fprintf (pFile,
|
|
toansi(L" %ws %ws occurred %d times. Last time at %d:%d\n"),
|
|
pErrorEntry->lpTransport,
|
|
pErrorEntry->lpDomain,
|
|
pErrorEntry->nCount,
|
|
pErrorEntry->wHour,
|
|
pErrorEntry->wMinute);
|
|
}
|
|
|
|
if (nErrorType == WRONG_NUM_MASTER) {
|
|
fprintf (pFile,
|
|
" %d masters returned.\n",
|
|
pErrorEntry->nVal1);
|
|
} else if (nErrorType == BROWSE_TOO_LONG) {
|
|
fprintf (pFile,
|
|
" Request took %d milliseconds.\n",
|
|
pErrorEntry->nVal1);
|
|
} else if (nErrorType == WRONG_NUM_BACKUP) {
|
|
fprintf (pFile,
|
|
" nNTMachine = %d nBackupBrowser = %d nServer = %d, nExpected %d \n",
|
|
pErrorEntry->nVal1,
|
|
pErrorEntry->nVal2,
|
|
pErrorEntry->nVal3,
|
|
pErrorEntry->nVal4);
|
|
|
|
}
|
|
else
|
|
{
|
|
if (pErrorEntry->nVal1 != 0)
|
|
{
|
|
fprintf (pFile,
|
|
" Error %d occurred : %s",
|
|
pErrorEntry->nVal1,
|
|
toansi (GetError (pErrorEntry->nVal1)));
|
|
|
|
if ((pErrorEntry->nVal1 != 0) &&
|
|
((nErrorType == MASTER_NO_SERVER_LIST) ||
|
|
(nErrorType == MASTER_NO_DOMAIN_LIST) ||
|
|
(nErrorType == BROWSER_NO_SERVER_LIST) ||
|
|
(nErrorType == BROWSER_NO_DOMAIN_LIST) ||
|
|
(nErrorType == MASTER_NO_LOCAL_LIST)))
|
|
{
|
|
fprintf (pFile,
|
|
" NetServerGetInfo returned %d : %s",
|
|
pErrorEntry->nVal2,
|
|
toansi (GetError (pErrorEntry->nVal2)));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
pErrorEntry = pErrorEntry->pNextEntry;
|
|
}
|
|
}
|
|
|
|
void MyFreeList ()
|
|
{
|
|
INT i;
|
|
PERRORLIST pThisEntry;
|
|
PERRORLIST pErrorEntry;
|
|
|
|
for (i=0 ; i < ERRORTYPENUM ; i++)
|
|
{
|
|
pErrorEntry = pErrorList[i];
|
|
|
|
while (pErrorEntry != NULL)
|
|
{
|
|
pThisEntry = pErrorEntry;
|
|
pErrorEntry = pThisEntry->pNextEntry;
|
|
|
|
if (pThisEntry->lpServer != NULL)
|
|
{
|
|
LocalFree(pThisEntry->lpServer);
|
|
}
|
|
LocalFree (pThisEntry->lpTransport);
|
|
LocalFree (pThisEntry->lpDomain);
|
|
|
|
if ((i == STALE_SERVER) ||
|
|
(i == STALE_DOMAIN))
|
|
{
|
|
PENTRYLIST pEntryList;
|
|
PENTRYLIST pFreeEntry;
|
|
|
|
pEntryList = (PENTRYLIST)pThisEntry->nVal1;
|
|
|
|
while (pEntryList != NULL)
|
|
{
|
|
pFreeEntry = pEntryList;
|
|
pEntryList = pFreeEntry->pNextEntry;
|
|
|
|
LocalFree (pFreeEntry);
|
|
}
|
|
}
|
|
|
|
LocalFree (pThisEntry);
|
|
}
|
|
}
|
|
}
|
|
|