497 lines
11 KiB
C
497 lines
11 KiB
C
/*++
|
|
|
|
Copyright (c) 1995 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
net\rtm\rtmdlg.c
|
|
|
|
Abstract:
|
|
Routing Table Manager DLL. Debugging code to display table entries
|
|
in dialog box
|
|
|
|
|
|
Author:
|
|
|
|
Vadim Eydelman
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "pchrtm.h"
|
|
#pragma hdrstop
|
|
|
|
#if DBG
|
|
|
|
|
|
#define IP_PROTOCOL RR_RoutingProtocol
|
|
#define IP_INTERFACE RR_InterfaceID
|
|
#define IP_METRIC RR_FamilySpecificData.FSD_Metric1
|
|
#define IP_TIMESTAMP RR_TimeStamp
|
|
#define IP_NET_NUM RR_Network.N_NetNumber
|
|
#define IP_NET_MSK RR_Network.N_NetMask
|
|
#define IP_NEXT_HOP_NUM RR_NextHopAddress.N_NetNumber
|
|
#define IP_NEXT_HOP_MSK RR_NextHopAddress.N_NetMask
|
|
#define IP_ADPTER_INDEX RR_FamilySpecificData.FSD_AdapterIndex
|
|
#define IP_PROTOCOL_METRIC RR_FamilySpecificData.FSD_ProtocolMetric
|
|
#define IP_PSD RR_ProtocolSpecificData
|
|
|
|
#define IPX_PROTOCOL RR_RoutingProtocol
|
|
#define IPX_INTERFACE RR_InterfaceID
|
|
#define IPX_METRIC RR_FamilySpecificData.FSD_TickCount
|
|
#define IPX_TIMESTAMP RR_TimeStamp
|
|
#define IPX_NET_NUM RR_Network.N_NetNumber
|
|
#define IPX_NEXT_HOP_MAC RR_NextHopAddress.NHA_Mac
|
|
#define IPX_HOP_COUNT RR_FamilySpecificData.FSD_HopCount
|
|
#define IPX_PSD RR_ProtocolSpecificData
|
|
|
|
// Make table accessible to debugging code
|
|
extern RTM_TABLE Tables[RTM_NUM_OF_PROTOCOL_FAMILIES];
|
|
|
|
// Define protype internal to rtm.c
|
|
VOID
|
|
ConsolidateNetNumberLists (
|
|
PRTM_TABLE Table // Table for which operation is performed
|
|
);
|
|
|
|
DWORD DbgLevel = 0;
|
|
DWORD MaxTicks = MAXULONG;
|
|
DWORD MaxMessages=10000;
|
|
|
|
|
|
|
|
HANDLE RTDlgThreadHdl;
|
|
ULONG DisplayedTableIdx = 0xFFFFFFFF;
|
|
HWND RTDlg=NULL;
|
|
|
|
// Internal function prototypes
|
|
INT_PTR CALLBACK
|
|
RTDlgProc (
|
|
HWND hDlg,
|
|
UINT uMsg,
|
|
WPARAM wParam,
|
|
LPARAM lParam
|
|
);
|
|
|
|
INT
|
|
PrintRoute (
|
|
char *buffer,
|
|
PRTM_ROUTE_NODE node,
|
|
BOOLEAN full
|
|
);
|
|
|
|
VOID
|
|
FillUpRouteLB (
|
|
);
|
|
|
|
|
|
|
|
#define DLLInstanceHdl ((HANDLE)param)
|
|
DWORD WINAPI
|
|
RTDialogThread (
|
|
LPVOID param
|
|
) {
|
|
MSG msg;
|
|
DWORD status;
|
|
BOOLEAN Done = FALSE;
|
|
HANDLE RegChangeEvt;
|
|
HKEY regHdl;
|
|
DWORD length, disposition, value;
|
|
|
|
|
|
RegChangeEvt = CreateEvent (NULL, FALSE, TRUE, NULL);
|
|
ASSERTERR (RegChangeEvt!=NULL);
|
|
|
|
status = RegCreateKeyEx (HKEY_LOCAL_MACHINE,
|
|
TEXT ("System\\CurrentControlSet\\Services\\RemoteAccess\\RTM"),
|
|
0,
|
|
NULL,
|
|
REG_OPTION_NON_VOLATILE,
|
|
KEY_READ,
|
|
NULL,
|
|
®Hdl,
|
|
&disposition
|
|
);
|
|
ASSERTMSG ("Can't create registry key. ", status==NO_ERROR);
|
|
|
|
length = sizeof (DWORD);
|
|
status = RegQueryValueEx (regHdl, TicksWrapAroundValueName, NULL, NULL,
|
|
(PUCHAR)&value, &length);
|
|
|
|
if (status==NO_ERROR)
|
|
MaxTicks = value;
|
|
|
|
length = sizeof (DWORD);
|
|
status = RegQueryValueEx (regHdl, MaxMessagesValueName, NULL, NULL,
|
|
(PUCHAR)&value, &length);
|
|
|
|
if (status==NO_ERROR)
|
|
MaxMessages = value;
|
|
|
|
while (!Done) {
|
|
status = MsgWaitForMultipleObjects (1, &RegChangeEvt,
|
|
FALSE, INFINITE, QS_ALLINPUT);
|
|
if (status==(WAIT_OBJECT_0+1)) {
|
|
while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) {
|
|
if (msg.message==WM_QUIT) {
|
|
Done = TRUE;
|
|
break;
|
|
}
|
|
else if (!IsWindow(RTDlg)
|
|
|| !IsDialogMessage(RTDlg, &msg)) {
|
|
TranslateMessage (&msg);
|
|
DispatchMessage (&msg);
|
|
}
|
|
}
|
|
}
|
|
else if (status==WAIT_OBJECT_0) {
|
|
length = sizeof (DWORD);
|
|
status = RegQueryValueEx (regHdl, DbgLevelValueName, NULL, NULL,
|
|
(PUCHAR)&DbgLevel, &length);
|
|
if (status!=NO_ERROR)
|
|
DbgLevel = 0;
|
|
|
|
IF_DEBUG (DISPLAY_TABLE) {
|
|
if (!IsWindow(RTDlg)) {
|
|
RTDlg = CreateDialog (DLLInstanceHdl,
|
|
MAKEINTRESOURCE (IDD_RTM_TABLE),
|
|
NULL,
|
|
&RTDlgProc);
|
|
|
|
ASSERTERR (RTDlg!=NULL);
|
|
}
|
|
}
|
|
else {
|
|
if (IsWindow (RTDlg)) {
|
|
DestroyWindow (RTDlg);
|
|
RTDlg = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
status = RegNotifyChangeKeyValue (regHdl,
|
|
FALSE,
|
|
REG_NOTIFY_CHANGE_LAST_SET,
|
|
RegChangeEvt,
|
|
TRUE);
|
|
ASSERTMSG ("Can't start registry notifications. ",
|
|
status==NO_ERROR);
|
|
}
|
|
}
|
|
|
|
if (IsWindow (RTDlg)) {
|
|
DestroyWindow (RTDlg);
|
|
RTDlg = NULL;
|
|
}
|
|
RegCloseKey (regHdl);
|
|
return 0;
|
|
}
|
|
#undef DLLInstanceHdl
|
|
|
|
// Dialog box procedure
|
|
INT_PTR CALLBACK
|
|
RTDlgProc (
|
|
HWND hDlg,
|
|
UINT uMsg,
|
|
WPARAM wParam,
|
|
LPARAM lParam
|
|
) {
|
|
BOOL res = FALSE;
|
|
char buf[32];
|
|
int idx;
|
|
TIMER_BASIC_INFORMATION TimerInfo;
|
|
DWORD status;
|
|
|
|
switch (uMsg) {
|
|
case WM_INITDIALOG: // Dialog is being created
|
|
// Fill in protocol family combo box
|
|
SendDlgItemMessage (hDlg,
|
|
IDC_PROTOCOL_FAMILY,
|
|
CB_INSERTSTRING,
|
|
RTM_PROTOCOL_FAMILY_IPX,
|
|
(LPARAM)"IPX"
|
|
);
|
|
|
|
SendDlgItemMessage (hDlg,
|
|
IDC_PROTOCOL_FAMILY,
|
|
CB_INSERTSTRING,
|
|
RTM_PROTOCOL_FAMILY_IP,
|
|
(LPARAM)"IP"
|
|
);
|
|
|
|
DisplayedTableIdx = RTM_PROTOCOL_FAMILY_IPX;
|
|
SendDlgItemMessage (hDlg,
|
|
IDC_PROTOCOL_FAMILY,
|
|
CB_SETCURSEL,
|
|
DisplayedTableIdx,
|
|
0
|
|
);
|
|
|
|
// Start timer (updates improvized clock)
|
|
SetTimer (hDlg, 0, 1000, NULL);
|
|
|
|
res = TRUE;
|
|
break;
|
|
|
|
case WM_COMMAND: // Process child window messages only
|
|
switch (LOWORD(wParam)) {
|
|
case IDCANCEL:
|
|
res = FALSE;
|
|
break;
|
|
case IDC_PROTOCOL_FAMILY:
|
|
if (HIWORD(wParam)==CBN_SELENDOK) {
|
|
DWORD newFamily = (DWORD)SendMessage (
|
|
(HWND)lParam,
|
|
CB_GETCURSEL,
|
|
0, 0);
|
|
if ((newFamily!=CB_ERR)
|
|
&& (newFamily!=DisplayedTableIdx)) {
|
|
// Change the displayed table if
|
|
// user makes different selection
|
|
DisplayedTableIdx = newFamily;
|
|
SendDlgItemMessage (hDlg,
|
|
IDL_ROUTES,
|
|
LB_RESETCONTENT,
|
|
0, 0);
|
|
if (Tables[DisplayedTableIdx].RT_Heap!=NULL) {
|
|
ConsolidateNetNumberLists (&Tables[DisplayedTableIdx]);
|
|
FillUpRouteLB ();
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
// case IDL_ROUTES:
|
|
// // Update entry on which user double clicks
|
|
// if (HIWORD(wParam)==LBN_SELCHANGE)
|
|
// UpdateLBSelections ();
|
|
// break;
|
|
case IDB_RESYNC:
|
|
SendDlgItemMessage (hDlg,
|
|
IDL_ROUTES,
|
|
LB_RESETCONTENT,
|
|
0, 0);
|
|
if (Tables[DisplayedTableIdx].RT_Heap!=NULL) {
|
|
ConsolidateNetNumberLists (&Tables[DisplayedTableIdx]);
|
|
FillUpRouteLB ();
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case WM_TIMER:
|
|
// Update improvised clock
|
|
sprintf (buf, "%08d", GetTickCount ()/1000);
|
|
SendDlgItemMessage (hDlg, IDT_TICK_COUNT, WM_SETTEXT,
|
|
0, (LPARAM)buf);
|
|
status = NtQueryTimer (
|
|
Tables[DisplayedTableIdx].RT_ExpirationTimer,
|
|
TimerBasicInformation,
|
|
&TimerInfo,
|
|
sizeof (TimerInfo),
|
|
NULL);
|
|
if (NT_SUCCESS (status)) {
|
|
if (!TimerInfo.TimerState)
|
|
sprintf (buf, "%08d",
|
|
(ULONG)((LONGLONG)TimerInfo.RemainingTime.QuadPart
|
|
/(10000*1000)));
|
|
else
|
|
sprintf (buf, "Not set");
|
|
}
|
|
else
|
|
sprintf (buf, "error");
|
|
SendDlgItemMessage (hDlg, IDT_EXPIRATION, WM_SETTEXT,
|
|
0, (LPARAM)buf);
|
|
|
|
status = NtQueryTimer (
|
|
Tables[DisplayedTableIdx].RT_UpdateTimer,
|
|
TimerBasicInformation,
|
|
&TimerInfo,
|
|
sizeof (TimerInfo),
|
|
NULL);
|
|
if (NT_SUCCESS (status)) {
|
|
if (!TimerInfo.TimerState)
|
|
sprintf (buf, "%08d",
|
|
(ULONG)((LONGLONG)TimerInfo.RemainingTime.QuadPart
|
|
/(10000*1000)));
|
|
else
|
|
sprintf (buf, "Not set");
|
|
}
|
|
else
|
|
sprintf (buf, "error");
|
|
SendDlgItemMessage (hDlg, IDT_UPDATE, WM_SETTEXT,
|
|
0, (LPARAM)buf);
|
|
res = TRUE;
|
|
break;
|
|
case RT_ADDROUTE:
|
|
SendDlgItemMessage (hDlg, IDL_ROUTES,
|
|
LB_INSERTSTRING, wParam, lParam);
|
|
// Trace2 (ANY, "%2d - %s added\n", wParam, lParam);
|
|
GlobalFree ((VOID *)lParam);
|
|
res = TRUE;
|
|
break;
|
|
|
|
case RT_DELETEROUTE:
|
|
idx = (int) SendDlgItemMessage (hDlg, IDL_ROUTES,
|
|
LB_FINDSTRING, (WPARAM)0, lParam);
|
|
if (idx!=LB_ERR)
|
|
SendDlgItemMessage (hDlg, IDL_ROUTES,
|
|
LB_DELETESTRING, (WPARAM)idx, 0);
|
|
// Trace2 (ANY, "%2d - %s deleted\n", idx, lParam);
|
|
GlobalFree ((VOID *)lParam);
|
|
res = TRUE;
|
|
break;
|
|
case WM_DESTROY:
|
|
DisplayedTableIdx = 0xFFFFFFFF;
|
|
break;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
|
|
// Prints route information
|
|
INT
|
|
PrintRoute (
|
|
char *buf, // Buffer to print to
|
|
PRTM_ROUTE_NODE node, // Route to print
|
|
BOOLEAN full // Print everything (including variable part)
|
|
) {
|
|
INT res;
|
|
|
|
switch (DisplayedTableIdx) {
|
|
case RTM_PROTOCOL_FAMILY_IPX:
|
|
res = sprintf (buf,
|
|
" %08x ",
|
|
((PRTM_IPX_ROUTE)&node->RN_Route)->IPX_NET_NUM
|
|
);
|
|
break;
|
|
|
|
case RTM_PROTOCOL_FAMILY_IP:
|
|
res = sprintf (buf,
|
|
"%08x-%08x",
|
|
((PRTM_IP_ROUTE)&node->RN_Route)->IP_NET_NUM,
|
|
((PRTM_IP_ROUTE)&node->RN_Route)->IP_NET_MSK
|
|
);
|
|
break;
|
|
}
|
|
res += sprintf (&buf[res],
|
|
" %4d %4d",
|
|
node->RN_Route.XX_INTERFACE,
|
|
node->RN_Route.XX_PROTOCOL);
|
|
|
|
switch (DisplayedTableIdx) {
|
|
case RTM_PROTOCOL_FAMILY_IPX:
|
|
res += sprintf (&buf[res],
|
|
" %02x%02x%02x%02x%02x%02x ",
|
|
((PRTM_IPX_ROUTE)&node->RN_Route)->IPX_NEXT_HOP_MAC[0],
|
|
((PRTM_IPX_ROUTE)&node->RN_Route)->IPX_NEXT_HOP_MAC[1],
|
|
((PRTM_IPX_ROUTE)&node->RN_Route)->IPX_NEXT_HOP_MAC[2],
|
|
((PRTM_IPX_ROUTE)&node->RN_Route)->IPX_NEXT_HOP_MAC[3],
|
|
((PRTM_IPX_ROUTE)&node->RN_Route)->IPX_NEXT_HOP_MAC[4],
|
|
((PRTM_IPX_ROUTE)&node->RN_Route)->IPX_NEXT_HOP_MAC[5]
|
|
);
|
|
break;
|
|
|
|
case RTM_PROTOCOL_FAMILY_IP:
|
|
res += sprintf (&buf[res],
|
|
" %08x-%08x",
|
|
((PRTM_IP_ROUTE)&node->RN_Route)->IP_NEXT_HOP_NUM,
|
|
((PRTM_IP_ROUTE)&node->RN_Route)->IP_NEXT_HOP_MSK
|
|
);
|
|
break;
|
|
}
|
|
|
|
if (full) {
|
|
switch (DisplayedTableIdx) {
|
|
case RTM_PROTOCOL_FAMILY_IPX:
|
|
res += sprintf (&buf[res],
|
|
" %6d %08d %1d %1d",
|
|
((PRTM_IPX_ROUTE)&node->RN_Route)->IPX_METRIC,
|
|
node->RN_ExpirationTime/1000,
|
|
IsBest (node),
|
|
IsEnabled (node));
|
|
break;
|
|
case RTM_PROTOCOL_FAMILY_IP:
|
|
res += sprintf (&buf[res],
|
|
" %6d %08d %1d %1d",
|
|
((PRTM_IP_ROUTE)&node->RN_Route)->IP_METRIC,
|
|
node->RN_ExpirationTime/1000,
|
|
IsBest (node),
|
|
IsEnabled (node));
|
|
break;
|
|
}
|
|
}
|
|
return res;
|
|
}
|
|
|
|
|
|
// Fills list box with all routes in the current table
|
|
VOID
|
|
FillUpRouteLB (
|
|
void
|
|
) {
|
|
PLIST_ENTRY cur;
|
|
INT idx=0;
|
|
PRTM_TABLE Table = &Tables[DisplayedTableIdx];
|
|
|
|
// Make sure we own the table while printing
|
|
EnterSyncList (Table, &Table->RT_NetNumberMasterList, TRUE);
|
|
cur = Table->RT_NetNumberMasterList.RSL_Head.Flink;
|
|
|
|
while (cur!=&Table->RT_NetNumberMasterList.RSL_Head) {
|
|
PRTM_ROUTE_NODE node = CONTAINING_RECORD (cur,
|
|
RTM_ROUTE_NODE,
|
|
RN_Links[RTM_NET_NUMBER_LIST_LINK]);
|
|
if (!IsEnumerator (node))
|
|
AddRouteToLB (Table, node, idx++);
|
|
|
|
cur = cur->Flink;
|
|
}
|
|
|
|
LeaveSyncList (Table, &Table->RT_NetNumberMasterList);
|
|
}
|
|
|
|
|
|
// Insert line with item data at specified position in the list box
|
|
VOID
|
|
AddRouteToLB (
|
|
PRTM_TABLE Table,
|
|
PRTM_ROUTE_NODE node,
|
|
INT idx
|
|
) {
|
|
char *buf;
|
|
|
|
if (IsWindow (RTDlg)
|
|
&& (Table==&Tables[DisplayedTableIdx])) {
|
|
buf = (char *)GlobalAlloc (GMEM_FIXED, 80);
|
|
|
|
// Print node
|
|
PrintRoute (buf, node, TRUE);
|
|
// Insert at specified position
|
|
SendNotifyMessage (RTDlg, RT_ADDROUTE, (WPARAM)idx, (LPARAM)buf);
|
|
}
|
|
}
|
|
|
|
// Deletes route line from the list box
|
|
VOID
|
|
DeleteRouteFromLB (
|
|
PRTM_TABLE Table,
|
|
PRTM_ROUTE_NODE node
|
|
) {
|
|
char *buf;
|
|
|
|
if (IsWindow (RTDlg)
|
|
&& (Table==&Tables[DisplayedTableIdx])) {
|
|
buf = (char *)GlobalAlloc (GMEM_FIXED, 80);
|
|
|
|
// Print route info
|
|
PrintRoute (buf, node, FALSE);
|
|
// Find corresponding line in the list
|
|
SendNotifyMessage (RTDlg, RT_DELETEROUTE, 0, (LPARAM)buf);
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|