/*
File: diagrprt.c
'ras diag' sub context
09/13/01
*/
#include "precomp.h"
static CONST WCHAR g_wchUnicodeMarker = 0xFEFF;
static CONST WCHAR g_pwszNewLine[] = L"\r\n";
static CONST WCHAR g_pwszHeaderSep[] =
L"-------------------------------------------------------------------------------\r\n";
static CONST WCHAR g_pwszCmMappings[] =
L"Software\\Microsoft\\Connection Manager\\Mappings";
CONST WCHAR g_pwszLBracket = L'[';
CONST WCHAR g_pwszRBracket = L']';
CONST WCHAR g_pwszSpace[] = L" ";
CONST WCHAR g_pwszBackSlash = L'\\';
CONST WCHAR g_pwszNull = L'\0';
CONST WCHAR g_pwszLogSrchStr[] = L"*.LOG";
CONST WCHAR g_pwszLogging[] = L"Logging";
CONST WCHAR g_pwszDispNewLine[] = L"\n";
CONST WCHAR g_pwszEmpty[] = L"";
CONST WCHAR g_pwszNewLineHtml[] = L"
";
CONST WCHAR g_pwszPreStart[] = L"";
CONST WCHAR g_pwszPreEnd[] = L"
";
CONST WCHAR g_pwszAnNameStart[] = L" ";
CONST WCHAR g_pwszAnNameEnd[] = L"
";
CONST WCHAR g_pwszAnStart[] = L" ";
CONST WCHAR g_pwszAnEnd[] = L" ";
CONST WCHAR g_pwszLiStart[] = L"";
CONST WCHAR g_pwszLiEnd[] = L"";
static CONST WCHAR g_wszQuoteHtm[] = L""";
static CONST WCHAR g_wszAmpHtm[] = L"&";
static CONST WCHAR g_wszLeftHtm[] = L"<";
static CONST WCHAR g_wszRightHtm[] = L">";
static CONST WCHAR g_pwszPER[] = L"PER";
static CONST WCHAR g_pwszPRO[] = L"PRO";
static CONST WCHAR g_pwszDTC[] = L"DTC";
static CONST WCHAR g_pwszADS[] = L"ADS";
static CONST WCHAR g_pwszSRV[] = L"SRV";
static CONST WCHAR g_pwszx86[] = L"x86";
static CONST WCHAR g_pwszIA64[] = L"IA64";
static CONST WCHAR g_pwszIA32[] = L"IA32";
static CONST WCHAR g_pwszAMD64[] = L"AMD64";
static CONST WCHAR g_pwszRasUser[] = L"\\Microsoft\\Network\\Connections\\Pbk\\";
static CONST WCHAR g_pwszCmUser[] = L"\\Microsoft\\Network\\Connections\\Cm\\";
static CONST WCHAR g_pwszMsinfo[] = L"\\Common Files\\Microsoft Shared\\MSInfo\\";
CONST WCHAR g_pwszTableOfContents[] = L"TableOfContents";
CONST WCHAR g_pwszTraceCollectTracingLogs[] = L"TraceCollectTracingLogs";
CONST WCHAR g_pwszTraceCollectCmLogs[] = L"TraceCollectCmLogs";
CONST WCHAR g_pwszTraceCollectModemLogs[] = L"g_pwszTraceCollectModemLogs";
CONST WCHAR g_pwszTraceCollectIpsecLogs[] = L"g_pwszTraceCollectIpsecLogs";
CONST WCHAR g_pwszPrintRasEventLogs[] = L"PrintRasEventLogs";
CONST WCHAR g_pwszPrintSecurityEventLogs[] = L"PrintSecurityEventLogs";
CONST WCHAR g_pwszPrintRasInfData[] = L"PrintRasInfData";
CONST WCHAR g_pwszHrValidateRas[] = L"HrValidateRas";
CONST WCHAR g_pwszHrShowNetComponentsAll[] = L"HrShowNetComponentsAll";
CONST WCHAR g_pwszCheckRasRegistryKeys[] = L"CheckRasRegistryKeys";
CONST WCHAR g_pwszPrintRasEnumDevices[] = L"PrintRasEnumDevices";
CONST WCHAR g_pwszPrintProcessInfo[] = L"PrintProcessInfo";
CONST WCHAR g_pwszPrintConsoleUtils[] = L"PrintConsoleUtils";
CONST WCHAR g_pwszPrintWinMsdReport[] = L"PrintWinMsdReport";
CONST WCHAR g_pwszPrintAllRasPbks[] = L"PrintAllRasPbks";
static CONST CMD_LINE_UTILS g_CmdLineUtils[] =
{
{L"arp.exe -a", L"arp.exe"},
{L"ipconfig.exe /all", L"ipconfig.exe1"},
{L"ipconfig.exe /displaydns", L"ipconfig.exe2"},
{L"route.exe print", L"route.exe"},
{L"net.exe start", L"net.exe"},
{L"netstat.exe -e", L"netstat.exe1"},
{L"netstat.exe -o", L"netstat.exe2"},
{L"netstat.exe -s", L"netstat.exe3"},
{L"netstat.exe -n", L"netstat.exe4"},
{L"nbtstat.exe -c", L"nbtstat.exe1"},
{L"nbtstat.exe -n", L"nbtstat.exe2"},
{L"nbtstat.exe -r", L"nbtstat.exe3"},
{L"nbtstat.exe -S", L"nbtstat.exe4"},
{L"netsh.exe dump", L"netsh.exe"},
};
static CONST UINT g_ulNumCmdLines = sizeof(g_CmdLineUtils) / sizeof(CMD_LINE_UTILS);
//
// Declarations from rasnetcfg
//
VOID
HrValidateRas(
IN BUFFER_WRITE_FILE* pBuff);
VOID
HrShowNetComponentsAll(
IN BUFFER_WRITE_FILE* pBuff);
//
// Local declarations
//
DWORD
WriteUnicodeMarker(
IN BUFFER_WRITE_FILE* pBuff);
DWORD
AllocBufferWriteFile(
IN BUFFER_WRITE_FILE* pBuff);
VOID
FreeBufferWriteFile(
IN BUFFER_WRITE_FILE* pBuff);
DWORD
BufferWriteFile(
IN BUFFER_WRITE_FILE* pBuff,
IN CONST LPBYTE lpBuff,
IN DWORD dwSize);
DWORD
BufferWriteToHtml(
IN BUFFER_WRITE_FILE* pBuff,
IN CONST LPBYTE lpBuff,
IN DWORD dwSize);
DWORD
BufferWriteToHtmlA(
IN BUFFER_WRITE_FILE* pBuff,
IN CONST LPBYTE lpBuff,
IN DWORD dwSize);
DWORD
BufferWriteMessageVA(
IN BUFFER_WRITE_FILE* pBuff,
IN LPCWSTR pwszFormat,
IN va_list* parglist);
PWCHAR
FindLastCmLogHeader(
IN LPCWSTR pStart,
IN LPCWSTR pEnd,
IN LPCWSTR pCurrent);
PWCHAR
GetCMLoggingPath(
IN LPCWSTR pwcszCMPFile);
PWCHAR
GetSystemInfoString();
PWCHAR
GetVersionExString(
OUT PDWORD pdwBuild);
VOID
PrintConsoleUtilsToc(
IN BUFFER_WRITE_FILE* pBuff);
BOOL
GetCommonFolderPath(
IN DWORD dwMode,
OUT TCHAR* pszPathBuf);
LONG
ProcessTimeString(
IN PCHAR pszTime,
IN DWORD dwHours);
BOOL
CALLBACK
EnumWindowsProc(
HWND hwnd,
LPARAM lParam);
BOOL
EnumMessageWindows(
WNDENUMPROC lpEnumFunc,
LPARAM lParam);
BOOL
CALLBACK
EnumDesktopProc(
LPTSTR lpszDesktop,
LPARAM lParam);
BOOL
CALLBACK
EnumWindowStationProc(
LPTSTR lpszWindowStation,
LPARAM lParam);
VOID
GetWindowTitles(
PTASK_LIST_ENUM te);
VOID
PrintRasInfData(
IN BUFFER_WRITE_FILE* pBuff);
VOID
PrintRasEnumDevices(
IN BUFFER_WRITE_FILE* pBuff);
VOID
PrintProcessInfo(
IN BUFFER_WRITE_FILE* pBuff);
VOID
PrintConsoleUtils(
IN REPORT_INFO* pInfo);
VOID
PrintWinMsdReport(
IN REPORT_INFO* pInfo);
BOOL
PrintRasPbk(
IN REPORT_INFO* pInfo,
IN DWORD dwType);
VOID
PrintAllRasPbks(
IN REPORT_INFO* pInfo);
PUCHAR
GetSystemProcessInfo();
VOID
FreeSystemProcessInfo(
IN PUCHAR pProcessInfo);
DWORD
DiagGetReport(
IN DWORD dwFlags,
IN OUT LPCWSTR pwszString,
IN OPTIONAL DiagGetReportCb pCallback,
IN OPTIONAL PVOID pContext)
{
DWORD dwErr = NO_ERROR;
PWCHAR pwszTempFile = NULL;
REPORT_INFO ReportInfo;
BUFFER_WRITE_FILE Buff;
GET_REPORT_STRING_CB CbInfo;
do
{
ZeroMemory(&ReportInfo, sizeof(REPORT_INFO));
ZeroMemory(&Buff, sizeof(BUFFER_WRITE_FILE));
ZeroMemory(&CbInfo, sizeof(GET_REPORT_STRING_CB));
if (!pwszString)
{
dwErr = ERROR_INVALID_PARAMETER;
break;
}
if ((dwFlags & RAS_DIAG_EXPORT_TO_EMAIL) ||
(dwFlags & RAS_DIAG_DISPLAY_FILE)
)
{
WCHAR wszTempFileName[MAX_PATH + 1];
dwErr = CopyTempFileName(wszTempFileName);
BREAK_ON_DWERR(dwErr);
pwszTempFile = CreateHtmFileName(wszTempFileName);
if (!pwszTempFile)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
break;
}
}
else if (dwFlags & RAS_DIAG_EXPORT_TO_FILE)
{
pwszTempFile = CreateHtmFileName(pwszString);
if (!pwszTempFile)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
break;
}
}
else
{
dwErr = ERROR_INVALID_PARAMETER;
break;
}
//
// Init the Report Information structure
//
ReportInfo.fVerbose = !!(dwFlags & RAS_DIAG_VERBOSE_REPORT);
ReportInfo.pBuff = &Buff;
//
// Create the report file
//
dwErr = CreateReportFile(ReportInfo.pBuff, pwszTempFile);
BREAK_ON_DWERR(dwErr);
//
// Print header and table of contents to report
//
PrintHtmlHeader(ReportInfo.pBuff);
PrintTableOfContents(&ReportInfo, SHOW_ALL);
//
// Init callback data
//
if (pCallback)
{
CbInfo.pContext = pContext;
CbInfo.pwszState = RutlAlloc(
(MAX_MSG_LENGTH + 1) * sizeof(WCHAR),
FALSE);
ReportInfo.pCbInfo = &CbInfo;
ReportInfo.pCallback = pCallback;
}
dwErr = RasDiagShowAll(&ReportInfo);
PrintHtmlFooter(ReportInfo.pBuff);
CloseReportFile(ReportInfo.pBuff);
//
// If report gathering was cancelled via the UI, dwErr will =
// ERROR_CANCELLED. We do not want to continue in this case.
//
if (dwErr)
{
DeleteFile(pwszTempFile);
break;
}
if (dwFlags & RAS_DIAG_EXPORT_TO_EMAIL)
{
PWCHAR pwszCabFile = NULL;
pwszCabFile = CabCompressFile(pwszTempFile);
if (!pwszCabFile)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
break;
}
dwErr = MapiSendMail(pwszString, pwszCabFile);
DeleteFile(pwszCabFile);
DeleteFile(pwszTempFile);
RutlFree(pwszCabFile);
}
else
{
lstrcpyn((PWCHAR)pwszString, pwszTempFile, MAX_PATH);
}
} while (FALSE);
//
// Clean up
//
RutlFree(CbInfo.pwszState);
RutlFree(pwszTempFile);
return dwErr;
}
VOID
WriteLinkBackToToc(
IN BUFFER_WRITE_FILE* pBuff)
{
BufferWriteFileStrW(pBuff, g_pwszSpace);
BufferWriteFileCharW(pBuff, g_pwszLBracket);
BufferWriteFileStrW(pBuff, g_pwszAnStart);
BufferWriteFileStrW(pBuff, g_pwszTableOfContents);
BufferWriteFileStrW(pBuff, g_pwszAnMiddle);
BufferWriteMessage(pBuff, g_hModule, MSG_RASDIAG_REPORT_TOC);
BufferWriteFileStrW(pBuff, g_pwszAnEnd);
BufferWriteFileCharW(pBuff, g_pwszRBracket);
return;
}
VOID
WriteHtmlSection(
IN BUFFER_WRITE_FILE* pBuff,
IN LPCWSTR pwszAnchor,
IN DWORD dwMsgId)
{
BufferWriteFileStrW(pBuff, g_pwszAnNameStart);
BufferWriteFileStrW(pBuff, pwszAnchor);
BufferWriteFileStrW(pBuff, g_pwszAnNameMiddle);
BufferWriteMessage(pBuff, g_hModule, dwMsgId);
WriteLinkBackToToc(pBuff);
BufferWriteFileStrW(pBuff, g_pwszAnNameEnd);
}
DWORD
WriteUnicodeMarker(
IN BUFFER_WRITE_FILE* pBuff)
{
return BufferWriteFile(
pBuff,
(LPBYTE)&g_wchUnicodeMarker,
sizeof(g_wchUnicodeMarker));
}
DWORD
WriteNewLine(
IN BUFFER_WRITE_FILE* pBuff)
{
return BufferWriteFileStrW(pBuff, g_pwszNewLine);
}
VOID
WriteHeaderSep(
IN BUFFER_WRITE_FILE* pBuff,
IN LPCWSTR pwszTitle)
{
BufferWriteFileStrW(pBuff, g_pwszHeaderSep);
BufferWriteFileStrW(pBuff, pwszTitle);
WriteNewLine(pBuff);
BufferWriteFileStrW(pBuff, g_pwszHeaderSep);
}
VOID
WriteEventLogEntry(
IN BUFFER_WRITE_FILE* pBuff,
IN PEVENTLOGRECORD pevlr,
IN LPCWSTR pwszDescr,
IN LPCWSTR pwszCategory)
{
PSID psid;
DWORD dwName = MAX_USERNAME_SIZE, dwDomain = MAX_DOMAIN_SIZE, dwArg;
WCHAR wszName[MAX_USERNAME_SIZE + 1], wszDomain[MAX_DOMAIN_SIZE + 1],
wszDate[TIMEDATESTR], wszTime[TIMEDATESTR];
PWCHAR pwszSource, pwszComputer, pwszType = NULL, pwszTemp,
pwszCat = NULL, pwszName = NULL;
SID_NAME_USE snu;
switch (pevlr->EventType)
{
case EVENTLOG_SUCCESS:
dwArg = MSG_RASDIAG_SHOW_EVENT_SUCCESS;
break;
case EVENTLOG_ERROR_TYPE:
dwArg = MSG_RASDIAG_SHOW_EVENT_ERROR;
break;
case EVENTLOG_WARNING_TYPE:
dwArg = MSG_RASDIAG_SHOW_EVENT_WARNING;
break;
case EVENTLOG_INFORMATION_TYPE:
dwArg = MSG_RASDIAG_SHOW_EVENT_INFO;
break;
case EVENTLOG_AUDIT_SUCCESS:
dwArg = MSG_RASDIAG_SHOW_EVENT_SAUDIT;
break;
case EVENTLOG_AUDIT_FAILURE:
dwArg = MSG_RASDIAG_SHOW_EVENT_FAUDIT;
break;
default:
dwArg = 0;
break;
}
if (dwArg)
{
pwszType = LoadStringFromHinst(g_hModule, dwArg);
}
pwszSource = (PWCHAR)((LPBYTE) pevlr + sizeof(EVENTLOGRECORD));
if (!pwszCategory)
{
pwszCat = LoadStringFromHinst(g_hModule, MSG_RASDIAG_SHOW_EVENT_NONE);
}
RutlGetDateStr(
pevlr->TimeGenerated,
wszDate,
TIMEDATESTR);
RutlGetTimeStr(
pevlr->TimeGenerated,
wszTime,
TIMEDATESTR);
psid = (PSID) (((PBYTE) pevlr) + pevlr->UserSidOffset);
if (!LookupAccountSid(
NULL,
psid,
wszName,
&dwName,
wszDomain,
&dwDomain,
&snu)
)
{
wszName[0] = g_pwszNull;
wszDomain[0] = g_pwszNull;
pwszName = LoadStringFromHinst(g_hModule, MSG_RASDIAG_SHOW_EVENT_NA);
}
pwszTemp = pwszSource;
while(*pwszTemp++ != g_pwszNull);
pwszComputer = pwszTemp;
if (wszDomain[0] != g_pwszNull)
{
BufferWriteMessage(
pBuff,
g_hModule,
MSG_RASDIAG_SHOW_EVENT_LOG_USERDOM,
pwszType ? pwszType : g_pwszEmpty,
pwszSource,
(pwszCat ? pwszCat :
(pwszCategory ? pwszCategory : g_pwszEmpty)),
pevlr->EventID,
wszDate,
wszTime,
wszDomain,
pwszName ? pwszName : wszName,
pwszComputer,
pwszDescr);
}
else
{
BufferWriteMessage(
pBuff,
g_hModule,
MSG_RASDIAG_SHOW_EVENT_LOG_USER,
pwszType ? pwszType : g_pwszEmpty,
pwszSource,
(pwszCat ? pwszCat :
(pwszCategory ? pwszCategory : g_pwszEmpty)),
pevlr->EventID,
wszDate,
wszTime,
pwszName ? pwszName : wszName,
pwszComputer,
pwszDescr);
}
//
// Clean up
//
FreeStringFromHinst(pwszName);
FreeStringFromHinst(pwszCat);
FreeStringFromHinst(pwszType);
return;
}
DWORD
AllocBufferWriteFile(
IN BUFFER_WRITE_FILE* pBuff)
{
DWORD dwErr = NO_ERROR;
do
{
if (!pBuff || !pBuff->hFile ||
pBuff->hFile == INVALID_HANDLE_VALUE)
{
dwErr = ERROR_INVALID_PARAMETER;
break;
}
pBuff->lpBuff = RutlAlloc(BUF_WRITE_SIZE, FALSE);
if (!pBuff->lpBuff)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
break;
}
pBuff->dwPosition = 0;
} while (FALSE);
return dwErr;
}
VOID
FreeBufferWriteFile(
IN BUFFER_WRITE_FILE* pBuff)
{
//
// Whistler .NET BUG: 492078
//
if (pBuff->dwPosition && pBuff->lpBuff)
{
DWORD dwTemp;
WriteFile(
pBuff->hFile,
pBuff->lpBuff,
pBuff->dwPosition,
&dwTemp,
NULL);
pBuff->dwPosition = 0;
RutlFree(pBuff->lpBuff);
pBuff->lpBuff = NULL;
}
return;
}
DWORD
BufferWriteFile(
IN BUFFER_WRITE_FILE* pBuff,
IN CONST LPBYTE lpBuff,
IN DWORD dwSize)
{
DWORD dwErr = NO_ERROR, dwCurSize, dwCopy, dwTemp;
LPBYTE lpEnd, lpCurrent;
do
{
if (!pBuff || !lpBuff || !dwSize)
{
dwErr = ERROR_INVALID_PARAMETER;
break;
}
lpEnd = lpBuff + dwSize;
lpCurrent = lpBuff;
dwCurSize = dwSize;
for (;;)
{
dwCopy = min(dwCurSize, BUF_WRITE_SIZE - pBuff->dwPosition);
CopyMemory(pBuff->lpBuff + pBuff->dwPosition, lpCurrent, dwCopy);
pBuff->dwPosition += dwCopy;
if (pBuff->dwPosition == BUF_WRITE_SIZE)
{
if (!WriteFile(
pBuff->hFile,
pBuff->lpBuff,
BUF_WRITE_SIZE,
&dwTemp,
NULL))
{
dwErr = GetLastError();
break;
}
pBuff->dwPosition = 0;
}
lpCurrent += dwCopy;
if (lpCurrent == lpEnd)
{
break;
}
dwCurSize = (DWORD)(lpEnd - lpCurrent);
}
} while (FALSE);
return dwErr;
}
//
// Remove HTML escape characters from buffer
//
DWORD
BufferWriteToHtml(
IN BUFFER_WRITE_FILE* pBuff,
IN CONST LPBYTE lpBuff,
IN DWORD dwSize)
{
DWORD i, dwTemp = 0, dwErr = NO_ERROR;
LPBYTE lpTemp = NULL, lpCurrent;
PWCHAR pwszReplace;
//For .Net 506188
PWCHAR pwCheck = NULL;
lpCurrent = lpBuff;
for (i = 0; i < dwSize; i += sizeof(WCHAR))
{
//For .Net 506188
pwCheck = (WCHAR *) (lpCurrent+i);
switch ( *(pwCheck) )
{
case L'\"':
pwszReplace = (PWCHAR)g_wszQuoteHtm;
break;
case L'@':
pwszReplace = (PWCHAR)g_wszAmpHtm;
break;
case L'<':
pwszReplace = (PWCHAR)g_wszLeftHtm;
break;
case L'>':
pwszReplace = (PWCHAR)g_wszRightHtm;
break;
default:
pwszReplace = NULL;
break;
}
if (pwszReplace)
{
//
// Flush out stuff we are not going to replace
//
if (lpTemp && dwTemp)
{
dwErr = BufferWriteFile(
pBuff,
lpTemp,
dwTemp * sizeof(WCHAR));
lpTemp = NULL;
dwTemp = 0;
BREAK_ON_DWERR(dwErr);
}
//
// Write out the converted escape seq
//
dwErr = BufferWriteFile(
pBuff,
(LPBYTE)pwszReplace,
lstrlen(pwszReplace) * sizeof(WCHAR));
BREAK_ON_DWERR(dwErr);
}
else
{
//
// Not an escape seq, continue
//
if (!lpTemp)
{
lpTemp = lpCurrent + i;
}
dwTemp++;
}
}
//
// Make sure we didn't leave any around to write out
//
if (lpTemp && dwTemp)
{
dwErr = BufferWriteFile(
pBuff,
lpTemp,
dwTemp * sizeof(WCHAR));
}
return dwErr;
}
DWORD
BufferWriteToHtmlA(
IN BUFFER_WRITE_FILE* pBuff,
IN CONST LPBYTE lpBuff,
IN DWORD dwSize)
{
UINT i;
DWORD dwErr = NO_ERROR;
LPWSTR pTempBuff = NULL;
DWORD dwNewSize = 0;
do
{
if (!dwSize)
{
dwErr = ERROR_INVALID_PARAMETER;
break;
}
//
// First call MultiByteToWideChar to get how large of a Unicode string
// will result from conversion.
//
dwNewSize = MultiByteToWideChar(CP_ACP, 0, lpBuff, dwSize, NULL, 0);
if (0 == dwNewSize)
{
dwErr = GetLastError();
break;
}
//
// Okay, now allocate enough memory for the new string
//
pTempBuff = RutlAlloc((dwNewSize * sizeof(WCHAR)), FALSE);
if (!pTempBuff)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
break;
}
//
// Now do the conversion by calling MultiByteToWideChar again
//
if (0 == MultiByteToWideChar(CP_ACP, 0, lpBuff, dwSize, pTempBuff, dwNewSize))
{
dwErr = GetLastError();
break;
}
//
// Finally, write out the buffer to the html file
//
dwErr = BufferWriteToHtml(
pBuff,
(LPBYTE)pTempBuff,
dwNewSize * sizeof(WCHAR));
} while (FALSE);
//
// Clean up
//
RutlFree(pTempBuff);
return dwErr;
}
DWORD
BufferWriteFileStrWtoA(
IN BUFFER_WRITE_FILE* pBuff,
IN LPCWSTR pwszString)
{
PCHAR pszString = NULL;
DWORD dwErr = NO_ERROR;
if (!pwszString)
{
return ERROR_INVALID_PARAMETER;
}
pszString = RutlStrDupAFromW(pwszString);
if (!pszString)
{
return ERROR_NOT_ENOUGH_MEMORY;
}
dwErr = BufferWriteFile(
pBuff,
(LPBYTE)pszString,
lstrlenA(pszString));
RutlFree(pszString);
return dwErr;
}
DWORD
BufferWriteFileStrW(
IN BUFFER_WRITE_FILE* pBuff,
IN LPCWSTR pwszString)
{
if (!pwszString)
{
return ERROR_INVALID_PARAMETER;
}
return BufferWriteFile(
pBuff,
(LPBYTE)pwszString,
lstrlen(pwszString) * sizeof(WCHAR));
}
DWORD
BufferWriteFileCharW(
IN BUFFER_WRITE_FILE* pBuff,
IN CONST WCHAR wszChar)
{
return BufferWriteFile(pBuff, (LPBYTE)&wszChar, sizeof(WCHAR));
}
DWORD
BufferWriteMessageVA(
IN BUFFER_WRITE_FILE* pBuff,
IN LPCWSTR pwszFormat,
IN va_list* parglist)
{
DWORD dwErr = NO_ERROR, dwMsgLen = 0;
LPWSTR pwszOutput = NULL;
do
{
dwMsgLen = FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_STRING,
pwszFormat,
0,
0L,
(LPWSTR)&pwszOutput,
0,
parglist);
if(!dwMsgLen)
{
dwErr = GetLastError();
break;
}
dwErr = BufferWriteFile(
pBuff,
(LPBYTE)pwszOutput,
dwMsgLen * sizeof(WCHAR));
} while (FALSE);
if (pwszOutput)
{
LocalFree(pwszOutput);
}
return dwErr;
}
DWORD
BufferWriteMessage(
IN BUFFER_WRITE_FILE* pBuff,
IN HANDLE hModule,
IN DWORD dwMsgId,
...)
{
WCHAR rgwcInput[MAX_MSG_LENGTH + 1];
va_list arglist;
if (!LoadString(hModule, dwMsgId, rgwcInput, MAX_MSG_LENGTH))
{
return GetLastError();
}
va_start(arglist, dwMsgId);
return BufferWriteMessageVA(pBuff, rgwcInput, &arglist);
}
LPBYTE
ParseRasLogForTime(
IN LPBYTE pBuff,
IN DWORD dwSize,
IN DWORD dwHours)
{
CHAR szTime[TIMESIZE + 1];
LPBYTE pCurrent, pEnd, pStart, pTemp, pLast = NULL, pReturn = NULL;
CONST PCHAR c_pszRasLogString = "\r\n[";
CONST UINT c_ulRasLogStringSize = strlen(c_pszRasLogString);
pStart = pBuff;
pCurrent = pEnd = pBuff + dwSize;
do
{
if (pCurrent + TIMESIZE + 4 > pEnd)
{
pCurrent -= TIMESIZE + 4;
continue;
}
if (!strncmp(pCurrent, c_pszRasLogString, c_ulRasLogStringSize))
{
pTemp = pCurrent + c_ulRasLogStringSize;
//
// Find the space before the time
//
while ((*pTemp++ != ' ') &&
(*pTemp != g_pwszNull)
);
//
// Check for colons then the period before mil sec
//
if ((pTemp + TIMESIZE + 1 > pEnd) ||
(*(pTemp + 2) != ':') ||
(*(pTemp + 5) != ':') ||
(*(pTemp + TIMESIZE ) != ':')
)
{
continue;
}
strncpy(szTime, pTemp, TIMESIZE);
szTime[TIMESIZE] = '\0';
if (ProcessTimeString(szTime, dwHours) == -1)
{
pReturn = pLast;
break;
}
else
{
pLast = pCurrent + 2;
continue;
}
}
} while (--pCurrent >= pStart);
//
// Since we parsed the whole file, display the whole file
//
if (pCurrent < pStart)
{
pReturn = pStart;
}
return pReturn;
}
LPBYTE
ParseModemLogForTime(
IN LPBYTE pBuff,
IN DWORD dwSize,
IN DWORD dwHours)
{
PCHAR pszTimeA = NULL;
WCHAR wszTime[TIMESIZE + 1];
PWCHAR pCurrent, pEnd, pStart, pTemp, pLast = NULL, pReturn = NULL;
pStart = (PWCHAR)pBuff;
pCurrent = pEnd = (PWCHAR)((LPBYTE)pBuff + dwSize);
do
{
if (pCurrent + TIMESIZE + 4 > pEnd)
{
pCurrent -= TIMESIZE + 4;
continue;
}
if ((*pCurrent == '\r') &&
(*(pCurrent + 1) == '\n') &&
(*(pCurrent + 4) == '-') &&
(*(pCurrent + 7) == '-')
)
{
pTemp = pCurrent;
//
// Find the space
//
while ((*pTemp++ != ' ') &&
(*pTemp != g_pwszNull)
);
//
// Check for colons then the period before mil sec
//
if ((pTemp + TIMESIZE > pEnd) ||
(*(pTemp + 2) != ':') ||
(*(pTemp + 5) != ':') ||
(*(pTemp + TIMESIZE ) != '.')
)
{
continue;
}
//
// it seems that lstrcpyn subtracts 1 from the size for the NULL on
// your behalf then appends a NULL to the end
//
lstrcpyn(wszTime, pTemp, TIMESIZE + 1);
pszTimeA = RutlStrDupAFromWAnsi(wszTime);
if (!pszTimeA)
{
continue;
}
if (ProcessTimeString(pszTimeA, dwHours) == -1)
{
RutlFree(pszTimeA);
pszTimeA = NULL;
pReturn = pLast;
break;
}
else
{
RutlFree(pszTimeA);
pszTimeA = NULL;
pLast = pCurrent + 2;
continue;
}
}
} while (--pCurrent >= pStart);
//
// Since we parsed the whole file, display the whole file
// Also, This is a unicode file so we need to chop off the garbage in front
//
if (pCurrent < pStart)
{
pReturn = pStart + 1;
}
//
// Clean up
//
RutlFree(pszTimeA);
return (LPBYTE)pReturn;
}
PWCHAR
FindLastCmLogHeader(
IN LPCWSTR pStart,
IN LPCWSTR pEnd,
IN LPCWSTR pCurrent)
{
PWCHAR pCurrentCopy, pReturn = NULL;
CONST PWCHAR c_pwszCmLogString = L"\r\n*";
CONST UINT c_ulCmLogStringSize = lstrlen(c_pwszCmLogString);
pCurrentCopy = (PWCHAR)pCurrent;
do
{
if (!RutlStrNCmp(pCurrentCopy, c_pwszCmLogString, c_ulCmLogStringSize))
{
pReturn = pCurrentCopy + 2;
break;
}
} while (--pCurrentCopy >= pStart);
return pReturn;
}
LPBYTE
ParseCmLogForTime(
IN LPBYTE pBuff,
IN DWORD dwSize,
IN DWORD dwHours)
{
PCHAR pszTimeA = NULL;
WCHAR wszTime[TIMESIZE + 1];
PWCHAR pCurrent, pEnd, pStart, pTemp, pLast = NULL, pReturn = NULL;
CONST PWCHAR c_pwszCmLogString = L"\r\n\tStart Date/Time : ";
CONST UINT c_ulCmLogStringSize = lstrlen(c_pwszCmLogString);
pStart = (PWCHAR)pBuff;
pCurrent = pEnd = (PWCHAR)((LPBYTE)pBuff + dwSize);
do
{
if (pCurrent + TIMESIZE + 35 > pEnd)
{
pCurrent -= TIMESIZE + 35;
continue;
}
if (!RutlStrNCmp(pCurrent, c_pwszCmLogString, c_ulCmLogStringSize))
{
pTemp = pCurrent + c_ulCmLogStringSize;
//
// Find the space
//
while ((*pTemp++ != ' ') &&
(*pTemp != g_pwszNull)
);
//
// Check for colons then the period before mil sec
//
if ((pTemp + TIMESIZE > pEnd) ||
(*(pTemp + 2) != ':') ||
(*(pTemp + 5) != ':') ||
(*(pTemp + TIMESIZE ) != '\r')
)
{
continue;
}
//
// it seems that lstrcpyn subtracts 1 from the size for the NULL on
// your behalf then appends a NULL to the end
//
lstrcpyn(wszTime, pTemp, TIMESIZE + 1);
pszTimeA = RutlStrDupAFromWAnsi(wszTime);
if (!pszTimeA)
{
continue;
}
if (ProcessTimeString(pszTimeA, dwHours) == -1)
{
RutlFree(pszTimeA);
pszTimeA = NULL;
pReturn = pLast;
break;
}
else
{
RutlFree(pszTimeA);
pszTimeA = NULL;
pLast = FindLastCmLogHeader(pStart, pEnd, pCurrent - 1);
//
// If we are unable to find a CM log header above, we assume we
// have hit the start of the log. we add one because of unicode
// garbabe at front of file
//
if (!pLast)
{
pReturn = pStart + 1;
break;
}
continue;
}
}
} while (--pCurrent >= pStart);
//
// Clean up
//
RutlFree(pszTimeA);
return (LPBYTE)pReturn;
}
LPBYTE
ParseIpsecLogForTime(
IN LPBYTE pBuff,
IN DWORD dwSize,
IN DWORD dwHours)
{
CHAR szTime[TIMESIZE + 1];
LPBYTE pCurrent, pEnd, pStart, pTemp, pLast = NULL, pReturn = NULL;
CONST PCHAR c_pszIpsecLogString = "\r\n ";
CONST UINT c_ulIpsecLogStringSize = strlen(c_pszIpsecLogString);
pStart = pBuff;
pCurrent = pEnd = pBuff + dwSize;
do
{
if (pCurrent + TIMESIZE + 4 > pEnd)
{
pCurrent -= TIMESIZE + 4;
continue;
}
if (!strncmp(pCurrent, c_pszIpsecLogString, c_ulIpsecLogStringSize))
{
pTemp = pCurrent + c_ulIpsecLogStringSize;
//
// Find the space before the time
//
while ((*pTemp++ != ' ') &&
(*pTemp != g_pwszNull)
);
//
// Check for colons then the period before mil sec
//
if ((pTemp + TIMESIZE + 1 > pEnd) ||
(*(pTemp + 2) != ':') ||
(*(pTemp + 5) != ':') ||
(*(pTemp + TIMESIZE ) != ':')
)
{
continue;
}
strncpy(szTime, pTemp, TIMESIZE);
szTime[TIMESIZE] = '\0';
if (ProcessTimeString(szTime, dwHours) == -1)
{
pReturn = pLast;
break;
}
else
{
pLast = pCurrent + 2;
continue;
}
}
} while (--pCurrent >= pStart);
//
// Since we parsed the whole file, display the whole file
//
if (pCurrent < pStart)
{
pReturn = pStart;
}
return pReturn;
}
DWORD
PrintFile(
IN REPORT_INFO* pInfo,
IN LPCWSTR pwszFile,
IN BOOL fWritePath,
IN RAS_PRINTFILE_FUNC_CB pCallback)
{
BOOL bIsWide = FALSE;
DWORD dwErr = NO_ERROR, dwFileSize = 0, dwBytesRead;
HANDLE hFile = NULL;
LPBYTE lpBuff = NULL, pFound = NULL;
do
{
if (!pInfo || !pwszFile)
{
dwErr = ERROR_INVALID_PARAMETER;
break;
}
hFile = CreateFile(
pwszFile,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if(INVALID_HANDLE_VALUE == hFile)
{
dwErr = GetLastError();
break;
}
dwFileSize = GetFileSize(hFile, NULL);
if ((dwFileSize < sizeof(g_wchUnicodeMarker)) ||
(INVALID_FILE_SIZE == dwFileSize)
)
{
dwErr = ERROR_INVALID_PARAMETER;
break;
}
lpBuff = RutlAlloc(dwFileSize, FALSE);
if (!lpBuff)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
break;
}
if((!ReadFile(hFile, lpBuff, dwFileSize, &dwBytesRead, NULL)) ||
(dwBytesRead != dwFileSize)
)
{
dwErr = GetLastError();
break;
}
//
// If we got this far it is safe to go ahead and print the path
//
if (fWritePath)
{
WriteHeaderSep(pInfo->pBuff, pwszFile);
}
//
// check to see if the file is unicode
//
if (!memcmp(&g_wchUnicodeMarker, lpBuff, sizeof(g_wchUnicodeMarker)))
{
bIsWide = TRUE;
}
if (!pCallback || !pInfo->dwHours)
{
if (bIsWide)
{
//
// Unicode file has 2 bytes of leading stuff
//
pFound = lpBuff + sizeof(g_wchUnicodeMarker);
}
else
{
pFound = lpBuff;
}
}
else
{
//
// Call the callback
//
pFound = pCallback(lpBuff, dwFileSize, pInfo->dwHours);
if (!pFound)
{
dwErr = ERROR_FILE_NOT_FOUND;
break;
}
}
if (bIsWide)
{
dwErr = BufferWriteToHtml(
pInfo->pBuff,
pFound,
(DWORD)((lpBuff + dwFileSize) - pFound));
}
else
{
dwErr = BufferWriteToHtmlA(
pInfo->pBuff,
pFound,
(DWORD)((lpBuff + dwFileSize) - pFound));
}
WriteNewLine(pInfo->pBuff);
} while (FALSE);
//
// Clean up
//
RutlFree(lpBuff);
if (hFile)
{
CloseHandle(hFile);
}
return dwErr;
}
PWCHAR
GetCMLoggingPath(
IN LPCWSTR pwcszCMPFile)
{
DWORD dwSize;
WCHAR wszTemp[MAX_PATH + 1], wszFile[MAX_PATH + 1];
PWCHAR pwszCMSPath = NULL, pwszReturn = NULL;
CONST PWCHAR pwszCM = L"Connection Manager";
CONST PWCHAR pwszCMS = L"CMSFile";
CONST PWCHAR pwszFileDir = L"FileDirectory";
CONST PWCHAR pwszTempDir = L"%TEMP%\\";
do
{
if (!pwcszCMPFile ||
!ExpandEnvironmentStrings(
pwcszCMPFile,
wszTemp,
MAX_PATH)
)
{
break;
}
if (!GetPrivateProfileString(
pwszCM,
pwszCMS,
g_pwszEmpty,
wszFile,
MAX_PATH,
wszTemp)
)
{
break;
}
if (!GetCommonFolderPath(ALL_USERS_PROF | GET_FOR_CM, wszTemp))
{
break;
}
dwSize = lstrlen(wszFile) + lstrlen(wszTemp) + 1;
if (dwSize < 2)
{
break;
}
pwszCMSPath = RutlAlloc(dwSize * sizeof(WCHAR), TRUE);
if (!pwszCMSPath)
{
break;
}
lstrcpy(pwszCMSPath, wszTemp);
lstrcat(pwszCMSPath, wszFile);
if (!GetPrivateProfileString(
g_pwszLogging,
pwszFileDir,
pwszTempDir,
wszFile,
MAX_PATH,
pwszCMSPath)
)
{
break;
}
if (!ExpandEnvironmentStrings(
wszFile,
wszTemp,
MAX_PATH))
{
break;
}
//
// Must guarentee string ends with '\'
//
dwSize = lstrlen(wszTemp);
if (g_pwszBackSlash != wszTemp[dwSize - 1])
{
if (dwSize + 1 <= MAX_PATH)
{
wszTemp[dwSize - 1] = g_pwszBackSlash;
wszTemp[dwSize] = g_pwszNull;
}
else
{
break;
}
}
pwszReturn = RutlStrDup(wszTemp);
} while (FALSE);
//
// Clean up
//
RutlFree(pwszCMSPath);
return pwszReturn;
}
BOOL
GetCMLoggingSearchPath(
IN HANDLE hKey,
IN LPCWSTR pwszName,
IN LPCWSTR* ppwszLogPath,
IN LPCWSTR* ppwszSeach)
{
HKEY hMappings = NULL;
BOOL fRet = FALSE;
DWORD dwSize;
PWCHAR pwszCMPFile = NULL;
do
{
if (!ppwszLogPath || !ppwszSeach)
{
break;
}
*ppwszLogPath = NULL;
*ppwszSeach = NULL;
if (RegOpenKeyEx(
hKey,
g_pwszCmMappings,
0,
KEY_READ,
&hMappings) ||
RutlRegReadString(
hMappings,
pwszName,
&pwszCMPFile)
)
{
break;
}
*ppwszLogPath = GetCMLoggingPath(pwszCMPFile);
if (!(*ppwszLogPath))
{
break;
}
dwSize = lstrlen(pwszName) + lstrlen(g_pwszLogSrchStr) + 1;
if (dwSize < 2)
{
break;
}
*ppwszSeach = RutlAlloc(dwSize * sizeof(WCHAR), FALSE);
if (!(*ppwszSeach))
{
break;
}
lstrcpy((PWCHAR)(*ppwszSeach), pwszName);
lstrcat((PWCHAR)(*ppwszSeach), g_pwszLogSrchStr);
fRet = TRUE;
} while (FALSE);
//
// Clean up
//
RutlFree(pwszCMPFile);
return fRet;
}
PWCHAR
GetTracingDir()
{
DWORD dwSize = 0;
WCHAR wszWindir[MAX_PATH + 1];
PWCHAR pwszReturn = NULL;
CONST WCHAR c_pwszTracingPath[] = L"\\tracing\\";
do
{
dwSize = GetSystemWindowsDirectory(wszWindir, MAX_PATH);
if (!dwSize)
{
break;
}
dwSize += lstrlen(c_pwszTracingPath) + 1;
pwszReturn = RutlAlloc(dwSize * sizeof(WCHAR), TRUE);
if (!pwszReturn)
{
break;
}
lstrcpy(pwszReturn, wszWindir);
lstrcat(pwszReturn, c_pwszTracingPath);
} while (FALSE);
return pwszReturn;
}
PWCHAR
CreateErrorString(
IN WORD wNumStrs,
IN LPCWSTR pswzStrings,
IN LPCWSTR pswzErrorMsg)
{
UINT i, ulSize = 0, ulStrCount = 0;
PWCHAR pwszReturn = NULL, pwszCurrent, pwszEnd;
PWCHAR pswzStrs = (PWCHAR)pswzStrings, pswzError = (PWCHAR)pswzErrorMsg;
PWCHAR* ppwszStrArray = NULL;
do
{
//
// only handle between 1 - 99 strings
//
if ((wNumStrs < 1) ||
(wNumStrs > 99) ||
(!pswzStrs || !pswzError)
)
{
break;
}
ppwszStrArray = RutlAlloc(wNumStrs * sizeof(PWCHAR), TRUE);
if (!ppwszStrArray)
{
break;
}
for (i = 0; i < wNumStrs; i++)
{
ppwszStrArray[i] = pswzStrs;
ulSize += lstrlen(pswzStrs);
while(*pswzStrs++ != g_pwszNull);
}
ulSize += lstrlen(pswzError) + 1;
pwszReturn = RutlAlloc(ulSize * sizeof(WCHAR), TRUE);
if (!pwszReturn)
{
break;
}
//
// Walk through the string and replacing any inserts with proper string
//
pwszCurrent = pswzError;
pwszEnd = pswzError + lstrlen(pswzError);
while((*pwszCurrent != g_pwszNull) &&
(pwszCurrent + 1 <= pwszEnd) &&
(ulStrCount < wNumStrs)
)
{
if ((*pwszCurrent == L'%') &&
(*(pwszCurrent + 1) >= L'0') &&
(*(pwszCurrent + 1) <= L'9')
)
{
*pwszCurrent = g_pwszNull;
if ((pwszCurrent + 2 <= pwszEnd) &&
(*(pwszCurrent + 2) >= L'0') &&
(*(pwszCurrent + 2) <= L'9')
)
{
pwszCurrent += 3;
}
else
{
pwszCurrent += 2;
}
lstrcat(pwszReturn, pswzError);
lstrcat(pwszReturn, ppwszStrArray[ulStrCount++]);
pswzError = pwszCurrent;
}
else
{
pwszCurrent++;
}
}
if (pwszEnd > pswzError)
{
lstrcat(pwszReturn, pswzError);
}
} while (FALSE);
//
// Clean up
//
RutlFree(ppwszStrArray);
return pwszReturn;
}
PWCHAR
FormatMessageFromMod(
IN HANDLE hModule,
IN DWORD dwId)
{
PWCHAR pwszReturn = NULL;
FormatMessage(
FORMAT_MESSAGE_IGNORE_INSERTS |
FORMAT_MESSAGE_MAX_WIDTH_MASK |
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_HMODULE,
hModule,
dwId,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPWSTR)&pwszReturn,
0,
NULL);
return pwszReturn;
}
VOID
FreeFormatMessageFromMod(
IN LPCWSTR pwszMessage)
{
if (pwszMessage)
{
LocalFree((PWCHAR)pwszMessage);
}
}
PWCHAR
LoadStringFromHinst(
IN HINSTANCE hInst,
IN DWORD dwId)
{
WCHAR rgwcInput[MAX_MSG_LENGTH + 1];
PWCHAR pwszReturn = NULL;
if (LoadString(hInst, dwId, rgwcInput, MAX_MSG_LENGTH))
{
pwszReturn = RutlStrDup(rgwcInput);
}
return pwszReturn;
}
VOID
FreeStringFromHinst(
IN LPCWSTR pwszMessage)
{
RutlFree((PWCHAR)pwszMessage);
}
DWORD
CopyAndCallCB(
IN REPORT_INFO* pInfo,
IN DWORD dwId)
{
DWORD dwErr = NO_ERROR;
PWCHAR pwszTemp = NULL;
GET_REPORT_STRING_CB* pCbInfo = pInfo->pCbInfo;
if (pCbInfo->pwszState)
{
pwszTemp = LoadStringFromHinst(g_hModule, dwId);
if (pwszTemp)
{
lstrcpyn(pCbInfo->pwszState, pwszTemp, MAX_MSG_LENGTH);
FreeStringFromHinst(pwszTemp);
}
else
{
pCbInfo->pwszState[0] = g_pwszNull;
}
}
pCbInfo->dwPercent += ADD_PERCENT_DONE(pInfo->fVerbose);
//
// Call the callback
//
dwErr = pInfo->pCallback(pCbInfo);
//
// Ignore all errors except ERROR_CANCELLED
//
if (dwErr && dwErr != ERROR_CANCELLED)
{
dwErr = NO_ERROR;
}
return dwErr;
}
//
// Get a temp filename of at most MAX_PATH
//
DWORD
CopyTempFileName(
OUT LPCWSTR pwszTempFileName)
{
WCHAR wszTempBuffer[MAX_PATH + 1];
if (!GetTempPath(MAX_PATH, wszTempBuffer) ||
!GetTempFileName(wszTempBuffer, L"RAS", 0, (PWCHAR)pwszTempFileName)
)
{
return GetLastError();
}
else
{
//
// Delete the temp file that was created by GetTempFileName
//
DeleteFile(pwszTempFileName);
return NO_ERROR;
}
}
PWCHAR
CreateHtmFileName(
IN LPCWSTR pwszFile)
{
DWORD dwSize = 0;
WCHAR wszTemp[MAX_PATH] = L"\0";
PWCHAR pwszSearch, pwszReturn = NULL;
static CONST WCHAR c_pwszHtmExt[] = L".htm";
static CONST WCHAR c_pwszHtmlExt[] = L".html";
do
{
dwSize = lstrlen(pwszFile);
if (!dwSize)
{
break;
}
//
// .Net bug# 523850 SECURITY: Specifying the diagnostics report file
// with more than 255 characters causes a buffer overrun
//
// CreateFile fails if you have more than 258 characters in the path
//
if (!ExpandEnvironmentStrings(
pwszFile,
wszTemp,
(sizeof(wszTemp) / sizeof(WCHAR)) - lstrlen(c_pwszHtmExt) - 1)
)
{
break;
}
//
// If string already has .htm, get outta here
//
pwszSearch = (PWCHAR)(pwszFile + dwSize - lstrlen(c_pwszHtmExt));
if (lstrcmpi(pwszSearch, c_pwszHtmExt) == 0)
{
pwszReturn = RutlStrDup(pwszFile);
break;
}
//
// If string already has .html, get outta here
//
pwszSearch = (PWCHAR)(pwszFile + dwSize - lstrlen(c_pwszHtmlExt));
if (lstrcmpi(pwszSearch, c_pwszHtmlExt) == 0)
{
pwszReturn = RutlStrDup(pwszFile);
break;
}
lstrcat(wszTemp, c_pwszHtmExt);
pwszReturn = RutlStrDup(wszTemp);
} while (FALSE);
return pwszReturn;
}
DWORD
CreateReportFile(
IN BUFFER_WRITE_FILE* pBuff,
IN LPCWSTR pwszReport)
{
DWORD dwErr = NO_ERROR;
do
{
if (!pBuff || !pwszReport)
{
dwErr = ERROR_INVALID_PARAMETER;
break;
}
pBuff->hFile = CreateFile(
pwszReport,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if(pBuff->hFile == INVALID_HANDLE_VALUE)
{
dwErr = GetLastError();
pBuff->hFile = NULL;
break;
}
//
// .Net bug# 523037 SECURITY: Specifying the diagnostics report file as
// the Printer Port (LPT1) will cause netsh to hang
//
else if (GetFileType(pBuff->hFile) != FILE_TYPE_DISK)
{
dwErr = ERROR_FILE_NOT_FOUND;
break;
}
dwErr = AllocBufferWriteFile(pBuff);
BREAK_ON_DWERR(dwErr);
dwErr = WriteUnicodeMarker(pBuff);
BREAK_ON_DWERR(dwErr);
} while (FALSE);
if (dwErr)
{
CloseReportFile(pBuff);
}
return dwErr;
}
VOID
CloseReportFile(
IN BUFFER_WRITE_FILE* pBuff)
{
//
// Whistler .NET BUG: 492078
//
if (pBuff && pBuff->hFile)
{
FreeBufferWriteFile(pBuff);
CloseHandle(pBuff->hFile);
pBuff->hFile = NULL;
}
}
DWORD
RasDiagShowAll(
IN REPORT_INFO* pInfo)
{
DWORD dwErr = NO_ERROR;
do
{
dwErr = TraceCollectAll(pInfo);
BREAK_ON_DWERR(dwErr);
dwErr = RasDiagShowInstallation(pInfo);
BREAK_ON_DWERR(dwErr);
dwErr = RasDiagShowConfiguration(pInfo);
BREAK_ON_DWERR(dwErr);
} while (FALSE);
return dwErr;
}
VOID
PrintHtmlHeader(
IN BUFFER_WRITE_FILE* pBuff)
{
static CONST WCHAR c_pwszHtmlStart[] = L" ";
static CONST WCHAR c_pwszBodyStart[] =
L" ";
static CONST WCHAR c_pwszBodyEnd[] = L"";
static CONST WCHAR c_pwszH1End[] = L"
";
BufferWriteFileStrW(pBuff, c_pwszHtmlStart);
BufferWriteMessage(pBuff, g_hModule, MSG_RASDIAG_REPORT_TITLE);
BufferWriteFileStrW(pBuff, c_pwszBodyStart);
BufferWriteMessage(pBuff, g_hModule, MSG_RASDIAG_REPORT_TITLE);
BufferWriteFileStrW(pBuff, c_pwszH1End);
return;
}
VOID
PrintHtmlFooter(
IN BUFFER_WRITE_FILE* pBuff)
{
static CONST WCHAR c_pwszBodyEnd[] = L"