windows-nt/Source/XPSP1/NT/shell/themes/uxbud/uxbud.cpp
2020-09-26 16:20:57 +08:00

402 lines
10 KiB
C++

//---------------------------------------------------------------------------
// UxBud.cpp - quick cmdline test for uxtheme.dll
//---------------------------------------------------------------------------
#include "stdafx.h"
#include "uxbud.h"
//---------------------------------------------------------------------------
BOOL fQuiet = FALSE;
HANDLE hFileOutput = NULL;
TESTINFO *pTestInfo;
int iTestCount;
//---------------------------------------------------------------------------
void Output(LPCSTR pszFormat, ...)
{
//---- writes to both "uxbud.log" and console ----
va_list args;
va_start(args, pszFormat);
//---- format caller's string ----
CHAR szBigBuff[256];
vsprintf(szBigBuff, pszFormat, args);
if (hFileOutput != INVALID_HANDLE_VALUE)
{
//---- expand all LF to CR/LF ----
CHAR szBuff2[512];
CHAR *s = szBigBuff;
CHAR *p = szBuff2;
while (*s)
{
if (*s == '\n')
{
*p++ = '\r';
}
*p++ = *s++;
}
*p = 0; // zero terminate szBuff2
//---- write expanded buff to log file ----
DWORD dw;
WriteFile(hFileOutput, szBuff2, strlen(szBuff2), &dw, NULL);
}
if (! fQuiet)
printf(szBigBuff);
va_end(args);
}
//-----------------------------------------------------------------
BOOL ReportResults(BOOL fPassed, HRESULT hr, LPCWSTR pszTestName)
{
Output("%S ", pszTestName);
if (fPassed)
{
Output("PASSED\n\n");
}
else
{
if (hr == S_OK)
hr = GetLastError();
WCHAR szBuff[2*MAX_PATH];
if (THEME_PARSING_ERROR(hr))
{
PARSE_ERROR_INFO Info = {sizeof(Info)};
HRESULT hr2 = GetThemeParseErrorInfo(&Info);
if (SUCCEEDED(hr2))
{
lstrcpy(szBuff, Info.szMsg);
}
else
{
wsprintf(szBuff, L"Unknown parsing error");
}
}
else
{
// normal win32 error
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, hr, 0, szBuff, ARRAYSIZE(szBuff), NULL);
}
Output("FAILED [%S]\n\n", pszTestName, szBuff);
}
return fPassed;
}
//---------------------------------------------------------------------------
BOOL RunCmd(LPCWSTR pszExeName, LPCWSTR pszParams, BOOL fHide, BOOL fDisplayParams,
BOOL fWait)
{
HANDLE hInst;
BOOL fRanOk = FALSE;
STARTUPINFO si;
memset(&si, 0, sizeof(si));
si.cb = sizeof(STARTUPINFO);
si.dwFlags = STARTF_FORCEOFFFEEDBACK; // don't mess with our cursor
if (fHide)
{
si.dwFlags |= STARTF_USESHOWWINDOW; // hide window
si.wShowWindow = SW_HIDE;
}
PROCESS_INFORMATION pi;
TCHAR pszBuff[2*_MAX_PATH];
if (pszParams)
wsprintf(pszBuff, _T("%s %s"), pszExeName, pszParams);
else
{
lstrcpy(pszBuff, pszExeName);
}
BOOL bSuccess = CreateProcess(NULL, pszBuff, NULL, NULL,
FALSE, 0, NULL, NULL, &si, &pi);
if (! bSuccess)
goto exit;
hInst = pi.hProcess;
if (! hInst)
goto exit;
if (fWait)
{
//---- wait for process to terminate ----
DWORD dwVal;
dwVal = WaitForSingleObject(hInst, INFINITE);
if (dwVal != WAIT_OBJECT_0)
goto exit;
DWORD dwExitCode;
if (! GetExitCodeProcess(hInst, &dwExitCode))
goto exit;
if (dwExitCode)
goto exit;
}
fRanOk = TRUE;
exit:
if (fWait) // being used for the test...
{
if (fDisplayParams)
Output(" RunCmd: %S (ranok=%d)\n", pszBuff, fRanOk);
else
Output(" RunCmd: %S <params> (ranok=%d)\n", pszExeName, fRanOk);
}
CloseHandle(hInst);
return fRanOk;
}
//---------------------------------------------------------------------------
BOOL TestAll()
{
DWORD dwStartTicks = GetTickCount();
for (int i=0; i < iTestCount; i++)
{
pTestInfo[i].pfnTest();
}
DWORD dwTicks = GetTickCount() - dwStartTicks;
if (! fQuiet)
printf("Total test time: %d secs\n", dwTicks/1000);
return TRUE;
}
//---------------------------------------------------------------------------
void PrintTests()
{
printf("available tests: \n");
for (int i=0; i < iTestCount; i++)
{
printf(" %s \t(%s)\n", pTestInfo[i].pszName, pTestInfo[i].pszDesc);
}
printf("\n");
}
//---------------------------------------------------------------------------
void PrintHelp()
{
printf("\nusage\n");
printf(" uxbud [ <options> ] \n\n");
printf("UxBud will run a set of quick tests to verify basic \"uxtheme.dll\"\n");
printf("functionality. If no options are specified, one pass over the normal\n");
printf("set of tests will be run and the \"uxbud.log\" file created will be \n");
printf("compared against the known good \"uxbud.ok\" log file. This will result\n");
printf("in an overall PASS or FAIL msg at the end of the uxbud run.\n\n");
printf("<options>:\n\n");
printf(" -r <number> (to specify a repeat factor)\n");
printf(" -q (to run in quiet mode\n");
printf(" -? (to print this usage msg\n");
printf(" <test> (to run a specific test\n\n");
PrintTests();
}
//---------------------------------------------------------------------------
BOOL HandleOptions(LPTSTR pszCmdLine, TESTPROC *ppfnTest, int *piRepeat, BOOL *pfQuiet, int *piRetVal)
{
BOOL fContinue = TRUE;
USES_CONVERSION;
*piRetVal = 0;
if ((! pszCmdLine) || (! *pszCmdLine)) // no options
return TRUE;
LPCSTR p = W2A(pszCmdLine);
while ((p) && (*p))
{
while (isspace(*p))
p++;
//---- process switches ----
if ((*p == '/') || (*p == '-'))
{
p++;
if ((*p == 'r') || (*p == 'R')) // repeat factor
{
p++;
while (isspace(*p))
p++;
sscanf(p, "%d", piRepeat);
//---- skip over the scanned number ----
while (isdigit(*p))
p++;
}
else if ((*p == 'q') || (*p == 'Q')) // quiet mode
{
p++;
*pfQuiet = TRUE;
}
else if (*p == '?') // cmdline help
{
p++;
PrintHelp();
fContinue = FALSE;
break;
}
}
else // test name specified
{
for (int i=0; i < iTestCount; i++)
{
if (lstrcmpiA(p, pTestInfo[i].pszName)==0)
{
*ppfnTest = pTestInfo[i].pfnTest;
break;
}
}
if (i == iTestCount) // not found
{
printf("\nError - unrecognized test: %s\n\n", p);
PrintTests();
*piRetVal = 1;
fContinue = FALSE;
}
break;
}
}
return fContinue;
}
//---------------------------------------------------------------------------
BOOL FileCompare(LPCWSTR pszName1, LPCWSTR pszName2)
{
BOOL fSame = FALSE;
HANDLE hFile1 = NULL;
HANDLE hFile2 = NULL;
CHAR *pszBuff1 = NULL;
CHAR *pszBuff2= NULL;
DWORD dw1, dw2;
//---- open files ----
hFile1 = CreateFile(pszName1, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
if (hFile1 == INVALID_HANDLE_VALUE)
goto exit;
hFile2 = CreateFile(pszName2, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
if (hFile2 == INVALID_HANDLE_VALUE)
goto exit;
DWORD dwSize1, dwSize2;
dwSize1 = GetFileSize(hFile1, NULL);
dwSize2 = GetFileSize(hFile1, NULL);
if ((! dwSize1) || (dwSize1 != dwSize2))
goto exit;
pszBuff1 = new CHAR[dwSize1];
if (! pszBuff1)
goto exit;
pszBuff2 = new CHAR[dwSize1];
if (! pszBuff2)
goto exit;
ReadFile(hFile1, pszBuff1, dwSize1, &dw1, NULL);
ReadFile(hFile2, pszBuff2, dwSize1, &dw2, NULL);
if ((dw1 != dwSize1) || (dw2 != dwSize1))
goto exit;
if (memcmp(pszBuff1, pszBuff2, dwSize1)!=0)
goto exit;
fSame = TRUE;
exit:
delete [] pszBuff1;
delete [] pszBuff2;
CloseHandle(hFile1);
CloseHandle(hFile2);
return fSame;
}
//---------------------------------------------------------------------------
extern "C" WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE previnst,
LPTSTR pszCmdLine, int nShowCmd)
{
//---- default run params ----
int iRepeat = 1;
int iRetVal = 0;
TESTPROC pfnTest = TestAll;
GetTestInfo(&pTestInfo, &iTestCount);
if (! HandleOptions(pszCmdLine, &pfnTest, &iRepeat, &fQuiet, &iRetVal))
return iRetVal;
//---- create the log file ----
hFileOutput = CreateFile(L"uxbud.log", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
if (hFileOutput == INVALID_HANDLE_VALUE)
{
printf("\nError - could not open uxbud.log output file\n");
return 1;
}
printf("\nUxBud - quick (under 3 mins) test for uxtheme.dll (version 1.0)\n\n");
if (iRepeat > 1)
Output("REPEAT FACTOR=%d\n\n", iRepeat);
//---- run the needed test ----
for (int i=0; i < iRepeat; i++)
{
if (iRepeat > 1)
Output("TEST PASS: %d\n\n", i);
pfnTest();
}
//---- close the log file ----
if (hFileOutput)
CloseHandle(hFileOutput);
if ((iRepeat == 1) && (pfnTest == TestAll)) // standard run
{
if (FileCompare(L"uxbud.log", L"uxbud.ok"))
{
printf("*** UxBud PASSED ****\n");
}
else
{
printf("\nFailure detected - running: windiff uxbud.ok uxbud.log...)\n\n");
printf("*** UxBud FAILED ****\n");
RunCmd(L"windiff", L"uxbud.ok uxbud.log", TRUE, FALSE, FALSE);
}
}
return 0;
}
//---------------------------------------------------------------------------