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.

569 lines
16 KiB

  1. #include "stdinc.h"
  2. #include "st.h"
  3. #include "stressharness.h"
  4. #include "wfp.h"
  5. #define WFP_INI_SECTION (L"wfp")
  6. #define WFP_INI_KEY_VICTIM (L"Victim")
  7. #define WFP_INI_KEY_MODE (L"Mode")
  8. #define WFP_INI_KEY_USE_SHORTFNAME (L"UseShortnameFile")
  9. #define WFP_INI_KEY_USE_SHORTDNAME (L"UseShortnameDir")
  10. #define WFP_INI_KEY_INSTALL (L"InstallManifest")
  11. #define WFP_INI_KEY_PAUSE_AFTER (L"PauseLength")
  12. #define WFP_INI_KEY_MODE_DELETE_FILES (L"DeleteFiles")
  13. #define WFP_INI_KEY_MODE_TOUCH_FILES (L"TouchFiles")
  14. #define WFP_INI_KEY_MODE_DELETE_DIR (L"DeleteDirectory")
  15. #define WFP_INI_KEY_MODE_DELETE_MAN (L"DeleteManifest")
  16. #define WFP_INI_KEY_MODE_DELETE_CAT (L"DeleteCatalog")
  17. #define WFP_INI_KEY_MODE_HAVOC (L"Havoc")
  18. #define WFP_INI_KEY_MODE_DEFAULT (WFP_INI_KEY_MODE_DELETE_FILES)
  19. BOOL
  20. SxspGenerateSxsPath(
  21. IN DWORD Flags,
  22. IN ULONG PathType,
  23. IN PCWSTR AssemblyRootDirectory OPTIONAL,
  24. IN SIZE_T AssemblyRootDirectoryCch OPTIONAL,
  25. IN PCASSEMBLY_IDENTITY pAssemblyIdentity,
  26. OUT CBaseStringBuffer &PathBuffer
  27. )
  28. {
  29. PROBING_ATTRIBUTE_CACHE pac = { 0 };
  30. return SxspGenerateSxsPath(
  31. Flags,
  32. PathType,
  33. AssemblyRootDirectory,
  34. AssemblyRootDirectoryCch,
  35. pAssemblyIdentity,
  36. &pac,
  37. PathBuffer);
  38. }
  39. CWfpJobEntry::~CWfpJobEntry()
  40. {
  41. }
  42. //
  43. // Defaulted
  44. //
  45. BOOL
  46. CWfpJobEntry::SetupSelfForRun()
  47. {
  48. return TRUE;
  49. }
  50. BOOL
  51. CWfpJobEntry::Cleanup()
  52. {
  53. FN_PROLOG_WIN32
  54. IFW32FALSE_EXIT(CStressJobEntry::Cleanup());
  55. if ( this->m_buffManifestToInstall.Cch() != 0 )
  56. {
  57. //
  58. // Uninstall the assembly that we added
  59. //
  60. SXS_UNINSTALLW Uninstall = { sizeof(Uninstall) };
  61. Uninstall.dwFlags = SXS_UNINSTALL_FLAG_FORCE_DELETE;
  62. Uninstall.lpAssemblyIdentity = this->m_buffVictimAssemblyIdentity;
  63. IFW32FALSE_EXIT(SxsUninstallW(&Uninstall, NULL));
  64. }
  65. FN_EPILOG
  66. }
  67. BOOL
  68. CWfpJobEntry::GenFileListFrom(
  69. PCWSTR pcwszPath,
  70. CFusionArray < CStringBuffer > & tgt
  71. )
  72. {
  73. FN_PROLOG_WIN32
  74. CStringBuffer buffTemp;
  75. CFindFile ffile;
  76. WIN32_FIND_DATAW findData;
  77. IFW32FALSE_EXIT(tgt.Win32Reset());
  78. IFW32FALSE_EXIT(buffTemp.Win32Assign(pcwszPath, ::wcslen(pcwszPath)));
  79. IFW32FALSE_EXIT(buffTemp.Win32RemoveLastPathElement());
  80. ffile.Win32FindFirstFile( pcwszPath, &findData );
  81. if ( ffile != ffile.GetInvalidValue() ) do
  82. {
  83. IFW32FALSE_EXIT(buffTemp.Win32AppendPathElement(
  84. findData.cFileName,
  85. wcslen(findData.cFileName)));
  86. IFW32FALSE_EXIT(tgt.Win32Append(buffTemp));
  87. }
  88. while ( ::FindNextFileW(ffile, &findData) );
  89. FN_EPILOG
  90. }
  91. BOOL
  92. CWfpJobEntry::RunTest(
  93. bool &rfTestSuccessful
  94. )
  95. {
  96. FN_PROLOG_WIN32;
  97. CSmartAssemblyIdentity pIdent;
  98. CSmallStringBuffer buffAssemblyRoot;
  99. SxspGetAssemblyRootDirectory(buffAssemblyRoot);
  100. if ( m_buffVictimAssemblyIdentity.Cch() == 0 )
  101. {
  102. //
  103. // Pick an installed assembly at random from the manifests
  104. // directory.
  105. //
  106. CStringBuffer buffRootDir;
  107. CFusionArray<CStringBuffer> arrManifestsInstalled;
  108. SxspGetAssemblyRootDirectory(buffRootDir);
  109. buffRootDir.Win32AppendPathElement(L"Manifests\\*.manifest", ::wcslen(L"Manifests\\*.manifest"));
  110. this->GenFileListFrom(buffRootDir, arrManifestsInstalled);
  111. //
  112. // Repeatedly try getting info on different manifests
  113. //
  114. do
  115. {
  116. SIZE_T iWhich = rand() % arrManifestsInstalled.GetSize();
  117. struct
  118. {
  119. SXS_MANIFEST_INFORMATION_BASIC Info;
  120. WCHAR wchBuffer[MAX_PATH*3];
  121. } ManifestInfo;
  122. if ( SxsQueryManifestInformation(
  123. 0,
  124. arrManifestsInstalled[iWhich],
  125. SXS_QUERY_MANIFEST_INFORMATION_INFOCLASS_BASIC,
  126. SXS_QUERY_MANIFEST_INFORMATION_INFOCLASS_BASIC_FLAG_OMIT_SHORTNAME,
  127. sizeof(ManifestInfo),
  128. &ManifestInfo,
  129. NULL) )
  130. {
  131. m_buffVictimAssemblyIdentity.Win32Assign(
  132. ManifestInfo.Info.lpIdentity,
  133. wcslen(ManifestInfo.Info.lpIdentity));
  134. break;
  135. }
  136. }
  137. while ( TRUE );
  138. }
  139. if ( ( m_buffVictimAssemblyIdentity.Cch() != 0 ) && ( pIdent == NULL ) )
  140. {
  141. SxspCreateAssemblyIdentityFromTextualString(
  142. m_buffVictimAssemblyIdentity,
  143. &pIdent);
  144. }
  145. switch ( this->m_eChangeMode )
  146. {
  147. case eWfpChangeDeleteFile:
  148. case eWfpChangeTouchFile:
  149. {
  150. int iMethod = rand() % 5;
  151. CStringBuffer buffAssemblyPath;
  152. CFusionArray<CStringBuffer> buffPickFileList;
  153. //
  154. // Pick a file
  155. //
  156. SxspGenerateSxsPath(
  157. 0,
  158. SXSP_GENERATE_SXS_PATH_PATHTYPE_ASSEMBLY,
  159. buffAssemblyRoot,
  160. buffAssemblyRoot.Cch(),
  161. pIdent,
  162. buffAssemblyPath);
  163. GenFileListFrom(buffAssemblyPath, buffPickFileList);
  164. CStringBuffer &cbuffVictim = buffPickFileList[rand() % buffPickFileList.GetSize()];
  165. if ( iMethod == 0 )
  166. {
  167. //
  168. // Touch the timestamp
  169. //
  170. CFusionFile ffile;
  171. FILETIME ft = { 0, 0 };
  172. IFW32FALSE_EXIT(ffile.Win32CreateFile(
  173. cbuffVictim,
  174. GENERIC_READ | GENERIC_WRITE,
  175. FILE_SHARE_READ,
  176. OPEN_EXISTING));
  177. ::SetFileTime(ffile, &ft, &ft, &ft );
  178. }
  179. else if ( iMethod == 1 )
  180. {
  181. //
  182. // Read from the file
  183. //
  184. CFusionFile ffile;
  185. BYTE buff[20];
  186. DWORD dwRead;
  187. IFW32FALSE_EXIT(ffile.Win32CreateFile(
  188. cbuffVictim,
  189. GENERIC_READ,
  190. FILE_SHARE_READ,
  191. OPEN_EXISTING));
  192. ::ReadFile( ffile, buff, sizeof(buff), &dwRead, NULL);
  193. }
  194. else if ( iMethod == 2 )
  195. {
  196. //
  197. // Write to an alternate stream
  198. //
  199. CFusionFile ffile;
  200. DWORD dwWrite;
  201. static const WCHAR pcwszThing[] = L"thing";
  202. cbuffVictim.Win32Append(L":dummy", 6);
  203. IFW32FALSE_EXIT(ffile.Win32CreateFile(
  204. cbuffVictim,
  205. GENERIC_WRITE,
  206. FILE_SHARE_READ,
  207. OPEN_EXISTING));
  208. ::WriteFile( ffile, pcwszThing, sizeof(pcwszThing), &dwWrite, NULL);
  209. }
  210. else if ( iMethod == 3 )
  211. {
  212. }
  213. else if ( iMethod == 4 )
  214. {
  215. }
  216. }
  217. break;
  218. case eWfpChangeDeleteDirectory:
  219. {
  220. //
  221. // Create a list of files to delete in the directory, then blow
  222. // them away. This is probably more guaranteed to get everything
  223. // deleted while WFP is running...
  224. //
  225. CStringBuffer buffPath;
  226. CFusionArray<CStringBuffer> arrFilenames;
  227. CFindFile finder;
  228. WIN32_FIND_DATAW findData;
  229. SxspGenerateSxsPath(
  230. 0,
  231. SXSP_GENERATE_SXS_PATH_PATHTYPE_ASSEMBLY,
  232. buffAssemblyRoot,
  233. buffAssemblyRoot.Cch(),
  234. pIdent,
  235. buffPath);
  236. IFW32FALSE_EXIT(arrFilenames.Win32Initialize());
  237. IFW32FALSE_EXIT(buffPath.Win32AppendPathElement(L"*", 1));
  238. finder.Win32FindFirstFile(buffPath, &findData);
  239. IFW32FALSE_EXIT(buffPath.Win32RemoveLastPathElement());
  240. if ( finder != finder.GetInvalidValue() ) do
  241. {
  242. buffPath.Win32AppendPathElement(findData.cFileName, ::wcslen(findData.cFileName));
  243. arrFilenames.Win32Append(buffPath);
  244. buffPath.Win32RemoveLastPathElement();
  245. }
  246. while( FindNextFileW( finder, &findData ) );
  247. //
  248. // Now go delete them all.
  249. //
  250. for ( SIZE_T ul = 0; ul < arrFilenames.GetSize(); ul++ )
  251. {
  252. DeleteFileW( arrFilenames[ul] );
  253. }
  254. //
  255. // And delete the directory
  256. //
  257. RemoveDirectoryW(buffPath);
  258. }
  259. break;
  260. case eWfpChangeDeleteManifest:
  261. case eWfpChangeDeleteCatalog:
  262. {
  263. CStringBuffer buffTemp;
  264. int iOperation = rand() % 2;
  265. //
  266. // Generate the path to this manifest
  267. //
  268. SxspGenerateSxsPath(
  269. 0,
  270. SXSP_GENERATE_SXS_PATH_PATHTYPE_MANIFEST,
  271. buffAssemblyRoot,
  272. buffAssemblyRoot.Cch(),
  273. pIdent,
  274. buffTemp);
  275. if ( this->m_eChangeMode == eWfpChangeDeleteCatalog )
  276. {
  277. IFW32FALSE_EXIT(buffTemp.Win32ChangePathExtension(
  278. FILE_EXTENSION_CATALOG,
  279. FILE_EXTENSION_CATALOG_CCH,
  280. eErrorIfNoExtension));
  281. }
  282. if ( iOperation == 0 )
  283. {
  284. DeleteFileW(buffTemp);
  285. }
  286. else
  287. {
  288. CFusionFile ffile;
  289. if ( ffile.Win32CreateFile( buffTemp, GENERIC_WRITE, FILE_SHARE_READ, OPEN_EXISTING ) )
  290. {
  291. DWORD dwWritten;
  292. WriteFile(ffile, "boom", 4, &dwWritten, NULL);
  293. }
  294. }
  295. }
  296. break;
  297. //
  298. // Go change everything everywhere. 50% of the time, delete the file.
  299. // 25% of the time, change the file. 25% of the time, open the file, change it,
  300. // then hold it open.
  301. //
  302. case eWfpChangeCompleteHavoc:
  303. {
  304. CStringBuffer buffTemp;
  305. WIN32_FIND_DATAW data;
  306. CFindFile finder;
  307. SxspGetAssemblyRootDirectory(buffTemp);
  308. buffTemp.Win32AppendPathElement(L"*", 1);
  309. finder.Win32FindFirstFile(buffTemp, &data);
  310. IFW32FALSE_EXIT(buffTemp.Win32RemoveLastPathElement());
  311. if ( finder != finder.GetInvalidValue() ) do
  312. {
  313. //
  314. // 1/3 chance of actually hitting the directory
  315. //
  316. if ( ( rand() % 3 ) != 1 ) continue;
  317. CFindFile finder2;
  318. WIN32_FIND_DATAW data2;
  319. buffTemp.Win32AppendPathElement(buffTemp);
  320. buffTemp.Win32AppendPathElement(L"*", 1);
  321. finder2.Win32FindFirstFile(buffTemp, &data2);
  322. buffTemp.Win32RemoveLastPathElement();
  323. if ( finder2 != finder.GetInvalidValue() ) do
  324. {
  325. //
  326. // 50% chance of hitting this file
  327. //
  328. if ( ( rand() % 2 ) == 1 ) continue;
  329. CStringBuffer ActualTarget;
  330. int iOperation = rand() % 4;
  331. ActualTarget.Win32Assign(buffTemp);
  332. ActualTarget.Win32AppendPathElement(data2.cFileName, ::wcslen(data2.cFileName));
  333. //
  334. // Most often, we'll just nuke the file
  335. //
  336. if ( ( iOperation == 0 ) || ( iOperation == 1 ) )
  337. {
  338. ::DeleteFileW(ActualTarget);
  339. }
  340. //
  341. // Just touch the first few bytes of the file.
  342. //
  343. else if ( ( iOperation == 2 ) || ( iOperation == 3 ) )
  344. {
  345. CFusionFile ffile;
  346. DWORD dwWritten;
  347. if ( ffile.Win32CreateFile(
  348. ActualTarget,
  349. GENERIC_READ | GENERIC_WRITE,
  350. FILE_SHARE_READ,
  351. OPEN_EXISTING))
  352. {
  353. WriteFile( ffile, "boom", 4, &dwWritten, NULL );
  354. }
  355. //
  356. // 20 seconds sounds good enough
  357. //
  358. if ( iOperation == 3 )
  359. {
  360. ::Sleep(5000);
  361. }
  362. }
  363. }
  364. while ( FindNextFileW( finder2, &data2 ) );
  365. buffTemp.Win32RemoveLastPathElement();
  366. }
  367. while ( FindNextFileW(finder, &data) );
  368. }
  369. break;
  370. }
  371. rfTestSuccessful = true;
  372. FN_EPILOG
  373. }
  374. CWfpJobEntry::LoadFromSettingsFile(
  375. PCWSTR pcwszSettingsFile
  376. )
  377. {
  378. FN_PROLOG_WIN32
  379. CSmallStringBuffer buffJunk;
  380. INT iJunk;
  381. //
  382. // Are we using shortnames for files?
  383. //
  384. IFW32FALSE_EXIT(SxspIsPrivateProfileStringEqual(
  385. WFP_INI_SECTION,
  386. WFP_INI_KEY_USE_SHORTFNAME,
  387. L"no",
  388. this->m_fUseShortnameFile,
  389. pcwszSettingsFile));
  390. //
  391. // Are we using shortnames for directories?
  392. //
  393. IFW32FALSE_EXIT(SxspIsPrivateProfileStringEqual(
  394. WFP_INI_SECTION,
  395. WFP_INI_KEY_USE_SHORTDNAME,
  396. L"no",
  397. this->m_fUseShortnameDirectory,
  398. pcwszSettingsFile));
  399. //
  400. // How long are we to wait between twiddling and uninstalling?
  401. //
  402. IFW32FALSE_EXIT(SxspGetPrivateProfileIntW(
  403. WFP_INI_SECTION,
  404. WFP_INI_KEY_PAUSE_AFTER,
  405. 5000,
  406. iJunk,
  407. pcwszSettingsFile));
  408. this->m_dwPauseBetweenTwiddleAndUninstall = iJunk;
  409. //
  410. // The test mode
  411. //
  412. IFW32FALSE_EXIT(SxspGetPrivateProfileStringW(
  413. WFP_INI_SECTION,
  414. WFP_INI_KEY_MODE,
  415. WFP_INI_KEY_MODE_DEFAULT,
  416. buffJunk,
  417. pcwszSettingsFile));
  418. #define TEST_MODE( mds, mdn ) if (FusionpStrCmpI((WFP_INI_KEY_MODE_##mds), buffJunk) == 0) this->m_eChangeMode = mdn
  419. TEST_MODE(DELETE_FILES, eWfpChangeDeleteFile);
  420. TEST_MODE(TOUCH_FILES, eWfpChangeTouchFile);
  421. TEST_MODE(DELETE_DIR, eWfpChangeDeleteDirectory);
  422. TEST_MODE(DELETE_MAN, eWfpChangeDeleteManifest);
  423. TEST_MODE(DELETE_CAT, eWfpChangeDeleteCatalog);
  424. TEST_MODE(HAVOC, eWfpChangeCompleteHavoc);
  425. //
  426. // The victim assembly identity
  427. //
  428. IFW32FALSE_EXIT(SxspGetPrivateProfileStringW(
  429. WFP_INI_SECTION,
  430. WFP_INI_KEY_VICTIM,
  431. L"",
  432. m_buffVictimAssemblyIdentity,
  433. pcwszSettingsFile));
  434. //
  435. // Are we installing an assembly to do this to?
  436. //
  437. IFW32FALSE_EXIT(SxspGetPrivateProfileStringW(
  438. WFP_INI_SECTION,
  439. WFP_INI_KEY_INSTALL,
  440. L"",
  441. buffJunk,
  442. pcwszSettingsFile));
  443. if ( buffJunk.Cch() != 0 )
  444. {
  445. IFW32FALSE_EXIT(this->m_buffManifestToInstall.Win32Assign(this->m_buffTestDirectory));
  446. IFW32FALSE_EXIT(this->m_buffManifestToInstall.Win32AppendPathElement( buffJunk ));
  447. }
  448. FN_EPILOG
  449. }
  450. CWfpJobManager::CWfpJobManager()
  451. {
  452. //
  453. // Nothing
  454. //
  455. }
  456. CWfpJobManager::~CWfpJobManager()
  457. {
  458. //
  459. // Nothing
  460. //
  461. }
  462. BOOL
  463. CWfpJobManager::CreateJobEntry(
  464. CStressJobEntry* &rpJobEntry
  465. )
  466. {
  467. FN_PROLOG_WIN32
  468. rpJobEntry = NULL;
  469. rpJobEntry = FUSION_NEW_SINGLETON(CWfpJobEntry(this));
  470. FN_EPILOG
  471. }