/*++ Copyright (c) 1998 Microsoft Corporation Module Name: routing\netsh\shell\utils.c Abstract: Utilities. Revision History: 6/12/96 V Raman --*/ #include "precomp.h" #include #include #define STOP_EVENT L"NetshStopRefreshEvent" extern HANDLE g_hModule; BOOL WINAPI MatchCmdLine( IN LPWSTR *ppwcArguments, IN DWORD dwArgCount, IN LPCWSTR pwszCmdToken, OUT PDWORD pdwNumMatched ) { LPCWSTR pwcToken; DWORD dwCount; WCHAR wcszBuffer[256]; // // Compare the two strings // dwCount = 0; if (!ppwcArguments || !pwszCmdToken || !pdwNumMatched) { return FALSE; } *pdwNumMatched = 0; // init OUT parameter if ( (wcslen(pwszCmdToken) + 1) > (sizeof(wcszBuffer)/sizeof(wcszBuffer[0])) ) { // incoming command string is too large for processing return FALSE; } // copy into a buffer which wcstok can munge wcscpy(wcszBuffer, pwszCmdToken); if((pwcToken = wcstok(wcszBuffer, NETSH_CMD_DELIMITER)) != NULL) { do { if (dwCount < dwArgCount && (_wcsnicmp(ppwcArguments[dwCount], pwcToken, wcslen(ppwcArguments[dwCount])) == 0)) { dwCount++; } else { return FALSE; } } while((pwcToken = wcstok((LPWSTR) NULL, NETSH_CMD_DELIMITER )) != NULL); } *pdwNumMatched = dwCount; return TRUE; } #if 0 BOOL WINAPI MatchCmdTokenId( IN HANDLE hModule, IN LPCWSTR *ppwcArguments, IN DWORD dwArgCount, IN DWORD dwCmdId, OUT PDWORD pdwNumMatched ) /*++ Routine Description: Tries to match a command in the given command line. The function takes the id of the command of the command message. A command message consists of command words separated by white space. The function tokenises this messages into separate words and then tries to match the first N arguments against the N separate tokens that constitute the command. e.g if the command is "add if neighbour" - the function will generate 3 tokens "add" "if" and "neighbour". It will then try and match the all these to the given arg array. Arguments: ppwcArguments - Argument array dwArgCount - Number of arguments dwTokenId - Token Id of command pdwNumMatched - Number of arguments matched in the array Return Value: TRUE if matched else FALSE --*/ { WCHAR pwszTemp[NETSH_MAX_CMD_TOKEN_LENGTH]; LPCWSTR pwcToken; DWORD dwCount; if(!LoadStringW(hModule, dwCmdId, pwszTemp, NETSH_MAX_CMD_TOKEN_LENGTH) ) { return FALSE; } // // Compare the two strings // dwCount = 0; if((pwcToken = wcstok(pwszTemp, NETSH_CMD_DELIMITER)) != NULL) { do { if (dwCount < dwArgCount && (_wcsnicmp(ppwcArguments[dwCount], pwcToken, wcslen(ppwcArguments[dwCount])) == 0)) { dwCount++; } else { *pdwNumMatched = 0; return FALSE; } } while((pwcToken = wcstok((LPCWSTR) NULL, NETSH_CMD_DELIMITER )) != NULL); } *pdwNumMatched = dwCount; return TRUE; } #endif DWORD WINAPI MatchEnumTag( IN HANDLE hModule, IN LPCWSTR pwcArg, IN DWORD dwNumArg, IN CONST TOKEN_VALUE *pEnumTable, OUT PDWORD pdwValue ) /*++ Routine Description: Used for options that take a specific set of values. Matches argument with the set of values specified and returns corresponding value. Arguments: pwcArg - Argument dwNumArg - Number of possible values. Return Value: NO_ERROR ERROR_NOT_FOUND --*/ { DWORD i; if ( (!pdwValue) || (!pEnumTable) ) { return ERROR_INVALID_PARAMETER; } for (i = 0; i < dwNumArg; i++) { if (MatchToken(pwcArg, pEnumTable[i].pwszToken)) { *pdwValue = pEnumTable[i].dwValue; return NO_ERROR; } } return ERROR_NOT_FOUND; } DWORD MatchTagsInCmdLine( IN HANDLE hModule, IN OUT LPWSTR *ppwcArguments, IN DWORD dwCurrentIndex, IN DWORD dwArgCount, IN OUT PTAG_TYPE pttTagToken, IN DWORD dwNumTags, OUT PDWORD pdwOut ) /*++ Routine Description: Identifies each argument based on its tag. It also removes tag= from each argument. It also sets the bPresent flag in the tags present. Arguments: ppwcArguments - The argument array. Each argument has tag=value form dwCurrentIndex - ppwcArguments[dwCurrentIndex] is first arg. dwArgCount - ppwcArguments[dwArgCount - 1] is last arg. pttTagToken - Array of tag token ids that are allowed in the args dwNumTags - Size of pttTagToken pdwOut - Array identifying the type of each argument, where pdwOut[0] is for ppwcArguments[dwCurrentIndex] Return Value: NO_ERROR, ERROR_INVALID_PARAMETER, ERROR_INVALID_OPTION_TAG --*/ { DWORD i,j,len; LPCWSTR pwcTag; LPWSTR pwcTagVal, pwszArg; BOOL bFound = FALSE; // // This function assumes that every argument has a tag // It goes ahead and removes the tag. // for (i = dwCurrentIndex; i < dwArgCount; i++) { if (!wcspbrk(ppwcArguments[i], NETSH_ARG_DELIMITER)) { pdwOut[i - dwCurrentIndex] = (DWORD) -2; continue; } len = wcslen(ppwcArguments[i]); if (len is 0) { // // something wrong with arg // pdwOut[i - dwCurrentIndex] = (DWORD) -1; continue; } pwszArg = HeapAlloc(GetProcessHeap(),0,(len + 1) * sizeof(WCHAR)); if (pwszArg is NULL) { PrintMessageFromModule(g_hModule, MSG_NOT_ENOUGH_MEMORY); return ERROR_NOT_ENOUGH_MEMORY; } wcscpy(pwszArg, ppwcArguments[i]); pwcTag = wcstok(pwszArg, NETSH_ARG_DELIMITER); // // Got the first part // Now if next call returns NULL then there was no tag // pwcTagVal = wcstok((LPWSTR)NULL, NETSH_ARG_DELIMITER); if (pwcTagVal is NULL) { PrintMessageFromModule(g_hModule, ERROR_NO_TAG, ppwcArguments[i]); HeapFree(GetProcessHeap(),0,pwszArg); return ERROR_INVALID_PARAMETER; } // // Got the tag. Now try to match it // bFound = FALSE; pdwOut[i - dwCurrentIndex] = (DWORD) -1; for ( j = 0; j < dwNumTags; j++) { if (MatchToken(pwcTag, pttTagToken[j].pwszTag)) { // // Tag matched // if (pttTagToken[j].bPresent && !(pttTagToken[j].dwRequired & NS_REQ_ALLOW_MULTIPLE)) { HeapFree(GetProcessHeap(),0,pwszArg); PrintMessageFromModule(g_hModule, ERROR_TAG_ALREADY_PRESENT, pwcTag); return ERROR_TAG_ALREADY_PRESENT; } bFound = TRUE; pdwOut[i - dwCurrentIndex] = j; pttTagToken[j].bPresent = TRUE; break; } } if (bFound) { // // Remove tag from the argument // wcscpy(ppwcArguments[i], pwcTagVal); } else { PrintMessageFromModule(g_hModule, ERROR_INVALID_OPTION_TAG, pwcTag); HeapFree(GetProcessHeap(),0,pwszArg); return ERROR_INVALID_OPTION_TAG; } HeapFree(GetProcessHeap(),0,pwszArg); } // Now tag all untagged arguments for (i = dwCurrentIndex; i < dwArgCount; i++) { if ( pdwOut[i - dwCurrentIndex] != -2) { continue; } bFound = FALSE; for ( j = 0; j < dwNumTags; j++) { if (!pttTagToken[j].bPresent) { bFound = TRUE; pdwOut[i - dwCurrentIndex] = j; pttTagToken[j].bPresent = TRUE; break; } } if (!bFound) { pdwOut[i - dwCurrentIndex] = (DWORD) -1; } } return NO_ERROR; } BOOL WINAPI MatchToken( IN LPCWSTR pwszUserToken, IN LPCWSTR pwszCmdToken ) { if ( (!pwszUserToken) || (!pwszCmdToken) ) { return ERROR_INVALID_PARAMETER; } return !_wcsnicmp(pwszUserToken, pwszCmdToken, wcslen(pwszUserToken)); } BOOL WINAPI MatchTokenId( // changed this name since I don't think anything will use it IN HANDLE hModule, IN LPCWSTR pwszToken, IN DWORD dwTokenId ) /*++ Routine Description: Sees if the given string and the string corresponding to dwTokenId are the same. Arguments: pwszToken - Token string dwTokenId - Token Id Return Value: TRUE is matched else FALSE --*/ { WCHAR pwszTemp[NETSH_MAX_TOKEN_LENGTH]; if(!LoadStringW(hModule, dwTokenId, pwszTemp, NETSH_MAX_TOKEN_LENGTH)) { return FALSE; } return MatchToken(pwszToken, pwszTemp); } extern HANDLE g_hLogFile; //+-------------------------------------------------------------------------- // // Function: GetPasswdStr // // Synopsis: Reads a password string from stdin without echoing the keystrokes // // Arguments: [buf - OUT] : buffer to put string in // [buflen - IN] : size of the buffer // [&len - OUT] : length of the string placed into the buffer // // Returns: DWORD : 0 or ERROR_INSUFFICIENT_BUFFER if user typed too much. // Buffer contents are only valid on 0 return. // // History: 07-Dec-2001 deonb Copied from dscmd parseutil.cpp sources // 07-Sep-2000 JeffJon Created // //--------------------------------------------------------------------------- #define CR 0xD #define BACKSPACE 0x8 DWORD GetPasswdStr(IN LPTSTR buf, IN DWORD buflen, IN PDWORD len) { TCHAR ch; TCHAR *bufPtr = buf; DWORD c; int err; DWORD mode; buflen -= 1; /* make space for null terminator */ *len = 0; /* GP fault probe (a la API's) */ GetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), &mode); SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), (~(ENABLE_ECHO_INPUT|ENABLE_LINE_INPUT)) & mode); while (TRUE) { err = ReadConsole(GetStdHandle(STD_INPUT_HANDLE), &ch, 1, &c, 0); if (!err || c != 1) ch = 0xffff; if ((ch == CR) || (ch == 0xffff)) /* end of the line */ break; if (ch == BACKSPACE) { /* back up one or two */ /* * IF bufPtr == buf then the next two lines are * a no op. */ if (bufPtr != buf) { bufPtr--; (*len)--; } } else { *bufPtr = ch; if (*len < buflen) bufPtr++ ; /* don't overflow buf */ (*len)++; /* always increment len */ } } SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), mode); *bufPtr = TEXT('\0'); /* null terminate the string */ putwchar(TEXT('\n')); return ((*len <= buflen) ? 0 : ERROR_INSUFFICIENT_BUFFER); } LPWSTR OEMfgets( OUT PDWORD pdwLen, IN FILE *fp ) { LPWSTR pwszUnicode; DWORD dwErr = NO_ERROR; DWORD dwLen; CHAR buff[MAX_CMD_LEN]; fflush(stdout); if (fgets( buff, sizeof(buff), fp ) is NULL) { return NULL; } dwLen = MultiByteToWideChar( GetConsoleOutputCP(), 0, buff, -1, NULL, 0 ); if (g_hLogFile) { DWORD dwWritten; CHAR szCrLf[] = "\r\n"; if (0 == WriteFile( g_hLogFile, buff, dwLen-2, &dwWritten, NULL )) { CloseHandle(g_hLogFile); g_hLogFile = NULL; PrintError(NULL, GetLastError()); } if (0 == WriteFile( g_hLogFile, szCrLf, 2, &dwWritten, NULL )) { CloseHandle(g_hLogFile); g_hLogFile = NULL; PrintError(NULL, GetLastError()); } } pwszUnicode = MALLOC(dwLen * sizeof(WCHAR)); if (pwszUnicode) { MultiByteToWideChar( GetConsoleOutputCP(), 0, buff, sizeof(buff), pwszUnicode, dwLen ); } *pdwLen = dwLen; return pwszUnicode; } VOID OEMfprintf( IN HANDLE hHandle, IN LPCWSTR pwszUnicode ) { PCHAR achOem; DWORD dwLen, dwWritten; dwLen = WideCharToMultiByte( GetConsoleOutputCP(), 0, pwszUnicode, -1, NULL, 0, NULL, NULL ); achOem = MALLOC(dwLen); if (achOem) { WideCharToMultiByte( GetConsoleOutputCP(), 0, pwszUnicode, -1, achOem, dwLen, NULL, NULL ); WriteFile( hHandle, achOem, dwLen-1, &dwWritten, NULL ); if (g_hLogFile) { if (0 == WriteFile( g_hLogFile, achOem, dwLen-1, &dwWritten, NULL )) { CloseHandle(g_hLogFile); g_hLogFile = NULL; PrintError(NULL, GetLastError()); } } FREE(achOem); } } #define OEMprintf(pwszUnicode) \ OEMfprintf( GetStdHandle(STD_OUTPUT_HANDLE), pwszUnicode) LPWSTR WINAPI GetEnumString( IN HANDLE hModule, IN DWORD dwValue, IN DWORD dwNumVal, IN PTOKEN_VALUE pEnumTable ) /*++ Routine Description: This routine looks up the value specified, dwValue, in the Value table pEnumTable and returns the string corresponding to the value Arguments : hModule - handle to current module dwValue - Value whose display string is required dwNumVal - Number of elements in pEnumTable pEnumTable - Table of enumerated value and corresp. string IDs Return Value : NULL - Value not found in pEnumTable Pointer to string on success --*/ { DWORD dwInd; for ( dwInd = 0; dwInd < dwNumVal; dwInd++ ) { if ( pEnumTable[ dwInd ].dwValue == dwValue ) { // ISSUE: const_cast return (LPWSTR)pEnumTable[ dwInd ].pwszToken; } } return NULL; } LPWSTR WINAPI MakeString( IN HANDLE hModule, IN DWORD dwMsgId, ... ) { DWORD dwMsgLen; LPWSTR pwszInput, pwszOutput = NULL; va_list arglist; do { va_start( arglist, dwMsgId ); pwszInput = HeapAlloc(GetProcessHeap(), 0, MAX_MSG_LENGTH * sizeof(WCHAR) ); if ( pwszInput == NULL ) { break; } if ( !LoadStringW(hModule, dwMsgId, pwszInput, MAX_MSG_LENGTH) ) { break; } FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING, pwszInput, 0, 0L, // Default country ID. (LPWSTR)&pwszOutput, 0, &arglist); } while ( FALSE ); if ( pwszInput ) { HeapFree( GetProcessHeap(), 0, pwszInput ); } return pwszOutput; } VOID WINAPI FreeString( IN LPWSTR pwszMadeString ) /*++ Routine Description: Frees string allocated by make string. Arguments: Return Value: --*/ { LocalFree( pwszMadeString ); } LPWSTR WINAPI MakeQuotedString( IN LPCWSTR pwszOrigString ) { LPWSTR pwszNewString; pwszNewString = HeapAlloc(GetProcessHeap(), 0, (wcslen(pwszOrigString) + 3) * sizeof(WCHAR)); if(pwszNewString == NULL) { return NULL; } wsprintfW(pwszNewString, L"\"%s\"",pwszOrigString); pwszNewString[wcslen(pwszOrigString) + 2] = UNICODE_NULL; return pwszNewString; } VOID WINAPI FreeQuotedString( LPWSTR pwszString ) { HeapFree(GetProcessHeap(), 0, pwszString); } DWORD PrintError( IN HANDLE hModule, OPTIONAL IN DWORD dwErrId, ... ) /*++ Routine Description: Displays an error message. We first search for the error code in the module specified by the caller (if one is specified) If no module is given, or the error code doesnt exist we look for MPR errors, RAS errors and Win32 errors - in that order Arguments: hModule - Module to load the string from dwMsgId - Message to be printed ... - Insert strings Return Value: Message length --*/ { DWORD dwMsgLen; LPWSTR pwszOutput = NULL; WCHAR rgwcInput[MAX_MSG_LENGTH + 1]; va_list arglist; va_start(arglist, dwErrId); if(hModule) { if(LoadStringW(hModule, dwErrId, rgwcInput, MAX_MSG_LENGTH)) { // // Found the message in the callers module // dwMsgLen = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |FORMAT_MESSAGE_FROM_STRING, rgwcInput, 0, 0L, (LPWSTR)&pwszOutput, 0, &arglist); if(dwMsgLen == 0) { ASSERT(pwszOutput == NULL); } else { OEMprintf(pwszOutput); LocalFree(pwszOutput); return dwMsgLen; } } else { return 0; } } // // Next try, local errors // if((dwErrId > NETSH_ERROR_BASE) && (dwErrId < NETSH_ERROR_END)) { if(LoadStringW(g_hModule, dwErrId, rgwcInput, MAX_MSG_LENGTH)) { // // Found the message in our module // dwMsgLen = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |FORMAT_MESSAGE_FROM_STRING, rgwcInput, 0, 0L, (LPWSTR)&pwszOutput, 0, &arglist); if(dwMsgLen == 0) { ASSERT(pwszOutput == NULL); } else { OEMprintf(pwszOutput); LocalFree(pwszOutput); return dwMsgLen; } } } // // Next try MPR errors // if (MprAdminGetErrorString(dwErrId, &pwszOutput) == NO_ERROR) { wcscpy(rgwcInput, pwszOutput); LocalFree(pwszOutput); wcscat(rgwcInput, L"\r\n"); OEMprintf(rgwcInput); dwMsgLen = wcslen(rgwcInput); return dwMsgLen; } // // Next try RAS errors // if (RasGetErrorStringW(dwErrId, rgwcInput, MAX_MSG_LENGTH) == NO_ERROR) { wcscat(rgwcInput, L"\r\n"); OEMprintf(rgwcInput); dwMsgLen = wcslen(rgwcInput); return dwMsgLen; } // // Finally try Win32 // dwMsgLen = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwErrId, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), rgwcInput, MAX_MSG_LENGTH, &arglist); if(dwMsgLen) { OEMprintf(rgwcInput); return dwMsgLen; } return 0; } DWORD DisplayMessageVA( IN LPCWSTR pwszFormat, IN va_list *parglist ) { DWORD dwMsgLen = 0; LPWSTR pwszOutput = NULL; do { dwMsgLen = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |FORMAT_MESSAGE_FROM_STRING, pwszFormat, 0, 0L, // Default country ID. (LPWSTR)&pwszOutput, 0, parglist); if(dwMsgLen == 0) { // ISSUE: Unlocalized string. wprintf( L"Error %d in FormatMessageW()\n", GetLastError()); ASSERT(pwszOutput == NULL); break; } OEMprintf( pwszOutput ); } while ( FALSE ); if ( pwszOutput) { LocalFree( pwszOutput ); } return dwMsgLen; } DWORD PrintMessage( IN LPCWSTR rgwcInput, ... ) { DWORD dwMsgLen = 0; LPCWSTR pwszOutput = NULL; va_list arglist; va_start(arglist, rgwcInput); if (!rgwcInput) { return ERROR_INVALID_PARAMETER; } return DisplayMessageVA(rgwcInput, &arglist); } DWORD PrintMessageFromModule( IN HANDLE hModule, IN DWORD dwMsgId, ... ) { WCHAR rgwcInput[MAX_MSG_LENGTH + 1]; va_list arglist; if ( !LoadStringW(hModule, dwMsgId, rgwcInput, MAX_MSG_LENGTH) ) { return 0; } va_start(arglist, dwMsgId); return DisplayMessageVA(rgwcInput, &arglist); } DWORD DisplayMessageM( IN HANDLE hModule, IN DWORD dwMsgId, ... ) { DWORD dwMsgLen; LPWSTR pwszOutput = NULL; va_list arglist; do { va_start(arglist, dwMsgId); dwMsgLen = FormatMessageW( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_HMODULE, hModule, dwMsgId, 0L, (LPWSTR)&pwszOutput, 0, &arglist ); if(dwMsgLen == 0) { DWORD dwErr; dwErr = GetLastError(); ASSERT(pwszOutput == NULL); break; } OEMprintf( pwszOutput ); } while ( FALSE ); if ( pwszOutput) { LocalFree( pwszOutput ); } return dwMsgLen; } DWORD DisplayMessageToConsole( IN HANDLE hModule, IN HANDLE hConsole, IN DWORD dwMsgId, ... ) { DWORD dwMsgLen = 0; LPWSTR pwszInput, pwszOutput = NULL; va_list arglist; DWORD dwNumWritten; do { va_start(arglist, dwMsgId); pwszInput = HeapAlloc(GetProcessHeap(), 0, MAX_MSG_LENGTH * sizeof(WCHAR)); if ( pwszInput == (LPCWSTR) NULL ) { break; } if ( !LoadStringW(hModule, dwMsgId, pwszInput, MAX_MSG_LENGTH) ) { break; } dwMsgLen = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING, pwszInput, 0, 0L, // Default country ID. (LPWSTR)&pwszOutput, 0, &arglist); if ( dwMsgLen == 0 ) { break; } OEMfprintf( hConsole, pwszOutput ); fflush(stdout); } while ( FALSE ); if ( pwszInput ) { HeapFree( GetProcessHeap(), 0, pwszInput ); } if ( pwszOutput) { LocalFree( pwszOutput ); } return dwMsgLen; } BOOL WINAPI HandlerRoutine( DWORD dwCtrlType // control signal type ) { HANDLE hStop; if (dwCtrlType == CTRL_C_EVENT) { hStop = OpenEvent(EVENT_ALL_ACCESS, FALSE, STOP_EVENT); if (hStop isnot NULL) { SetEvent(hStop); CloseHandle(hStop); } return TRUE; } else { // Need to handle the other events... // CTRL_BREAK_EVENT // CTRL_CLOSE_EVENT // CTRL_LOGOFF_EVENT // Need to clean up, free all the dll's we loaded. // FreeHelpers(); FreeDlls(); // Always need to return false for these events, otherwise the app will hang. // return FALSE; } }; void cls( IN HANDLE hConsole ) { COORD coordScreen = { 0, 0 }; BOOL bSuccess; DWORD cCharsWritten; CONSOLE_SCREEN_BUFFER_INFO csbi; DWORD dwConSize; WORD wAttr; bSuccess = GetConsoleScreenBufferInfo(hConsole, &csbi); dwConSize = (WORD) csbi.dwSize.X * (WORD) csbi.dwSize.Y; bSuccess = FillConsoleOutputCharacter(hConsole, _TEXT(' '), dwConSize, coordScreen, &cCharsWritten); // // get the current text attribute // bSuccess = GetConsoleScreenBufferInfo(hConsole, &csbi); // // Make the background and foreground the same // wAttr = (csbi.wAttributes & 0xFFF0) | ((csbi.wAttributes & 0x00F0) >> 4); // // now set the buffer's attributes accordingly // bSuccess = FillConsoleOutputAttribute(hConsole, wAttr, dwConSize, coordScreen, &cCharsWritten); bSuccess = SetConsoleCursorPosition(hConsole, coordScreen); return; } BOOL WINAPI InitializeConsole( IN OUT PDWORD pdwRR, OUT HANDLE *phMib, OUT HANDLE *phConsole ) { HANDLE hMib, hStdOut, hConsole; CONSOLE_SCREEN_BUFFER_INFO csbi; hStdOut = GetStdHandle(STD_OUTPUT_HANDLE); if (hStdOut is INVALID_HANDLE_VALUE) { return FALSE; } if (!*pdwRR) { // // No refresh. Display to standard output // *phConsole = hStdOut; *phMib = (HANDLE) NULL; return TRUE; } do { hMib = CreateEvent( NULL, TRUE, FALSE, STOP_EVENT); if (hMib == NULL) { *pdwRR = 0; *phConsole = hStdOut; *phMib = (HANDLE) NULL; break; } *phMib = hMib; hConsole = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE, 0, // NO sharing NULL, CONSOLE_TEXTMODE_BUFFER, NULL); if (hConsole is INVALID_HANDLE_VALUE) { // // No refresh will be done // *pdwRR = 0; *phConsole = hStdOut; *phMib = (HANDLE) NULL; break; } else { GetConsoleScreenBufferInfo(hStdOut, &csbi); csbi.dwSize.X = 80; SetConsoleScreenBufferSize(hConsole, csbi.dwSize); SetConsoleActiveScreenBuffer(hConsole); SetConsoleCtrlHandler(HandlerRoutine,TRUE); *phConsole = hConsole; } }while (FALSE); return TRUE; } DWORD WINAPI RefreshConsole( IN HANDLE hMib, IN HANDLE hConsole, IN DWORD dwRR ) { COORD origin = {0,0}; if (dwRR) { SetConsoleCursorPosition(hConsole, origin); if (WaitForSingleObject(hMib, dwRR) == WAIT_OBJECT_0) { // // End of refresh // ResetEvent(hMib); SetConsoleCtrlHandler(HandlerRoutine,FALSE); CloseHandle(hMib); CloseHandle(hConsole); // SetConsoleActiveScreenBuffer(g_hStdOut); return FALSE; } else { // // Go in loop again // cls(hConsole); return TRUE; } } return FALSE; } #define HT_TOP 0 #define HT_CONTEXT 1 #define HT_GROUP 2 typedef struct { HANDLE hModule; LPCWSTR pwszContext; DWORD dwType; LPCWSTR pwszCommand; DWORD dwDescr; LPCWSTR pwszDescr; LPCWSTR pwszGroup; } help_t; #define MAX_HELP_COMMANDS 100 help_t help[MAX_HELP_COMMANDS]; ULONG ulNumHelpCommands = 0; DWORD FindHelpCommand( IN LPCWSTR pwszCommand ) { ULONG i; for (i=0; ipwszCommand, ((help_t*)b)->pwszCommand); } DWORD DisplayAllHelpCommands( ) { ULONG i; // Sort qsort( (void*)help, ulNumHelpCommands, sizeof(help_t), helpcmp ); for (i=0; idwFlags & ~dwDisplayFlags) { continue; } if (!VerifyOsVersion(pContext->pfnOsVersionCheck)) { continue; } PrintMessage(L" %1!s!", pContext->pwszContext); } PrintMessage(MSG_NEWLINE); } DWORD DisplayContextHelp( IN PCNS_CONTEXT_ATTRIBUTES pContext, IN DWORD dwDisplayFlags, IN DWORD dwCmdFlags, IN DWORD dwArgsRemaining, IN LPCWSTR pwszGroup ) { DWORD i, j, dwErr; PNS_HELPER_TABLE_ENTRY pHelper; ULONG ulNumContexts; DWORD dwContextSize; PBYTE pByteContexts; PNS_DLL_TABLE_ENTRY pDll; PCNS_CONTEXT_ATTRIBUTES pSubContext; LPWSTR pwszFullContextName = NULL; dwErr = GetHelperEntry(&pContext->guidHelper, &pHelper); if (dwErr) { return dwErr; } dwErr = GetDllEntry( pHelper->dwDllIndex, &pDll ); if (dwErr) { return dwErr; } dwErr = AppendFullContextName(pContext, &pwszFullContextName); ulNumContexts = pHelper->ulNumSubContexts; dwContextSize = pHelper->ulSubContextSize; pByteContexts = pHelper->pSubContextTable; // First set up flags if (dwCmdFlags & CMD_FLAG_INTERACTIVE) { dwDisplayFlags |= CMD_FLAG_INTERACTIVE; } if (dwCmdFlags & CMD_FLAG_ONLINE) { dwDisplayFlags |= CMD_FLAG_ONLINE; } if (dwCmdFlags & CMD_FLAG_LOCAL) { dwDisplayFlags |= CMD_FLAG_LOCAL; } if (IsImmediate(dwCmdFlags, dwArgsRemaining)) { dwCmdFlags |= CMD_FLAG_IMMEDIATE; } // Turn on any flags not used to limit commands // so they won't cause commands to not be displayed dwDisplayFlags |= ~CMD_FLAG_LIMIT_MASK; if (dwDisplayFlags & CMD_FLAG_PRIVATE) { PrintMessageFromModule(g_hModule, MSG_SHELL_CMD_HELP_HEADER); } // dwDisplayFlags has PRIVATE set *unless* this is called as a result of // printing help in the parent context, and non-inheritable commands // should not be printed. // // dwCmdFlags has IMMEDIATE set *unless* this is called from a parent // context, in which case parent help should not be printed. if ((!(dwDisplayFlags & CMD_FLAG_PRIVATE) || (dwCmdFlags & CMD_FLAG_IMMEDIATE))) { // Print help on inherited commands PCNS_CONTEXT_ATTRIBUTES pParentContext; dwErr = GetParentContext( pContext, &pParentContext ); if (dwErr is NO_ERROR) { dwErr = DisplayContextHelp( pParentContext, dwDisplayFlags & ~CMD_FLAG_PRIVATE, dwCmdFlags, dwArgsRemaining, pwszGroup ); } } for(i = 0; !pwszGroup && (i < pContext->ulNumTopCmds); i++) { if (((*pContext->pTopCmds)[i].dwCmdHlpToken == MSG_NULL) || ((*pContext->pTopCmds)[i].dwFlags & ~dwDisplayFlags)) { continue; } if (!VerifyOsVersion((*pContext->pTopCmds)[i].pOsVersionCheck)) { continue; } AddHelpCommand( pDll->hDll, pwszFullContextName, HT_TOP, (*pContext->pTopCmds)[i].pwszCmdToken, (*pContext->pTopCmds)[i].dwShortCmdHelpToken, NULL, NULL ); } for(i = 0; i < pContext->ulNumGroups; i++) { if (((*pContext->pCmdGroups)[i].dwShortCmdHelpToken == MSG_NULL) || ((*pContext->pCmdGroups)[i].dwFlags & ~dwDisplayFlags)) { continue; } if (!(*pContext->pCmdGroups)[i].pwszCmdGroupToken[0]) { continue; } if (pwszGroup) { if (_wcsicmp(pwszGroup, (*pContext->pCmdGroups)[i].pwszCmdGroupToken)) { continue; } if (!VerifyOsVersion((*pContext->pCmdGroups)[i].pOsVersionCheck)) { continue; } for (j = 0; j < (*pContext->pCmdGroups)[i].ulCmdGroupSize; j++) { if ((*pContext->pCmdGroups)[i].pCmdGroup[j].dwFlags & ~dwDisplayFlags) { continue; } if (!VerifyOsVersion((*pContext->pCmdGroups)[i].pCmdGroup[j].pOsVersionCheck)) { continue; } AddHelpCommand( pDll->hDll, pwszFullContextName, HT_GROUP, (*pContext->pCmdGroups)[i].pCmdGroup[j].pwszCmdToken, (*pContext->pCmdGroups)[i].pCmdGroup[j].dwShortCmdHelpToken, NULL, pwszGroup); } } else { if (!VerifyOsVersion((*pContext->pCmdGroups)[i].pOsVersionCheck)) { continue; } AddHelpCommand( pDll->hDll, pwszFullContextName, HT_GROUP, (*pContext->pCmdGroups)[i].pwszCmdGroupToken, (*pContext->pCmdGroups)[i].dwShortCmdHelpToken, NULL, NULL ); } } for (i = 0; !pwszGroup && (i < ulNumContexts); i++) { pSubContext = (PCNS_CONTEXT_ATTRIBUTES)(pByteContexts + i * dwContextSize); if ((pSubContext->dwFlags & ~dwDisplayFlags)) { continue; } if (!VerifyOsVersion(pSubContext->pfnOsVersionCheck)) { continue; } AddHelpCommand( g_hModule, pwszFullContextName, HT_CONTEXT, pSubContext->pwszContext, MSG_HELPER_HELP, pSubContext->pwszContext, NULL ); } if (dwDisplayFlags & CMD_FLAG_PRIVATE) { // Add any ubiquitous commands that aren't already added for(i = 0; !pwszGroup && (i < g_ulNumUbiqCmds); i++) { if ((g_UbiqCmds[i].dwCmdHlpToken == MSG_NULL) || (g_UbiqCmds[i].dwFlags & ~dwDisplayFlags)) { continue; } if (FindHelpCommand(g_UbiqCmds[i].pwszCmdToken) isnot -1) { continue; } AddHelpCommand( g_hModule, pwszFullContextName, HT_TOP, g_UbiqCmds[i].pwszCmdToken, g_UbiqCmds[i].dwShortCmdHelpToken, NULL, NULL ); } } if (ulNumHelpCommands > 0) { if (dwDisplayFlags & CMD_FLAG_PRIVATE) { PrintMessageFromModule( g_hModule, MSG_LOCAL_COMMANDS ); } else if (help[0].pwszContext[0]) { PrintMessageFromModule( g_hModule, MSG_INHERITED_COMMANDS, help[0].pwszContext ); } else { PrintMessageFromModule( g_hModule, MSG_GLOBAL_COMMANDS ); } DisplayAllHelpCommands(); } // Once we've popped the stack back up to the original context // in which the help command was run, display all the subcontexts // available here. if ((dwDisplayFlags & CMD_FLAG_PRIVATE) && !pwszGroup) { DisplayContextsHere( pHelper->ulNumSubContexts, pHelper->pSubContextTable, pHelper->ulSubContextSize, dwDisplayFlags ); PrintMessageFromModule( g_hModule, MSG_HELP_FOOTER, CMD_HELP2 ); } if (pwszFullContextName) { FREE(pwszFullContextName); } return NO_ERROR; } DWORD WINAPI DisplayHelp( IN CONST GUID *pguidHelper, IN LPCWSTR pwszContext, IN DWORD dwDisplayFlags, IN DWORD dwCmdFlags, IN DWORD dwArgsRemaining, IN LPCWSTR pwszGroup ) { DWORD i, j, dwErr; PCNS_CONTEXT_ATTRIBUTES pContext; PNS_HELPER_TABLE_ENTRY pHelper; // Locate helper dwErr = GetHelperEntry( pguidHelper, &pHelper ); // Locate context dwErr = GetContextEntry( pHelper, pwszContext, &pContext ); if (dwErr) { return dwErr; } return DisplayContextHelp( pContext, dwDisplayFlags, dwCmdFlags, dwArgsRemaining, pwszGroup ); } DWORD WINAPI PreprocessCommand( IN HANDLE hModule, IN OUT LPWSTR *ppwcArguments, IN DWORD dwCurrentIndex, IN DWORD dwArgCount, IN OUT PTAG_TYPE pttTags, IN DWORD dwTagCount, IN DWORD dwMinArgs, IN DWORD dwMaxArgs, OUT DWORD *pdwTagType ) /*++ Description: Make sure the number of arguments is valid. Make sure there are no duplicate or unrecognized tags. Arguments: ppwcArguments - Argument array dwCurrentIndex - ppwcArguments[dwCurrentIndex] is the first arg dwArgCount - ppwcArguments[dwArgCount - 1] is the last arg pttTags - Legal tags dwTagCount - Number of legal tags dwMinArgs - minimum # of args required dwMaxArgs - maximum # of args required pdwTagType - Index into pttTags for each argument --*/ { DWORD dwNumArgs, i; DWORD dwErr = NO_ERROR; DWORD dwTagEnum; if ( (!ppwcArguments) || (!pttTags) || (!pdwTagType) ) { return ERROR_INVALID_PARAMETER; } for (dwTagEnum = 0; dwTagEnum < dwTagCount; dwTagEnum++) { pttTags->bPresent = FALSE; } #ifdef EXTRA_DEBUG PRINT("PreHandleCommand:"); for( i = 0; i < dwArgCount; i++) { PRINT(ppwcArguments[i]); } #endif dwNumArgs = dwArgCount - dwCurrentIndex; if((dwNumArgs < dwMinArgs) or (dwNumArgs > dwMaxArgs)) { // // Wrong number of arguments specified // return ERROR_INVALID_SYNTAX; } if ( dwNumArgs > 0 ) { dwErr = MatchTagsInCmdLine(hModule, ppwcArguments, dwCurrentIndex, dwArgCount, pttTags, dwTagCount, pdwTagType); if (dwErr isnot NO_ERROR) { if (dwErr is ERROR_INVALID_OPTION_TAG) { return ERROR_INVALID_SYNTAX; } return dwErr; } } // Make sure we don't have duplicate or unrecognized tags for(i = 0; i < dwNumArgs; i ++) { if ((int) pdwTagType[i] < 0 || pdwTagType[i] >= dwTagCount) { dwErr = ERROR_INVALID_SYNTAX; break; } } switch(dwErr) { case NO_ERROR: { break; } default: { return dwErr; } } // Make sure every required tag is present for(i = 0; i < dwTagCount; i++) { if ((pttTags[i].dwRequired & NS_REQ_PRESENT) && !pttTags[i].bPresent) { PrintMessageFromModule(g_hModule, ERROR_MISSING_OPTION); return ERROR_INVALID_SYNTAX; } } return NO_ERROR; } #define HISTORY_MASK (NS_EVENT_LAST_N | NS_EVENT_FROM_N | \ NS_EVENT_FROM_START | NS_EVENT_LAST_SECS) DWORD SetupEventLogSeekPtr( OUT PHANDLE phEventLog, IN PEVENT_PRINT_INFO pEventInfo ) /*++ Routine Description: This function opens a handle to the appropriate event log and "rewinds" to the correct point as specified by the fflags. When the function returns the eventlog handle is setup such that reading the log sequentially in a forward direction will get the events the caller wants Locks: None Arguments: See above, args are passed pretty much the same Return Value: Win32 --*/ { DWORD dwResult, dwRead, dwNeed, i, dwHistoryContext; BYTE Buffer[2048]; // Huge buffer DWORD_PTR pNextEvent; BOOL bResult, bDone; LPCWSTR pwszComponent; EVENTLOGRECORD *pStartEvent; dwResult = NO_ERROR; // // Open the event log // *phEventLog = OpenEventLogW(g_pwszRouterName, pEventInfo->pwszLogName); if(*phEventLog is NULL) { return GetLastError(); } if(pEventInfo->fFlags is 0) { // // If no history is being requested, just return. Our seek ptr // will be already setup // return NO_ERROR; } if(pEventInfo->fFlags & NS_EVENT_FROM_START) { // // We can use the same matching for this as we do for NS_EVENT_FROM_N // by setting component to eventlog and dwHistoryContext to 6005 // pwszComponent = L"eventlog"; dwHistoryContext = 6005; } else { pwszComponent = pEventInfo->pwszComponent; dwHistoryContext = pEventInfo->dwHistoryContext; } // // Okay so she wants history. Either way we read backwards // i = 0; pStartEvent = NULL; bDone = FALSE; // // Read the event log till we find a record to stop at // This is signalled by the code setting bDone to TRUE // while(!bDone) { // // Get a bunch of events // bResult = ReadEventLogW( *phEventLog, EVENTLOG_SEQUENTIAL_READ | EVENTLOG_BACKWARDS_READ, 0, (PVOID)Buffer, sizeof(Buffer), &dwRead, &dwNeed ); if(bResult isnot TRUE) { dwResult = GetLastError(); if(dwResult is ERROR_HANDLE_EOF) { // // If we have reached the end of the log, break out // bDone = TRUE; break; } else { return dwResult; } } // // Start at the beginning of the buffer we just read // pNextEvent = (DWORD_PTR)Buffer; // // Read till we walk off the end of the buffer or find a record // // If we find the starting record, we set pStartEvent to one after that // It may so happen that the starting record is the last one in // the block that we have read. In that case, we set pStartEvent // to NULL but bDone to TRUE // while((pNextEvent < (DWORD_PTR)Buffer + dwRead) and !bDone) { EVENTLOGRECORD *pCurrentEvent; pCurrentEvent = (EVENTLOGRECORD *)pNextEvent; pNextEvent += pCurrentEvent->Length; switch(pEventInfo->fFlags) { case NS_EVENT_LAST_N: case NS_EVENT_LAST_SECS: { // // We are being asked to go back N (of our records) // or go back N secs // if(!IsOurRecord(pCurrentEvent, pEventInfo)) { // // Not one of ours // continue; } if(pEventInfo->fFlags is NS_EVENT_LAST_N) { // // i is the count of events // i++; } else { time_t CurrentTime; // // i is the time difference in seconds // = currentTime - eventTime // time(&CurrentTime); // // Subtract and truncate // i = (DWORD)(CurrentTime - pCurrentEvent->TimeGenerated); } if(i >= dwHistoryContext) { // // Have gone back N (records or seconds) // if(pNextEvent < (DWORD_PTR)Buffer + dwRead) { // // Have some more records in this buffer, so // set pStartEvent to the next one // pStartEvent = (EVENTLOGRECORD *)pNextEvent; } else { pStartEvent = NULL; } // // Done, break out of while(pNextEvent... and // while(!bDone) // bDone = TRUE; break; } break; } case NS_EVENT_FROM_N: case NS_EVENT_FROM_START: { // // We are being asked to go to the the most recent // occurance of a certain event. // if(_wcsicmp((LPCWSTR)((DWORD_PTR)pCurrentEvent + sizeof(*pCurrentEvent)), pwszComponent) == 0) { if(pCurrentEvent->EventID is dwHistoryContext) { if(pNextEvent < (DWORD_PTR)Buffer + dwRead) { pStartEvent = (EVENTLOGRECORD *)pNextEvent; } else { pStartEvent = NULL; } // // Done, break out of while(pCurrent... // and while(!bDone) // bDone = TRUE; break; } } } default: { ASSERT(FALSE); } } } } if(pStartEvent) { // // So we found a record at which to start. // API wants a buffer even if we set the size to 0 // bResult = ReadEventLogW(*phEventLog, EVENTLOG_SEEK_READ | EVENTLOG_FORWARDS_READ, pStartEvent->RecordNumber, (PVOID)Buffer, 0, &dwRead, &dwNeed); if(dwNeed < sizeof(Buffer)) { ReadEventLogW(*phEventLog, EVENTLOG_SEEK_READ | EVENTLOG_FORWARDS_READ, pStartEvent->RecordNumber, (PVOID)Buffer, dwNeed, &dwRead, &dwNeed); } } return NO_ERROR; } BOOL IsOurRecord( IN EVENTLOGRECORD *pRecord, IN PEVENT_PRINT_INFO pEventInfo ) { BOOL bRet; DWORD i; if(_wcsicmp((LPCWSTR)((DWORD_PTR)pRecord + sizeof(*pRecord)), pEventInfo->pwszComponent) isnot 0) { return FALSE; } bRet = TRUE; // // If ulEventCount is 0 means any event. So return TRUE // for(i = 0; i < pEventInfo->ulEventCount; i++) { bRet = (pRecord->EventID is pEventInfo->pdwEventIds[i]); if(bRet) { break; } } if(bRet) { if(pEventInfo->pfnEventFilter) { if(!(pEventInfo->pfnEventFilter)(pRecord, pEventInfo->pwszLogName, pEventInfo->pwszComponent, pEventInfo->pwszSubComponent, pEventInfo->pvFilterContext)) { // // It fell in our subcomp, but the caller doesnt // consider it so // bRet = FALSE; } } } return bRet; }