Leaked source code of windows server 2003
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.

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