|
|
#include "stdinc.h"
#include "st.h"
#include "stressharness.h"
#include "wfp.h"
#define WFP_INI_SECTION (L"wfp")
#define WFP_INI_KEY_VICTIM (L"Victim")
#define WFP_INI_KEY_MODE (L"Mode")
#define WFP_INI_KEY_USE_SHORTFNAME (L"UseShortnameFile")
#define WFP_INI_KEY_USE_SHORTDNAME (L"UseShortnameDir")
#define WFP_INI_KEY_INSTALL (L"InstallManifest")
#define WFP_INI_KEY_PAUSE_AFTER (L"PauseLength")
#define WFP_INI_KEY_MODE_DELETE_FILES (L"DeleteFiles")
#define WFP_INI_KEY_MODE_TOUCH_FILES (L"TouchFiles")
#define WFP_INI_KEY_MODE_DELETE_DIR (L"DeleteDirectory")
#define WFP_INI_KEY_MODE_DELETE_MAN (L"DeleteManifest")
#define WFP_INI_KEY_MODE_DELETE_CAT (L"DeleteCatalog")
#define WFP_INI_KEY_MODE_HAVOC (L"Havoc")
#define WFP_INI_KEY_MODE_DEFAULT (WFP_INI_KEY_MODE_DELETE_FILES)
BOOL SxspGenerateSxsPath( IN DWORD Flags, IN ULONG PathType, IN PCWSTR AssemblyRootDirectory OPTIONAL, IN SIZE_T AssemblyRootDirectoryCch OPTIONAL, IN PCASSEMBLY_IDENTITY pAssemblyIdentity, OUT CBaseStringBuffer &PathBuffer ) { PROBING_ATTRIBUTE_CACHE pac = { 0 };
return SxspGenerateSxsPath( Flags, PathType, AssemblyRootDirectory, AssemblyRootDirectoryCch, pAssemblyIdentity, &pac, PathBuffer); }
CWfpJobEntry::~CWfpJobEntry() { }
//
// Defaulted
//
BOOL CWfpJobEntry::SetupSelfForRun() { return TRUE; }
BOOL CWfpJobEntry::Cleanup() { FN_PROLOG_WIN32
IFW32FALSE_EXIT(CStressJobEntry::Cleanup());
if ( this->m_buffManifestToInstall.Cch() != 0 ) { //
// Uninstall the assembly that we added
//
SXS_UNINSTALLW Uninstall = { sizeof(Uninstall) };
Uninstall.dwFlags = SXS_UNINSTALL_FLAG_FORCE_DELETE; Uninstall.lpAssemblyIdentity = this->m_buffVictimAssemblyIdentity; IFW32FALSE_EXIT(SxsUninstallW(&Uninstall, NULL));
} FN_EPILOG }
BOOL CWfpJobEntry::GenFileListFrom( PCWSTR pcwszPath, CFusionArray < CStringBuffer > & tgt ) { FN_PROLOG_WIN32
CStringBuffer buffTemp; CFindFile ffile; WIN32_FIND_DATAW findData;
IFW32FALSE_EXIT(tgt.Win32Reset()); IFW32FALSE_EXIT(buffTemp.Win32Assign(pcwszPath, ::wcslen(pcwszPath))); IFW32FALSE_EXIT(buffTemp.Win32RemoveLastPathElement());
ffile.Win32FindFirstFile( pcwszPath, &findData ); if ( ffile != ffile.GetInvalidValue() ) do { IFW32FALSE_EXIT(buffTemp.Win32AppendPathElement( findData.cFileName, wcslen(findData.cFileName))); IFW32FALSE_EXIT(tgt.Win32Append(buffTemp)); } while ( ::FindNextFileW(ffile, &findData) );
FN_EPILOG }
BOOL CWfpJobEntry::RunTest( bool &rfTestSuccessful ) { FN_PROLOG_WIN32;
CSmartAssemblyIdentity pIdent; CSmallStringBuffer buffAssemblyRoot;
SxspGetAssemblyRootDirectory(buffAssemblyRoot);
if ( m_buffVictimAssemblyIdentity.Cch() == 0 ) { //
// Pick an installed assembly at random from the manifests
// directory.
//
CStringBuffer buffRootDir; CFusionArray<CStringBuffer> arrManifestsInstalled;
SxspGetAssemblyRootDirectory(buffRootDir); buffRootDir.Win32AppendPathElement(L"Manifests\\*.manifest", ::wcslen(L"Manifests\\*.manifest")); this->GenFileListFrom(buffRootDir, arrManifestsInstalled);
//
// Repeatedly try getting info on different manifests
//
do { SIZE_T iWhich = rand() % arrManifestsInstalled.GetSize(); struct { SXS_MANIFEST_INFORMATION_BASIC Info; WCHAR wchBuffer[MAX_PATH*3]; } ManifestInfo; if ( SxsQueryManifestInformation( 0, arrManifestsInstalled[iWhich], SXS_QUERY_MANIFEST_INFORMATION_INFOCLASS_BASIC, SXS_QUERY_MANIFEST_INFORMATION_INFOCLASS_BASIC_FLAG_OMIT_SHORTNAME, sizeof(ManifestInfo), &ManifestInfo, NULL) ) { m_buffVictimAssemblyIdentity.Win32Assign( ManifestInfo.Info.lpIdentity, wcslen(ManifestInfo.Info.lpIdentity)); break; }
} while ( TRUE ); }
if ( ( m_buffVictimAssemblyIdentity.Cch() != 0 ) && ( pIdent == NULL ) ) { SxspCreateAssemblyIdentityFromTextualString( m_buffVictimAssemblyIdentity, &pIdent); }
switch ( this->m_eChangeMode ) { case eWfpChangeDeleteFile: case eWfpChangeTouchFile: { int iMethod = rand() % 5; CStringBuffer buffAssemblyPath; CFusionArray<CStringBuffer> buffPickFileList;
//
// Pick a file
//
SxspGenerateSxsPath( 0, SXSP_GENERATE_SXS_PATH_PATHTYPE_ASSEMBLY, buffAssemblyRoot, buffAssemblyRoot.Cch(), pIdent, buffAssemblyPath);
GenFileListFrom(buffAssemblyPath, buffPickFileList); CStringBuffer &cbuffVictim = buffPickFileList[rand() % buffPickFileList.GetSize()];
if ( iMethod == 0 ) { //
// Touch the timestamp
//
CFusionFile ffile; FILETIME ft = { 0, 0 };
IFW32FALSE_EXIT(ffile.Win32CreateFile( cbuffVictim, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, OPEN_EXISTING)); ::SetFileTime(ffile, &ft, &ft, &ft ); } else if ( iMethod == 1 ) { //
// Read from the file
//
CFusionFile ffile; BYTE buff[20]; DWORD dwRead;
IFW32FALSE_EXIT(ffile.Win32CreateFile( cbuffVictim, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING));
::ReadFile( ffile, buff, sizeof(buff), &dwRead, NULL); } else if ( iMethod == 2 ) { //
// Write to an alternate stream
//
CFusionFile ffile; DWORD dwWrite; static const WCHAR pcwszThing[] = L"thing";
cbuffVictim.Win32Append(L":dummy", 6);
IFW32FALSE_EXIT(ffile.Win32CreateFile( cbuffVictim, GENERIC_WRITE, FILE_SHARE_READ, OPEN_EXISTING));
::WriteFile( ffile, pcwszThing, sizeof(pcwszThing), &dwWrite, NULL); } else if ( iMethod == 3 ) { } else if ( iMethod == 4 ) { } } break; case eWfpChangeDeleteDirectory: { //
// Create a list of files to delete in the directory, then blow
// them away. This is probably more guaranteed to get everything
// deleted while WFP is running...
//
CStringBuffer buffPath; CFusionArray<CStringBuffer> arrFilenames; CFindFile finder; WIN32_FIND_DATAW findData;
SxspGenerateSxsPath( 0, SXSP_GENERATE_SXS_PATH_PATHTYPE_ASSEMBLY, buffAssemblyRoot, buffAssemblyRoot.Cch(), pIdent, buffPath);
IFW32FALSE_EXIT(arrFilenames.Win32Initialize()); IFW32FALSE_EXIT(buffPath.Win32AppendPathElement(L"*", 1)); finder.Win32FindFirstFile(buffPath, &findData); IFW32FALSE_EXIT(buffPath.Win32RemoveLastPathElement());
if ( finder != finder.GetInvalidValue() ) do { buffPath.Win32AppendPathElement(findData.cFileName, ::wcslen(findData.cFileName)); arrFilenames.Win32Append(buffPath); buffPath.Win32RemoveLastPathElement(); } while( FindNextFileW( finder, &findData ) );
//
// Now go delete them all.
//
for ( SIZE_T ul = 0; ul < arrFilenames.GetSize(); ul++ ) { DeleteFileW( arrFilenames[ul] ); }
//
// And delete the directory
//
RemoveDirectoryW(buffPath); } break; case eWfpChangeDeleteManifest: case eWfpChangeDeleteCatalog: { CStringBuffer buffTemp; int iOperation = rand() % 2;
//
// Generate the path to this manifest
//
SxspGenerateSxsPath( 0, SXSP_GENERATE_SXS_PATH_PATHTYPE_MANIFEST, buffAssemblyRoot, buffAssemblyRoot.Cch(), pIdent, buffTemp);
if ( this->m_eChangeMode == eWfpChangeDeleteCatalog ) { IFW32FALSE_EXIT(buffTemp.Win32ChangePathExtension( FILE_EXTENSION_CATALOG, FILE_EXTENSION_CATALOG_CCH, eErrorIfNoExtension)); }
if ( iOperation == 0 ) { DeleteFileW(buffTemp); } else { CFusionFile ffile; if ( ffile.Win32CreateFile( buffTemp, GENERIC_WRITE, FILE_SHARE_READ, OPEN_EXISTING ) ) { DWORD dwWritten; WriteFile(ffile, "boom", 4, &dwWritten, NULL); } }
} break; //
// Go change everything everywhere. 50% of the time, delete the file.
// 25% of the time, change the file. 25% of the time, open the file, change it,
// then hold it open.
//
case eWfpChangeCompleteHavoc: { CStringBuffer buffTemp; WIN32_FIND_DATAW data; CFindFile finder; SxspGetAssemblyRootDirectory(buffTemp); buffTemp.Win32AppendPathElement(L"*", 1); finder.Win32FindFirstFile(buffTemp, &data); IFW32FALSE_EXIT(buffTemp.Win32RemoveLastPathElement());
if ( finder != finder.GetInvalidValue() ) do { //
// 1/3 chance of actually hitting the directory
//
if ( ( rand() % 3 ) != 1 ) continue; CFindFile finder2; WIN32_FIND_DATAW data2;
buffTemp.Win32AppendPathElement(buffTemp); buffTemp.Win32AppendPathElement(L"*", 1); finder2.Win32FindFirstFile(buffTemp, &data2); buffTemp.Win32RemoveLastPathElement();
if ( finder2 != finder.GetInvalidValue() ) do { //
// 50% chance of hitting this file
//
if ( ( rand() % 2 ) == 1 ) continue; CStringBuffer ActualTarget; int iOperation = rand() % 4;
ActualTarget.Win32Assign(buffTemp); ActualTarget.Win32AppendPathElement(data2.cFileName, ::wcslen(data2.cFileName));
//
// Most often, we'll just nuke the file
//
if ( ( iOperation == 0 ) || ( iOperation == 1 ) ) { ::DeleteFileW(ActualTarget); } //
// Just touch the first few bytes of the file.
//
else if ( ( iOperation == 2 ) || ( iOperation == 3 ) ) { CFusionFile ffile; DWORD dwWritten;
if ( ffile.Win32CreateFile( ActualTarget, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, OPEN_EXISTING)) { WriteFile( ffile, "boom", 4, &dwWritten, NULL ); }
//
// 20 seconds sounds good enough
//
if ( iOperation == 3 ) { ::Sleep(5000); } } } while ( FindNextFileW( finder2, &data2 ) );
buffTemp.Win32RemoveLastPathElement(); } while ( FindNextFileW(finder, &data) ); } break; }
rfTestSuccessful = true; FN_EPILOG }
CWfpJobEntry::LoadFromSettingsFile( PCWSTR pcwszSettingsFile ) { FN_PROLOG_WIN32
CSmallStringBuffer buffJunk; INT iJunk;
//
// Are we using shortnames for files?
//
IFW32FALSE_EXIT(SxspIsPrivateProfileStringEqual( WFP_INI_SECTION, WFP_INI_KEY_USE_SHORTFNAME, L"no", this->m_fUseShortnameFile, pcwszSettingsFile));
//
// Are we using shortnames for directories?
//
IFW32FALSE_EXIT(SxspIsPrivateProfileStringEqual( WFP_INI_SECTION, WFP_INI_KEY_USE_SHORTDNAME, L"no", this->m_fUseShortnameDirectory, pcwszSettingsFile));
//
// How long are we to wait between twiddling and uninstalling?
//
IFW32FALSE_EXIT(SxspGetPrivateProfileIntW( WFP_INI_SECTION, WFP_INI_KEY_PAUSE_AFTER, 5000, iJunk, pcwszSettingsFile)); this->m_dwPauseBetweenTwiddleAndUninstall = iJunk; //
// The test mode
//
IFW32FALSE_EXIT(SxspGetPrivateProfileStringW( WFP_INI_SECTION, WFP_INI_KEY_MODE, WFP_INI_KEY_MODE_DEFAULT, buffJunk, pcwszSettingsFile));
#define TEST_MODE( mds, mdn ) if (FusionpStrCmpI((WFP_INI_KEY_MODE_##mds), buffJunk) == 0) this->m_eChangeMode = mdn
TEST_MODE(DELETE_FILES, eWfpChangeDeleteFile); TEST_MODE(TOUCH_FILES, eWfpChangeTouchFile); TEST_MODE(DELETE_DIR, eWfpChangeDeleteDirectory); TEST_MODE(DELETE_MAN, eWfpChangeDeleteManifest); TEST_MODE(DELETE_CAT, eWfpChangeDeleteCatalog); TEST_MODE(HAVOC, eWfpChangeCompleteHavoc);
//
// The victim assembly identity
//
IFW32FALSE_EXIT(SxspGetPrivateProfileStringW( WFP_INI_SECTION, WFP_INI_KEY_VICTIM, L"", m_buffVictimAssemblyIdentity, pcwszSettingsFile));
//
// Are we installing an assembly to do this to?
//
IFW32FALSE_EXIT(SxspGetPrivateProfileStringW( WFP_INI_SECTION, WFP_INI_KEY_INSTALL, L"", buffJunk, pcwszSettingsFile));
if ( buffJunk.Cch() != 0 ) { IFW32FALSE_EXIT(this->m_buffManifestToInstall.Win32Assign(this->m_buffTestDirectory)); IFW32FALSE_EXIT(this->m_buffManifestToInstall.Win32AppendPathElement( buffJunk )); } FN_EPILOG }
CWfpJobManager::CWfpJobManager() { //
// Nothing
//
}
CWfpJobManager::~CWfpJobManager() { //
// Nothing
//
}
BOOL CWfpJobManager::CreateJobEntry( CStressJobEntry* &rpJobEntry ) { FN_PROLOG_WIN32 rpJobEntry = NULL; rpJobEntry = FUSION_NEW_SINGLETON(CWfpJobEntry(this)); FN_EPILOG }
|