windows-nt/Source/XPSP1/NT/base/win32/fusion/tools/st/st.cpp
2020-09-26 16:20:57 +08:00

381 lines
11 KiB
C++

#include "stdinc.h"
#include "st.h"
#include "create.h"
#include "install.h"
#include "csrss.h"
#include "wfp.h"
extern "C" { void (__cdecl * _aexit_rtn)(int); }
CEvent ResumeThreadsEvent;
CEvent StopEvent;
LONG ThreadsWaiting;
LONG TotalThreads;
CStringBuffer BaseDirectory;
PCWSTR g_pszImage = L"st";
FILE *g_pLogFile = NULL;
void ReportFailure(const char szFormat[], ...);
extern "C"
{
BOOL WINAPI SxsDllMain(HINSTANCE hInst, DWORD dwReason, PVOID pvReserved);
void __cdecl wmainCRTStartup();
};
void ExeEntry()
{
if (!::SxsDllMain(GetModuleHandleW(NULL), DLL_PROCESS_ATTACH, NULL))
goto Exit;
::wmainCRTStartup();
Exit:
::SxsDllMain(GetModuleHandleW(NULL), DLL_PROCESS_DETACH, NULL);
}
void
ReportFailure(
const char szFormat[],
...
)
{
const DWORD dwLastError = ::FusionpGetLastWin32Error();
va_list ap;
char rgchBuffer[4096];
WCHAR rgchWin32Error[4096];
va_start(ap, szFormat);
_vsnprintf(rgchBuffer, sizeof(rgchBuffer) / sizeof(rgchBuffer[0]), szFormat, ap);
va_end(ap);
if (!::FormatMessageW(
FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
dwLastError,
0,
rgchWin32Error,
NUMBER_OF(rgchWin32Error),
&ap))
{
const DWORD dwLastError2 = ::FusionpGetLastWin32Error();
_snwprintf(rgchWin32Error, sizeof(rgchWin32Error) / sizeof(rgchWin32Error[0]), L"Error formatting Win32 error %lu\nError from FormatMessage is %lu", dwLastError, dwLastError2);
}
fprintf(stderr, "%ls: %s\n%ls\n", g_pszImage, rgchBuffer, rgchWin32Error);
if (g_pLogFile != NULL)
fprintf(g_pLogFile, "%ls: %s\n%ls\n", g_pszImage, rgchBuffer, rgchWin32Error);
}
BOOL Win32Cleanup()
{
FN_PROLOG_WIN32
//
// delete the stuff in the registry and under %windir%\winsxs
//
const static PCWSTR StuffToDelete[] =
{
#if !defined(_AMD64_) && !defined(_M_AMD64)
L"amd64_",
#endif
#if !defined(_IA64_) && !defined(_M_IA64)
L"ia64_",
#endif
L"test"
};
ULONG i = 0;
ULONG j = 0;
CRegKey RegKey;
const static WCHAR RegRootBlah[] = L"Software\\Microsoft\\Windows\\CurrentVersion\\SideBySide\\Installations";
CStringBuffer WindowsDirectory;
IFREGFAILED_ORIGINATE_AND_EXIT(
RegOpenKeyExW(
HKEY_LOCAL_MACHINE,
RegRootBlah,
0,
KEY_ALL_ACCESS | FUSIONP_KEY_WOW64_64KEY,
&RegKey
));
for (j = 0 ; j != NUMBER_OF(StuffToDelete); ++j)
{
SIZE_T k = ::wcslen(StuffToDelete[j]);
BOOL Done = FALSE;
for (i = 0 ; !Done; )
{
CStringBuffer SubKeyName;
FILETIME LastWriteTime;
IFW32FALSE_EXIT(RegKey.EnumKey(i, SubKeyName, &LastWriteTime, &Done));
if (Done)
break;
if (::_wcsnicmp(SubKeyName, StuffToDelete[j], k) == 0)
{
CRegKey SubKey;
printf("stresstool : cleanup : deleting HKLM\\%ls\\%ls\n", RegRootBlah, static_cast<PCWSTR>(SubKeyName));
IFW32FALSE_EXIT(RegKey.OpenSubKey(SubKey, SubKeyName, KEY_ALL_ACCESS | FUSIONP_KEY_WOW64_64KEY));
IFW32FALSE_EXIT(SubKey.DestroyKeyTree());
IFW32FALSE_EXIT(RegKey.DeleteKey(SubKeyName));
}
else
{
++i;
}
}
}
IFW32FALSE_EXIT(WindowsDirectory.Win32ResizeBuffer(MAX_PATH, eDoNotPreserveBufferContents));
{
CStringBufferAccessor StringAccessor(&WindowsDirectory);
IFW32FALSE_EXIT(GetSystemDirectoryW(StringAccessor, StringAccessor.GetBufferCchAsUINT()));
}
WindowsDirectory.RemoveLastPathElement();
for (j = 0 ; j != NUMBER_OF(StuffToDelete); ++j)
{
SIZE_T k = ::wcslen(StuffToDelete[j]);
CSmallStringBuffer StringBuffer;
CSmallStringBuffer StringBuffer2;
WIN32_FIND_DATAW wfd;
IFW32FALSE_EXIT(StringBuffer.Win32Assign(WindowsDirectory));
#define X L"Winsxs\\Manifests"
IFW32FALSE_EXIT(StringBuffer.Win32AppendPathElement(X, NUMBER_OF(X) - 1));
#undef X
IFW32FALSE_EXIT(StringBuffer2.Win32Assign(StringBuffer));
IFW32FALSE_EXIT(StringBuffer.Win32AppendPathElement(L"*", 1));
IFW32FALSE_EXIT(StringBuffer.Win32Append(StuffToDelete[j], k));
IFW32FALSE_EXIT(StringBuffer.Win32Append(L"*", 1));
{
CFindFile FindFileHandle;
if (FindFileHandle.Win32FindFirstFile(StringBuffer, &wfd))
{
do
{
CSmallStringBuffer StringBuffer3;
IFW32FALSE_EXIT(StringBuffer3.Win32Assign(StringBuffer2));
IFW32FALSE_EXIT(StringBuffer3.Win32AppendPathElement(wfd.cFileName, ::wcslen(wfd.cFileName)));
printf("stresstool : cleanup : deleting %ls\n", static_cast<PCWSTR>(StringBuffer3));
DeleteFileW(StringBuffer3);
} while (::FindNextFileW(FindFileHandle, &wfd));
}
}
IFW32FALSE_EXIT(StringBuffer.Win32Assign(WindowsDirectory));
#define X L"Winsxs"
IFW32FALSE_EXIT(StringBuffer.Win32AppendPathElement(X, NUMBER_OF(X) - 1));
#undef X
IFW32FALSE_EXIT(StringBuffer2.Win32Assign(StringBuffer));
IFW32FALSE_EXIT(StringBuffer.Win32AppendPathElement(L"*", 1));
IFW32FALSE_EXIT(StringBuffer.Win32Append(StuffToDelete[j], k));
IFW32FALSE_EXIT(StringBuffer.Win32Append(L"*", 1));
{
CFindFile FindFileHandle;
if (FindFileHandle.Win32FindFirstFile(StringBuffer, &wfd))
{
do
{
CSmallStringBuffer StringBuffer3;
IFW32FALSE_EXIT(StringBuffer3.Win32Assign(StringBuffer2));
IFW32FALSE_EXIT(StringBuffer3.Win32AppendPathElement(wfd.cFileName, ::wcslen(wfd.cFileName)));
printf("deleting %ls\n", static_cast<PCWSTR>(StringBuffer3));
SxspDeleteDirectory(StringBuffer3);
} while (::FindNextFileW(FindFileHandle, &wfd));
}
}
}
FN_EPILOG
}
//
// If we don't do this, control-c makes us fail assertions.
// Instead, handle it more gracefully.
//
BOOL
WINAPI
ConsoleCtrlHandler(
DWORD Event
)
{
if (IsDebuggerPresent())
{
OutputDebugStringA("hardcoded breakpoint upon control-c while in debugger\n");
DebugBreak();
}
switch (Event)
{
default:
case CTRL_C_EVENT:
case CTRL_BREAK_EVENT:
case CTRL_CLOSE_EVENT:
case CTRL_LOGOFF_EVENT:
case CTRL_SHUTDOWN_EVENT:
::SetEvent(StopEvent); // wake up the controller thread
::SetEvent(ResumeThreadsEvent); // in case control-c pressed near the start
break;
}
return TRUE;
}
extern "C" int __cdecl wmain(int argc, wchar_t** argv)
{
int iReturnStatus = EXIT_FAILURE;
//
// Default of 6 hour runtime? Wow..
//
DWORD iRunTime = 6 * 60;
CWfpJobManager WfpStresser;
CStressJobManager* StressManagers[] = { &WfpStresser };
if ((argc < 2) || (argc > 3))
{
fprintf(stderr,
"%ls: Usage:\n"
" %ls <sourcedir> [minutesofstress]\n",
argv[0], argv[0]);
goto Exit;
}
if ( argc == 3 )
{
int iMaybeRunTime = ::_wtoi(argv[2]);
if ( iMaybeRunTime <= 0 )
{
fprintf(stderr, "%ls: Usage: \n %ls <sourcedir> [minutesofstress]\n",
argv[0],
argv[0]);
goto Exit;
}
iRunTime = iMaybeRunTime;
}
ThreadsWaiting = 0;
if (!ResumeThreadsEvent.Win32CreateEvent(TRUE, FALSE))
{
::ReportFailure("CreateEvent\n");
goto Exit;
}
if (!StopEvent.Win32CreateEvent(TRUE, FALSE))
{
::ReportFailure("CreateEvent\n");
goto Exit;
}
::SetConsoleCtrlHandler(ConsoleCtrlHandler, TRUE);
if (!BaseDirectory.Win32Assign(argv[1], wcslen(argv[1])))
goto Exit;
if (!Win32Cleanup())
goto Exit;
if (!InitializeMSIInstallTest())
goto Exit;
if (!InitializeInstall())
goto Exit;
if (!InitializeCreateActCtx())
goto Exit;
if (!InitializeCsrssStress(BaseDirectory, 0))
goto Exit;
{
ULONG ulThreadsCreated;
if (!CsrssStressStartThreads(ulThreadsCreated))
goto Exit;
else
TotalThreads += ulThreadsCreated;
}
for ( ULONG ul = 0; ul < NUMBER_OF(StressManagers); ul++ )
{
CStressJobManager *pManager = StressManagers[ul];
CSmallStringBuffer buffTestDirPath;
ULONG ulThreads;
if ((!buffTestDirPath.Win32Assign(BaseDirectory)) ||
(!buffTestDirPath.Win32Assign(
pManager->GetGroupName(),
::wcslen(pManager->GetGroupName()))))
goto Exit;
if ((!pManager->LoadFromDirectory(buffTestDirPath)) ||
(!pManager->CreateWorkerThreads(&ulThreads)))
goto Exit;
}
// wait for them all to get to their starts (should use a semaphore here)
while (ThreadsWaiting != TotalThreads)
{
Sleep(0);
}
OutputDebugStringA("********************************\n");
OutputDebugStringA("* *\n");
OutputDebugStringA("* start *\n");
OutputDebugStringA("* *\n");
OutputDebugStringA("********************************\n");
// Go!
if (!::SetEvent(ResumeThreadsEvent))
{
::ReportFailure("SetEvent(ResumeThreadsEvent)\n");
goto Exit;
}
//
// Start the WFP stresser
//
for ( ULONG ul = 0; ul < NUMBER_OF(StressManagers); ul++ )
{
if (!StressManagers[ul]->StartJobs())
goto Exit;
}
//
// Let them run a while.
//
iRunTime = iRunTime * 60 * 1000;
::WaitForSingleObject(StopEvent, iRunTime);
RequestShutdownMSIInstallTestThreads();
RequestShutdownInstallThreads();
RequestShutdownCreateActCtxThreads();
RequestCsrssStressShutdown();
for ( ULONG ul = 0; ul < NUMBER_OF(StressManagers); ul++ )
{
StressManagers[ul]->StopJobs();
}
::Sleep(1000);
WaitForMSIInstallTestThreads();
WaitForInstallThreads();
WaitForCreateActCtxThreads();
WaitForCsrssStressShutdown();
for ( ULONG ul = 0; ul < NUMBER_OF(StressManagers); ul++ )
{
StressManagers[ul]->WaitForAllJobsComplete();
}
iReturnStatus = EXIT_SUCCESS;
Exit:
CleanupMSIInstallTest();
CleanupCreateActCtx();
CleanupInstall();
CleanupCsrssTests();
for ( ULONG ul = 0; ul < NUMBER_OF(StressManagers); ul++ )
{
StressManagers[ul]->CleanupJobs();
}
Win32Cleanup();
return iReturnStatus;
}