Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

499 lines
16 KiB

  1. #include "stdinc.h"
  2. #include "csrss.h"
  3. #define CSRSS_TEST_DIR_NAME (L"csrss")
  4. #define CSRSS_TEST_DIR_NAME_CCH (NUMBER_OF(CSRSS_TEST_DIR_NAME) - 1)
  5. #define CSRSS_SETTINGS_FILE_NAME (L"csrss.ini")
  6. #define CSRSS_SETTINGS_FILE_NAME_CCH (NUMBER_OF(CSRSS_SETTINGS_FILE_NAME) - 1)
  7. BOOL pOpenStreamOnFile(
  8. PCWSTR pcwszFilename,
  9. IStream** ppStream,
  10. PCWSTR pcwszResourceType = NULL,
  11. PCWSTR pcwszResourceName = NULL,
  12. WORD Language = 0)
  13. {
  14. FN_PROLOG_WIN32
  15. PARAMETER_CHECK(pcwszFilename);
  16. PARAMETER_CHECK(ppStream);
  17. *ppStream = NULL;
  18. //
  19. // If this is non-null, then we have to open the file as an image and get the
  20. // resource specified. Otherwise, we just open the file like a normal file.
  21. //
  22. if ( pcwszResourceName )
  23. {
  24. CResourceStream *pResourceStream = NULL;
  25. IFW32NULL_EXIT(pResourceStream = FUSION_NEW_SINGLETON(CResourceStream));
  26. IFW32FALSE_EXIT(pResourceStream->Initialize(
  27. pcwszFilename,
  28. pcwszResourceType,
  29. pcwszResourceName,
  30. Language));
  31. *ppStream = pResourceStream;
  32. }
  33. else
  34. {
  35. CReferenceCountedFileStream *pFileStream = NULL;
  36. CImpersonationData ImpData;
  37. IFW32NULL_EXIT(pFileStream = FUSION_NEW_SINGLETON(CReferenceCountedFileStream));
  38. IFW32FALSE_EXIT(pFileStream->OpenForRead(pcwszFilename, ImpData, FILE_SHARE_READ, OPEN_EXISTING, 0));
  39. *ppStream = pFileStream;
  40. }
  41. if ( *ppStream ) (*ppStream)->AddRef();
  42. FN_EPILOG
  43. }
  44. BOOL ParseDecimalOrHexString(PCWSTR pcwszString, SIZE_T cch, ULONG &out )
  45. {
  46. BOOL fIsHex;
  47. FN_PROLOG_WIN32
  48. PARAMETER_CHECK(pcwszString != NULL);
  49. fIsHex = ((cch > 2 ) && ( pcwszString[0] == L'0' ) &&
  50. ((pcwszString[1] == L'x') || (pcwszString[1] == L'X')));
  51. if ( fIsHex )
  52. {
  53. pcwszString += 2;
  54. cch -= 2;
  55. }
  56. out = 0;
  57. while ( cch )
  58. {
  59. const int val = SxspHexDigitToValue((*pcwszString));
  60. PARAMETER_CHECK( fIsHex || ( val < 10 ) );
  61. out = out * ( fIsHex ? 16 : 10 ) + val;
  62. cch--;
  63. pcwszString++;
  64. }
  65. FN_EPILOG
  66. }
  67. class CCsrssPoundingThreadEntry
  68. {
  69. public:
  70. CDequeLinkage Linkage;
  71. SXS_GENERATE_ACTIVATION_CONTEXT_PARAMETERS Request;
  72. ULONG ulRuns;
  73. BOOL fStopNextRound;
  74. BOOL fShouldSucceed;
  75. CThread hOurThreadHandle;
  76. CStringBuffer buffTestDirectory;
  77. CSmallStringBuffer buffTestName;
  78. DWORD dwSleepTime;
  79. CSmallStringBuffer buffProcArch;
  80. CStringBuffer buffAssemblyDirectory;
  81. CStringBuffer buffTextualIdentityString;
  82. CStringBuffer buffManifestStreamPath;
  83. CStringBuffer buffPolicyStreamPath;
  84. CCsrssPoundingThreadEntry() : ulRuns(0), fStopNextRound(FALSE) { }
  85. BOOL AcquireSettingsFrom( PCWSTR pcwszSettingsFile );
  86. DWORD DoWork();
  87. BOOL StopAndWaitForCompletion();
  88. static DWORD WINAPI ThreadProcEntry( PVOID pv )
  89. {
  90. CCsrssPoundingThreadEntry *pEntry = NULL;
  91. pEntry = reinterpret_cast<CCsrssPoundingThreadEntry*>(pv);
  92. return ( pEntry != NULL ) ? pEntry->DoWork() : 0;
  93. }
  94. };
  95. BOOL
  96. CCsrssPoundingThreadEntry::StopAndWaitForCompletion()
  97. {
  98. this->fStopNextRound = true;
  99. return WaitForSingleObject(this->hOurThreadHandle, INFINITE) == WAIT_OBJECT_0;
  100. }
  101. DWORD
  102. CCsrssPoundingThreadEntry::DoWork()
  103. {
  104. if ( !WaitForThreadResumeEvent() )
  105. goto Exit;
  106. while ( !this->fStopNextRound )
  107. {
  108. //
  109. // Call to generate the structure
  110. //
  111. BOOL fResult;
  112. SXS_GENERATE_ACTIVATION_CONTEXT_PARAMETERS TempParams = this->Request;
  113. CSmartRef<IStream> isManifest;
  114. CSmartRef<IStream> isPolicy;
  115. if ( this->buffManifestStreamPath.Cch() != 0 )
  116. {
  117. if (pOpenStreamOnFile(this->buffManifestStreamPath, &isManifest))
  118. {
  119. TempParams.Manifest.Path = this->buffManifestStreamPath;
  120. TempParams.Manifest.PathType = ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE;
  121. TempParams.Manifest.Stream = isManifest;
  122. }
  123. }
  124. if ( this->buffPolicyStreamPath.Cch() != 0 )
  125. {
  126. if (pOpenStreamOnFile(this->buffPolicyStreamPath, &isPolicy))
  127. {
  128. TempParams.Policy.Path = this->buffManifestStreamPath;
  129. TempParams.Policy.PathType = ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE;
  130. TempParams.Policy.Stream = isPolicy;
  131. }
  132. }
  133. fResult = SxsGenerateActivationContext( &TempParams );
  134. //
  135. // Did we fail when we were to succeed, or succeed when we were to fail?
  136. //
  137. if ( ( !fResult && this->fShouldSucceed ) || ( fResult && this->fShouldSucceed ) )
  138. {
  139. const DWORD dwLastError = ::FusionpGetLastWin32Error();
  140. ::ReportFailure("CsrssStress: Test %ls expected %ls, got %ls; Error %ld\n",
  141. static_cast<PCWSTR>(this->buffTestName),
  142. this->fShouldSucceed ? L"success" : L"failure",
  143. fResult ? L"success" : L"failure",
  144. dwLastError);
  145. }
  146. else
  147. {
  148. wprintf(L"CsrssStress: Test %ls passed\n", static_cast<PCWSTR>(this->buffTestName));
  149. }
  150. if ((TempParams.SectionObjectHandle != INVALID_HANDLE_VALUE ) &&
  151. (TempParams.SectionObjectHandle != NULL))
  152. {
  153. CloseHandle(TempParams.SectionObjectHandle);
  154. }
  155. if ( !this->fStopNextRound )
  156. ::Sleep(this->dwSleepTime);
  157. }
  158. Exit:
  159. return 0;
  160. }
  161. #define SLEN(n) (NUMBER_OF(n)-1)
  162. #define CSRSS_INI_KEY_PROC_ARCH (L"ProcArch")
  163. #define CSRSS_INI_KEY_PROC_ARCH_CCH SLEN(CSRSS_INI_KEY_PROC_ARCH)
  164. #define CSRSS_INI_KEY_LANGID (L"LangId")
  165. #define CSRSS_INI_KEY_LANGID_CCH SLEN(CSRSS_INI_KEY_PROC_ARCH)
  166. #define CSRSS_INI_KEY_ASMDIR (L"AssemblyDirectory")
  167. #define CSRSS_INI_KEY_ASMDIR_CCH SLEN(CSRSS_INI_KEY_PROC_ARCH)
  168. #define CSRSS_INI_KEY_TEXTUALIDENT (L"TextualIdentity")
  169. #define CSRSS_INI_KEY_TEXTUALIDENT_CCH SLEN(CSRSS_INI_KEY_PROC_ARCH)
  170. #define CSRSS_INI_KEY_MANIFEST (L"ManifestPath")
  171. #define CSRSS_INI_KEY_MANIFEST_CCH SLEN(CSRSS_INI_KEY_PROC_ARCH)
  172. #define CSRSS_INI_KEY_POLICY (L"PolicyPath")
  173. #define CSRSS_INI_KEY_POLICY_CCH SLEN(CSRSS_INI_KEY_PROC_ARCH)
  174. #define CSRSS_INI_KEY_SUCCESS (L"ShouldSucceed")
  175. #define CSRSS_INI_KEY_SUCCESS_CCH SLEN(CSRSS_INI_KEY_SUCCESS)
  176. #define CSRSS_INI_KEY_SLEEP (L"SleepTime")
  177. #define CSRSS_INI_KEY_SLEEP_CCH SLEN(CSRSS_INI_KEY_SLEEP)
  178. #define CSRSS_INI_KEY_SYSDEFAULTIDENTFLAG (L"SysDefaultTextualIdentityFlag")
  179. #define CSRSS_INI_KEY_SYSDEFAULTIDENTFLAG_CCH SLEN(CSRSS_INI_KEY_SYSDEFAULTIDENTFLAG)
  180. #define CSRSS_INI_KEY_TEXTUALIDENTFLAG (L"TextualIdentityFlag")
  181. #define CSRSS_INI_KEY_TEXTUALIDENTFLAG_CCH SLEN(CSRSS_INI_KEY_TEXTUALIDENTFLAG);
  182. BOOL CCsrssPoundingThreadEntry::AcquireSettingsFrom( PCWSTR pcwszSettingsFile )
  183. {
  184. FN_PROLOG_WIN32
  185. LANGID lidCurrentLang = GetUserDefaultUILanguage();
  186. CSmallStringBuffer buffJunk;
  187. BOOL fDumpBool;
  188. ZeroMemory(&this->Request, sizeof(this->Request));
  189. //
  190. // Format of the settings file:
  191. //
  192. // [testname]
  193. // SysDefaultTextualIdentityFlag = yes|no (add SXS_GENERATE_ACTIVATION_CONTEXT_FLAG_SYSTEM_DEFAULT_TEXTUAL_ASSEMBLY_IDENTITY)
  194. // TextualIdentityFlag = yes|no (add SXS_GENERATE_ACTIVATION_CONTEXT_FLAG_TEXTUAL_ASSEMBLY_IDENTITY)
  195. // ProcArch = PA ident string (will use FusionpParseProcessorArchitecture)
  196. // LangId = number or string
  197. // AssemblyDirectory = dirname
  198. // TextualIdentity = textualIdentityString
  199. // ManifestPath = manifest name under test directory
  200. // PolicyPath = policy path file name under test directory
  201. // ShouldSucceed = yes|no - whether this test succeeds or fails
  202. //
  203. // Flags is required.
  204. // PA and LangId, if not present, are defaulted to the current user's settings.
  205. // AssemblyDirectory, if not present, defaults to %systemroot%\winsxs
  206. // TextualIdentity is required.
  207. // ManifestPath is required.
  208. //
  209. // If textualIdentity is present, then the streams are not created.
  210. //
  211. //
  212. // Flags are set by key names
  213. //
  214. IFW32FALSE_EXIT(SxspIsPrivateProfileStringEqual(buffTestName, CSRSS_INI_KEY_SYSDEFAULTIDENTFLAG, L"yes", fDumpBool, pcwszSettingsFile));
  215. if ( fDumpBool )
  216. this->Request.Flags |= SXS_GENERATE_ACTIVATION_CONTEXT_FLAG_SYSTEM_DEFAULT_TEXTUAL_ASSEMBLY_IDENTITY;
  217. IFW32FALSE_EXIT(SxspIsPrivateProfileStringEqual(buffTestName, CSRSS_INI_KEY_TEXTUALIDENTFLAG, L"yes", fDumpBool, pcwszSettingsFile));
  218. if ( fDumpBool )
  219. this->Request.Flags |= SXS_GENERATE_ACTIVATION_CONTEXT_FLAG_TEXTUAL_ASSEMBLY_IDENTITY;
  220. //
  221. // Get the success/failure value
  222. //
  223. IFW32FALSE_EXIT(SxspIsPrivateProfileStringEqual(buffTestName, CSRSS_INI_KEY_SUCCESS, L"yes", this->fShouldSucceed, pcwszSettingsFile));
  224. //
  225. // And how long this is to sleep
  226. //
  227. INT dump;
  228. IFW32FALSE_EXIT(SxspGetPrivateProfileIntW(buffTestName, CSRSS_INI_KEY_SLEEP, 200, dump, pcwszSettingsFile));
  229. this->dwSleepTime = dump;
  230. //
  231. // PA setting is a string
  232. //
  233. IFW32FALSE_EXIT(SxspGetPrivateProfileStringW(buffTestName, CSRSS_INI_KEY_PROC_ARCH, L"x86", buffJunk, pcwszSettingsFile));
  234. if ( buffJunk.Cch() != 0 )
  235. {
  236. bool fValid = false;
  237. IFW32FALSE_EXIT(FusionpParseProcessorArchitecture(
  238. buffJunk,
  239. buffJunk.Cch(),
  240. &this->Request.ProcessorArchitecture,
  241. fValid));
  242. if ( !fValid ) this->Request.ProcessorArchitecture = PROCESSOR_ARCHITECTURE_INTEL;
  243. }
  244. else
  245. {
  246. this->Request.ProcessorArchitecture = PROCESSOR_ARCHITECTURE_INTEL;
  247. }
  248. //
  249. // Maybe this is a string like en-us, or maybe just a number.
  250. //
  251. IFW32FALSE_EXIT(SxspGetPrivateProfileStringW(buffTestName, CSRSS_INI_KEY_LANGID, L"", buffJunk, pcwszSettingsFile));
  252. if ( buffJunk.Cch() != 0 )
  253. {
  254. ULONG ulTemp;
  255. if ( !ParseDecimalOrHexString(buffJunk, buffJunk.Cch(), ulTemp) )
  256. {
  257. BOOL fFound = FALSE;
  258. IFW32FALSE_EXIT(SxspMapCultureToLANGID(buffJunk, lidCurrentLang, &fFound));
  259. if ( !fFound )
  260. {
  261. goto Exit;
  262. }
  263. }
  264. else lidCurrentLang = static_cast<LANGID>(ulTemp);
  265. }
  266. this->Request.LangId = lidCurrentLang;
  267. //
  268. // Assembly root directory. Not really required to be present?
  269. //
  270. IFW32FALSE_EXIT(SxspGetAssemblyRootDirectory(buffJunk));
  271. IFW32FALSE_EXIT(SxspGetPrivateProfileStringW(buffTestName, CSRSS_INI_KEY_ASMDIR, buffJunk, this->buffAssemblyDirectory, pcwszSettingsFile));
  272. this->Request.AssemblyDirectory = this->buffAssemblyDirectory;
  273. //
  274. // Textual identity string - if not present, null out the value
  275. //
  276. IFW32FALSE_EXIT(SxspGetPrivateProfileStringW(buffTestName, CSRSS_INI_KEY_TEXTUALIDENT, L"", this->buffTextualIdentityString, pcwszSettingsFile));
  277. if ( this->buffTextualIdentityString.Cch() != 0 )
  278. {
  279. this->Request.TextualAssemblyIdentity = this->buffTextualIdentityString;
  280. }
  281. //
  282. // File paths
  283. //
  284. IFW32FALSE_EXIT(SxspGetPrivateProfileStringW(buffTestName, CSRSS_INI_KEY_MANIFEST, L"", buffJunk, pcwszSettingsFile));
  285. if ( buffJunk.Cch() != 0 )
  286. {
  287. IFW32FALSE_EXIT(this->buffManifestStreamPath.Win32Assign(this->buffTestDirectory));
  288. IFW32FALSE_EXIT(this->buffManifestStreamPath.Win32AppendPathElement(buffJunk));
  289. }
  290. IFW32FALSE_EXIT(SxspGetPrivateProfileStringW(buffTestName, CSRSS_INI_KEY_POLICY, L"", buffJunk, pcwszSettingsFile));
  291. if ( buffJunk.Cch() != 0 )
  292. {
  293. IFW32FALSE_EXIT(this->buffPolicyStreamPath.Win32Assign(this->buffTestDirectory));
  294. IFW32FALSE_EXIT(this->buffPolicyStreamPath.Win32AppendPathElement(buffJunk));
  295. }
  296. FN_EPILOG
  297. }
  298. typedef CDeque<CCsrssPoundingThreadEntry, offsetof(CCsrssPoundingThreadEntry, Linkage)> CStressEntryDeque;
  299. typedef CDequeIterator<CCsrssPoundingThreadEntry, offsetof(CCsrssPoundingThreadEntry, Linkage)> CStressEntryDequeIter;
  300. CStressEntryDeque g_CsrssStressers;
  301. BOOL InitializeCsrssStress(
  302. PCWSTR pcwszTargetDirectory,
  303. DWORD dwFlags
  304. )
  305. {
  306. FN_PROLOG_WIN32
  307. CFindFile Finder;
  308. WIN32_FIND_DATAW FindData;
  309. CStringBuffer buffTemp;
  310. CStringBuffer buffTestActualRoot;
  311. //
  312. // The target directory here is the root of all the test case dirs, not the
  313. // csrss-specific directory.
  314. //
  315. IFW32FALSE_EXIT(buffTestActualRoot.Win32Assign(
  316. pcwszTargetDirectory,
  317. wcslen(pcwszTargetDirectory)));
  318. IFW32FALSE_EXIT(buffTestActualRoot.Win32AppendPathElement(
  319. CSRSS_TEST_DIR_NAME,
  320. CSRSS_TEST_DIR_NAME_CCH));
  321. if ((FindData.dwFileAttributes = ::GetFileAttributesW(buffTestActualRoot)) == 0xffffffff
  322. && (FindData.dwFileAttributes = ::FusionpGetLastWin32Error()) == ERROR_FILE_NOT_FOUND)
  323. {
  324. printf("no %ls tests, skipping\n", CSRSS_TEST_DIR_NAME);
  325. FN_SUCCESSFUL_EXIT();
  326. }
  327. IFW32FALSE_EXIT(buffTestActualRoot.Win32AppendPathElement(L"*", 1));
  328. IFW32FALSE_EXIT(Finder.Win32FindFirstFile(buffTestActualRoot, &FindData));
  329. buffTestActualRoot.RemoveLastPathElement();
  330. do
  331. {
  332. CStringBuffer buffSettingsFile;
  333. CCsrssPoundingThreadEntry *TestEntry;
  334. if (( ( FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) == 0 ) ||
  335. FusionpIsDotOrDotDot(FindData.cFileName))
  336. {
  337. continue;
  338. }
  339. //
  340. // Tack on the name of this test
  341. //
  342. IFW32NULL_EXIT(TestEntry = FUSION_NEW_SINGLETON(CCsrssPoundingThreadEntry));
  343. IFW32FALSE_EXIT(TestEntry->buffTestName.Win32Assign(
  344. FindData.cFileName,
  345. wcslen(FindData.cFileName)));
  346. IFW32FALSE_EXIT(TestEntry->buffTestDirectory.Win32Assign(buffTestActualRoot));
  347. IFW32FALSE_EXIT(TestEntry->buffTestDirectory.Win32AppendPathElement(
  348. FindData.cFileName,
  349. wcslen(FindData.cFileName)));
  350. IFW32FALSE_EXIT(buffSettingsFile.Win32Assign(TestEntry->buffTestDirectory));
  351. IFW32FALSE_EXIT(buffSettingsFile.Win32AppendPathElement(
  352. CSRSS_SETTINGS_FILE_NAME,
  353. CSRSS_SETTINGS_FILE_NAME_CCH));
  354. //
  355. // Acquire settings for this test
  356. //
  357. IFW32FALSE_EXIT(TestEntry->AcquireSettingsFrom(buffSettingsFile));
  358. g_CsrssStressers.AddToTail(TestEntry);
  359. TestEntry = NULL;
  360. } while (::FindNextFileW(Finder, &FindData));
  361. FN_EPILOG
  362. }
  363. BOOL WaitForCsrssStressShutdown()
  364. {
  365. FN_PROLOG_WIN32
  366. CStressEntryDequeIter Iter(&g_CsrssStressers);
  367. for ( Iter.Reset(); Iter.More(); Iter.Next() )
  368. {
  369. CCsrssPoundingThreadEntry *Item = Iter.Current();
  370. Item->StopAndWaitForCompletion();
  371. Item->hOurThreadHandle.Win32Close();
  372. }
  373. FN_EPILOG
  374. }
  375. BOOL CsrssStressStartThreads( ULONG &ulThreadsCreated )
  376. {
  377. FN_PROLOG_WIN32
  378. CStressEntryDequeIter Iter(&g_CsrssStressers);
  379. ulThreadsCreated = 0;
  380. for ( Iter.Reset(); Iter.More(); Iter.Next() )
  381. {
  382. CCsrssPoundingThreadEntry *Item = Iter.Current();
  383. IFW32FALSE_EXIT(Item->hOurThreadHandle.Win32CreateThread(
  384. Item->ThreadProcEntry,
  385. Item));
  386. ulThreadsCreated++;
  387. }
  388. FN_EPILOG
  389. }
  390. BOOL CleanupCsrssTests()
  391. {
  392. FN_PROLOG_WIN32
  393. g_CsrssStressers.ClearAndDeleteAll();
  394. FN_EPILOG
  395. }
  396. RequestCsrssStressShutdown()
  397. {
  398. FN_PROLOG_WIN32
  399. CStressEntryDequeIter Iter(&g_CsrssStressers);
  400. for ( Iter.Reset(); Iter.More(); Iter.Next() )
  401. {
  402. CCsrssPoundingThreadEntry *Item = Iter.Current();
  403. Item->fStopNextRound = true;
  404. }
  405. FN_EPILOG
  406. }