#include "inc.h" CMD_ENTRY g_rgMainCmdTable[] = { {TOKEN_ROUTE, HandleRoute}, {TOKEN_ADDRESS, HandleAddress}, {TOKEN_INTERFACE, HandleInterface}, {TOKEN_ARP, HandleArp}, }; HMODULE g_hModule; DWORD _cdecl wmain( int argc, wchar_t *argv[] ) /*++ Routine Description Locks Arguments Return Value --*/ { LONG lIndex; setlocale(LC_ALL, ""); if(argc < 2) { DisplayMessage(HMSG_IPKERN_USAGE); return ERROR; } g_hModule = GetModuleHandle(NULL); if(g_hModule is NULL) { return GetLastError(); } lIndex = ParseCommand(g_rgMainCmdTable, sizeof(g_rgMainCmdTable)/sizeof(CMD_ENTRY), argv[1]); if(lIndex is -1) { DisplayMessage(HMSG_IPKERN_USAGE); return ERROR_INVALID_PARAMETER; } g_rgMainCmdTable[lIndex].pfnHandler(argc - 1, &argv[1]); return NO_ERROR; } BOOL MatchToken( IN PWCHAR pwszToken, IN DWORD dwTokenId ) { WCHAR pwszTemp[MAX_TOKEN_LENGTH] = L"\0"; if(!LoadStringW(g_hModule, dwTokenId, pwszTemp, MAX_TOKEN_LENGTH)) { return FALSE; } if(!_wcsicmp(pwszToken, pwszTemp)) { return TRUE; } return FALSE; } LONG ParseCommand( PCMD_ENTRY pCmdTable, LONG lNumEntries, PWCHAR pwszFirstArg ) { LONG i; for(i = 0; i < lNumEntries; i++) { if(MatchToken(pwszFirstArg, pCmdTable[i].dwTokenId)) { return i; } } return -1; } DWORD DisplayMessage( DWORD dwMsgId, ... ) { DWORD dwMsglen = 0; PWCHAR pwszOutput; va_list arglist; WCHAR rgwcInput[MAX_MSG_LENGTH]; pwszOutput = NULL; do { va_start(arglist, dwMsgId); if(!LoadStringW(g_hModule, dwMsgId, rgwcInput, MAX_MSG_LENGTH)) { break; } dwMsglen = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING, rgwcInput, 0, 0L, (PWCHAR)&pwszOutput, 0, &arglist); if(dwMsglen is 0) { break; } wprintf( L"%s", pwszOutput ); }while(FALSE); if(pwszOutput) { LocalFree(pwszOutput); } return dwMsglen; } PWCHAR MakeString( DWORD dwMsgId, ... ) { DWORD dwMsglen; PWCHAR pwszOutput; va_list arglist; WCHAR rgwcInput[MAX_MSG_LENGTH]; pwszOutput = NULL; do { va_start(arglist, dwMsgId); if(!LoadStringW(g_hModule, dwMsgId, rgwcInput, MAX_MSG_LENGTH)) { break; } FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_STRING, rgwcInput, 0, 0L, // Default country ID. (PWCHAR)&pwszOutput, 0, &arglist); }while(FALSE); return pwszOutput; } VOID FreeString( PWCHAR pwszString ) { LocalFree(pwszString); } // // This preinitialized array defines the strings to be used. // The index of each row corresponds to the value for a byte // in an IP address. The first three bytes of each row are the // char/string value for the byte, and the fourth byte in each row is // the length of the string required for the byte. This approach // allows a fast implementation with no jumps. // static const WCHAR NToUWCharStrings[][4] = { L'0', L'x', L'x', 1, L'1', L'x', L'x', 1, L'2', L'x', L'x', 1, L'3', L'x', L'x', 1, L'4', L'x', L'x', 1, L'5', L'x', L'x', 1, L'6', L'x', L'x', 1, L'7', L'x', L'x', 1, L'8', L'x', L'x', 1, L'9', L'x', L'x', 1, L'1', L'0', L'x', 2, L'1', L'1', L'x', 2, L'1', L'2', L'x', 2, L'1', L'3', L'x', 2, L'1', L'4', L'x', 2, L'1', L'5', L'x', 2, L'1', L'6', L'x', 2, L'1', L'7', L'x', 2, L'1', L'8', L'x', 2, L'1', L'9', L'x', 2, L'2', L'0', L'x', 2, L'2', L'1', L'x', 2, L'2', L'2', L'x', 2, L'2', L'3', L'x', 2, L'2', L'4', L'x', 2, L'2', L'5', L'x', 2, L'2', L'6', L'x', 2, L'2', L'7', L'x', 2, L'2', L'8', L'x', 2, L'2', L'9', L'x', 2, L'3', L'0', L'x', 2, L'3', L'1', L'x', 2, L'3', L'2', L'x', 2, L'3', L'3', L'x', 2, L'3', L'4', L'x', 2, L'3', L'5', L'x', 2, L'3', L'6', L'x', 2, L'3', L'7', L'x', 2, L'3', L'8', L'x', 2, L'3', L'9', L'x', 2, L'4', L'0', L'x', 2, L'4', L'1', L'x', 2, L'4', L'2', L'x', 2, L'4', L'3', L'x', 2, L'4', L'4', L'x', 2, L'4', L'5', L'x', 2, L'4', L'6', L'x', 2, L'4', L'7', L'x', 2, L'4', L'8', L'x', 2, L'4', L'9', L'x', 2, L'5', L'0', L'x', 2, L'5', L'1', L'x', 2, L'5', L'2', L'x', 2, L'5', L'3', L'x', 2, L'5', L'4', L'x', 2, L'5', L'5', L'x', 2, L'5', L'6', L'x', 2, L'5', L'7', L'x', 2, L'5', L'8', L'x', 2, L'5', L'9', L'x', 2, L'6', L'0', L'x', 2, L'6', L'1', L'x', 2, L'6', L'2', L'x', 2, L'6', L'3', L'x', 2, L'6', L'4', L'x', 2, L'6', L'5', L'x', 2, L'6', L'6', L'x', 2, L'6', L'7', L'x', 2, L'6', L'8', L'x', 2, L'6', L'9', L'x', 2, L'7', L'0', L'x', 2, L'7', L'1', L'x', 2, L'7', L'2', L'x', 2, L'7', L'3', L'x', 2, L'7', L'4', L'x', 2, L'7', L'5', L'x', 2, L'7', L'6', L'x', 2, L'7', L'7', L'x', 2, L'7', L'8', L'x', 2, L'7', L'9', L'x', 2, L'8', L'0', L'x', 2, L'8', L'1', L'x', 2, L'8', L'2', L'x', 2, L'8', L'3', L'x', 2, L'8', L'4', L'x', 2, L'8', L'5', L'x', 2, L'8', L'6', L'x', 2, L'8', L'7', L'x', 2, L'8', L'8', L'x', 2, L'8', L'9', L'x', 2, L'9', L'0', L'x', 2, L'9', L'1', L'x', 2, L'9', L'2', L'x', 2, L'9', L'3', L'x', 2, L'9', L'4', L'x', 2, L'9', L'5', L'x', 2, L'9', L'6', L'x', 2, L'9', L'7', L'x', 2, L'9', L'8', L'x', 2, L'9', L'9', L'x', 2, L'1', L'0', L'0', 3, L'1', L'0', L'1', 3, L'1', L'0', L'2', 3, L'1', L'0', L'3', 3, L'1', L'0', L'4', 3, L'1', L'0', L'5', 3, L'1', L'0', L'6', 3, L'1', L'0', L'7', 3, L'1', L'0', L'8', 3, L'1', L'0', L'9', 3, L'1', L'1', L'0', 3, L'1', L'1', L'1', 3, L'1', L'1', L'2', 3, L'1', L'1', L'3', 3, L'1', L'1', L'4', 3, L'1', L'1', L'5', 3, L'1', L'1', L'6', 3, L'1', L'1', L'7', 3, L'1', L'1', L'8', 3, L'1', L'1', L'9', 3, L'1', L'2', L'0', 3, L'1', L'2', L'1', 3, L'1', L'2', L'2', 3, L'1', L'2', L'3', 3, L'1', L'2', L'4', 3, L'1', L'2', L'5', 3, L'1', L'2', L'6', 3, L'1', L'2', L'7', 3, L'1', L'2', L'8', 3, L'1', L'2', L'9', 3, L'1', L'3', L'0', 3, L'1', L'3', L'1', 3, L'1', L'3', L'2', 3, L'1', L'3', L'3', 3, L'1', L'3', L'4', 3, L'1', L'3', L'5', 3, L'1', L'3', L'6', 3, L'1', L'3', L'7', 3, L'1', L'3', L'8', 3, L'1', L'3', L'9', 3, L'1', L'4', L'0', 3, L'1', L'4', L'1', 3, L'1', L'4', L'2', 3, L'1', L'4', L'3', 3, L'1', L'4', L'4', 3, L'1', L'4', L'5', 3, L'1', L'4', L'6', 3, L'1', L'4', L'7', 3, L'1', L'4', L'8', 3, L'1', L'4', L'9', 3, L'1', L'5', L'0', 3, L'1', L'5', L'1', 3, L'1', L'5', L'2', 3, L'1', L'5', L'3', 3, L'1', L'5', L'4', 3, L'1', L'5', L'5', 3, L'1', L'5', L'6', 3, L'1', L'5', L'7', 3, L'1', L'5', L'8', 3, L'1', L'5', L'9', 3, L'1', L'6', L'0', 3, L'1', L'6', L'1', 3, L'1', L'6', L'2', 3, L'1', L'6', L'3', 3, L'1', L'6', L'4', 3, L'1', L'6', L'5', 3, L'1', L'6', L'6', 3, L'1', L'6', L'7', 3, L'1', L'6', L'8', 3, L'1', L'6', L'9', 3, L'1', L'7', L'0', 3, L'1', L'7', L'1', 3, L'1', L'7', L'2', 3, L'1', L'7', L'3', 3, L'1', L'7', L'4', 3, L'1', L'7', L'5', 3, L'1', L'7', L'6', 3, L'1', L'7', L'7', 3, L'1', L'7', L'8', 3, L'1', L'7', L'9', 3, L'1', L'8', L'0', 3, L'1', L'8', L'1', 3, L'1', L'8', L'2', 3, L'1', L'8', L'3', 3, L'1', L'8', L'4', 3, L'1', L'8', L'5', 3, L'1', L'8', L'6', 3, L'1', L'8', L'7', 3, L'1', L'8', L'8', 3, L'1', L'8', L'9', 3, L'1', L'9', L'0', 3, L'1', L'9', L'1', 3, L'1', L'9', L'2', 3, L'1', L'9', L'3', 3, L'1', L'9', L'4', 3, L'1', L'9', L'5', 3, L'1', L'9', L'6', 3, L'1', L'9', L'7', 3, L'1', L'9', L'8', 3, L'1', L'9', L'9', 3, L'2', L'0', L'0', 3, L'2', L'0', L'1', 3, L'2', L'0', L'2', 3, L'2', L'0', L'3', 3, L'2', L'0', L'4', 3, L'2', L'0', L'5', 3, L'2', L'0', L'6', 3, L'2', L'0', L'7', 3, L'2', L'0', L'8', 3, L'2', L'0', L'9', 3, L'2', L'1', L'0', 3, L'2', L'1', L'1', 3, L'2', L'1', L'2', 3, L'2', L'1', L'3', 3, L'2', L'1', L'4', 3, L'2', L'1', L'5', 3, L'2', L'1', L'6', 3, L'2', L'1', L'7', 3, L'2', L'1', L'8', 3, L'2', L'1', L'9', 3, L'2', L'2', L'0', 3, L'2', L'2', L'1', 3, L'2', L'2', L'2', 3, L'2', L'2', L'3', 3, L'2', L'2', L'4', 3, L'2', L'2', L'5', 3, L'2', L'2', L'6', 3, L'2', L'2', L'7', 3, L'2', L'2', L'8', 3, L'2', L'2', L'9', 3, L'2', L'3', L'0', 3, L'2', L'3', L'1', 3, L'2', L'3', L'2', 3, L'2', L'3', L'3', 3, L'2', L'3', L'4', 3, L'2', L'3', L'5', 3, L'2', L'3', L'6', 3, L'2', L'3', L'7', 3, L'2', L'3', L'8', 3, L'2', L'3', L'9', 3, L'2', L'4', L'0', 3, L'2', L'4', L'1', 3, L'2', L'4', L'2', 3, L'2', L'4', L'3', 3, L'2', L'4', L'4', 3, L'2', L'4', L'5', 3, L'2', L'4', L'6', 3, L'2', L'4', L'7', 3, L'2', L'4', L'8', 3, L'2', L'4', L'9', 3, L'2', L'5', L'0', 3, L'2', L'5', L'1', 3, L'2', L'5', L'2', 3, L'2', L'5', L'3', 3, L'2', L'5', L'4', 3, L'2', L'5', L'5', 3 }; VOID NetworkToUnicode( IN DWORD dwAddress, OUT PWCHAR pwszBuffer ) /*++ Routine Description: This function takes an Internet address structure specified by the in parameter. It returns an UNICODE string representing the address in ".'' notation as "a.b.c.d". Note that unlike inet_ntoa, this requires the user to supply a buffer. This is good because all of the TLS crap now can be thrown out - and the function is leaner and meaner. Ofcourse this does make it incompatible with inet_ntoa since the parameters are different. And it makes it less safe since bad buffers will cause an a.v. Arguments: iaAddress A structure which represents an Internet host address. pwszBufer User supplied buffer to ATLEAST WCHAR[16]. Since there is no try/except - you will crash if you dont supply a "good" buffer. The formatted address is returned in this buffer Return Value: None --*/ { PBYTE p; PWCHAR b; b = pwszBuffer; // // In an unrolled loop, calculate the string value for each of the four // bytes in an IP address. Note that for values less than 100 we will // do one or two extra assignments, but we save a test/jump with this // algorithm. // p = (PBYTE)&dwAddress; *b = NToUWCharStrings[*p][0]; *(b+1) = NToUWCharStrings[*p][1]; *(b+2) = NToUWCharStrings[*p][2]; b += NToUWCharStrings[*p][3]; *b++ = L'.'; p++; *b = NToUWCharStrings[*p][0]; *(b+1) = NToUWCharStrings[*p][1]; *(b+2) = NToUWCharStrings[*p][2]; b += NToUWCharStrings[*p][3]; *b++ = L'.'; p++; *b = NToUWCharStrings[*p][0]; *(b+1) = NToUWCharStrings[*p][1]; *(b+2) = NToUWCharStrings[*p][2]; b += NToUWCharStrings[*p][3]; *b++ = L'.'; p++; *b = NToUWCharStrings[*p][0]; *(b+1) = NToUWCharStrings[*p][1]; *(b+2) = NToUWCharStrings[*p][2]; b += NToUWCharStrings[*p][3]; *b = UNICODE_NULL; } DWORD UnicodeToNetwork( PWCHAR pwszAddr ) { CHAR szAddr[MAX_TOKEN_LENGTH + 1]; INT iCount; iCount = WideCharToMultiByte(CP_ACP, 0, pwszAddr, wcslen(pwszAddr), szAddr, MAX_TOKEN_LENGTH, NULL, NULL); szAddr[iCount] = '\0'; return inet_addr(szAddr); }