|
|
#include "stdinc.h"
#include "csrss.h"
#define CSRSS_TEST_DIR_NAME (L"csrss")
#define CSRSS_TEST_DIR_NAME_CCH (NUMBER_OF(CSRSS_TEST_DIR_NAME) - 1)
#define CSRSS_SETTINGS_FILE_NAME (L"csrss.ini")
#define CSRSS_SETTINGS_FILE_NAME_CCH (NUMBER_OF(CSRSS_SETTINGS_FILE_NAME) - 1)
#define CSRSS_INI_SECTION_TITLE (L"csrss")
BOOL pOpenStreamOnFile( PCWSTR pcwszFilename, IStream** ppStream, PCWSTR pcwszResourceType = NULL, PCWSTR pcwszResourceName = NULL, WORD Language = 0) { FN_PROLOG_WIN32
PARAMETER_CHECK(pcwszFilename); PARAMETER_CHECK(ppStream);
*ppStream = NULL;
//
// If this is non-null, then we have to open the file as an image and get the
// resource specified. Otherwise, we just open the file like a normal file.
//
if ( pcwszResourceName ) { CResourceStream *pResourceStream = NULL;
IFW32NULL_EXIT(pResourceStream = FUSION_NEW_SINGLETON(CResourceStream)); IFW32FALSE_EXIT(pResourceStream->Initialize( pcwszFilename, pcwszResourceType, pcwszResourceName, Language)); *ppStream = pResourceStream; } else { CReferenceCountedFileStream *pFileStream = NULL; CImpersonationData ImpData; IFW32NULL_EXIT(pFileStream = FUSION_NEW_SINGLETON(CReferenceCountedFileStream)); IFW32FALSE_EXIT(pFileStream->OpenForRead(pcwszFilename, ImpData, FILE_SHARE_READ, OPEN_EXISTING, 0)); *ppStream = pFileStream; }
if ( *ppStream ) (*ppStream)->AddRef();
FN_EPILOG }
BOOL ParseDecimalOrHexString(PCWSTR pcwszString, SIZE_T cch, ULONG &out ) { BOOL fIsHex;
FN_PROLOG_WIN32
PARAMETER_CHECK(pcwszString != NULL); fIsHex = ((cch > 2 ) && ( pcwszString[0] == L'0' ) && ((pcwszString[1] == L'x') || (pcwszString[1] == L'X')));
if ( fIsHex ) { pcwszString += 2; cch -= 2; }
out = 0;
while ( cch ) { const int val = SxspHexDigitToValue((*pcwszString)); PARAMETER_CHECK( fIsHex || ( val < 10 ) ); out = out * ( fIsHex ? 16 : 10 ) + val; cch--; pcwszString++; }
FN_EPILOG }
class CCsrssPoundingThreadEntry { PRIVATIZE_COPY_CONSTRUCTORS(CCsrssPoundingThreadEntry); public: CDequeLinkage Linkage; SXS_GENERATE_ACTIVATION_CONTEXT_PARAMETERS Request; ULONG ulRuns; BOOL fStopNextRound; BOOL fShouldSucceed; CThread hOurThreadHandle; CStringBuffer buffTestDirectory; CSmallStringBuffer buffTestName; DWORD dwSleepTime;
CSmallStringBuffer buffProcArch; CStringBuffer buffAssemblyDirectory; CStringBuffer buffTextualIdentityString; CStringBuffer buffManifestStreamPath; CStringBuffer buffPolicyStreamPath;
CCsrssPoundingThreadEntry() : ulRuns(0), fStopNextRound(FALSE) { } BOOL AcquireSettingsFrom( PCWSTR pcwszSettingsFile ); DWORD DoWork(); BOOL StopAndWaitForCompletion();
static DWORD WINAPI ThreadProcEntry( PVOID pv ) { CCsrssPoundingThreadEntry *pEntry = NULL;
pEntry = reinterpret_cast<CCsrssPoundingThreadEntry*>(pv); return ( pEntry != NULL ) ? pEntry->DoWork() : 0; } };
BOOL CCsrssPoundingThreadEntry::StopAndWaitForCompletion() { this->fStopNextRound = true; return WaitForSingleObject(this->hOurThreadHandle, INFINITE) == WAIT_OBJECT_0; }
DWORD CCsrssPoundingThreadEntry::DoWork() { if ( !WaitForThreadResumeEvent() ) goto Exit;
while ( !this->fStopNextRound ) { //
// Call to generate the structure
//
BOOL fResult; SXS_GENERATE_ACTIVATION_CONTEXT_PARAMETERS TempParams = this->Request; CSmartRef<IStream> isManifest; CSmartRef<IStream> isPolicy;
if ( this->buffManifestStreamPath.Cch() != 0 ) { if (pOpenStreamOnFile(this->buffManifestStreamPath, &isManifest)) { TempParams.Manifest.Path = this->buffManifestStreamPath; TempParams.Manifest.PathType = ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE; TempParams.Manifest.Stream = isManifest; } }
if ( this->buffPolicyStreamPath.Cch() != 0 ) { if (pOpenStreamOnFile(this->buffPolicyStreamPath, &isPolicy)) { TempParams.Policy.Path = this->buffManifestStreamPath; TempParams.Policy.PathType = ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE; TempParams.Policy.Stream = isPolicy; } }
fResult = SxsGenerateActivationContext( &TempParams );
//
// Did we fail when we were to succeed, or succeed when we were to fail?
//
if ( ( !fResult && this->fShouldSucceed ) || ( fResult && !this->fShouldSucceed ) ) { const DWORD dwLastError = ::FusionpGetLastWin32Error(); ::ReportFailure("CsrssStress: Test %ls expected %ls, got %ls; Error %ld\n", static_cast<PCWSTR>(this->buffTestName), this->fShouldSucceed ? L"success" : L"failure", fResult ? L"success" : L"failure", dwLastError); } else { wprintf(L"CsrssStress: Test %ls passed\n", static_cast<PCWSTR>(this->buffTestName)); }
if ((TempParams.SectionObjectHandle != INVALID_HANDLE_VALUE ) && (TempParams.SectionObjectHandle != NULL)) { CloseHandle(TempParams.SectionObjectHandle); }
if ( !this->fStopNextRound ) ::Sleep(this->dwSleepTime); }
Exit: return 0; }
#define SLEN(n) (NUMBER_OF(n)-1)
#define CSRSS_INI_KEY_PROC_ARCH (L"ProcArch")
#define CSRSS_INI_KEY_PROC_ARCH_CCH SLEN(CSRSS_INI_KEY_PROC_ARCH)
#define CSRSS_INI_KEY_LANGID (L"LangId")
#define CSRSS_INI_KEY_LANGID_CCH SLEN(CSRSS_INI_KEY_PROC_ARCH)
#define CSRSS_INI_KEY_ASMDIR (L"AssemblyDirectory")
#define CSRSS_INI_KEY_ASMDIR_CCH SLEN(CSRSS_INI_KEY_PROC_ARCH)
#define CSRSS_INI_KEY_TEXTUALIDENT (L"TextualIdentity")
#define CSRSS_INI_KEY_TEXTUALIDENT_CCH SLEN(CSRSS_INI_KEY_PROC_ARCH)
#define CSRSS_INI_KEY_MANIFEST (L"ManifestPath")
#define CSRSS_INI_KEY_MANIFEST_CCH SLEN(CSRSS_INI_KEY_PROC_ARCH)
#define CSRSS_INI_KEY_POLICY (L"PolicyPath")
#define CSRSS_INI_KEY_POLICY_CCH SLEN(CSRSS_INI_KEY_PROC_ARCH)
#define CSRSS_INI_KEY_SUCCESS (L"ShouldSucceed")
#define CSRSS_INI_KEY_SUCCESS_CCH SLEN(CSRSS_INI_KEY_SUCCESS)
#define CSRSS_INI_KEY_SLEEP (L"SleepTime")
#define CSRSS_INI_KEY_SLEEP_CCH SLEN(CSRSS_INI_KEY_SLEEP)
#define CSRSS_INI_KEY_SYSDEFAULTIDENTFLAG (L"SysDefaultTextualIdentityFlag")
#define CSRSS_INI_KEY_SYSDEFAULTIDENTFLAG_CCH SLEN(CSRSS_INI_KEY_SYSDEFAULTIDENTFLAG)
#define CSRSS_INI_KEY_TEXTUALIDENTFLAG (L"TextualIdentityFlag")
#define CSRSS_INI_KEY_TEXTUALIDENTFLAG_CCH SLEN(CSRSS_INI_KEY_TEXTUALIDENTFLAG);
BOOL CCsrssPoundingThreadEntry::AcquireSettingsFrom( PCWSTR pcwszSettingsFile ) { FN_PROLOG_WIN32
LANGID lidCurrentLang = GetUserDefaultUILanguage(); CSmallStringBuffer buffJunk; BOOL fDumpBool; ZeroMemory(&this->Request, sizeof(this->Request)); //
// Format of the settings file:
//
// [testname]
// SysDefaultTextualIdentityFlag = yes|no (add SXS_GENERATE_ACTIVATION_CONTEXT_FLAG_SYSTEM_DEFAULT_TEXTUAL_ASSEMBLY_IDENTITY)
// TextualIdentityFlag = yes|no (add SXS_GENERATE_ACTIVATION_CONTEXT_FLAG_TEXTUAL_ASSEMBLY_IDENTITY)
// ProcArch = PA ident string (will use FusionpParseProcessorArchitecture)
// LangId = number or string
// AssemblyDirectory = dirname
// TextualIdentity = textualIdentityString
// ManifestPath = manifest name under test directory
// PolicyPath = policy path file name under test directory
// ShouldSucceed = yes|no - whether this test succeeds or fails
//
// Flags is required.
// PA and LangId, if not present, are defaulted to the current user's settings.
// AssemblyDirectory, if not present, defaults to %systemroot%\winsxs
// TextualIdentity is required.
// ManifestPath is required.
//
// If textualIdentity is present, then the streams are not created.
//
//
// Flags are set by key names
//
IFW32FALSE_EXIT(SxspIsPrivateProfileStringEqual(CSRSS_INI_SECTION_TITLE, CSRSS_INI_KEY_SYSDEFAULTIDENTFLAG, L"yes", fDumpBool, pcwszSettingsFile)); if ( fDumpBool ) this->Request.Flags |= SXS_GENERATE_ACTIVATION_CONTEXT_FLAG_SYSTEM_DEFAULT_TEXTUAL_ASSEMBLY_IDENTITY;
IFW32FALSE_EXIT(SxspIsPrivateProfileStringEqual(CSRSS_INI_SECTION_TITLE, CSRSS_INI_KEY_TEXTUALIDENTFLAG, L"yes", fDumpBool, pcwszSettingsFile)); if ( fDumpBool ) this->Request.Flags |= SXS_GENERATE_ACTIVATION_CONTEXT_FLAG_TEXTUAL_ASSEMBLY_IDENTITY;
//
// Get the success/failure value
//
IFW32FALSE_EXIT(SxspIsPrivateProfileStringEqual(CSRSS_INI_SECTION_TITLE, CSRSS_INI_KEY_SUCCESS, L"yes", this->fShouldSucceed, pcwszSettingsFile)); //
// And how long this is to sleep
//
INT dump; IFW32FALSE_EXIT(SxspGetPrivateProfileIntW(CSRSS_INI_SECTION_TITLE, CSRSS_INI_KEY_SLEEP, 200, dump, pcwszSettingsFile)); this->dwSleepTime = dump; //
// PA setting is a string
//
IFW32FALSE_EXIT(SxspGetPrivateProfileStringW(CSRSS_INI_SECTION_TITLE, CSRSS_INI_KEY_PROC_ARCH, L"x86", buffJunk, pcwszSettingsFile)); if ( buffJunk.Cch() != 0 ) { bool fValid = false; IFW32FALSE_EXIT(FusionpParseProcessorArchitecture( buffJunk, buffJunk.Cch(), &this->Request.ProcessorArchitecture, fValid)); if ( !fValid ) this->Request.ProcessorArchitecture = PROCESSOR_ARCHITECTURE_INTEL; } else { this->Request.ProcessorArchitecture = PROCESSOR_ARCHITECTURE_INTEL; } //
// Maybe this is a string like en-us, or maybe just a number.
//
IFW32FALSE_EXIT(SxspGetPrivateProfileStringW(CSRSS_INI_SECTION_TITLE, CSRSS_INI_KEY_LANGID, L"", buffJunk, pcwszSettingsFile)); if ( buffJunk.Cch() != 0 ) { ULONG ulTemp; if ( !ParseDecimalOrHexString(buffJunk, buffJunk.Cch(), ulTemp) ) { BOOL fFound = FALSE;
IFW32FALSE_EXIT(SxspMapCultureToLANGID(buffJunk, lidCurrentLang, &fFound)); if ( !fFound ) { goto Exit; } } else lidCurrentLang = static_cast<LANGID>(ulTemp); } this->Request.LangId = lidCurrentLang; //
// Assembly root directory. Not really required to be present?
//
IFW32FALSE_EXIT(SxspGetAssemblyRootDirectory(buffJunk)); IFW32FALSE_EXIT(SxspGetPrivateProfileStringW(CSRSS_INI_SECTION_TITLE, CSRSS_INI_KEY_ASMDIR, buffJunk, this->buffAssemblyDirectory, pcwszSettingsFile)); this->Request.AssemblyDirectory = this->buffAssemblyDirectory;
//
// Textual identity string - if not present, null out the value
//
IFW32FALSE_EXIT(SxspGetPrivateProfileStringW(CSRSS_INI_SECTION_TITLE, CSRSS_INI_KEY_TEXTUALIDENT, L"", this->buffTextualIdentityString, pcwszSettingsFile)); if ( this->buffTextualIdentityString.Cch() != 0 ) { this->Request.TextualAssemblyIdentity = this->buffTextualIdentityString; }
//
// File paths
//
IFW32FALSE_EXIT(SxspGetPrivateProfileStringW(CSRSS_INI_SECTION_TITLE, CSRSS_INI_KEY_MANIFEST, L"", buffJunk, pcwszSettingsFile)); if ( buffJunk.Cch() != 0 ) { IFW32FALSE_EXIT(this->buffManifestStreamPath.Win32Assign(this->buffTestDirectory)); IFW32FALSE_EXIT(this->buffManifestStreamPath.Win32AppendPathElement(buffJunk)); }
IFW32FALSE_EXIT(SxspGetPrivateProfileStringW(CSRSS_INI_SECTION_TITLE, CSRSS_INI_KEY_POLICY, L"", buffJunk, pcwszSettingsFile)); if ( buffJunk.Cch() != 0 ) { IFW32FALSE_EXIT(this->buffPolicyStreamPath.Win32Assign(this->buffTestDirectory)); IFW32FALSE_EXIT(this->buffPolicyStreamPath.Win32AppendPathElement(buffJunk)); }
FN_EPILOG }
typedef CDeque<CCsrssPoundingThreadEntry, offsetof(CCsrssPoundingThreadEntry, Linkage)> CStressEntryDeque; typedef CDequeIterator<CCsrssPoundingThreadEntry, offsetof(CCsrssPoundingThreadEntry, Linkage)> CStressEntryDequeIter;
CStressEntryDeque g_CsrssStressers;
BOOL InitializeCsrssStress( PCWSTR pcwszTargetDirectory, DWORD dwFlags ) { FN_PROLOG_WIN32
CFindFile Finder; WIN32_FIND_DATAW FindData; CStringBuffer buffTemp; CStringBuffer buffTestActualRoot;
//
// The target directory here is the root of all the test case dirs, not the
// csrss-specific directory.
//
IFW32FALSE_EXIT(buffTestActualRoot.Win32Assign( pcwszTargetDirectory, wcslen(pcwszTargetDirectory))); IFW32FALSE_EXIT(buffTestActualRoot.Win32AppendPathElement( CSRSS_TEST_DIR_NAME, CSRSS_TEST_DIR_NAME_CCH));
if ((FindData.dwFileAttributes = ::GetFileAttributesW(buffTestActualRoot)) == 0xffffffff && (FindData.dwFileAttributes = ::FusionpGetLastWin32Error()) == ERROR_FILE_NOT_FOUND) { printf("no %ls tests, skipping\n", CSRSS_TEST_DIR_NAME); FN_SUCCESSFUL_EXIT(); } IFW32FALSE_EXIT(buffTestActualRoot.Win32AppendPathElement(L"*", 1)); IFW32FALSE_EXIT(Finder.Win32FindFirstFile(buffTestActualRoot, &FindData)); IFW32FALSE_EXIT(buffTestActualRoot.Win32RemoveLastPathElement());
do { CStringBuffer buffSettingsFile; CCsrssPoundingThreadEntry *TestEntry;
if (( ( FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) == 0 ) || FusionpIsDotOrDotDot(FindData.cFileName)) { continue; }
//
// Tack on the name of this test
//
IFW32NULL_EXIT(TestEntry = FUSION_NEW_SINGLETON(CCsrssPoundingThreadEntry)); IFW32FALSE_EXIT(TestEntry->buffTestName.Win32Assign( FindData.cFileName, wcslen(FindData.cFileName))); IFW32FALSE_EXIT(TestEntry->buffTestDirectory.Win32Assign(buffTestActualRoot)); IFW32FALSE_EXIT(TestEntry->buffTestDirectory.Win32AppendPathElement( FindData.cFileName, wcslen(FindData.cFileName)));
IFW32FALSE_EXIT(buffSettingsFile.Win32Assign(TestEntry->buffTestDirectory)); IFW32FALSE_EXIT(buffSettingsFile.Win32AppendPathElement( CSRSS_SETTINGS_FILE_NAME, CSRSS_SETTINGS_FILE_NAME_CCH));
//
// Acquire settings for this test
//
IFW32FALSE_EXIT(TestEntry->AcquireSettingsFrom(buffSettingsFile)); g_CsrssStressers.AddToTail(TestEntry); TestEntry = NULL; } while (::FindNextFileW(Finder, &FindData));
FN_EPILOG }
BOOL WaitForCsrssStressShutdown() { FN_PROLOG_WIN32
CStressEntryDequeIter Iter(&g_CsrssStressers);
for ( Iter.Reset(); Iter.More(); Iter.Next() ) { CCsrssPoundingThreadEntry *Item = Iter.Current(); Item->StopAndWaitForCompletion(); Item->hOurThreadHandle.Win32Close(); }
FN_EPILOG }
BOOL CsrssStressStartThreads( ULONG &ulThreadsCreated ) { FN_PROLOG_WIN32
CStressEntryDequeIter Iter(&g_CsrssStressers);
ulThreadsCreated = 0;
for ( Iter.Reset(); Iter.More(); Iter.Next() ) { CCsrssPoundingThreadEntry *Item = Iter.Current();
IFW32FALSE_EXIT(Item->hOurThreadHandle.Win32CreateThread( Item->ThreadProcEntry, Item)); ulThreadsCreated++; }
FN_EPILOG }
BOOL CleanupCsrssTests() { FN_PROLOG_WIN32
g_CsrssStressers.ClearAndDeleteAll(); FN_EPILOG }
RequestCsrssStressShutdown() { FN_PROLOG_WIN32
CStressEntryDequeIter Iter(&g_CsrssStressers);
for ( Iter.Reset(); Iter.More(); Iter.Next() ) { CCsrssPoundingThreadEntry *Item = Iter.Current(); Item->fStopNextRound = true; } FN_EPILOG }
|