/*++ Copyright (C) 1999 Microsoft Corporation --*/ #include "precomp.h" #define WCHARTONUM(wchr) (iswalpha(wchr)?(towlower(wchr)-L'a')+10:wchr-L'0') UCHAR StringToHexA(IN LPCWSTR pwcString) { UCHAR ch = (CHAR)0x00; if( pwcString is NULL ) return ch; while(*pwcString != L'\0') { ch <<= 4; ch |= WCHARTONUM(*pwcString); pwcString++; } return ch; } ULONG LA_TableSize = 0; VOID FreeLATable(ULONG TableSize) { DWORD i = 0; if( IsBadReadPtr((void *)LA_Table, TableSize) is FALSE && TableSize > 0 ) { for( i=0; i<TableSize; i++ ) { if( IsBadStringPtr(LA_Table[i], 20*sizeof(WCHAR)) is FALSE ) { WinsFreeMemory((PVOID)LA_Table[i]); LA_Table[i] = NULL; } } WinsFreeMemory((PVOID)LA_Table); LA_Table = NULL; } } VOID FreeSOTable(ULONG TableSize) { DWORD i = 0; if( SO_Table ) { for( i=0; i<TableSize; i++ ) { if( SO_Table[i] ) { WinsFreeMemory((PVOID)SO_Table[i]); SO_Table[i] = NULL; } } WinsFreeMemory((PVOID)SO_Table); SO_Table = NULL; } } VOID DumpSOTable( IN DWORD MasterOwners, IN BOOL fFile, IN FILE * pFile ) { ULONG i; ULONG j; DisplayMessage(g_hModule, MSG_WINS_SOTABLE_HEADER); if( fFile is TRUE ) { DumpMessage(g_hModule, pFile, FMSG_WINS_SOTABLE_HEADER); } for (i = 0; i < MasterOwners; i++) { DisplayMessage(g_hModule, MSG_WINS_MASTEROWNER_INDEX, i); if( fFile ) { DumpMessage(g_hModule, pFile, FMSG_WINS_MASTEROWNER_INDEX, i); } } DisplayMessage(g_hModule, WINS_FORMAT_LINE); if( fFile ) { DumpMessage(g_hModule, pFile, WINS_FORMAT_LINE); } for (i = 0; i < MasterOwners; i++) { DisplayMessage(g_hModule, MSG_WINS_MASTEROWNER_INDEX1, i); if( fFile ) { DumpMessage(g_hModule, pFile, FMSG_WINS_MASTEROWNER_INDEX1, i); } for (j = 0; j < MasterOwners; j++) { DisplayMessage(g_hModule, MSG_WINS_MASTEROWNER_INDEX, SO_Table[i][j]); if( fFile ) { DumpMessage(g_hModule, pFile, FMSG_WINS_MASTEROWNER_INDEX, SO_Table[i][j]); } } DisplayMessage(g_hModule, WINS_FORMAT_LINE); if( fFile ) { DumpMessage(g_hModule, pFile, WINS_FORMAT_LINE); } } DisplayMessage(g_hModule, MSG_WINS_MAP_SOURCE); if( fFile ) { DumpMessage(g_hModule, pFile, FMSG_WINS_MAP_SOURCE); } DumpLATable(MasterOwners, fFile, pFile); } VOID DumpLATable( IN DWORD MasterOwners, IN BOOL fFile, IN FILE * pFile ) { ULONG i; ULONG j; DisplayMessage(g_hModule, MSG_WINS_INDEXTOIP_TABLE); if( fFile ) { DumpMessage(g_hModule, pFile, FMSG_WINS_INDEXTOIP_TABLE); } for (i = 0; i < MasterOwners; i++) { if (LA_Table[i][0] == '0') { break; } DisplayMessage(g_hModule, MSG_WINS_INDEXTOIP_ENTRY, i, LA_Table[i]); if( pFile ) { DumpMessage(g_hModule, pFile, FMSG_WINS_INDEXTOIP_ENTRY, i, LA_Table[i]); } } DisplayMessage(g_hModule, WINS_FORMAT_LINE); if( fFile ) { DumpMessage(g_hModule, pFile, WINS_FORMAT_LINE); } } LONG IPToIndex( IN LPWSTR IpAddr, DWORD NoOfOwners ) { ULONG i=0; WCHAR **pTempLA = NULL; // // Get the Row # // for ( i = 0; i < NoOfOwners; i++) { if (wcscmp(LA_Table[i], IpAddr) == 0) { return i; } // // The first NULL entry indicates end // if (LA_Table[i][0] is L'0') { break; } } // // Entry not found - add // wcscpy(LA_Table[i], IpAddr); LA_TableSize = i+1; return i; } // // Check if the diagonal elements are the max in their cols. // VOID CheckSOTableConsistency( DWORD MasterOwners ) { ULONG i; ULONG j; BOOLEAN fProblem = FALSE; for (i = 0; i < MasterOwners; i++) { // // Is the diagonal element at i the largest in its column? // for (j = 0; j < MasterOwners; j++) { if (i == j) { continue; } // // Compare only non-zero values // if (SO_Table[i][i].QuadPart && SO_Table[j][i].QuadPart && (SO_Table[i][i].QuadPart < SO_Table[j][i].QuadPart)) { DisplayMessage(g_hModule, EMSG_WINS_VERSION_HIGHER, LA_Table[j], LA_Table[i]); fProblem = TRUE; } } } if ( fProblem is FALSE ) { DisplayMessage(g_hModule, EMSG_WINS_VERSION_CORRECT); } } DWORD InitLATable( PWINSINTF_ADD_VERS_MAP_T pAddVersMaps, DWORD MasterOwners, // 0 first time DWORD NoOfOwners ) { ULONG i, j, k; if( LA_Table is NULL ) { LA_Table = WinsAllocateMemory(MAX_WINS*sizeof(LPWSTR)); if( LA_Table is NULL ) { return 0; } for( i=0; i< MAX_WINS; i++ ) { LA_Table[i] = WinsAllocateMemory(20*sizeof(WCHAR)); if( LA_Table[i] is NULL ) { FreeLATable(i); return 0; } } } if (MasterOwners == 0) { // // first time - init the LA table // for (i = 0; i < NoOfOwners; i++, pAddVersMaps++) { struct in_addr InAddr; LPWSTR pwsz = IpAddressToString(pAddVersMaps->Add.IPAdd); if( pwsz is NULL ) { FreeLATable(MAX_WINS); return 0; } wcscpy(LA_Table[i], pwsz); WinsFreeMemory(pwsz); pwsz = NULL; } } else { // // More came in this time - add them to the LA table after the others // for (i = 0; i < NoOfOwners; i++, pAddVersMaps++) { LPWSTR pwszIp = IpAddressToString(pAddVersMaps->Add.IPAdd); if( pwszIp is NULL ) { FreeLATable(MAX_WINS); return 0; } // // If this entry is not in the LA table, insert // for (j = 0; j < MasterOwners; j++) { if (wcscmp(LA_Table[j], pwszIp) is 0 ) { WinsFreeMemory(pwszIp); pwszIp = NULL; break; } } if (j == MasterOwners) { // // Insert // wcscpy(LA_Table[MasterOwners], pwszIp); MasterOwners++; } if( pwszIp ) { WinsFreeMemory(pwszIp); pwszIp = NULL; } } } if( SO_Table is NULL ) { SO_Table = WinsAllocateMemory((MAX_WINS+1)*sizeof(LARGE_INTEGER *)); if (SO_Table == NULL) { FreeLATable(MAX_WINS); return 0; } for( i=0; i<MAX_WINS+1; i++ ) { SO_Table[i] = WinsAllocateMemory((MAX_WINS+1)*sizeof(LARGE_INTEGER)); if( SO_Table[i] is NULL ) { FreeLATable(MAX_WINS); FreeSOTable(MAX_WINS+1); return 0; } } } LA_TableSize = NoOfOwners; return MasterOwners; } VOID AddSOTableEntry ( IN LPWSTR IpAddr, PWINSINTF_ADD_VERS_MAP_T pMasterMaps, DWORD NoOfOwners, DWORD MasterOwners ) { ULONG i; LONG Row; struct in_addr InAddr; Row = IPToIndex(IpAddr, MasterOwners); // // Fill the row // for ( i = 0; i < NoOfOwners; i++, pMasterMaps++) { LONG col; LPTSTR pstr; InAddr.s_addr = htonl(pMasterMaps->Add.IPAdd); pstr = IpAddressToString(pMasterMaps->Add.IPAdd); if (pstr == NULL) break; col = IPToIndex(pstr, MasterOwners); // // Place only a non-deleted entry // if (!((pMasterMaps->VersNo.HighPart == MAXLONG) && (pMasterMaps->VersNo.LowPart == MAXULONG))) { // // Also if the entry above us was 0, write 0 there so as to make the fail case stand out // if (Row && SO_Table[Row-1][col].QuadPart == 0) { SO_Table[Row][col].QuadPart = 0; } else { SO_Table[Row][col] = pMasterMaps->VersNo; } } } } VOID RemoveFromSOTable( IN LPWSTR IpAddr, IN DWORD MasterOwners ) { ULONG i; LONG Row; struct in_addr InAddr; Row = IPToIndex(IpAddr, MasterOwners); // // Mark the row and col as down (0's) // for (i = 0; i < MasterOwners; i++) { SO_Table[Row][i].QuadPart = SO_Table[i][Row].QuadPart = 0; } } // // Get the <owner address> - <version #> [OV table] mapping tables from each WINS server on the net and check for inconsistencies. // VOID CheckVersionNumbers( IN LPCSTR pStartIp, IN BOOL fFile, OUT FILE * pFile ) { DWORD Status = NO_ERROR; ULONG i, k; PWINSINTF_ADD_VERS_MAP_T pAddVersMaps; PWINSINTF_ADD_VERS_MAP_T pMasterMaps; // master OV maps used to place into the OV table DWORD NoOfOwners=0; DWORD MasterOwners=0; struct in_addr InAddr; WINSINTF_RESULTS_NEW_T ResultsN; DWORD ret; handle_t hBindTemp = g_hBind; WINSINTF_BIND_DATA_T BindDataTemp = g_BindData; LPWSTR wszStartIp = NULL; if( pStartIp is NULL ) return; wszStartIp = WinsOemToUnicode(pStartIp, NULL); if( wszStartIp is NULL ) { DisplayMessage(g_hModule, EMSG_WINS_OUT_OF_MEMORY); return; } // // Get the OV table from this server // if (NO_ERROR isnot (Status = GetStatus(TRUE, &ResultsN, TRUE, FALSE, pStartIp)) ) { DisplayErrorMessage(EMSG_SRVR_CHECK_VERSION, Status); WinsFreeMemory(wszStartIp); wszStartIp = NULL; return; } else { DisplayMessage(g_hModule, MSG_WINS_GETSTATUS_SUCCESS); DisplayMessage(g_hModule, WINS_FORMAT_LINE); } MasterOwners = NoOfOwners = ResultsN.NoOfOwners; pMasterMaps = pAddVersMaps = ResultsN.pAddVersMaps; ret = InitLATable(pAddVersMaps, 0, NoOfOwners); if( LA_Table is NULL ) { DisplayMessage(g_hModule, EMSG_WINS_OUT_OF_MEMORY); WinsFreeMemory(wszStartIp); wszStartIp = NULL; return; } if( SO_Table is NULL ) { DisplayMessage(g_hModule, EMSG_WINS_OUT_OF_MEMORY); FreeLATable(MAX_WINS); WinsFreeMemory(wszStartIp); wszStartIp = NULL; return; } AddSOTableEntry(wszStartIp, pMasterMaps, NoOfOwners, MasterOwners); if( ResultsN.pAddVersMaps ) { WinsFreeMem(ResultsN.pAddVersMaps); ResultsN.pAddVersMaps = NULL; } // // For each server X (other than Start addr) in the LA table: // for ( i = 0; i < MasterOwners; i++) { LPSTR pszName = NULL; if( wcscmp(LA_Table[i], wszStartIp) is 0 ) { continue; } // // Get X's OV table // pszName = WinsUnicodeToOem(LA_Table[i], NULL); if( pszName is NULL ) { DisplayMessage(g_hModule, EMSG_WINS_OUT_OF_MEMORY); if( SO_Table ) { FreeSOTable(MAX_WINS+1); } if( wszStartIp ) { WinsFreeMemory(wszStartIp); wszStartIp = NULL; } if( LA_Table ) { FreeLATable(MAX_WINS); } return; } if( NO_ERROR isnot (Status = GetStatus(TRUE, &ResultsN, TRUE, FALSE, pszName) ) ) { RemoveFromSOTable(LA_Table[i], MasterOwners); if( pszName ) { WinsFreeMemory(pszName); pszName = NULL; } if( ResultsN.pAddVersMaps ) { WinsFreeMem(ResultsN.pAddVersMaps); ResultsN.pAddVersMaps = NULL; } DisplayErrorMessage(EMSG_WINS_GETSTATUS_FAILED, Status); continue; } else { DisplayMessage(g_hModule, MSG_WINS_GETSTATUS_SUCCESS); } if (MasterOwners < ResultsN.NoOfOwners) { ret = InitLATable(ResultsN.pAddVersMaps, MasterOwners, ResultsN.NoOfOwners); if( LA_Table is NULL or SO_Table is NULL ) { DisplayMessage(g_hModule, EMSG_WINS_OUT_OF_MEMORY); if( pszName ) { WinsFreeMemory(pszName); pszName = NULL; } if( ResultsN.pAddVersMaps ) { WinsFreeMem(ResultsN.pAddVersMaps); ResultsN.pAddVersMaps = NULL; } if( SO_Table ) { WinsFreeMemory(SO_Table); SO_Table = NULL; } if( LA_Table ) { WinsFreeMemory(LA_Table); LA_Table = NULL; } if( wszStartIp ) { WinsFreeMemory(wszStartIp); wszStartIp = NULL; } return; } MasterOwners = ret; } // // Place entry in the SO Table in proper order // AddSOTableEntry(LA_Table[i], ResultsN.pAddVersMaps, ResultsN.NoOfOwners, MasterOwners); if( pszName ) { WinsFreeMemory(pszName); pszName = NULL; } if( ResultsN.pAddVersMaps ) { WinsFreeMem(ResultsN.pAddVersMaps); ResultsN.pAddVersMaps = NULL; } } // // Check if diagonal elements in the [SO] table are the highest in their cols. // CheckSOTableConsistency(MasterOwners); DumpSOTable(MasterOwners, fFile, pFile); // // Destroy SO table // FreeSOTable(MasterOwners+1); FreeLATable(MasterOwners); }