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.

7413 lines
227 KiB

  1. #include "stdinc.h" // actually from dll\whistler directory
  2. /*-----------------------------------------------------------------------------
  3. Side X ("by") Side Test
  4. -----------------------------------------------------------------------------*/
  5. #include "nt.h"
  6. #include "ntrtl.h"
  7. #include "nturtl.h"
  8. #include "windows.h"
  9. #include "fusionlastwin32error.h"
  10. #include <stddef.h>
  11. #include <stdlib.h>
  12. #include <stdio.h>
  13. #include <stdarg.h>
  14. #pragma warning(push)
  15. #pragma warning(disable: 4511)
  16. #pragma warning(disable: 4512)
  17. #pragma warning(disable: 4663)
  18. #include <yvals.h>
  19. #pragma warning(disable: 4663)
  20. #include <string>
  21. #include <deque>
  22. #include <vector>
  23. #pragma warning(pop)
  24. #include "FusionBuffer.h"
  25. #include "fusion.h"
  26. #include "sxsasmname.h"
  27. #include "util.h"
  28. #include "filestream.cpp"
  29. #include "sxsapi.h"
  30. #include "fusiontrace.h"
  31. #include "cresourcestream.cpp"
  32. #include "cmemorystream.cpp"
  33. #include "wintrust.h"
  34. #include "softpub.h"
  35. #include "perfclocking.h"
  36. #include "strongname.h"
  37. #include "fusionversion.h"
  38. #include <setupapi.h>
  39. #include <string>
  40. #include "commctrl.h"
  41. #include <algorithm>
  42. #include "fusionsha1.h"
  43. #include "cguid.h"
  44. #include "winbasep.h"
  45. #undef LoadLibraryA
  46. #undef LoadLibraryW
  47. #undef LoadLibraryExA
  48. #undef LoadLibraryExW
  49. #undef InitCommonControls
  50. BOOL IamExe;
  51. BOOL IamDll;
  52. extern "C" { void (__cdecl * _aexit_rtn)(int); }
  53. void __cdecl Trace(const char* FormatString, ...)
  54. {
  55. char buffer[2000];
  56. va_list args;
  57. va_start(args, FormatString);
  58. _vsnprintf(buffer, RTL_NUMBER_OF(buffer), FormatString, args);
  59. buffer[RTL_NUMBER_OF(buffer) - 1] = 0;
  60. for (PSTR s = buffer ; *s != 0 ; )
  61. {
  62. PSTR t = strchr(s, '\n');
  63. if (t != NULL)
  64. *t = 0;
  65. printf("stdout : %s\n", s);
  66. OutputDebugStringA("debugger: ");
  67. OutputDebugStringA(s);
  68. OutputDebugStringA("\n");
  69. if (t != NULL)
  70. s = t + 1;
  71. }
  72. va_end(args);
  73. }
  74. typedef BOOL (WINAPI * PSXSPGENERATEMANIFESTPATHONASSEMBLYIDENTITY)(
  75. PWSTR str, // input string, must have name, version, langid and processorarchitecture
  76. PWSTR psz, // output string, like x86_cards_strongname,.......
  77. SIZE_T * pCch, // IN : length of psz, OUT : used
  78. PASSEMBLY_IDENTITY *ppAssemblyIdentity // could be NULL
  79. );
  80. /*-----------------------------------------------------------------------------
  81. work around the fact that SxsHeap doesn't let us use a non debug operator new
  82. -----------------------------------------------------------------------------*/
  83. template <typename T>
  84. class Allocator : public std::allocator<T>
  85. {
  86. public:
  87. pointer allocate(size_type n, const void*)
  88. {
  89. return reinterpret_cast<pointer>(malloc(n * sizeof(T)));
  90. }
  91. char* _Charalloc(size_type n)
  92. {
  93. return reinterpret_cast<char*>(malloc(n));
  94. }
  95. void deallocate(void* p, size_type)
  96. {
  97. free(p);
  98. }
  99. };
  100. #define SXSTEST_BEGIN_INSTALL (0x4000000000000000i64)
  101. #define SXSTEST_INSTALL (0x2000000000000000i64)
  102. #define SXSTEST_END_INSTALL (0x1000000000000000i64)
  103. #define SXSTEST_INSTALL_MY_QUEUE (0x0800000000000000i64)
  104. #define SXSTEST_INSTALL_SETUPAPI_QUEUE (0x0400000000000000i64)
  105. #define SXSTEST_END_OF_FLAGS (0x0200000000000000i64)
  106. #define SXSTEST_THREADS (0x0100000000000000i64)
  107. #define SXSTEST_CREATEPROCESS (0x0080000000000000i64)
  108. inline int PRINTABLE(int ch) { return isprint(ch) ? ch : '.'; }
  109. void PrintIfAnyCriticalSectionsHeld(const char* file, int line, const char* function)
  110. #define PrintIfAnyCriticalSectionsHeld() PrintIfAnyCriticalSectionsHeld(__FILE__, __LINE__, __FUNCTION__)
  111. {
  112. const DWORD dwLastError = ::GetLastError();
  113. PTEB teb;
  114. teb = NtCurrentTeb();
  115. if (teb->CountOfOwnedCriticalSections != 0)
  116. {
  117. DbgPrint("%s(%d):%s teb->CountOfOwnedCriticalSections %d\n", file, line, function, teb->CountOfOwnedCriticalSections);
  118. }
  119. SetLastError(dwLastError);
  120. }
  121. static
  122. VOID
  123. PrintBlob(
  124. FILE *pf,
  125. PVOID Data,
  126. SIZE_T Length,
  127. PCWSTR PerLinePrefix
  128. );
  129. BOOL TestLeakMemory(DWORD Amount);
  130. BOOL TestAssemblyProbing(int argc, wchar_t **argv, int *piNext);
  131. BOOL TestDirectoryChangeWatcher(int argc, wchar_t **argv, int *piNext);
  132. BOOL TestXMLParsing(int argc, wchar_t **argv, int *piNext);
  133. BOOL TestMultiAct(int argc, wchar_t **argv);
  134. BOOL TestManifestSchema(int argc, wchar_t **argv, int *piNext);
  135. BOOL TestDirect(int argc, wchar_t **argv, int *piNext);
  136. void TestWin32(wchar_t** argv);
  137. BOOL TestAct(int argc, wchar_t **argv, int *piNext);
  138. BOOL TestInstall(PCWSTR manifest, __int64 flags, DWORD beginInstallFlags, DWORD installFlags, DWORD endInstallFlags);
  139. int TestDiffDir(PCWSTR dir1, PCWSTR dir2);
  140. BOOL TestSearchPath(int argc, wchar_t** argv, int* piNext);
  141. BOOL TestMSIInstall(int argc, wchar_t** argv, int* piNext);
  142. int TestDirWalk(PCWSTR root, PWSTR filter);
  143. BOOL TestLoadLibrary(int argc, wchar_t** argv, int* piNext);
  144. int TestAssemblyName(VOID);
  145. int TestPrecomiledManifest(PCWSTR szFileName);
  146. int TestPCMTime(PCWSTR manifestFilename);
  147. int TestCreateProcess(wchar_t** argv);
  148. int TestCreateProcess2(wchar_t** argv);
  149. BOOL TestInstallPrivateAssembly(int argc, wchar_t** argv, int* piNext);
  150. BOOL TestManifestProbing(int argc, wchar_t** argv, int* piNext);
  151. int TestCreateMultiLevelDirectory(PCWSTR dirs);
  152. BOOL TestXMLDOM(PCWSTR xmlfilename);
  153. BOOL TestFusionArray(PCWSTR, PCWSTR);
  154. BOOL TestGeneratePathFromIdentityAttributeString(PCWSTR str);
  155. BOOL TestRefreshAssembly(PCWSTR wsAssembly);
  156. BOOL TestInstallWithInstallInfo(PCWSTR wsAssemblyManifest, PCWSTR wsReference);
  157. BOOL TestOpeningStuff(PCWSTR wsSourceName, PCWSTR wsType, PCWSTR wsCount);
  158. BOOL TestVerifyFileSignature(PCWSTR wsFilename);
  159. BOOL TestInstallLikeWindowsSetup(PCWSTR szDirectory, PCWSTR szCodebase);
  160. BOOL TestDumpContainedManifests(PCWSTR wsFilename);
  161. BOOL TestGenerateStringWithIdenticalHash(WCHAR iString[33]);
  162. BOOL TestAssemblyIdentityHash();
  163. void TestInherit();
  164. void TestNoInherit();
  165. void TestEmpty();
  166. BOOL TestMessagePerf(int argc, wchar_t **arg, int *piNext);
  167. LRESULT CALLBACK TestMessagePerfWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  168. void TestTrickyMultipleAssemblyCacheItems(PCWSTR);
  169. void TestSfcScanKickoff();
  170. void GenerateStrongNameAndPublicKey(PCWSTR wsCertificate);
  171. VOID TestCreateActctxLeakHandles(DWORD num);
  172. BOOL TestSystemDefaultActivationContextGeneration();
  173. BOOL TestAsyncIO(int argc, wchar_t **argv, int *piNext);
  174. void TestRefCount();
  175. void TestGuidSort();
  176. void TestStringSort();
  177. BOOL TestNewCatalogSignerThingy(PCWSTR pcwszCatalog);
  178. void TestExeDll();
  179. int TestThreadInheritLeak();
  180. BOOL TestSxsSfcUI();
  181. void TestGetModuleHandleEx();
  182. void TestGetFullPathName(PCWSTR);
  183. void TestCreateFile(PCWSTR);
  184. void TestGetPathBaseName(LPCWSTR Path);
  185. PCSTR PrintPathToString(RTL_PATH_TYPE);
  186. void TestPathType(PCWSTR*);
  187. void TestVersion();
  188. void TestGetProcessImageFileName();
  189. void TestErrorInfra();
  190. void TestQueryActCtx();
  191. void TestQueryActCtx2();
  192. void Test64k();
  193. void TestDotLocalSingleInstancing();
  194. void TestCreateActCtx(int nCreations, wchar_t **rgCreations);
  195. void TestCreateActctxLikeCreateProcess();
  196. void TestCreateActctxAdminOverride();
  197. void TestQueryManifestInformationBasic(PCWSTR pszManifest);
  198. void TestCreateActctxWindowsShellManifest();
  199. void TestCreateGlobalEvent();
  200. void TestHandleLeaks(void);
  201. void TestCRuntimeAsms(void);
  202. BOOL TestMfcCreateAndMarshal(void);
  203. void TestAtlCreate(void);
  204. void TestAlignment(void);
  205. BOOL TestPrivateSha1Impl(PCWSTR pcwszDirName);
  206. BOOL TestNewSxsInstallAPI(PCWSTR pcwszManifest);
  207. void TestImage(void);
  208. void TestInterlockedAlignment(void);
  209. void TestCreateActCtx_PE_flags0(void);
  210. void TestUninstall(PCWSTR ManifestPath, PCWSTR ReferenceString);
  211. PCWSTR GetLastErrorMessage();
  212. BOOL SimpleTestFindAndUseSurrogateInformation(PCWSTR filename, PCWSTR GuidToDisplay);
  213. BOOL TestSxsExportedSurrogateStuff(PCWSTR pcwszManifest, PCWSTR pcwszWhat, PCWSTR pcwszData);
  214. DWORD LastError;
  215. static void LoadSxs();
  216. static int Main(int argc, wchar_t** argv);
  217. static void SetLastOperation(const wchar_t* format, ...);
  218. static const wchar_t* GetLastOperation(const wchar_t* format, ...);
  219. static int Usage(const char* argv0);
  220. template <typename PFN> void GetSxsProc(PCSTR name, PFN* ppfn);
  221. template <typename PFN> void GetSxsProc(int name, PFN* ppfn);
  222. SXSP_DEBUG_FUNCTION pfnSxspDebug = NULL;
  223. BOOL ParseProcessorArchitecture(int argc, wchar_t** argv, int* piCurrent);
  224. BOOL ParseLangId(int argc, wchar_t** argv, int* piCurrent);
  225. PCWSTR FusionpThreadUnsafeGetLastWin32ErrorMessageW()
  226. {
  227. CSxsPreserveLastError ple;
  228. static WCHAR LastErrorMessage[4096];
  229. LastErrorMessage[0] = 0;
  230. ::FormatMessageW(
  231. FORMAT_MESSAGE_FROM_SYSTEM,
  232. NULL,
  233. ::FusionpGetLastWin32Error(),
  234. 0,
  235. LastErrorMessage,
  236. RTL_NUMBER_OF(LastErrorMessage),
  237. NULL);
  238. if (LastErrorMessage[0] != 0)
  239. {
  240. PWSTR p = LastErrorMessage + ::StringLength(LastErrorMessage) - 1;
  241. while (p != LastErrorMessage && (*p == '\n' || *p == '\r' || *p == ' ' || *p == '\t'))
  242. {
  243. *p-- = 0;
  244. }
  245. }
  246. ple.Restore();
  247. return LastErrorMessage;
  248. }
  249. void __stdcall ThrowLastError(DWORD error = ::GetLastError())
  250. {
  251. RaiseException(error, 0, 0, NULL);
  252. //throw HRESULT_FROM_WIN32(error);
  253. }
  254. void __stdcall ThrowWin32(ULONG_PTR error = ::GetLastError())
  255. {
  256. ThrowLastError(static_cast<DWORD>(error));
  257. }
  258. void __stdcall CheckHresult(HRESULT hr)
  259. {
  260. if (FAILED(hr))
  261. throw hr;
  262. }
  263. void SetDllBitInPeImage(PCWSTR Path)
  264. /*++
  265. .exes and .dlls are the same format except one bit in the headers distinguishes them.
  266. --*/
  267. {
  268. CFusionFile File;
  269. CFileMapping FileMapping;
  270. CMappedViewOfFile MappedViewOfFile;
  271. if (!File.Win32CreateFile(Path, GENERIC_READ | GENERIC_WRITE, 0, OPEN_EXISTING))
  272. ThrowLastError();
  273. if (!FileMapping.Win32CreateFileMapping(File, PAGE_READWRITE))
  274. ThrowLastError();
  275. if (!MappedViewOfFile.Win32MapViewOfFile(FileMapping, FILE_MAP_WRITE))
  276. ThrowLastError();
  277. PIMAGE_NT_HEADERS NtHeaders = RtlImageNtHeader(static_cast<PVOID>(MappedViewOfFile));
  278. if (NtHeaders == NULL)
  279. ThrowLastError(ERROR_BAD_EXE_FORMAT);
  280. // This is correct for PE32 or PE32+.
  281. NtHeaders->FileHeader.Characteristics |= IMAGE_FILE_DLL;
  282. if (!MappedViewOfFile.Win32Close())
  283. ThrowLastError();
  284. if (!FileMapping.Win32Close())
  285. ThrowLastError();
  286. if (!File.Win32Close())
  287. ThrowLastError();
  288. }
  289. PCSTR PrintPathToString(RTL_PATH_TYPE PathType)
  290. {
  291. switch (PathType)
  292. {
  293. #define X(x) case x: return #x;
  294. X(RtlPathTypeUnknown)
  295. X(RtlPathTypeUncAbsolute)
  296. X(RtlPathTypeDriveAbsolute)
  297. X(RtlPathTypeDriveRelative)
  298. X(RtlPathTypeRooted)
  299. X(RtlPathTypeRelative)
  300. X(RtlPathTypeLocalDevice)
  301. X(RtlPathTypeRootLocalDevice)
  302. #undef X
  303. default:
  304. return "unknown";
  305. }
  306. }
  307. void TestPathType(const PCWSTR* argv)
  308. {
  309. if (*argv != NULL)
  310. {
  311. while (*argv != NULL)
  312. {
  313. RTL_PATH_TYPE PathType = SxspDetermineDosPathNameType(*argv);
  314. printf("%ls -> %s\n", *argv, PrintPathToString(PathType));
  315. argv += 1;
  316. }
  317. }
  318. else
  319. {
  320. const static PCWSTR args[] =
  321. {
  322. L"a",
  323. L"\\a",
  324. L"\\\\a",
  325. L"\\\\\\a",
  326. L"a:",
  327. L"a:\\",
  328. L"\\?",
  329. L"\\.",
  330. L"\\\\?",
  331. L"\\\\.",
  332. L"\\\\?\\",
  333. L"\\\\.\\",
  334. L"\\\\?\\a",
  335. L"\\\\.\\a",
  336. L"\\\\?\\a:",
  337. L"\\\\.\\a:",
  338. L"\\\\?\\a:\\",
  339. L"\\\\.\\a:\\",
  340. L"\\\\?\\unc",
  341. L"\\\\.\\unc",
  342. L"\\\\?\\unc\\",
  343. L"\\\\.\\unc\\",
  344. NULL
  345. };
  346. TestPathType(args);
  347. }
  348. }
  349. class CUnknown : public IUnknown
  350. {
  351. public:
  352. virtual HRESULT __stdcall QueryInterface(const IID& iid, void** ppv)
  353. {
  354. return E_NOINTERFACE;
  355. }
  356. virtual ULONG __stdcall AddRef()
  357. {
  358. return 1;
  359. }
  360. virtual ULONG __stdcall Release()
  361. {
  362. return 1;
  363. }
  364. };
  365. struct G
  366. {
  367. HINSTANCE sxsDll;
  368. USHORT wProcessorArchitecture;
  369. LANGID wLangId;
  370. HANDLE MainThread;
  371. INT NumberOfThreads;
  372. HANDLE Threads[MAXIMUM_WAIT_OBJECTS];
  373. HANDLE ThreadExitEvent;
  374. wchar_t lastOperation[256];
  375. CUnknown unknown;
  376. CSmartRef<IGlobalInterfaceTable> GlobalInterfaceTable;
  377. //
  378. // the start of some automation / record keeping..
  379. //
  380. ULONG Failures;
  381. ULONG Successes;
  382. } g;
  383. const static struct
  384. {
  385. DWORD (WINAPI* GetModuleFileNameW)(HMODULE, LPWSTR, DWORD);
  386. SIZE_T (WINAPI* VirtualQuery)(LPCVOID, PMEMORY_BASIC_INFORMATION, SIZE_T);
  387. }
  388. Kernel32 =
  389. {
  390. GetModuleFileNameW,
  391. VirtualQuery
  392. };
  393. const static struct
  394. {
  395. HRESULT (WINAPI* IIDFromString)(LPOLESTR, LPIID);
  396. HRESULT (WINAPI* CLSIDFromString)(LPOLESTR, LPIID);
  397. HRESULT (WINAPI* CoCreateInstance)(REFCLSID, LPUNKNOWN, DWORD, REFIID, LPVOID*);
  398. HRESULT (WINAPI* CoInitialize)(LPVOID);
  399. void (WINAPI* CoUninitialize)();
  400. }
  401. Ole32 =
  402. {
  403. IIDFromString,
  404. CLSIDFromString,
  405. CoCreateInstance,
  406. CoInitialize,
  407. CoUninitialize
  408. };
  409. void
  410. ManifestStringToTempFile(
  411. PCWSTR ManifestString,
  412. CBaseStringBuffer &rTempFilePath
  413. )
  414. {
  415. CFusionFile File;
  416. WCHAR xTempFilePath[MAX_PATH];
  417. WCHAR TempDirectory[MAX_PATH];
  418. const static WCHAR NativeUnicodeByteOrderMark = 0xfeff;
  419. DWORD BytesWritten;
  420. //if (!::GetTempPathW(NUMBER_OF(TempDirectory), TempDirectory))
  421. // ThrowLastError();
  422. ::GetModuleFileNameW(NULL, TempDirectory, NUMBER_OF(TempDirectory));
  423. *wcsrchr(TempDirectory, '\\') = 0;
  424. ::Trace("TempDirectory:%ls\n", TempDirectory);
  425. if (!::GetTempFileNameW(TempDirectory, L"", 0, xTempFilePath))
  426. ::ThrowLastError();
  427. rTempFilePath.Win32Assign(xTempFilePath, wcslen(xTempFilePath));
  428. ::Trace("xTempFilePath:%ls\n", xTempFilePath);
  429. ::Trace("TempFilePath:%ls\n", static_cast<PCWSTR>(xTempFilePath));
  430. if (!File.Win32CreateFile(rTempFilePath, GENERIC_WRITE, 0, CREATE_ALWAYS))
  431. ::ThrowLastError();
  432. if (!::WriteFile(File, &NativeUnicodeByteOrderMark, sizeof(NativeUnicodeByteOrderMark), &BytesWritten, NULL))
  433. ::ThrowLastError();
  434. if (!::WriteFile(File, ManifestString, static_cast<DWORD>(sizeof(*ManifestString) * StringLength(ManifestString)), &BytesWritten, NULL))
  435. ::ThrowLastError();
  436. }
  437. HANDLE
  438. CreateActivationContextFromStringW(
  439. PCWSTR ManifestString
  440. )
  441. {
  442. CStringBuffer TempFilePath;
  443. ::ManifestStringToTempFile(ManifestString, TempFilePath);
  444. ACTCTXW ActivationContextCreate = { sizeof(ActivationContextCreate) };
  445. ActivationContextCreate.lpSource = TempFilePath;
  446. HANDLE ActivationContextHandle = ::CreateActCtxW(&ActivationContextCreate);
  447. DWORD Error = ::GetLastError();
  448. ::DeleteFileW(TempFilePath);
  449. if (ActivationContextHandle == INVALID_HANDLE_VALUE)
  450. ::ThrowLastError(Error);
  451. return ActivationContextHandle;
  452. }
  453. int Usage(const wchar_t* argv0)
  454. {
  455. std::wstring strargv0 = argv0;
  456. fprintf(stderr,
  457. "%ls",
  458. (
  459. L"Usage: \n"
  460. L" " + strargv0 + L" [install-flags] manifest-or-image-with-manifest-resource-path\n"
  461. L" " + strargv0 + L" [-pa processor-architecture] [-langid langid] -d manifest-path ...\n"
  462. L" " + strargv0 + L" [-pa processor-architecture] [-langid langid] -p manifest-path ...\n"
  463. L" " + strargv0 + L" [-pa processor-architecture] [-langid langid] -w32 manifest-path ...\n"
  464. L" " + strargv0 + L" [-pa processor-architecture] [-langid langid] -msi msi-script...\n"
  465. L" " + strargv0 + L" -tcreateprocess ...\n"
  466. L" " + strargv0 + L" -tsearchpath ...\n"
  467. L" " + strargv0 + L" -tcreateprocess ...\n"
  468. L" " + strargv0 + L" -tempty test pushing a special empty context ...\n"
  469. L" " + strargv0 + L" -tinherit test the usual default inheritance ...\n"
  470. L" " + strargv0 + L" -tnoinherit test the noinherit bit ...\n"
  471. L" " + strargv0 + L" [-threads n] create n threads for some tests ...\n"
  472. L" " + strargv0 + L" probably other choices, use the source\n"
  473. L"\n"
  474. L"install-flags:\n"
  475. L" -i\n"
  476. L" -install\n"
  477. L" -install-my-queue\n"
  478. L" -install-setupapi-queue\n"
  479. L" -install-from-resource\n"
  480. L" -install-move\n"
  481. L" -install-my-queue\n"
  482. L" -install-setupapi-queue [requires debugger]\n"
  483. L" -install-from-resource\n"
  484. ).c_str()
  485. );
  486. return EXIT_FAILURE;
  487. }
  488. const wchar_t* GetLastOperation()
  489. {
  490. return g.lastOperation;
  491. }
  492. void SetLastOperation(const wchar_t* format, ...)
  493. {
  494. va_list args;
  495. g.lastOperation[0] = 0;
  496. g.lastOperation[NUMBER_OF(g.lastOperation) - 1] = 0;
  497. va_start(args, format);
  498. _vsnwprintf(g.lastOperation, NUMBER_OF(g.lastOperation) - 1, format, args);
  499. va_end(args);
  500. }
  501. HANDLE DuplicateHandle(HANDLE handle)
  502. {
  503. HANDLE newHandle = NULL;
  504. if (!DuplicateHandle(GetCurrentProcess(), handle, GetCurrentProcess(), &newHandle, 0, FALSE, DUPLICATE_SAME_ACCESS))
  505. {
  506. ThrowLastError();
  507. }
  508. return newHandle;
  509. }
  510. __int64 IsFlag(PCWSTR arg)
  511. {
  512. const static struct
  513. {
  514. WCHAR name[32];
  515. __int64 value;
  516. } flags[] =
  517. {
  518. { L"i", SXSTEST_BEGIN_INSTALL},
  519. { L"install", SXSTEST_BEGIN_INSTALL},
  520. { L"install-my-queue", SXSTEST_INSTALL_MY_QUEUE },
  521. { L"install-setupapi-queue", SXSTEST_INSTALL_SETUPAPI_QUEUE },
  522. { L"install-from-resource", SXS_INSTALL_ASSEMBLY_FLAG_FROM_RESOURCE | SXSTEST_INSTALL},
  523. { L"install-move", SXS_INSTALL_ASSEMBLY_FLAG_MOVE | SXSTEST_INSTALL },
  524. { L"install-dir", SXS_INSTALL_ASSEMBLY_FLAG_FROM_DIRECTORY | SXSTEST_INSTALL},
  525. { L"install-dir-recursive", SXS_INSTALL_ASSEMBLY_FLAG_FROM_DIRECTORY_RECURSIVE | SXSTEST_INSTALL},
  526. { L"install-no-verify", SXS_INSTALL_ASSEMBLY_FLAG_NO_VERIFY | SXSTEST_INSTALL},
  527. { L"install-no-transact", SXS_INSTALL_ASSEMBLY_FLAG_NOT_TRANSACTIONAL | SXSTEST_INSTALL},
  528. { L"install-replace-existing", SXS_INSTALL_ASSEMBLY_FLAG_REPLACE_EXISTING | SXSTEST_INSTALL},
  529. { L"begin-install-replace-existing", SXS_BEGIN_ASSEMBLY_INSTALL_FLAG_REPLACE_EXISTING | SXSTEST_BEGIN_INSTALL},
  530. { L"begin-install-from-resource", SXS_BEGIN_ASSEMBLY_INSTALL_FLAG_FROM_RESOURCE | SXSTEST_BEGIN_INSTALL},
  531. { L"begin-install-move", SXS_BEGIN_ASSEMBLY_INSTALL_FLAG_MOVE | SXSTEST_BEGIN_INSTALL },
  532. { L"begin-install-dir", SXS_BEGIN_ASSEMBLY_INSTALL_FLAG_FROM_DIRECTORY | SXSTEST_BEGIN_INSTALL},
  533. { L"begin-install-dir-recursive", SXS_BEGIN_ASSEMBLY_INSTALL_FLAG_FROM_DIRECTORY_RECURSIVE | SXSTEST_BEGIN_INSTALL},
  534. { L"begin-install-no-verify", SXS_BEGIN_ASSEMBLY_INSTALL_FLAG_NO_VERIFY | SXSTEST_BEGIN_INSTALL},
  535. { L"begin-install-no-transact", SXS_BEGIN_ASSEMBLY_INSTALL_FLAG_NOT_TRANSACTIONAL | SXSTEST_BEGIN_INSTALL},
  536. { L"end-install-no-verify", SXS_END_ASSEMBLY_INSTALL_FLAG_NO_VERIFY | SXSTEST_END_INSTALL},
  537. { L"threads", SXSTEST_THREADS },
  538. { L"-", SXSTEST_END_OF_FLAGS }
  539. };
  540. if (*arg == '-')
  541. {
  542. arg += 1;
  543. for (ULONG i = 0 ; i != NUMBER_OF(flags) ; ++i)
  544. {
  545. if (_wcsicmp(flags[i].name, arg) == 0)
  546. return flags[i].value;
  547. }
  548. }
  549. return 0;
  550. }
  551. DWORD __stdcall ThreadMain(PVOID)
  552. {
  553. //
  554. // We run stuff in other threads via QueueUserAPC.
  555. //
  556. __try
  557. {
  558. WaitForSingleObjectEx(g.ThreadExitEvent, INFINITE, TRUE);
  559. }
  560. __except(EXCEPTION_EXECUTE_HANDLER)
  561. {
  562. #if DBG
  563. if (IsDebuggerPresent())
  564. {
  565. FUSION_DEBUG_BREAK();
  566. }
  567. #endif
  568. QueueUserAPC(ThrowWin32, g.MainThread, GetExceptionCode());
  569. }
  570. return 0;
  571. }
  572. void CreateThreads()
  573. {
  574. INT i;
  575. g.MainThread = DuplicateHandle(GetCurrentThread());
  576. g.ThreadExitEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
  577. if (g.ThreadExitEvent == NULL)
  578. {
  579. ThrowLastError();
  580. }
  581. for (i = 0 ; i < g.NumberOfThreads ; i++)
  582. {
  583. g.Threads[i] = CreateThread(NULL, 0, ThreadMain, NULL, 0, NULL);
  584. if (g.Threads[i] == NULL)
  585. {
  586. int error = ::GetLastError();
  587. if (i > 2)
  588. {
  589. fprintf(stderr, "Only able to created %d threads, error=%d, continuing\n", i, error);
  590. g.NumberOfThreads = i;
  591. break;
  592. }
  593. fprintf(stderr, "Unable to create threads, error=%d, terminating\n", error);
  594. ThrowWin32(error);
  595. }
  596. }
  597. }
  598. void
  599. GetFlags(
  600. wchar_t**& argv,
  601. __int64& flags,
  602. DWORD& beginInstallFlags,
  603. DWORD& installFlags,
  604. DWORD& endInstallFlags
  605. )
  606. {
  607. __int64 flag;
  608. while (flag = IsFlag(argv[1]))
  609. {
  610. ++argv;
  611. if (flag & SXSTEST_END_OF_FLAGS)
  612. {
  613. break;
  614. }
  615. else if (flag & SXSTEST_BEGIN_INSTALL)
  616. {
  617. beginInstallFlags |= flag;
  618. }
  619. else if (flag & SXSTEST_INSTALL)
  620. {
  621. installFlags |= flag;
  622. }
  623. else if (flag & SXSTEST_END_INSTALL)
  624. {
  625. endInstallFlags |= flag;
  626. }
  627. else if (flag & SXSTEST_THREADS)
  628. {
  629. g.NumberOfThreads = _wtoi(*++argv);
  630. if (g.NumberOfThreads > NUMBER_OF(g.Threads))
  631. {
  632. g.NumberOfThreads = NUMBER_OF(g.Threads);
  633. }
  634. }
  635. // always set flags because normal installation is 0 now
  636. flags |= flag;
  637. }
  638. }
  639. VOID
  640. FusionpSetSystemSetupInProgress(bool f)
  641. {
  642. CFusionRegKey Regkey;
  643. CFusionRegKey RegkeyLocalMachine(HKEY_LOCAL_MACHINE);
  644. if (!RegkeyLocalMachine.OpenSubKey(Regkey, L"System\\Setup", KEY_ALL_ACCESS))
  645. return;
  646. Regkey.SetValue(L"SystemSetupInProgress", f ? 1 : 0);
  647. }
  648. extern "C"
  649. BOOL
  650. WINAPI
  651. SxsDllMain(
  652. HINSTANCE hInst,
  653. DWORD dwReason,
  654. PVOID pvReserved
  655. );
  656. int Main(int argc, wchar_t** argv)
  657. {
  658. int i = 0;
  659. __int64 flags = 0;
  660. //__int64 flag = 0;
  661. DWORD beginInstallFlags = 0;
  662. DWORD installFlags = 0;
  663. DWORD endInstallFlags = 0;
  664. wchar_t* argv0 = argv[0];
  665. g.wProcessorArchitecture = SxspGetSystemProcessorArchitecture();
  666. g.wLangId = ::GetUserDefaultLangID();
  667. if (argc > 1)
  668. {
  669. FusionpSetSystemSetupInProgress(false);
  670. __try
  671. {
  672. __try
  673. {
  674. if (!SxsDllMain(GetModuleHandle(NULL), DLL_PROCESS_ATTACH, NULL))
  675. ThrowLastError();
  676. GetFlags(argv, flags, beginInstallFlags, installFlags, endInstallFlags);
  677. i = 1;
  678. // consume global flags...
  679. for (;;)
  680. {
  681. if (::FusionpStrCmpI(argv[i], L"-pa") == 0)
  682. {
  683. if (!ParseProcessorArchitecture(argc, argv, &i))
  684. goto Exit;
  685. }
  686. else if (::FusionpStrCmpI(argv[i], L"-langid") == 0)
  687. {
  688. if (!ParseLangId(argc, argv, &i))
  689. goto Exit;
  690. }
  691. else
  692. break;
  693. }
  694. if (false) { }
  695. else if (::FusionpStrCmpI(argv[i], L"-id") == 0)
  696. {
  697. DWORD index = 0;
  698. if (argv[3]){ // have an index present
  699. index = argv[3][0] - L'0';
  700. }
  701. i = TestGeneratePathFromIdentityAttributeString(argv[2]);
  702. }
  703. else if (::FusionpStrCmpI(argv[i], L"-tPathType") == 0)
  704. {
  705. TestPathType(argv + i + 1);
  706. }
  707. else if (::FusionpStrCmpI(argv[i], L"-systemdefault") == 0)
  708. {
  709. i = TestSystemDefaultActivationContextGeneration();
  710. }
  711. else if (::FusionpStrCmpI(argv[i], L"-dom") == 0)
  712. {
  713. i = TestXMLDOM(argv[2]);
  714. }
  715. else if (::FusionpStrCmpI(argv[i], L"-hash") == 0)
  716. {
  717. i = TestGenerateStringWithIdenticalHash(argv[2]);
  718. }
  719. else if (::FusionpStrCmpI(argv[i], L"-tasyncio") == 0)
  720. {
  721. i++;
  722. i = TestAsyncIO(argc, argv, &i);
  723. }
  724. else if (::FusionpStrCmpI(argv[i], L"-assemblyidentityhash") == 0)
  725. {
  726. i = TestAssemblyIdentityHash();
  727. }
  728. else if (::FusionpStrCmpI(argv[i], L"-array") == 0)
  729. {
  730. i = TestFusionArray(argv[2], argv[3]);
  731. }
  732. else if (::FusionpStrCmpI(argv[i], L"-diffdir") == 0)
  733. {
  734. i = TestDiffDir(argv[i + 1], argv[i + 2]);
  735. }
  736. else if (::FusionpStrCmpI(argv[1], L"-pcm") == 0)
  737. {
  738. i = TestPrecomiledManifest(argv[2]);
  739. }
  740. else if (::FusionpStrCmpI(argv[1], L"-testpcm") == 0)
  741. {
  742. i = TestPCMTime(argv[2]);
  743. }
  744. else if (::FusionpStrCmpI(argv[1], L"-cd") == 0)
  745. {
  746. i = TestCreateMultiLevelDirectory(argv[2]);
  747. }
  748. else if (!::FusionpStrCmpI(argv[i], L"-manifests"))
  749. {
  750. TestDumpContainedManifests(argv[++i]);
  751. }
  752. else if (::FusionpStrCmpI(argv[1], L"-dirwalk") == 0)
  753. {
  754. i = TestDirWalk(argv[i + 1], argv[i + 2]);
  755. }
  756. else if (::FusionpStrCmpI(argv[1], L"-tmultiact") == 0)
  757. {
  758. i = TestMultiAct(argc, argv);
  759. }
  760. else if (flags)
  761. {
  762. PrintIfAnyCriticalSectionsHeld();
  763. i = TestInstall(argv[i], flags, beginInstallFlags, installFlags, endInstallFlags);
  764. PrintIfAnyCriticalSectionsHeld();
  765. }
  766. else if (!::FusionpStrCmpI(argv[i], L"-sfcui"))
  767. {
  768. if ( !TestSxsSfcUI() )
  769. goto Exit;
  770. i++;
  771. }
  772. else if ( !FusionpStrCmpI( argv[i], L"-installwithinfo" ) )
  773. {
  774. TestInstallWithInstallInfo(
  775. ( i + 1 < argc ) ? argv[i + 1] : NULL,
  776. ( i + 2 < argc ) ? argv[i+2] : NULL);
  777. i += 2;
  778. }
  779. else if (!::FusionpStrCmpI(argv[i], L"-multicache"))
  780. {
  781. TestTrickyMultipleAssemblyCacheItems(argv[i + 1]);
  782. i++;
  783. }
  784. else if (::FusionpStrCmpI(argv[i], L"-d") == 0)
  785. {
  786. if (!TestDirect(argc, argv, &i))
  787. goto Exit;
  788. }
  789. else if (::FusionpStrCmpI(argv[i], L"-probe") == 0)
  790. {
  791. i++;
  792. argv[i] = L"foo,type=\"win32\",processorArchitecture=\"x86\",version=\"6.0.0.0\",publicKeyToken=\"6595b64144ccf1df\"";
  793. if (!TestAssemblyProbing(argc, argv, &i))
  794. goto Exit;
  795. }
  796. else if (::FusionpStrCmpI(argv[i], L"-dirchanges") == 0)
  797. {
  798. if (!TestDirectoryChangeWatcher(argc, argv, &i))
  799. goto Exit;
  800. }
  801. else if (::FusionpStrCmpI(argv[i], L"-newinstall") == 0)
  802. {
  803. if (!TestNewSxsInstallAPI(argv[++i]))
  804. goto Exit;
  805. }
  806. else if (::FusionpStrCmpI(argv[i], L"-tuninstall") == 0
  807. || ::FusionpStrCmpI(argv[i], L"-uninstall") == 0)
  808. {
  809. TestUninstall(argv[i + 1], argv[i + 2]);
  810. goto Exit;
  811. }
  812. else if (::FusionpStrCmpI(argv[i], L"-probemanifest") == 0)
  813. {
  814. if (!TestManifestProbing(argc, argv, &i))
  815. goto Exit;
  816. }
  817. else if (::FusionpStrCmpI(argv[i], L"-p") == 0)
  818. {
  819. if (!TestXMLParsing(argc, argv, &i))
  820. goto Exit;
  821. }
  822. else if (::FusionpStrCmpI(argv[i], L"-w32") == 0)
  823. {
  824. TestWin32(argv + i + 1);
  825. }
  826. else if (::FusionpStrCmpI(argv[i], L"-msi") == 0)
  827. {
  828. if (!TestMSIInstall(argc, argv, &i))
  829. goto Exit;
  830. }
  831. else if (::FusionpStrCmpI(argv[i], L"-mp") == 0)
  832. {
  833. if (!TestManifestSchema(argc, argv, &i))
  834. goto Exit;
  835. }
  836. else if (::FusionpStrCmpI(argv[i], L"-act") == 0)
  837. {
  838. if (!TestAct(argc, argv, &i))
  839. goto Exit;
  840. }
  841. else if (::FusionpStrCmpI(argv[i], L"-shatest") == 0)
  842. {
  843. if (!TestPrivateSha1Impl(argv[++i]))
  844. goto Exit;
  845. }
  846. else if (::FusionpStrCmpI(argv[1], L"-am") == 0)
  847. {
  848. i = TestAssemblyName();
  849. }
  850. else if (::FusionpStrCmpI(argv[i], L"-tsurrogates") == 0)
  851. {
  852. if (!SimpleTestFindAndUseSurrogateInformation(argv[i+1], argv[i+2]))
  853. goto Exit;
  854. i += 2;
  855. }
  856. else if (::FusionpStrCmpI(argv[i], L"-clrhelpers") == 0)
  857. {
  858. if (!TestSxsExportedSurrogateStuff(argv[i+1], argv[i+2], argv[i+3]))
  859. goto Exit;
  860. i += 3;
  861. }
  862. else if (::FusionpStrCmpI(argv[i], L"-tsearchpath") == 0)
  863. {
  864. if (!TestSearchPath(argc, argv, &i))
  865. goto Exit;
  866. }
  867. else if (!::FusionpStrCmpI(argv[i], L"-testmapping"))
  868. {
  869. if (!TestOpeningStuff(argv[i+1], argv[i+2], argv[i+3]))
  870. goto Exit;
  871. i += 3;
  872. }
  873. else if (!::FusionpStrCmpI(argv[i], L"-validatefile"))
  874. {
  875. if (!TestVerifyFileSignature(argv[++i]))
  876. goto Exit;
  877. }
  878. else if (::FusionpStrCmpI(argv[i], L"-tloadlibrary") == 0)
  879. {
  880. if (!TestLoadLibrary(argc, argv, &i))
  881. goto Exit;
  882. }
  883. else if (!::FusionpStrCmpI(argv[i], L"-refresh"))
  884. {
  885. if (!TestRefreshAssembly(argv[i+1]))
  886. goto Exit;
  887. }
  888. else if (::FusionpStrCmpI(argv[i], L"-leak") == 0)
  889. {
  890. //
  891. // We dump a little bit of memory
  892. //
  893. UINT iAmount = 0;
  894. iAmount = _wtoi(argv[++i]);
  895. if (!TestLeakMemory(iAmount))
  896. goto Exit;
  897. }
  898. else if (::FusionpStrCmpI(argv[i], L"-tcreateprocess") == 0)
  899. {
  900. if (!TestCreateProcess(argv + i + 1))
  901. goto Exit;
  902. }
  903. else if (::FusionpStrCmpI(argv[i], L"-tcreateprocess2") == 0)
  904. {
  905. if (!TestCreateProcess2(argv + i + 1))
  906. goto Exit;
  907. }
  908. else if (::FusionpStrCmpI(argv[i], L"-tinherit") == 0)
  909. {
  910. TestInherit();
  911. }
  912. else if (::FusionpStrCmpI(argv[i], L"-tnoinherit") == 0)
  913. {
  914. TestNoInherit();
  915. }
  916. else if (::FusionpStrCmpI(argv[i], L"-tempty") == 0)
  917. {
  918. TestEmpty();
  919. }
  920. else if (::FusionpStrCmpI(argv[i], L"-ttsappcmp") == 0)
  921. {
  922. TestCreateGlobalEvent();
  923. }
  924. else if (::FusionpStrCmpI(argv[i], L"-tmsgperf") == 0)
  925. {
  926. i++;
  927. if (!TestMessagePerf(argc, argv, &i))
  928. goto Exit;
  929. }
  930. else if (::FusionpStrCmpI(argv[i], L"-twinsetup") == 0)
  931. {
  932. FusionpSetSystemSetupInProgress(true);
  933. if (!TestInstallLikeWindowsSetup(argv[i + 1], (argv[i + 2] != NULL) ? argv[i + 2] : argv[i + 1]))
  934. goto Exit;
  935. i += 3;
  936. }
  937. else if (!::FusionpStrCmpI(argv[i], L"-sfcscan"))
  938. {
  939. TestSfcScanKickoff();
  940. }
  941. else if (!::FusionpStrCmpI(argv[i], L"-certinfo"))
  942. {
  943. GenerateStrongNameAndPublicKey(argv[++i]);
  944. }
  945. else if (::FusionpStrCmpI(argv[i], L"-thandle") == 0)
  946. {
  947. DWORD iAmount = 0;
  948. iAmount = _wtoi(argv[++i]);
  949. TestCreateActctxLeakHandles(iAmount);
  950. }
  951. else if (::FusionpStrCmpI(argv[i], L"-catsigner") == 0)
  952. {
  953. TestNewCatalogSignerThingy(argv[++i]);
  954. }
  955. else if (::FusionpStrCmpI(argv[i], L"-trefcount") == 0)
  956. {
  957. TestRefCount();
  958. }
  959. else if (::FusionpStrCmpI(argv[i], L"-ttileak") == 0)
  960. {
  961. TestThreadInheritLeak();
  962. }
  963. else if (::FusionpStrCmpI(argv[i], L"-tguidsort") == 0)
  964. {
  965. TestGuidSort();
  966. }
  967. else if (::FusionpStrCmpI(argv[i], L"-tstringsort") == 0)
  968. {
  969. TestStringSort();
  970. }
  971. else if (::FusionpStrCmpI(argv[i], L"-tExeDll") == 0)
  972. {
  973. TestExeDll();
  974. }
  975. else if (FusionpStrCmpI(argv[i], L"-tExitProcess") == 0)
  976. {
  977. LoadSxs();
  978. GetSxsProc(SXSP_DEBUG_ORDINAL, &pfnSxspDebug);
  979. pfnSxspDebug(SXS_DEBUG_EXIT_PROCESS, 0, 0, NULL);
  980. }
  981. else if (FusionpStrCmpI(argv[i], L"-tTerminateProcess") == 0)
  982. {
  983. LoadSxs();
  984. GetSxsProc(SXSP_DEBUG_ORDINAL, &pfnSxspDebug);
  985. pfnSxspDebug(SXS_DEBUG_TERMINATE_PROCESS, 0, 0, NULL);
  986. }
  987. else if (FusionpStrCmpI(argv[i], L"-tLastError") == 0)
  988. {
  989. ::SetLastError(123);
  990. printf("%lu\n", FusionpGetLastWin32Error());
  991. printf("%lu\n", ::GetLastError());
  992. ::FusionpSetLastWin32Error(456);
  993. printf("%lu\n", FusionpGetLastWin32Error());
  994. printf("%lu\n", ::GetLastError());
  995. }
  996. else if (FusionpStrCmpI(argv[i], L"-tGetModuleHandleEx") == 0)
  997. {
  998. TestGetModuleHandleEx();
  999. }
  1000. else if (FusionpStrCmpI(argv[i], L"-tGetFullPathName") == 0)
  1001. {
  1002. TestGetFullPathName(argv[i + 1]);
  1003. }
  1004. else if (FusionpStrCmpI(argv[i], L"-tCreateFile") == 0)
  1005. {
  1006. TestCreateFile(argv[i + 1]);
  1007. }
  1008. else if (FusionpStrCmpI(argv[i], L"-tGetPathBaseName") == 0)
  1009. {
  1010. TestGetPathBaseName(argv[i + 1]);
  1011. }
  1012. else if (FusionpStrCmpI(argv[i], L"-tVersion") == 0)
  1013. {
  1014. TestVersion();
  1015. }
  1016. else if (FusionpStrCmpI(argv[i], L"-tGetProcessImageFileName") == 0)
  1017. {
  1018. TestGetProcessImageFileName();
  1019. }
  1020. else if (FusionpStrCmpI(argv[i], L"-tErrorInfra") == 0)
  1021. {
  1022. TestErrorInfra();
  1023. }
  1024. else if (FusionpStrCmpI(argv[i], L"-tQueryActCtx") == 0)
  1025. TestQueryActCtx();
  1026. else if (FusionpStrCmpI(argv[i], L"-tQueryActCtx2") == 0)
  1027. TestQueryActCtx2();
  1028. else if (FusionpStrCmpI(argv[i], L"-tqmib") == 0)
  1029. {
  1030. TestQueryManifestInformationBasic(argv[i+1]);
  1031. }
  1032. else if (FusionpStrCmpI(argv[i], L"-t64k") == 0)
  1033. {
  1034. Test64k();
  1035. }
  1036. else if (FusionpStrCmpI(argv[i], L"-tcreateactctx") == 0)
  1037. {
  1038. TestCreateActCtx(argc - (i + 1), &argv[i+1]);
  1039. }
  1040. else if (FusionpStrCmpI(argv[i], L"-TestCreateActCtx_PE_flags0") == 0)
  1041. {
  1042. TestCreateActCtx_PE_flags0();
  1043. }
  1044. else if (FusionpStrCmpI(argv[i], L"-tDotLocalSingleInstancing") == 0)
  1045. {
  1046. TestDotLocalSingleInstancing();
  1047. }
  1048. else if (FusionpStrCmpI(argv[i], L"-tCreateActctxLikeCreateProcess") == 0)
  1049. {
  1050. TestCreateActctxLikeCreateProcess();
  1051. }
  1052. else if (FusionpStrCmpI(argv[i], L"-tCreateActctxLikeCreateProcess") == 0)
  1053. {
  1054. TestCreateActctxLikeCreateProcess();
  1055. }
  1056. else if (FusionpStrCmpI(argv[i], L"-tCreateActctxAdminOverride") == 0)
  1057. {
  1058. TestCreateActctxAdminOverride();
  1059. }
  1060. else if (FusionpStrCmpI(argv[i], L"-tCreateActctxWindowsShellManifest") == 0)
  1061. {
  1062. TestCreateActctxWindowsShellManifest();
  1063. }
  1064. else if (FusionpStrCmpI(argv[i], L"-tHandleLeak") == 0)
  1065. {
  1066. //for (ULONG i = 0 ; i != 5 ; i += 1)
  1067. TestHandleLeaks();
  1068. }
  1069. else if (FusionpStrCmpI(argv[i], L"-tMfcCreateAndMarshal") == 0)
  1070. {
  1071. TestMfcCreateAndMarshal();
  1072. }
  1073. else if (FusionpStrCmpI(argv[i], L"-tAtlCreate") == 0)
  1074. {
  1075. TestAtlCreate();
  1076. }
  1077. else if (FusionpStrCmpI(argv[i], L"-TestAlignment") == 0)
  1078. {
  1079. TestAlignment();
  1080. }
  1081. else if (FusionpStrCmpI(argv[i], L"-DoNothingJustSeeIfItRuns") == 0)
  1082. {
  1083. printf("%wZ ran successfully\n", &NtCurrentPeb()->ProcessParameters->ImagePathName);
  1084. }
  1085. else if (FusionpStrCmpI(argv[i], L"-TestImage") == 0)
  1086. {
  1087. TestImage();
  1088. }
  1089. else if (FusionpStrCmpI(argv[i], L"-TestInterlockedAlignment") == 0)
  1090. {
  1091. TestInterlockedAlignment();
  1092. }
  1093. else
  1094. {
  1095. i = Usage(argv0);
  1096. }
  1097. if (g.ThreadExitEvent)
  1098. {
  1099. SetEvent(g.ThreadExitEvent);
  1100. WaitForMultipleObjectsEx(g.NumberOfThreads, g.Threads, TRUE, INFINITE, TRUE);
  1101. }
  1102. if (g.sxsDll != NULL)
  1103. {
  1104. FreeLibrary(g.sxsDll);
  1105. }
  1106. }
  1107. __finally
  1108. {
  1109. FusionpSetSystemSetupInProgress(false);
  1110. }
  1111. }
  1112. __except(EXCEPTION_EXECUTE_HANDLER)
  1113. {
  1114. #if DBG
  1115. if (IsDebuggerPresent())
  1116. {
  1117. FUSION_DEBUG_BREAK();
  1118. }
  1119. #endif
  1120. i = GetExceptionCode();
  1121. WCHAR message[128];
  1122. DWORD flags = FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM;
  1123. FormatMessageW(flags, NULL, i, 0, message, NUMBER_OF(message), NULL);
  1124. PWSTR end = message + wcslen(message);
  1125. while (end != message && isspace(*(end - 1)))
  1126. {
  1127. --end;
  1128. }
  1129. *end = 0;
  1130. ::Trace("%ls failed, %d, %#x, %ls", g.lastOperation, i, i, message);
  1131. }
  1132. PTEB teb;
  1133. teb = NtCurrentTeb();
  1134. if (teb->CountOfOwnedCriticalSections != 0)
  1135. {
  1136. DbgPrint("teb->CountOfOwnedCriticalSections %d\n", teb->CountOfOwnedCriticalSections);
  1137. //ASSERT(teb->CountOfOwnedCriticalSections == 0);
  1138. }
  1139. return i ? EXIT_SUCCESS : EXIT_FAILURE;
  1140. }
  1141. return Usage(argv[0]);
  1142. Exit:
  1143. return ::GetLastError();
  1144. }
  1145. extern "C" int __cdecl wmain(int argc, wchar_t** argv)
  1146. {
  1147. // NtCurrentTeb()->CountOfOwnedCriticalSections = 0;
  1148. PrintIfAnyCriticalSectionsHeld();
  1149. int i = Main(argc, argv);
  1150. PrintIfAnyCriticalSectionsHeld();
  1151. return i;
  1152. }
  1153. int TestDiffDir(PCWSTR dir1, PCWSTR dir2)
  1154. {
  1155. CFusionDirectoryDifference diff;
  1156. CStringBuffer buf1;
  1157. CStringBuffer buf2;
  1158. BOOL fSuccess = FALSE;
  1159. if (!buf1.Win32Assign(dir1, ::wcslen(dir1)))
  1160. goto Exit;
  1161. if (!buf2.Win32Assign(dir2, ::wcslen(dir2)))
  1162. goto Exit;
  1163. if (!::FusionpCompareDirectoriesSizewiseRecursively(&diff, buf1, buf2))
  1164. goto Exit;
  1165. diff.DbgPrint(buf1, buf2);
  1166. fSuccess = TRUE;
  1167. Exit:
  1168. return fSuccess ? EXIT_SUCCESS : EXIT_FAILURE;
  1169. }
  1170. PCWSTR GetUser()
  1171. {
  1172. static bool fInited;
  1173. static WCHAR userName[MAX_PATH];
  1174. if (!fInited)
  1175. {
  1176. DWORD size = NUMBER_OF(userName);
  1177. userName[0] = 0;
  1178. userName[1] = 0;
  1179. GetUserNameW(userName, &size);
  1180. if (userName[1] == '-')
  1181. {
  1182. wmemcpy(userName, 2+userName, 1+wcslen(2+userName));
  1183. }
  1184. fInited = true;
  1185. }
  1186. return userName;
  1187. }
  1188. void UserBreakPoint(PCWSTR user)
  1189. {
  1190. if (::IsDebuggerPresent() && _wcsicmp(GetUser(), user) == 0)
  1191. {
  1192. ASSERT2_NTC(FALSE, __FUNCTION__);
  1193. }
  1194. }
  1195. void LoadSxs()
  1196. {
  1197. WCHAR ExePath[MAX_PATH];
  1198. if (g.sxsDll == NULL)
  1199. {
  1200. SetLastOperation(L"LoadLibrary(SXS.DLL)");
  1201. // sxstest is often run from nt\base\win32\fusion\tests\sxstest\whistler\obj\i386\sxstest.exe; try loading sxs.dll
  1202. // via a relative path first
  1203. g.sxsDll = ::LoadLibraryW(L"..\\..\\..\\..\\..\\dll\\whistler\\obj\\i386\\SXS.DLL");
  1204. if (g.sxsDll == NULL)
  1205. {
  1206. GetModuleFileNameW(NULL, ExePath, NUMBER_OF(ExePath));
  1207. wcscpy(1 + wcsrchr(ExePath, '\\'), L"SXS.DLL");
  1208. g.sxsDll = ::LoadLibraryW(ExePath);
  1209. }
  1210. if (g.sxsDll == NULL)
  1211. g.sxsDll = ::LoadLibraryW(L"SXS.DLL");
  1212. if (g.sxsDll == NULL)
  1213. ThrowLastError();
  1214. UserBreakPoint(L"JayKrell");
  1215. }
  1216. }
  1217. template <typename PFN>
  1218. void GetSxsProc(int name, PFN* ppfn)
  1219. {
  1220. SetLastOperation(L"GetProcAddress(#%d)", name);
  1221. if (!(*ppfn = reinterpret_cast<PFN>(GetProcAddress(g.sxsDll, reinterpret_cast<PCSTR>(IntToPtr(name))))))
  1222. {
  1223. ThrowLastError();
  1224. }
  1225. }
  1226. template <typename PFN>
  1227. void GetSxsProc(PCSTR name, PFN* ppfn)
  1228. {
  1229. SetLastOperation(L"GetProcAddress(%hs)", name);
  1230. if (!(*ppfn = reinterpret_cast<PFN>(GetProcAddress(g.sxsDll, name))))
  1231. {
  1232. ThrowLastError();
  1233. }
  1234. }
  1235. class CCopyQueueElement : public std::pair<std::wstring, std::wstring>
  1236. {
  1237. typedef std::pair<std::wstring, std::wstring> Base;
  1238. public:
  1239. CCopyQueueElement() { }
  1240. CCopyQueueElement(const first_type& source, const second_type& target)
  1241. :
  1242. Base(source, target)
  1243. {
  1244. }
  1245. first_type& Source() { return first; }
  1246. const first_type& Source() const { return first; }
  1247. second_type& Target() { return second; }
  1248. const second_type& Target() const { return second; }
  1249. };
  1250. template <typename T> class StdDeque : public std::deque<T, Allocator<T> > { };
  1251. template <typename T> class StdVector : public std::vector<T, Allocator<T> > { };
  1252. class CCopyQueue : public StdDeque<CCopyQueueElement>
  1253. {
  1254. typedef StdDeque<CCopyQueueElement> Base;
  1255. public:
  1256. BOOL Callback(
  1257. PSXS_INSTALLATION_FILE_COPY_CALLBACK_PARAMETERS parameters
  1258. )
  1259. {
  1260. push_back(value_type(parameters->pSourceFile, parameters->pDestinationFile));
  1261. parameters->nDisposition = SXS_INSTALLATION_FILE_COPY_DISPOSITION_FILE_QUEUED;
  1262. return TRUE;
  1263. }
  1264. static BOOL WINAPI StaticCallback(
  1265. PSXS_INSTALLATION_FILE_COPY_CALLBACK_PARAMETERS parameters
  1266. )
  1267. {
  1268. CCopyQueue* pThis = reinterpret_cast<CCopyQueue*>(parameters->pvContext);
  1269. BOOL fResult = pThis->Callback(parameters);
  1270. return fResult;
  1271. }
  1272. BOOL Flush()
  1273. {
  1274. BOOL fSuccess = FALSE;
  1275. for (; !empty() ; pop_back())
  1276. {
  1277. const std::wstring& target = back().Target();
  1278. const std::wstring targetDir = target.substr(0, target.find_last_of('\\'));
  1279. FusionpCreateDirectories(targetDir.c_str(), ::wcslen(targetDir.c_str()));
  1280. if (!CopyFileW(back().Source().c_str(), target.c_str(), TRUE))
  1281. {
  1282. goto Exit;
  1283. }
  1284. }
  1285. fSuccess = TRUE;
  1286. Exit:
  1287. return fSuccess;
  1288. }
  1289. };
  1290. int
  1291. TestInstall(
  1292. PCWSTR manifest,
  1293. __int64 flags,
  1294. DWORD beginInstallFlags,
  1295. DWORD installFlags,
  1296. DWORD endInstallFlags
  1297. )
  1298. {
  1299. PrintIfAnyCriticalSectionsHeld();
  1300. BOOL fSuccess = FALSE;
  1301. PVOID installCookie = NULL;
  1302. PSXS_BEGIN_ASSEMBLY_INSTALL sxsBeginAssemblyInstall = NULL;
  1303. PSXS_INSTALL_ASSEMBLY_W sxsInstallAssemblyW = NULL;
  1304. PSXS_END_ASSEMBLY_INSTALL sxsEndAssemblyInstall = NULL;
  1305. CCopyQueue copyQueue;
  1306. BOOL fCleanup = FALSE;
  1307. SXS_INSTALL_SOURCE_INFO SxsInstallInfo = {0};
  1308. PSXS_INSTALLATION_FILE_COPY_CALLBACK callback = NULL;
  1309. PVOID context = NULL;
  1310. HSPFILEQ hSetupCopyQueue = INVALID_HANDLE_VALUE;
  1311. PVOID pDefaultSetupCopyQueueContext = NULL;
  1312. LoadSxs();
  1313. GetSxsProc("SxsBeginAssemblyInstall", &sxsBeginAssemblyInstall);
  1314. GetSxsProc("SxsInstallAssemblyW", &sxsInstallAssemblyW);
  1315. GetSxsProc("SxsEndAssemblyInstall", &sxsEndAssemblyInstall);
  1316. if (flags & SXSTEST_INSTALL_MY_QUEUE)
  1317. {
  1318. callback = &CCopyQueue::StaticCallback;
  1319. context = &copyQueue;
  1320. }
  1321. else if (flags & SXSTEST_INSTALL_SETUPAPI_QUEUE)
  1322. {
  1323. callback = SXS_INSTALLATION_FILE_COPY_CALLBACK_SETUP_COPY_QUEUE;
  1324. if (INVALID_HANDLE_VALUE == (hSetupCopyQueue = SetupOpenFileQueue()))
  1325. {
  1326. goto Exit;
  1327. }
  1328. context = hSetupCopyQueue; // random non NULL, step through, then stop debugging
  1329. #if DBG
  1330. FUSION_DEBUG_BREAK();
  1331. #endif
  1332. }
  1333. PrintIfAnyCriticalSectionsHeld();
  1334. if (!(*sxsBeginAssemblyInstall)(
  1335. beginInstallFlags,
  1336. callback,
  1337. context,
  1338. NULL, // ImpersonationCallback,
  1339. NULL, // ImpersonationContext,
  1340. &installCookie))
  1341. {
  1342. goto Exit;
  1343. }
  1344. fCleanup = TRUE;
  1345. PrintIfAnyCriticalSectionsHeld();
  1346. memset(&SxsInstallInfo, 0, sizeof(SxsInstallInfo));
  1347. SxsInstallInfo.cbSize = sizeof(SxsInstallInfo);
  1348. SxsInstallInfo.dwFlags = SXSINSTALLSOURCE_INSTALLING_SETUP | SXSINSTALLSOURCE_HAS_CODEBASE;
  1349. SxsInstallInfo.pcwszCodebaseName = manifest;
  1350. fSuccess = sxsInstallAssemblyW(
  1351. installCookie,
  1352. installFlags | SXS_INSTALL_ASSEMBLY_FLAG_FROM_DIRECTORY_RECURSIVE | SXS_INSTALL_ASSEMBLY_FLAG_INCLUDE_CODEBASE,
  1353. manifest,
  1354. &SxsInstallInfo);
  1355. PrintIfAnyCriticalSectionsHeld();
  1356. fSuccess = copyQueue.Flush();
  1357. Exit:
  1358. if (fCleanup)
  1359. {
  1360. if (flags & SXSTEST_INSTALL_SETUPAPI_QUEUE)
  1361. {
  1362. if (!(pDefaultSetupCopyQueueContext = ::SetupInitDefaultQueueCallback(NULL)))
  1363. {
  1364. fSuccess = FALSE;
  1365. }
  1366. if (fSuccess && !::SetupCommitFileQueue(NULL,
  1367. hSetupCopyQueue,
  1368. SetupDefaultQueueCallback,
  1369. pDefaultSetupCopyQueueContext))
  1370. {
  1371. fSuccess = FALSE;
  1372. }
  1373. if (hSetupCopyQueue != INVALID_HANDLE_VALUE)
  1374. {
  1375. ::SetupCloseFileQueue(hSetupCopyQueue);
  1376. hSetupCopyQueue = NULL;
  1377. }
  1378. }
  1379. sxsEndAssemblyInstall(installCookie, endInstallFlags | (fSuccess ? SXS_END_ASSEMBLY_INSTALL_FLAG_COMMIT : SXS_END_ASSEMBLY_INSTALL_FLAG_ABORT), NULL);
  1380. }
  1381. PrintIfAnyCriticalSectionsHeld();
  1382. if (!fSuccess)
  1383. {
  1384. fprintf(stderr, "%s failed!\n", __FUNCTION__);
  1385. return EXIT_FAILURE;
  1386. }
  1387. else
  1388. return EXIT_SUCCESS;
  1389. }
  1390. BOOL
  1391. TestManifestSchema(
  1392. int argc,
  1393. wchar_t** argv,
  1394. int* piNext
  1395. )
  1396. {
  1397. SXSP_DEBUG_FUNCTION& pfn = pfnSxspDebug;
  1398. BOOL fSuccess = FALSE;
  1399. int i = (*piNext) + 1;
  1400. if (i >= argc)
  1401. {
  1402. fprintf(stderr, "%S: Missing parameter after \"%S\"\n", argv[0], argv[i-1]);
  1403. goto Exit;
  1404. }
  1405. LoadSxs();
  1406. GetSxsProc(SXSP_DEBUG_ORDINAL, &pfn);
  1407. fSuccess = (*pfn)(SXS_DEBUG_CHECK_MANIFEST_SCHEMA, 0, argv[i++], NULL);
  1408. if (!fSuccess)
  1409. {
  1410. fprintf(stderr, "%s failed!\n", __FUNCTION__);
  1411. goto Exit;
  1412. }
  1413. *piNext = i;
  1414. fSuccess = TRUE;
  1415. Exit:
  1416. return fSuccess;
  1417. }
  1418. BOOL
  1419. TestXMLParsing(
  1420. int argc,
  1421. wchar_t** argv,
  1422. int* piNext)
  1423. {
  1424. SXSP_DEBUG_FUNCTION pfn = NULL;
  1425. BOOL fSuccess = FALSE;
  1426. int i = (*piNext) + 1;
  1427. if (i >= argc)
  1428. {
  1429. fprintf(stderr, "%S: missing parameter after \"%S\"\n", argv[0], argv[i-1]);
  1430. goto Exit;
  1431. }
  1432. LoadSxs();
  1433. GetSxsProc(SXSP_DEBUG_ORDINAL, &pfn);
  1434. fSuccess = (*pfn)(SXS_DEBUG_XML_PARSER, 0, argv[i], NULL);
  1435. if (!fSuccess)
  1436. {
  1437. fprintf(stderr, "%s failed!\n", __FUNCTION__);
  1438. goto Exit;
  1439. }
  1440. *piNext = i + 1;
  1441. fSuccess = TRUE;
  1442. Exit:
  1443. return fSuccess;
  1444. }
  1445. BOOL
  1446. TestDirect(
  1447. int argc,
  1448. wchar_t** argv,
  1449. int* piNext)
  1450. {
  1451. SXSP_DEBUG_FUNCTION pfn = NULL;
  1452. BOOL fSuccess = FALSE;
  1453. int i = (*piNext) + 1;
  1454. if (i >= argc)
  1455. {
  1456. fprintf(stderr, "%S: missing parameter after \"%S\"\n", argv[0], argv[i-1]);
  1457. goto Exit;
  1458. }
  1459. LoadSxs();
  1460. GetSxsProc(SXSP_DEBUG_ORDINAL, &pfn);
  1461. fSuccess = (*pfn)(SXS_DEBUG_DLL_REDIRECTION, 0, argv[i], NULL);
  1462. if (!fSuccess)
  1463. {
  1464. fprintf(stderr, "%s failed!\n", __FUNCTION__);
  1465. goto Exit;
  1466. }
  1467. *piNext = i + 1;
  1468. fSuccess = TRUE;
  1469. Exit:
  1470. return fSuccess;
  1471. }
  1472. VOID
  1473. PrintBlob(
  1474. FILE *pf,
  1475. PVOID Data,
  1476. SIZE_T Length,
  1477. PCWSTR PerLinePrefix
  1478. )
  1479. {
  1480. ULONG Offset = 0;
  1481. if (PerLinePrefix == NULL)
  1482. PerLinePrefix = L"";
  1483. // we'll output in 8-byte chunks as shown:
  1484. //
  1485. // [prefix]Binary section %p (%d bytes)
  1486. // [prefix] 00000000: xx-xx-xx-xx-xx-xx-xx-xx (........)
  1487. // [prefix] 00000008: xx-xx-xx-xx-xx-xx-xx-xx (........)
  1488. // [prefix] 00000010: xx-xx-xx-xx-xx-xx-xx-xx (........)
  1489. //
  1490. while (Length >= 8)
  1491. {
  1492. BYTE *pb = (BYTE *) (((ULONG_PTR) Data) + Offset);
  1493. fprintf(
  1494. pf,
  1495. "%S %08lx: %02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x (%c%c%c%c%c%c%c%c)\n",
  1496. PerLinePrefix,
  1497. Offset,
  1498. pb[0], pb[1], pb[2], pb[3], pb[4], pb[5], pb[6], pb[7],
  1499. PRINTABLE(pb[0]),
  1500. PRINTABLE(pb[1]),
  1501. PRINTABLE(pb[2]),
  1502. PRINTABLE(pb[3]),
  1503. PRINTABLE(pb[4]),
  1504. PRINTABLE(pb[5]),
  1505. PRINTABLE(pb[6]),
  1506. PRINTABLE(pb[7]));
  1507. Offset += 8;
  1508. Length -= 8;
  1509. }
  1510. if (Length != 0)
  1511. {
  1512. CStringBuffer buffTemp;
  1513. bool First = true;
  1514. ULONG i;
  1515. BYTE *pb = (BYTE *) (((ULONG_PTR) Data) + Offset);
  1516. buffTemp.Win32ResizeBuffer(48, eDoNotPreserveBufferContents);
  1517. buffTemp.Win32Format(L" %08lx: ", Offset);
  1518. for (i=0; i<8; i++)
  1519. {
  1520. if (Length > 0)
  1521. {
  1522. if (!First)
  1523. buffTemp.Win32Append("-", 1);
  1524. else
  1525. First = false;
  1526. buffTemp.Win32FormatAppend(L"%02x", pb[i]);
  1527. Length--;
  1528. }
  1529. else
  1530. {
  1531. buffTemp.Win32Append(" ", 3);
  1532. }
  1533. }
  1534. buffTemp.Win32Append(" (", 2);
  1535. i = 0;
  1536. while (Length != 0)
  1537. {
  1538. CHAR chTemp = static_cast<CHAR>(PRINTABLE(pb[i]));
  1539. i++;
  1540. buffTemp.Win32Append(&chTemp, 1);
  1541. Length--;
  1542. }
  1543. buffTemp.Win32Append(L")", 1);
  1544. fprintf(
  1545. pf,
  1546. "%S%S\n",
  1547. PerLinePrefix,
  1548. static_cast<PCWSTR>(buffTemp));
  1549. }
  1550. }
  1551. void __stdcall TestWin32Apc(ULONG_PTR arg)
  1552. {
  1553. ACTCTXW ac = {sizeof(ac)};
  1554. int error = 0;
  1555. PWSTR source = reinterpret_cast<PWSTR>(arg);
  1556. HANDLE hActCtx = NULL;
  1557. BOOL fSuccess = FALSE;
  1558. ac.lpSource = source;
  1559. PWSTR pound = wcschr(source, '#');
  1560. if (pound != NULL)
  1561. {
  1562. *pound = 0;
  1563. ac.lpResourceName = pound + 1;
  1564. ac.dwFlags |= ACTCTX_FLAG_RESOURCE_NAME_VALID;
  1565. }
  1566. ac.wProcessorArchitecture = g.wProcessorArchitecture;
  1567. ac.wLangId = g.wLangId;
  1568. hActCtx = ::CreateActCtxW(&ac);
  1569. if (hActCtx == INVALID_HANDLE_VALUE)
  1570. {
  1571. error = ::GetLastError();
  1572. fwprintf(stderr, L"CreateActCtxW(%ls) failed; ::GetLastError() = %d\n", source, error);
  1573. goto Exit;
  1574. }
  1575. //fSuccess = ::ReleaseActCtx(hActCtx);
  1576. fSuccess = TRUE;
  1577. hActCtx = NULL;
  1578. if (!fSuccess)
  1579. {
  1580. error = ::GetLastError();
  1581. goto Exit;
  1582. }
  1583. Exit:
  1584. if (error)
  1585. ThrowWin32(error);
  1586. }
  1587. void
  1588. TestWin32(
  1589. wchar_t** argv
  1590. )
  1591. {
  1592. CreateThreads();
  1593. int i = 0;
  1594. for (i = 0 ; argv[i] ; ++i)
  1595. {
  1596. if (g.NumberOfThreads)
  1597. {
  1598. if (!QueueUserAPC(TestWin32Apc, g.Threads[i % g.NumberOfThreads], reinterpret_cast<ULONG_PTR>(argv[i])))
  1599. {
  1600. fprintf(stderr, "QueueUserAPC() failed\n");
  1601. ThrowWin32(((ULONG_PTR) (LONG_PTR) -1));
  1602. }
  1603. }
  1604. else
  1605. {
  1606. TestWin32Apc(reinterpret_cast<ULONG_PTR>(argv[i]));
  1607. }
  1608. }
  1609. }
  1610. #if BETA1
  1611. const static WCHAR InheritManifest[] =
  1612. L"<assembly manifestversion=\"1.0\" name=\"InheritManifest\">"
  1613. L"<dependency assemblyname=\"Microsoft-Visual-CPlusPlus-Runtime-Libraries\" version=\"6.0.0.0\" language=\"0000\"/>"
  1614. L"</assembly>"
  1615. ;
  1616. #else // suppose to be BETA2 or later
  1617. const static WCHAR InheritManifest[] =
  1618. L"<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
  1619. L"<assemblyIdentity type=\"win32\" name=\"Microsoft.Windows.SystemCompatibleAssembly\" version=\"1.0.0.0\" processorArchitecture=\"x86\" />"
  1620. L"<description>System Compatible Default</description> "
  1621. L"<dependency> <dependentAssembly>"
  1622. L"<assemblyIdentity type=\"win32\" name=\"Microsoft.Tools.VisualCPlusPlus.Runtime-Libraries\" version=\"6.0.0.0\" language=\"*\" processorArchitecture=\"x86\" publicKeyToken=\"6595b64144ccf1df\" />"
  1623. L"</dependentAssembly> </dependency></assembly>"
  1624. ;
  1625. #endif
  1626. const static WCHAR NoInheritManifest[] =
  1627. L"<assembly manifestversion=\"1.0\" name=\"InheritManifest\">"
  1628. L"<dependency assemblyname=\"Microsoft-Visual-CPlusPlus-Runtime-Libraries\" version=\"6.0.0.0\" language=\"0000\"/>"
  1629. L"<noinherit/>"
  1630. L"</assembly>"
  1631. ;
  1632. const static WCHAR RefCountManifest[] =
  1633. L"<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
  1634. L"<assemblyIdentity type=\"win32\" name=\"Microsoft.Windows.SxsTest.RefCount\" version=\"1.0.0.0\" processorArchitecture=\"x86\" />"
  1635. L"<description>blah</description> "
  1636. L"<dependency><dependentAssembly>"
  1637. //L"<assemblyIdentity type=\"win32\" name=\"Microsoft.Windows.SxsTest1\" version=\"1.0.0.0\" language=\"*\" processorArchitecture=\"x86\" publicKeyToken=\"6595b64144ccf1df\" />"
  1638. L"<assemblyIdentity type=\"win32\" name=\"Microsoft.Tools.VisualCPlusPlus.Runtime-Libraries\" version=\"6.0.0.0\" language=\"*\" processorArchitecture=\"x86\" publicKeyToken=\"6595b64144ccf1df\" />"
  1639. L"</dependentAssembly> </dependency></assembly>"
  1640. ;
  1641. // to test the empty actctx, we push this, probe, push empty, probe
  1642. const static PCWSTR DependentOnMsvc6Manifest = InheritManifest;
  1643. WCHAR SearchPathResult[MAX_PATH];
  1644. void ProbeContext(const char* Function, PCWSTR Dll = L"msvcrt.dll")
  1645. {
  1646. SearchPathResult[0] = 0;
  1647. SearchPathW(NULL, Dll, NULL, NUMBER_OF(SearchPathResult), SearchPathResult, NULL);
  1648. DbgPrint("%s %ls\n", Function, SearchPathResult);
  1649. }
  1650. DWORD CALLBACK InheritThreadMain(VOID*)
  1651. {
  1652. ProbeContext(__FUNCTION__);
  1653. return 0;
  1654. }
  1655. DWORD CALLBACK NoinheritThreadMain(VOID*)
  1656. {
  1657. ProbeContext(__FUNCTION__);
  1658. return 0;
  1659. }
  1660. void TestInherit()
  1661. {
  1662. ProbeContext(__FUNCTION__);
  1663. HANDLE ActivationContextHandle = ::CreateActivationContextFromStringW(InheritManifest);
  1664. ULONG_PTR Cookie;
  1665. ActivateActCtx(ActivationContextHandle, &Cookie);
  1666. ProbeContext(__FUNCTION__);
  1667. DWORD ThreadId;
  1668. WaitForSingleObject(CreateThread(NULL, 0, InheritThreadMain, NULL, 0, &ThreadId), INFINITE);
  1669. }
  1670. void TestNoInherit()
  1671. {
  1672. ProbeContext(__FUNCTION__);
  1673. HANDLE ActivationContextHandle = ::CreateActivationContextFromStringW(NoInheritManifest);
  1674. ULONG_PTR Cookie;
  1675. ActivateActCtx(ActivationContextHandle, &Cookie);
  1676. ProbeContext(__FUNCTION__);
  1677. DWORD ThreadId;
  1678. WaitForSingleObject(CreateThread(NULL, 0, NoinheritThreadMain, NULL, 0, &ThreadId), INFINITE);
  1679. }
  1680. void TestEmpty()
  1681. {
  1682. ProbeContext(__FUNCTION__);
  1683. HANDLE ActivationContextHandle = ::CreateActivationContextFromStringW(DependentOnMsvc6Manifest);
  1684. ULONG_PTR Cookie1, Cookie2;
  1685. ActivateActCtx(ActivationContextHandle, &Cookie1);
  1686. ProbeContext(__FUNCTION__);
  1687. ActivateActCtx(ACTCTX_EMPTY, &Cookie2);
  1688. ProbeContext(__FUNCTION__);
  1689. DeactivateActCtx(0, Cookie2);
  1690. ProbeContext(__FUNCTION__);
  1691. DeactivateActCtx(0, Cookie1);
  1692. ProbeContext(__FUNCTION__);
  1693. }
  1694. #if 0
  1695. #define SXSTEST_NTOPENFILE_RET NTSTATUS
  1696. #define SXSTEST_NTOPENFILE_CALL NTAPI
  1697. #define SXSTEST_NTOPENFILE_ARG_NAMES_TYPES \
  1698. (\
  1699. OUT PHANDLE FileHandle, \
  1700. IN ACCESS_MASK DesiredAccess, \
  1701. IN POBJECT_ATTRIBUTES ObjectAttributes, \
  1702. OUT PIO_STATUS_BLOCK IoStatusBlock, \
  1703. IN ULONG ShareAccess, \
  1704. IN ULONG OpenOptions \
  1705. )
  1706. #define SXSTEST_NTCREATEFILE_RET NTSTATUS
  1707. #define SXSTEST_NTCREATEFILE_CALL NTAPI
  1708. #define SXSTEST_NTCREATEFILE_ARG_NAMES_TYPES \
  1709. (\
  1710. OUT PHANDLE FileHandle, \
  1711. IN ACCESS_MASK DesiredAccess, \
  1712. IN POBJECT_ATTRIBUTES ObjectAttributes, \
  1713. OUT PIO_STATUS_BLOCK IoStatusBlock, \
  1714. IN PLARGE_INTEGER AllocationSize OPTIONAL, \
  1715. IN ULONG FileAttributes, \
  1716. IN ULONG ShareAccess, \
  1717. IN ULONG CreateDisposition, \
  1718. IN ULONG CreateOptions, \
  1719. IN PVOID EaBuffer OPTIONAL, \
  1720. IN ULONG EaLength \
  1721. )
  1722. SXSTEST_NTCREATEFILE_RET (SXSTEST_NTCREATEFILE_CALL* SxsTestDynamicNtCreateFileTrampoline)(...);
  1723. SXSTEST_NTCREATEFILE_RET
  1724. DETOUR_TRAMPOLINE(
  1725. SXSTEST_NTCREATEFILE_RET SXSTEST_NTCREATEFILE_CALL SxsTestNtCreateFileTrampoline SXSTEST_NTCREATEFILE_ARG_NAMES_TYPES,
  1726. NtCreateFile
  1727. );
  1728. DETOUR_TRAMPOLINE(
  1729. SXSTEST_NTOPENFILE_RET SXSTEST_NTOPENFILE_CALL SxsTestNtOpenFileTrampoline SXSTEST_NTCREATEFILE_ARG_NAMES_TYPES,
  1730. NtOpenFile
  1731. );
  1732. #endif
  1733. void TestRefCount()
  1734. {
  1735. //
  1736. // 1) newly created actctx has refcount==1
  1737. // 2) activated actctx has refcount==1
  1738. // 3) load a library with no deps with actctx, refcount==2
  1739. // 4) freelibrary, refcount==1
  1740. // directory of library is closed
  1741. // 5) release actctx refcount==0
  1742. //
  1743. // First order, just step through the code to look at the refcount.
  1744. // Second order, "detour" like crazy and look at the memory
  1745. // (including detouring away RtlFreeHeap, NtUnmapViewOfSection)
  1746. //
  1747. HANDLE ActivationContextHandle = ::CreateActivationContextFromStringW(RefCountManifest);
  1748. ULONG_PTR Cookie1;
  1749. ActivateActCtx(ActivationContextHandle, &Cookie1);
  1750. FreeLibrary(LoadLibraryW(L"msvcrt.dll"));
  1751. DeactivateActCtx(0, Cookie1);
  1752. ReleaseActCtx(ActivationContextHandle);
  1753. #if 0
  1754. WCHAR RenameDirectorySource[MAX_PATH];
  1755. WCHAR RenameDirectoryDestination[MAX_PATH];
  1756. //
  1757. // Try to rename the directory.
  1758. //
  1759. DbgPrint("dll was loaded from %ls, now see if we can rename that directory\n", SearchPathResult);
  1760. wcscpy(RenameDirectorySource, SearchPathResult);
  1761. *wcsrchr(SearchPathResult, '\\') = 0;
  1762. wcscpy(RenameDirectoryDestination, RenameDirectorySource);
  1763. wcscpy(wcsrchr(RenameDirectoryDestination, '\\'), L"blah");
  1764. BOOL Success = MoveFileW(RenameDirectorySource, RenameDirectoryDestination);
  1765. int Error = ::GetLastError();
  1766. DbgPrint("MoveFile(%ls -> %ls) %s, Error=%d\n",
  1767. RenameDirectorySource, RenameDirectoryDestination, Success ? "succeeded" : "failed", Error);
  1768. #endif
  1769. }
  1770. GUID Guids[100];
  1771. WCHAR GuidStrings[100][64];
  1772. void FormatGuid(WCHAR* String, const GUID& Guid)
  1773. {
  1774. swprintf(
  1775. String,
  1776. L"%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
  1777. Guid.Data1,
  1778. Guid.Data2,
  1779. Guid.Data3,
  1780. Guid.Data4[0], Guid.Data4[1], Guid.Data4[2], Guid.Data4[3],
  1781. Guid.Data4[4], Guid.Data4[5], Guid.Data4[6], Guid.Data4[7]);
  1782. }
  1783. extern "C" HRESULT __stdcall
  1784. DllGetClassObject(
  1785. REFCLSID rclsid, //CLSID for the class object
  1786. REFIID riid, //Reference to the identifier of the interface
  1787. // that communicates with the class object
  1788. LPVOID * ppv //Address of output variable that receives the
  1789. // interface pointer requested in riid
  1790. )
  1791. {
  1792. WCHAR GuidString[64];
  1793. FormatGuid(GuidString, rclsid);
  1794. printf("%s : {%ls}\n", __FUNCTION__, GuidString);
  1795. if (riid == IID_IUnknown)
  1796. {
  1797. *ppv = &g.unknown;
  1798. return S_OK;
  1799. }
  1800. else
  1801. {
  1802. return E_NOINTERFACE;
  1803. }
  1804. }
  1805. void TestGuidSort()
  1806. {
  1807. const int MAX = 100;
  1808. FN_TRACE_SMART_TLS();
  1809. CStringBuffer Manifest;
  1810. int i = 0;
  1811. Ole32.CoInitialize(NULL);
  1812. Manifest.Win32ResizeBuffer(1 << 15, eDoNotPreserveBufferContents);
  1813. Manifest.Win32Format(
  1814. L"<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\"> \
  1815. <assemblyIdentity \
  1816. type=\"win32\" \
  1817. name=\"Microsoft.Windows.SxsTest.GuidSort\" \
  1818. version=\"1.0.0.0\" \
  1819. processorArchitecture=\"x86\" \
  1820. publicKeyToken=\"6595b64144ccf1df\" \
  1821. /> \
  1822. <file name=\"sxstest.exe\">");
  1823. for (i = 0 ; i < MAX ; ++i)
  1824. {
  1825. GUID& Guid = Guids[i];
  1826. CoCreateGuid(&Guid);
  1827. FormatGuid(GuidStrings[i], Guid);
  1828. if (!Manifest.Win32FormatAppend(
  1829. L"\n<comClass description=\"a%d\" clsid=\"{%ls}\"/>",
  1830. i,
  1831. static_cast<PCWSTR>(GuidStrings[i])))
  1832. ThrowLastError();
  1833. }
  1834. if (!Manifest.Win32FormatAppend(L"\n</file>\n</assembly>"))
  1835. ThrowLastError();
  1836. //LoadSxs();
  1837. //GetSxsProc(SXSP_DEBUG_ORDINAL, &pfn);
  1838. //fSuccess = (*pfn)(SXS_DEBUG_DLL_REDIRECTION, 0, argv[i], NULL);
  1839. printf("%ls\n", static_cast<PCWSTR>(Manifest));
  1840. HANDLE ActivationContextHandle = ::CreateActivationContextFromStringW(Manifest);
  1841. ULONG_PTR Cookie1;
  1842. ActivateActCtx(ActivationContextHandle, &Cookie1);
  1843. for (i = 0 ; i < MAX ; ++i)
  1844. {
  1845. HRESULT hr;
  1846. PVOID pv = NULL;
  1847. hr = Ole32.CoCreateInstance(Guids[i], NULL, CLSCTX_INPROC, IID_IUnknown, &pv);
  1848. printf("CoCreateInstance({%ls}): %08lx%s%s%s\n",
  1849. GuidStrings[i],
  1850. static_cast<unsigned long>(hr),
  1851. ( (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND))
  1852. || hr == REGDB_E_CLASSNOTREG
  1853. || (hr == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER))
  1854. || (hr == E_NOINTERFACE)
  1855. ) ? "(" : "",
  1856. (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND))
  1857. ? "ERROR_FILE_NOT_FOUND"
  1858. : (hr == REGDB_E_CLASSNOTREG)
  1859. ? "REGDB_E_CLASSNOTREG"
  1860. : (hr == ERROR_INVALID_PARAMETER)
  1861. ? "ERROR_INVALID_PARAMETER"
  1862. : (hr == E_NOINTERFACE)
  1863. ? "E_NOINTERFACE (ok)"
  1864. : "",
  1865. ( hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)
  1866. || hr == REGDB_E_CLASSNOTREG
  1867. || hr == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER))
  1868. || hr == E_NOINTERFACE
  1869. ? ")" : "");
  1870. }
  1871. DeactivateActCtx(0, Cookie1);
  1872. ReleaseActCtx(ActivationContextHandle);
  1873. }
  1874. void TestStringSort()
  1875. {
  1876. /*
  1877. Mike says this takes between 2 and 7 to visit the code.
  1878. */
  1879. const int MAX = 50;
  1880. FN_TRACE_SMART_TLS();
  1881. WCHAR ExePath[MAX_PATH];
  1882. CStringBuffer DllPaths[MAX];
  1883. CStringBuffer Manifest;
  1884. int i = 0;
  1885. if (!Kernel32.GetModuleFileNameW(NULL, ExePath, RTL_NUMBER_OF(ExePath)))
  1886. ThrowLastError();
  1887. if (!Manifest.Win32ResizeBuffer(1 << 15, eDoNotPreserveBufferContents))
  1888. ThrowLastError();
  1889. if (!Manifest.Win32Format(
  1890. L"<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\"> \
  1891. <assemblyIdentity \
  1892. type=\"win32\" \
  1893. name=\"Microsoft.Windows.SxsTest.StringSort\" \
  1894. version=\"1.0.0.0\" \
  1895. processorArchitecture=\"x86\" \
  1896. publicKeyToken=\"6595b64144ccf1df\" \
  1897. /> \
  1898. <file name=\"sxstest.exe\"/>"))
  1899. ThrowLastError();
  1900. for (i = 0 ; i < MAX ; ++i)
  1901. {
  1902. if (!DllPaths[i].Win32Format(L"%ls.%d.dll", ExePath, i))
  1903. ThrowLastError();
  1904. if (!::CopyFileW(ExePath, DllPaths[i], FALSE))
  1905. ThrowLastError();
  1906. SetDllBitInPeImage(DllPaths[i]);
  1907. if (!Manifest.Win32FormatAppend(L"\n<file name=\"%ls\"/>\n", 1 + wcsrchr(static_cast<PCWSTR>(DllPaths[i]), '\\')))
  1908. ThrowLastError();
  1909. }
  1910. if (!Manifest.Win32FormatAppend(L"\n</assembly>"))
  1911. ThrowLastError();
  1912. //LoadSxs();
  1913. //GetSxsProc(SXSP_DEBUG_ORDINAL, &pfn);
  1914. //fSuccess = (*pfn)(SXS_DEBUG_DLL_REDIRECTION, 0, argv[i], NULL);
  1915. printf("%ls\n", static_cast<PCWSTR>(Manifest));
  1916. HANDLE ActivationContextHandle = ::CreateActivationContextFromStringW(Manifest);
  1917. ULONG_PTR Cookie1;
  1918. ActivateActCtx(ActivationContextHandle, &Cookie1);
  1919. for (i = 0 ; i < MAX ; ++i)
  1920. {
  1921. HMODULE h;
  1922. PCWSTR DllName = 1 + wcsrchr(DllPaths[i], '\\');
  1923. h = ::LoadLibraryW(DllName);
  1924. printf("LoadLibrary(%ls):%p, LastError=%d\n",
  1925. DllName,
  1926. h,
  1927. ::GetLastError());
  1928. //FreeLibrary(h);
  1929. ::DeleteFileW(DllPaths[i]);
  1930. }
  1931. DeactivateActCtx(0, Cookie1);
  1932. ReleaseActCtx(ActivationContextHandle);
  1933. }
  1934. int
  1935. TestSearchPathHelper1(
  1936. PCSTR RunId,
  1937. PCWSTR Path,
  1938. PCWSTR File,
  1939. PCWSTR Extension,
  1940. bool GetFilePart,
  1941. ULONG cch
  1942. )
  1943. {
  1944. WCHAR Buffer[65536]; // we know that the underlying code can never use a buffer this big
  1945. PWSTR FilePart = NULL;
  1946. PWSTR *lpFilePart = (GetFilePart ? &FilePart : NULL);
  1947. SetLastError(ERROR_GEN_FAILURE);
  1948. ULONG Result = ::SearchPathW(
  1949. Path,
  1950. File,
  1951. Extension,
  1952. 0,
  1953. NULL,
  1954. lpFilePart);
  1955. printf("SearchPath() RunId = %s (Path %s; File %s; Extension %s; GetFilePart %s; cch = %lu; buffer=null) result = %lu ::GetLastError() = %u; FilePart = %s %u\n",
  1956. RunId,
  1957. Path ? "present" : "null",
  1958. File ? "present" : "null",
  1959. Extension ? "present" : "null",
  1960. GetFilePart ? "true" : "false",
  1961. 0,
  1962. Result,
  1963. ::GetLastError(),
  1964. FilePart ? "present" : "null",
  1965. FilePart ? (FilePart - Buffer) : 0);
  1966. SetLastError(ERROR_GEN_FAILURE);
  1967. FilePart = NULL;
  1968. ULONG NewResult = ::SearchPathW(
  1969. Path,
  1970. File,
  1971. Extension,
  1972. Result,
  1973. Buffer,
  1974. lpFilePart);
  1975. printf("SearchPath() RunId = %s (Path %s; File %s; Extension %s; GetFilePart %s; cch = %lu) result = %lu ::GetLastError() = %u; FilePart = %s %u\n",
  1976. RunId,
  1977. Path ? "present" : "null",
  1978. File ? "present" : "null",
  1979. Extension ? "present" : "null",
  1980. GetFilePart ? "true" : "false",
  1981. Result,
  1982. NewResult,
  1983. ::GetLastError(),
  1984. FilePart ? "present" : "null",
  1985. FilePart ? (FilePart - Buffer) : 0);
  1986. SetLastError(ERROR_GEN_FAILURE);
  1987. FilePart = NULL;
  1988. Result = ::SearchPathW(
  1989. Path,
  1990. File,
  1991. Extension,
  1992. cch,
  1993. Buffer,
  1994. lpFilePart);
  1995. printf("SearchPath() RunId = %s (Path %s; File %s; Extension %s; GetFilePart %s; cch = %lu) result = %lu ::GetLastError() = %u; FilePart = %s %u\n",
  1996. RunId,
  1997. Path ? "present" : "null",
  1998. File ? "present" : "null",
  1999. Extension ? "present" : "null",
  2000. GetFilePart ? "true" : "false",
  2001. cch,
  2002. Result,
  2003. ::GetLastError(),
  2004. FilePart ? "present" : "null",
  2005. FilePart ? (FilePart - Buffer) : 0);
  2006. return EXIT_SUCCESS;
  2007. }
  2008. int
  2009. TestSearchPathHelper2(
  2010. PCSTR RunId,
  2011. PCWSTR Path,
  2012. PCWSTR File,
  2013. PCWSTR Extension,
  2014. ULONG cch
  2015. )
  2016. {
  2017. TestSearchPathHelper1(RunId, NULL, File, NULL, true, cch);
  2018. TestSearchPathHelper1(RunId, NULL, File, NULL, false, cch);
  2019. TestSearchPathHelper1(RunId, Path, File, NULL, true, cch);
  2020. TestSearchPathHelper1(RunId, Path, File, NULL, false, cch);
  2021. TestSearchPathHelper1(RunId, NULL, File, Extension, true, cch);
  2022. TestSearchPathHelper1(RunId, NULL, File, Extension, false, cch);
  2023. TestSearchPathHelper1(RunId, Path, File, Extension, true, cch);
  2024. TestSearchPathHelper1(RunId, Path, File, Extension, false, cch);
  2025. return EXIT_SUCCESS;
  2026. }
  2027. int
  2028. TestSearchPathHelper3(
  2029. PCSTR RunId,
  2030. PCWSTR Path,
  2031. PCWSTR File,
  2032. PCWSTR Extension
  2033. )
  2034. {
  2035. ULONG i;
  2036. for (i=0; i<5; i++)
  2037. TestSearchPathHelper2(RunId, Path, File, Extension, i);
  2038. for (i=MAX_PATH-5; i<(MAX_PATH+5); i++)
  2039. TestSearchPathHelper2(RunId, Path, File, Extension, i);
  2040. for (i=32760; i<32770; i++)
  2041. TestSearchPathHelper2(RunId, Path, File, Extension, i);
  2042. return EXIT_SUCCESS;
  2043. }
  2044. BOOL
  2045. TestSearchPath(
  2046. int argc,
  2047. wchar_t** argv,
  2048. int* piNext
  2049. )
  2050. {
  2051. ULONG i;
  2052. PWSTR PathToSearch = (PWSTR) malloc(100000* sizeof(WCHAR));
  2053. int iNext = (*piNext) + 1;
  2054. PathToSearch[0] = L'C';
  2055. PathToSearch[1] = L'\\';
  2056. for (i=2; i<60000; i++)
  2057. PathToSearch[i] = L'X';
  2058. wcscpy(&PathToSearch[i], L";C:\\");
  2059. TestSearchPathHelper3("1.0", L"C:\\DirectoryDoesNotExist;C:\\", L"boot.ini", L".ini");
  2060. TestSearchPathHelper3("1.1", L"C:\\DirectoryDoesNotExist;C:\\", L"boot.", L".ini");
  2061. TestSearchPathHelper3("1.2", L"C:\\DirectoryDoesNotExist;C:\\", L"boot", L".ini");
  2062. TestSearchPathHelper3("1.3", L"C:\\DirectoryDoesNotExist;C:\\", L"doesnotexist.doesnotexist", L".ini");
  2063. TestSearchPathHelper3("1.4", L"C:\\DirectoryDoesNotExist;C:\\", L"d:\\readme.txt", L".ini");
  2064. TestSearchPathHelper3("1.5", L"C:\\DirectoryDoesNotExist;C:\\", L"kernel32.dll", L".dll");
  2065. TestSearchPathHelper3("1.6", L"C:\\DirectoryDoesNotExist;C:\\", L"kernel32.", L".dll");
  2066. TestSearchPathHelper3("1.7", L"C:\\DirectoryDoesNotExist;C:\\", L"kernel32", L".dll");
  2067. TestSearchPathHelper3("1.8", L"C:\\DirectoryDoesNotExist;C:\\", L"kernel32.dll", L".ini");
  2068. TestSearchPathHelper3("1.9", L"C:\\DirectoryDoesNotExist;C:\\", L"kernel32.", L".ini");
  2069. TestSearchPathHelper3("1.10", L"C:\\DirectoryDoesNotExist;C:\\", L"kernel32", L".ini");
  2070. TestSearchPathHelper3("2.0", L"C:\\;C:\\DirectoryDoesNotExist", L"boot.ini", L".ini");
  2071. TestSearchPathHelper3("2.1", L"C:\\;C:\\DirectoryDoesNotExist", L"boot.", L".ini");
  2072. TestSearchPathHelper3("2.2", L"C:\\;C:\\DirectoryDoesNotExist", L"boot", L".ini");
  2073. TestSearchPathHelper3("2.3", L"C:\\;C:\\DirectoryDoesNotExist", L"doesnotexist.doesnotexist", L".ini");
  2074. TestSearchPathHelper3("2.4", L"C:\\;C:\\DirectoryDoesNotExist", L"d:\\readme.txt", L".ini");
  2075. TestSearchPathHelper3("2.5", L"C:\\;C:\\DirectoryDoesNotExist", L"kernel32.dll", L".dll");
  2076. TestSearchPathHelper3("2.6", L"C:\\;C:\\DirectoryDoesNotExist", L"kernel32.", L".dll");
  2077. TestSearchPathHelper3("2.7", L"C:\\;C:\\DirectoryDoesNotExist", L"kernel32", L".dll");
  2078. TestSearchPathHelper3("2.8", L"C:\\;C:\\DirectoryDoesNotExist", L"kernel32.dll", L".ini");
  2079. TestSearchPathHelper3("2.9", L"C:\\;C:\\DirectoryDoesNotExist", L"kernel32.", L".ini");
  2080. TestSearchPathHelper3("2.10", L"C:\\;C:\\DirectoryDoesNotExist", L"kernel32", L".ini");
  2081. TestSearchPathHelper3("3.0", PathToSearch, L"boot.ini", L".ini");
  2082. TestSearchPathHelper3("3.1", PathToSearch, L"boot", L".ini");
  2083. TestSearchPathHelper3("3.1", PathToSearch, L"boot.", L".ini");
  2084. TestSearchPathHelper3("3.2", PathToSearch, L"doesnotexist.doesnotexist", L".ini");
  2085. TestSearchPathHelper3("3.3", PathToSearch, L"d:\\readme.txt", L".ini");
  2086. *piNext = iNext;
  2087. return EXIT_SUCCESS;
  2088. }
  2089. BOOL
  2090. TestAct(
  2091. int argc,
  2092. wchar_t** argv,
  2093. int* piNext)
  2094. {
  2095. ULONG i, c;
  2096. ULONG_PTR *prgCookies = NULL;
  2097. HANDLE hActCtx = NULL;
  2098. CHAR buffer[1024];
  2099. int iNext = (*piNext + 1);
  2100. BOOL fSuccess = FALSE;
  2101. if (iNext >= argc)
  2102. {
  2103. fprintf(stderr, "%S: missing parameter after \"%S\"\n", argv[0], argv[iNext - 1]);
  2104. goto Exit;
  2105. }
  2106. WideCharToMultiByte(CP_ACP, 0, argv[iNext++], -1, buffer, NUMBER_OF(buffer), NULL, NULL);
  2107. ACTCTXA ac;
  2108. ac.cbSize = sizeof(ac);
  2109. ac.dwFlags = 0;
  2110. ac.lpSource = buffer;
  2111. ac.wProcessorArchitecture = g.wProcessorArchitecture;
  2112. ac.wLangId = g.wLangId;
  2113. hActCtx = ::CreateActCtxA(&ac);
  2114. if (hActCtx == INVALID_HANDLE_VALUE)
  2115. {
  2116. fprintf(stderr, "CreateActCtxA() failed; ::GetLastError() = %d\n", ::GetLastError());
  2117. return EXIT_FAILURE;
  2118. }
  2119. c = 0;
  2120. if (argc > iNext)
  2121. c = _wtoi(argv[iNext++]);
  2122. if (c == 0)
  2123. c = 100;
  2124. prgCookies = NEW(ULONG_PTR[c]);
  2125. if (prgCookies == NULL)
  2126. {
  2127. fprintf(stderr, "Unable to allocate %lu cookies.\n", c);
  2128. goto Exit;
  2129. }
  2130. for (i=0; i<c; i++)
  2131. {
  2132. if (!ActivateActCtx(hActCtx, &prgCookies[i]))
  2133. {
  2134. fprintf(stderr, "Attempt to activate to depth %lu failed; ::GetLastError() = %d\n", i, ::GetLastError());
  2135. goto Exit;
  2136. }
  2137. }
  2138. for (i=0; i<c; i++)
  2139. {
  2140. ULONG j = (c - i) - 1;
  2141. DeactivateActCtx(0, prgCookies[j]);
  2142. }
  2143. ReleaseActCtx(hActCtx);
  2144. fSuccess = TRUE;
  2145. *piNext = iNext;
  2146. Exit:
  2147. delete []prgCookies;
  2148. return fSuccess;
  2149. }
  2150. HRESULT Helper_WriteStream(CBaseStringBuffer * pFileNameBuf,
  2151. IStream *pStream)
  2152. {
  2153. HRESULT hr = NOERROR;
  2154. LPBYTE pBuf[0x4000];
  2155. DWORD cbBuf = 0x4000;
  2156. DWORD dwWritten = 0;
  2157. DWORD cbRead = 0;
  2158. HANDLE hf = INVALID_HANDLE_VALUE;
  2159. hf = ::CreateFileW(static_cast<PCWSTR>(*pFileNameBuf), GENERIC_READ, FILE_SHARE_READ,
  2160. NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
  2161. if (hf == INVALID_HANDLE_VALUE){
  2162. hr = HRESULT_FROM_WIN32 (GetLastError());
  2163. goto Exit;
  2164. }
  2165. while (::ReadFile(hf, pBuf, cbBuf, &cbRead, NULL) && cbRead){
  2166. hr = pStream->Write(pBuf, cbRead, &dwWritten);
  2167. if (FAILED(hr))
  2168. goto Exit;
  2169. }
  2170. if (! SUCCEEDED(hr =pStream->Commit(0)))
  2171. goto Exit;
  2172. CloseHandle(hf);
  2173. Exit:
  2174. return hr;
  2175. }
  2176. BOOL
  2177. TestMSIInstall(
  2178. int argc,
  2179. wchar_t** argv,
  2180. int* piNext
  2181. )
  2182. {
  2183. BOOL fSuccess = FALSE;
  2184. FN_TRACE_WIN32(fSuccess);
  2185. CSmartRef<IAssemblyCache> pCache;
  2186. CSmartRef<IAssemblyCacheItem> ppCacheItem[4];
  2187. CSmartRef<IStream> pStream;
  2188. PFNCreateAssemblyCache pCreateAssemblyCache = NULL;
  2189. CStringBuffer SourceFilePathBuf;
  2190. CStringBuffer SourceFileNameBuf;
  2191. CHAR buf[1024];
  2192. FILE* fp = NULL;
  2193. LPSTR p1, pbuf ;
  2194. int i, cAsm;
  2195. int iArg = (*piNext) + 1;
  2196. if (iArg >= argc)
  2197. {
  2198. fprintf(stderr, "%S: missing parameter after \"%S\"\n", argv[0], argv[iArg-1]);
  2199. goto Exit;
  2200. }
  2201. LoadSxs();
  2202. GetSxsProc("CreateAssemblyCache", &pCreateAssemblyCache);
  2203. IFCOMFAILED_EXIT(pCreateAssemblyCache(&pCache, 0));
  2204. WideCharToMultiByte(CP_ACP, 0, argv[iArg], -1, buf, NUMBER_OF(buf), NULL, NULL);
  2205. fp = fopen(buf, "r");
  2206. if (!fp) {
  2207. fprintf(stderr, "%S: Error opening script file \"%S\"\n", argv[0], argv[iArg]);
  2208. goto Exit;
  2209. }
  2210. cAsm = 0;
  2211. while (! feof(fp)) {
  2212. if (! fgets(buf, 80, fp)) { // end of file or error
  2213. if (ferror(fp)){ // error occur
  2214. fprintf(stderr, "%S: Error occur while reading the script file\n", argv[0]);
  2215. goto Exit;
  2216. }
  2217. else{ // end of file
  2218. fprintf(stderr, "%S: end of script file\n", argv[0]);
  2219. break;
  2220. }
  2221. }
  2222. // trim the string
  2223. i = 0 ;
  2224. while (buf[i] == ' ') i++; // skip the whitespace at the beginning of the line
  2225. pbuf = buf + i ; // pointer to the first un-whitespace char in the line
  2226. i = 0 ;
  2227. while (pbuf[i] != '\n') i++;
  2228. pbuf[i] = '\0';
  2229. p1 = NULL;
  2230. p1 = strchr(pbuf, ' ');
  2231. if (p1 == NULL) { // instruction line
  2232. if (strcmp(pbuf, "BeginAsmCacheItem") == 0) {
  2233. IFCOMFAILED_EXIT(pCache->CreateAssemblyCacheItem(0, NULL, &ppCacheItem[cAsm], NULL));
  2234. }else
  2235. if (strcmp(pbuf, "EndAsmCacheItem") == 0) {
  2236. IFCOMFAILED_EXIT(ppCacheItem[cAsm]->Commit(0, NULL));
  2237. cAsm ++;
  2238. }
  2239. }
  2240. else
  2241. { // get the first word of the line
  2242. *p1 = '\0';
  2243. p1++; // p1 points to the filename now
  2244. IFW32FALSE_EXIT(SourceFileNameBuf.Win32Assign(p1, ::strlen(p1)));
  2245. if (strcmp(pbuf,"SourceFilePath") == 0) { // fullpath of source files, which would be in a CD
  2246. IFW32FALSE_EXIT(SourceFilePathBuf.Win32Assign(p1, ::strlen(p1)));
  2247. SourceFilePathBuf.Win32EnsureTrailingPathSeparator();
  2248. }else
  2249. if (strcmp(pbuf, "FILE") == 0) {
  2250. IFCOMFAILED_EXIT(ppCacheItem[cAsm]->CreateStream(0, SourceFileNameBuf, STREAM_FORMAT_WIN32_MODULE, 0, &pStream, NULL));
  2251. IFW32FALSE_EXIT(SourceFileNameBuf.Win32Assign(SourceFilePathBuf, ::wcslen(SourceFilePathBuf)));
  2252. IFW32FALSE_EXIT(SourceFileNameBuf.Win32Append(p1, ::strlen(p1))); // containing full-path of the source file
  2253. IFCOMFAILED_EXIT(Helper_WriteStream(&SourceFileNameBuf, pStream));
  2254. pStream.Release(); // stream should be released since writtingfile has been done
  2255. }else
  2256. if (strcmp(pbuf, "MANIFEST") == 0) {
  2257. IFCOMFAILED_EXIT(ppCacheItem[cAsm]->CreateStream(0, SourceFileNameBuf, STREAM_FORMAT_WIN32_MANIFEST, 0, &pStream, NULL));
  2258. IFW32FALSE_EXIT(SourceFileNameBuf.Win32Assign(SourceFilePathBuf, SourceFilePathBuf.Cch())); // containing full-path of the source file
  2259. IFW32FALSE_EXIT(SourceFileNameBuf.Win32Append(p1, ::strlen(p1)));
  2260. IFCOMFAILED_EXIT(Helper_WriteStream(&SourceFileNameBuf, pStream));
  2261. pStream.Release(); // stream should be released since writtingfile has been done
  2262. }
  2263. } // end of else
  2264. }// end of while
  2265. fSuccess = TRUE;
  2266. *piNext = iArg;
  2267. Exit:
  2268. fp ? fclose(fp) : 0;
  2269. return fSuccess;
  2270. }
  2271. CDirWalk::ECallbackResult
  2272. DirWalkCallback(
  2273. CDirWalk::ECallbackReason reason,
  2274. CDirWalk* dirWalk,
  2275. DWORD dwFlags
  2276. )
  2277. {
  2278. PCWSTR parent = dirWalk->m_strParent;
  2279. PCWSTR leaf = dirWalk->m_fileData.cFileName;
  2280. if (reason == CDirWalk::eFile)
  2281. printf("file %lu, %ls, %ls\n", reason, parent, leaf);
  2282. else
  2283. printf("directory %lu, %ls\n", reason, parent);
  2284. return CDirWalk::eKeepWalking;
  2285. }
  2286. int
  2287. TestDirWalk(
  2288. PCWSTR root,
  2289. PWSTR filter
  2290. )
  2291. {
  2292. CDirWalk dirWalk;
  2293. StdVector<std::wstring> vstrFilter;
  2294. StdVector<PCWSTR> vstrFilter2;
  2295. PWSTR filterTok;
  2296. if (filterTok = wcstok(filter, L";"))
  2297. {
  2298. do
  2299. {
  2300. vstrFilter.push_back(filterTok);
  2301. vstrFilter2.push_back(vstrFilter.back().c_str());
  2302. } while (filterTok = wcstok(NULL, L";"));
  2303. }
  2304. dirWalk.m_fileFiltersBegin = &*vstrFilter2.begin();
  2305. dirWalk.m_fileFiltersEnd = &*vstrFilter2.end();
  2306. dirWalk.m_strParent.Win32Assign(root, ::wcslen(root));
  2307. dirWalk.m_callback = DirWalkCallback;
  2308. dirWalk.Walk();
  2309. return 0;
  2310. }
  2311. int
  2312. TestMultiAct(
  2313. int argc,
  2314. wchar_t **argv
  2315. )
  2316. {
  2317. HANDLE h1, h2;
  2318. ACTCTXW acw;
  2319. memset(&acw, 0, sizeof(acw));
  2320. acw.cbSize = sizeof(acw);
  2321. acw.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID;
  2322. acw.lpSource = argv[2];
  2323. acw.lpResourceName = MAKEINTRESOURCEW(1);
  2324. h1 = ::CreateActCtxW(&acw);
  2325. if (h1 == INVALID_HANDLE_VALUE)
  2326. {
  2327. fprintf(stderr, "1st CreateActCtxW() failed; ::GetLastError() = %d\n", ::GetLastError());
  2328. return EXIT_FAILURE;
  2329. }
  2330. h2 = ::CreateActCtxW(&acw);
  2331. if (h2 == INVALID_HANDLE_VALUE)
  2332. {
  2333. fprintf(stderr, "2nd CreateActCtxW() failed; ::GetLastError() = %d\n", ::GetLastError());
  2334. return EXIT_FAILURE;
  2335. }
  2336. return EXIT_SUCCESS;
  2337. }
  2338. BOOL
  2339. ParseProcessorArchitecture(
  2340. int argc,
  2341. wchar_t** argv,
  2342. int* piCurrent
  2343. )
  2344. {
  2345. BOOL fSuccess = FALSE;
  2346. int i = *piCurrent;
  2347. i++;
  2348. if (i >= argc)
  2349. {
  2350. fprintf(stderr, "%S: missing parameter after %S\n", argv[0], argv[i - 1]);
  2351. goto Exit;
  2352. }
  2353. if (::FusionpStrCmpI(argv[i], L"x86") == 0)
  2354. g.wProcessorArchitecture = PROCESSOR_ARCHITECTURE_INTEL;
  2355. else if (::FusionpStrCmpI(argv[i], L"i386") == 0)
  2356. g.wProcessorArchitecture = PROCESSOR_ARCHITECTURE_INTEL;
  2357. else if (::FusionpStrCmpI(argv[i], L"ia64") == 0)
  2358. g.wProcessorArchitecture = PROCESSOR_ARCHITECTURE_IA64;
  2359. else if (::FusionpStrCmpI(argv[i], L"alpha64") == 0)
  2360. g.wProcessorArchitecture = PROCESSOR_ARCHITECTURE_ALPHA64;
  2361. else
  2362. {
  2363. fprintf(stderr, "%S: invalid -pa value \"%S\"\n", argv[0], argv[i]);
  2364. goto Exit;
  2365. }
  2366. *piCurrent = i + 1;
  2367. fSuccess = TRUE;
  2368. Exit:
  2369. return fSuccess;
  2370. }
  2371. BOOL
  2372. ParseLangId(
  2373. int argc,
  2374. wchar_t** argv,
  2375. int* piCurrent
  2376. )
  2377. {
  2378. BOOL fSuccess = FALSE;
  2379. int i = *piCurrent;
  2380. i++;
  2381. if (i >= argc)
  2382. {
  2383. fprintf(stderr, "%S: missing parameter after %S\n", argv[0], argv[i - 1]);
  2384. goto Exit;
  2385. }
  2386. swscanf(argv[i], L"%hx", &g.wLangId);
  2387. *piCurrent = i + 1;
  2388. fSuccess = TRUE;
  2389. Exit:
  2390. return fSuccess;
  2391. }
  2392. BOOL
  2393. TestLoadLibrary(
  2394. int argc,
  2395. wchar_t** argv,
  2396. int* piNext
  2397. )
  2398. {
  2399. int i = (*piNext) + 1;
  2400. HINSTANCE hInstance = NULL;
  2401. BOOL fExpectedToFail = FALSE;
  2402. BOOL fSuccess = FALSE;
  2403. while (i < argc)
  2404. {
  2405. if (::FusionpStrCmpI(argv[i], L"-fail-") == 0)
  2406. fExpectedToFail = TRUE;
  2407. else if (::FusionpStrCmpI(argv[i], L"-succeed-") == 0)
  2408. fExpectedToFail = FALSE;
  2409. else
  2410. {
  2411. hInstance = LoadLibraryW(argv[i]);
  2412. if (hInstance == NULL)
  2413. {
  2414. if (!fExpectedToFail)
  2415. {
  2416. fprintf(stderr, "%S: Failed to LoadLibraryW(\"%S\"); ::GetLastError() = %d\n", argv[0], argv[i], ::GetLastError());
  2417. }
  2418. }
  2419. else
  2420. {
  2421. if (fExpectedToFail)
  2422. {
  2423. WCHAR LibraryPath[4096];
  2424. Kernel32.GetModuleFileNameW(hInstance, LibraryPath, NUMBER_OF(LibraryPath));
  2425. fprintf(stderr, "%S: LoadLibraryW(\"%S\") was supposed to fail, but instead we got \"%S\"\n", argv[0], argv[i], LibraryPath);
  2426. }
  2427. ::FreeLibrary(hInstance);
  2428. hInstance = NULL;
  2429. }
  2430. }
  2431. i++;
  2432. }
  2433. fSuccess = TRUE;
  2434. // Exit:
  2435. return fSuccess;
  2436. }
  2437. int TestAssemblyName()
  2438. {
  2439. SXSP_DEBUG_FUNCTION pfn = NULL;
  2440. BOOL fSuccess = FALSE;
  2441. LoadSxs();
  2442. GetSxsProc(SXSP_DEBUG_ORDINAL, &pfn);
  2443. fSuccess = (*pfn)(SXS_DEBUG_ASSEMBLYNAME_CONVERSION, 0, NULL, NULL);
  2444. if (! fSuccess){
  2445. fprintf(stderr, "%s failed!\n", __FUNCTION__);
  2446. return EXIT_FAILURE;
  2447. }
  2448. else
  2449. return EXIT_SUCCESS;
  2450. }
  2451. int TestPrecomiledManifest(PCWSTR manifestFileName)
  2452. {
  2453. SXSP_DEBUG_FUNCTION pfn = NULL;
  2454. BOOL fSuccess = FALSE;
  2455. LoadSxs();
  2456. GetSxsProc(SXSP_DEBUG_ORDINAL, &pfn);
  2457. fSuccess = (*pfn)(SXS_DEBUG_PRECOMPILED_MANIFEST, 0, manifestFileName, NULL);
  2458. if (! fSuccess){
  2459. fprintf(stderr, "%s failed!\n", __FUNCTION__);
  2460. return EXIT_FAILURE;
  2461. }
  2462. else
  2463. return EXIT_SUCCESS;
  2464. }
  2465. int TestPCMTime(PCWSTR manifestFilename)
  2466. {
  2467. SXSP_DEBUG_FUNCTION pfn = NULL;
  2468. BOOL fSuccess = FALSE;
  2469. LoadSxs();
  2470. GetSxsProc(SXSP_DEBUG_ORDINAL, &pfn);
  2471. fSuccess = (*pfn)(SXS_DEBUG_TIME_PCM, 0, manifestFilename, NULL);
  2472. if (! fSuccess)
  2473. {
  2474. fprintf(stderr, "%s failed!\n", __FUNCTION__);
  2475. return EXIT_FAILURE;
  2476. }
  2477. else
  2478. return EXIT_SUCCESS;
  2479. }
  2480. int TestCreateMultiLevelDirectory(PCWSTR dirs)
  2481. {
  2482. SXSP_DEBUG_FUNCTION pfn = NULL;
  2483. BOOL fSuccess = FALSE;
  2484. LoadSxs();
  2485. GetSxsProc(SXSP_DEBUG_ORDINAL, &pfn);
  2486. fSuccess = (*pfn)(SXS_DEBUG_CREAT_MULTILEVEL_DIRECTORY, 0, dirs, NULL);
  2487. if (! fSuccess)
  2488. {
  2489. fprintf(stderr, "%s failed!\n", __FUNCTION__);
  2490. return EXIT_FAILURE;
  2491. }
  2492. else
  2493. return EXIT_SUCCESS;
  2494. }
  2495. BOOL
  2496. TestLeakMemory(
  2497. DWORD dwAmount
  2498. )
  2499. {
  2500. SXSP_DEBUG_FUNCTION pfn = NULL;
  2501. BOOL fSuccess = FALSE;
  2502. if (dwAmount < 1) {
  2503. fprintf(stderr, "%s got a bad parameter, %d; rectifying to 1.\n", __FUNCTION__, dwAmount);
  2504. dwAmount = 1;
  2505. }
  2506. LoadSxs();
  2507. GetSxsProc(SXSP_DEBUG_ORDINAL, &pfn);
  2508. fSuccess = (*pfn)(SXS_DEBUG_FORCE_LEAK, 0, NULL, (PDWORD)&dwAmount);
  2509. if (! fSuccess)
  2510. {
  2511. fprintf(stderr, "%s failed to leak %d bytes of memory!\n", __FUNCTION__, dwAmount);
  2512. return EXIT_FAILURE;
  2513. }
  2514. else
  2515. {
  2516. fprintf(stdout, "%s leaked %d bytes of memory.\n", __FUNCTION__, dwAmount);
  2517. return EXIT_SUCCESS;
  2518. }
  2519. }
  2520. BOOL
  2521. TestManifestProbing(
  2522. int argc,
  2523. wchar_t **argv,
  2524. int *piNext
  2525. )
  2526. {
  2527. SXSP_DEBUG_FUNCTION pfn = NULL;
  2528. BOOL fSuccess = FALSE;
  2529. LoadSxs();
  2530. GetSxsProc(SXSP_DEBUG_ORDINAL, &pfn);
  2531. fSuccess = (*pfn)(SXS_DEBUG_PROBE_MANIFST, 0, NULL, NULL);
  2532. if (! fSuccess){
  2533. fprintf(stderr, "%s failed!\n", __FUNCTION__);
  2534. return EXIT_FAILURE;
  2535. }
  2536. else
  2537. return EXIT_SUCCESS;
  2538. }
  2539. BOOL
  2540. TestAssemblyProbing(
  2541. int argc,
  2542. wchar_t **argv,
  2543. int *piNext
  2544. )
  2545. {
  2546. PSXS_PROBE_ASSEMBLY_INSTALLATION pfn;
  2547. BOOL fSuccess = FALSE;
  2548. DWORD dwDisposition = 0;
  2549. LoadSxs();
  2550. GetSxsProc(SXS_PROBE_ASSEMBLY_INSTALLATION, &pfn);
  2551. fSuccess = (*pfn)(0, argv[*piNext], &dwDisposition);
  2552. return (fSuccess ? EXIT_SUCCESS : EXIT_FAILURE);
  2553. }
  2554. int TestCreateProcess2(wchar_t** argv)
  2555. {
  2556. STARTUPINFOW StartupInfo = { sizeof(StartupInfo) };
  2557. PROCESS_INFORMATION ProcessInformation = {0};
  2558. *argv += wcsspn(*argv, L" \t\r\n");
  2559. BOOL f = ::CreateProcessW(
  2560. *argv,
  2561. NULL,
  2562. NULL,
  2563. NULL,
  2564. FALSE,
  2565. 0,
  2566. NULL,
  2567. NULL,
  2568. &StartupInfo,
  2569. &ProcessInformation);
  2570. printf("CreateProcess(%S) returned %s\n", *argv, f ? "True" : "False");
  2571. return EXIT_SUCCESS;
  2572. }
  2573. int TestCreateProcess(wchar_t** argv)
  2574. {
  2575. CUnicodeStringBuffer CommandLine;
  2576. STARTUPINFOW StartupInfo = { sizeof(StartupInfo) };
  2577. PROCESS_INFORMATION ProcessInformation = {0};
  2578. while (*argv)
  2579. {
  2580. CommandLine.Win32Append(L" ", 1);
  2581. CommandLine.Win32Append(*argv, ::wcslen(*argv));
  2582. argv++;
  2583. }
  2584. CUnicodeStringBufferAccessor MutableCommandLine(&CommandLine);
  2585. BOOL f = ::CreateProcessW(
  2586. NULL,
  2587. MutableCommandLine,
  2588. NULL,
  2589. NULL,
  2590. FALSE,
  2591. 0,
  2592. NULL,
  2593. NULL,
  2594. &StartupInfo,
  2595. &ProcessInformation);
  2596. printf("CreateProcess(%S) returned %s\n", static_cast<PCWSTR>(MutableCommandLine), f ? "True" : "False");
  2597. return EXIT_SUCCESS;
  2598. }
  2599. ////////////////////////////////////////////////////////////////////////////
  2600. // XMLDOM Helper function:
  2601. ////////////////////////////////////////////////////////////////////////////
  2602. HRESULT XMLDOMHelper_WalkTree(IXMLDOMNode* node, int level)
  2603. {
  2604. IXMLDOMNode* pChild, *pNext;
  2605. BSTR nodeName;
  2606. IXMLDOMNamedNodeMap* pattrs;
  2607. node->get_nodeName(&nodeName);
  2608. for (int i = 0; i < level; i++)
  2609. printf(" ");
  2610. printf("%S",nodeName);
  2611. SysFreeString(nodeName);
  2612. if (SUCCEEDED(node->get_attributes(&pattrs)) && pattrs != NULL)
  2613. {
  2614. pattrs->nextNode(&pChild);
  2615. while (pChild)
  2616. {
  2617. BSTR name;
  2618. pChild->get_nodeName(&name);
  2619. printf(" %S='", name);
  2620. ::SysFreeString(name);
  2621. VARIANT value;
  2622. pChild->get_nodeValue(&value);
  2623. if (value.vt == VT_BSTR)
  2624. {
  2625. printf("%S", V_BSTR(&value));
  2626. }
  2627. printf("'");
  2628. VariantClear(&value);
  2629. pChild->Release();
  2630. pattrs->nextNode(&pChild);
  2631. }
  2632. pattrs->Release();
  2633. }
  2634. printf("\n");
  2635. node->get_firstChild(&pChild);
  2636. while (pChild)
  2637. {
  2638. XMLDOMHelper_WalkTree(pChild, level+1);
  2639. pChild->get_nextSibling(&pNext);
  2640. pChild->Release();
  2641. pChild = pNext;
  2642. }
  2643. return S_OK;
  2644. }
  2645. ////////////////////////////////////////////////////////////////////////////
  2646. // XMLDOM Helper function:
  2647. ////////////////////////////////////////////////////////////////////////////
  2648. HRESULT XMLDOMHelper_ReportError(IXMLDOMParseError *pXMLError)
  2649. {
  2650. long line, linePos;
  2651. LONG errorCode;
  2652. BSTR pBURL = NULL, pBReason = NULL;
  2653. HRESULT hr;
  2654. hr = pXMLError->get_line(&line);
  2655. if (FAILED(hr))
  2656. goto Exit;
  2657. hr = pXMLError->get_linepos(&linePos);
  2658. if (FAILED(hr))
  2659. goto Exit;
  2660. hr = pXMLError->get_errorCode(&errorCode);
  2661. if (FAILED(hr))
  2662. goto Exit;
  2663. hr = pXMLError->get_url(&pBURL);
  2664. if (FAILED(hr))
  2665. goto Exit;
  2666. hr = pXMLError->get_reason(&pBReason);
  2667. if (FAILED(hr))
  2668. goto Exit;
  2669. fprintf(stderr, "%S", pBReason);
  2670. if (line > 0)
  2671. {
  2672. fprintf(stderr, "Error on line %d, position %d in \"%S\".\n",
  2673. line, linePos, pBURL);
  2674. }
  2675. hr= E_FAIL;
  2676. Exit:
  2677. SysFreeString(pBURL);
  2678. SysFreeString(pBReason);
  2679. return hr;
  2680. }
  2681. ////////////////////////////////////////////////////////////////////////////
  2682. // XMLDOM Helper function: Check load results
  2683. ////////////////////////////////////////////////////////////////////////////
  2684. HRESULT XMLDOMHelper_CheckLoad(IXMLDOMDocument* pDoc)
  2685. {
  2686. // And since we don't have the VARIANT_BOOL from load we
  2687. // need to check the parse Error errorCode property to see
  2688. // if everything went ok.
  2689. IXMLDOMParseError *pXMLError = NULL;
  2690. LONG errorCode;
  2691. HRESULT hr = NOERROR;
  2692. hr = pDoc->get_parseError(&pXMLError);
  2693. if (FAILED(hr))
  2694. goto Exit;
  2695. hr = pXMLError->get_errorCode(&errorCode);
  2696. if (FAILED(hr))
  2697. goto Exit;
  2698. if (errorCode != 0){
  2699. hr = XMLDOMHelper_ReportError(pXMLError);
  2700. goto Exit;
  2701. }
  2702. hr = NOERROR;
  2703. Exit:
  2704. if (pXMLError)
  2705. pXMLError->Release();
  2706. return hr;
  2707. }
  2708. ////////////////////////////////////////////////////////////////////////////
  2709. // XMLDOM Helper function:
  2710. ////////////////////////////////////////////////////////////////////////////
  2711. HRESULT XMLDOMHelper_LoadDocumentSync(IXMLDOMDocument *pDoc, BSTR pBURL)
  2712. {
  2713. IXMLDOMParseError *pXMLError = NULL;
  2714. VARIANT vURL;
  2715. VARIANT_BOOL vb;
  2716. HRESULT hr;
  2717. hr = pDoc->put_async(VARIANT_FALSE);
  2718. if (FAILED(hr))
  2719. goto Exit;
  2720. // Load xml document from the given URL or file path
  2721. VariantInit(&vURL);
  2722. vURL.vt = VT_BSTR;
  2723. V_BSTR(&vURL) = pBURL;
  2724. hr = pDoc->load(vURL, &vb);
  2725. if (FAILED(hr))
  2726. goto Exit;
  2727. hr = XMLDOMHelper_CheckLoad(pDoc);
  2728. if (FAILED(hr))
  2729. goto Exit;
  2730. hr = NOERROR;
  2731. Exit:
  2732. if (pXMLError)
  2733. pXMLError->Release();
  2734. return hr;
  2735. }
  2736. BOOL TestXMLDOM(PCWSTR pswzXMLFileName)
  2737. {
  2738. HRESULT hr = S_OK;
  2739. IXMLDOMDocument *pDoc = NULL;
  2740. IXMLDOMNode* pNode = NULL;
  2741. BSTR pBURL = NULL;
  2742. Ole32.CoInitialize(NULL);
  2743. // Create an empty XML document
  2744. hr = Ole32.CoCreateInstance(CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER,
  2745. IID_IXMLDOMDocument, (void**)&pDoc);
  2746. if (FAILED(hr))
  2747. goto Exit;
  2748. pBURL = SysAllocString(pswzXMLFileName);
  2749. hr = XMLDOMHelper_LoadDocumentSync(pDoc, pBURL);
  2750. if (FAILED(hr))
  2751. goto Exit;
  2752. // Now walk the loaded XML document dumping the node names to stdout.
  2753. hr = pDoc->QueryInterface(IID_IXMLDOMNode,(void**)&pNode);
  2754. if (FAILED(hr))
  2755. goto Exit;
  2756. hr = XMLDOMHelper_WalkTree(pNode,0);
  2757. if (FAILED(hr))
  2758. goto Exit;
  2759. hr = NOERROR;
  2760. Exit:
  2761. if (pDoc) pDoc->Release();
  2762. SysFreeString(pBURL);
  2763. if (pNode) pNode->Release();
  2764. Ole32.CoUninitialize();
  2765. return hr == 0 ? 0 : 1;
  2766. }
  2767. BOOL TestFusionArray(PCWSTR dir1, PCWSTR dir2)
  2768. {
  2769. SXSP_DEBUG_FUNCTION pfn = NULL;
  2770. BOOL fSuccess = FALSE;
  2771. LoadSxs();
  2772. GetSxsProc(SXSP_DEBUG_ORDINAL, &pfn);
  2773. fSuccess = (*pfn)(SXS_DEBUG_FUSION_ARRAY, 0, dir1, (PVOID)dir2);
  2774. if (! fSuccess){
  2775. fprintf(stderr, "%s failed!\n", __FUNCTION__);
  2776. return EXIT_FAILURE;
  2777. }
  2778. else
  2779. return EXIT_SUCCESS;
  2780. }
  2781. BOOL TestGeneratePathFromIdentityAttributeString(PCWSTR str)
  2782. {
  2783. PSXSPGENERATEMANIFESTPATHONASSEMBLYIDENTITY pfn = NULL;
  2784. BOOL fSuccess = FALSE;
  2785. WCHAR folderName[5000];
  2786. SIZE_T cch = NUMBER_OF(folderName);
  2787. LoadSxs();
  2788. GetSxsProc("SxspGenerateManifestPathOnAssemblyIdentity", &pfn);
  2789. fSuccess = (*pfn)((PWSTR) str, folderName, &cch, NULL);
  2790. if (! fSuccess)
  2791. {
  2792. fprintf(stderr, "%s failed!\n", __FUNCTION__);
  2793. return EXIT_FAILURE;
  2794. }
  2795. else
  2796. {
  2797. wprintf(L"Folder name returned is %s\n", folderName);
  2798. return EXIT_SUCCESS;
  2799. }
  2800. }
  2801. BOOL
  2802. TestDirectoryChangeWatcher(
  2803. int argc,
  2804. wchar_t **argv,
  2805. int *piNext
  2806. )
  2807. {
  2808. SXSP_DEBUG_FUNCTION pfn;
  2809. BOOL fSuccess;
  2810. LoadSxs();
  2811. GetSxsProc(SXSP_DEBUG_ORDINAL, &pfn);
  2812. fSuccess = (*pfn)(SXS_DEBUG_DIRECTORY_WATCHER, 0, NULL, NULL);
  2813. return (fSuccess ? EXIT_SUCCESS : EXIT_FAILURE);
  2814. }
  2815. BOOL
  2816. TestRefreshAssembly(
  2817. PCWSTR wsAssemblyManifest
  2818. )
  2819. {
  2820. BOOL fSuccess = FALSE;
  2821. PSXS_INSTALL_ASSEMBLY_W sxsInstallAssemblyW = NULL;
  2822. LoadSxs();
  2823. GetSxsProc("SxsInstallAssemblyW", &sxsInstallAssemblyW);
  2824. if (!sxsInstallAssemblyW(
  2825. NULL,
  2826. SXS_INSTALL_ASSEMBLY_FLAG_REPLACE_EXISTING,
  2827. wsAssemblyManifest,
  2828. NULL))
  2829. {
  2830. fwprintf(
  2831. stderr,
  2832. L"Failed reinstalling assembly '%ls', 0x%08X\n",
  2833. wsAssemblyManifest,
  2834. ::GetLastError());
  2835. }
  2836. else
  2837. {
  2838. fSuccess = TRUE;
  2839. }
  2840. return fSuccess;
  2841. }
  2842. BOOL
  2843. TestInstallWithInstallInfo(
  2844. PCWSTR wsAssemblyManifest,
  2845. PCWSTR wsReferenceString
  2846. )
  2847. {
  2848. #define SXS_TEST
  2849. BOOL fSuccess = FALSE;
  2850. FN_TRACE_WIN32(fSuccess);
  2851. PSXS_INSTALL_W_ROUTINE sxsInstallW = NULL;
  2852. SXS_INSTALLW InstallParameters = {sizeof(InstallParameters)};
  2853. SXS_INSTALL_REFERENCEW InstallReference = {sizeof(InstallReference)};
  2854. LoadSxs();
  2855. GetSxsProc("SxsInstallW", &sxsInstallW);
  2856. InstallParameters.dwFlags =
  2857. //SXS_INSTALL_FLAG_MOVE |
  2858. SXS_INSTALL_FLAG_REPLACE_EXISTING |
  2859. SXS_INSTALL_FLAG_CODEBASE_URL_VALID |
  2860. SXS_INSTALL_FLAG_REFERENCE_VALID |
  2861. SXS_INSTALL_FLAG_REFRESH_PROMPT_VALID;
  2862. InstallParameters.lpCodebaseURL = wsAssemblyManifest;
  2863. InstallParameters.lpManifestPath = wsAssemblyManifest;
  2864. InstallParameters.lpReference = &InstallReference;
  2865. InstallParameters.lpRefreshPrompt = L"boop";
  2866. InstallReference.guidScheme = SXS_INSTALL_REFERENCE_SCHEME_OPAQUESTRING;
  2867. InstallReference.lpIdentifier = wsReferenceString ? wsReferenceString : L"TempRef";
  2868. if (!(*sxsInstallW)(&InstallParameters))
  2869. {
  2870. goto Exit;
  2871. }
  2872. fSuccess = TRUE;
  2873. Exit:
  2874. if (!fSuccess)
  2875. {
  2876. fprintf(stderr, "%s failed!\n", __FUNCTION__);
  2877. return EXIT_FAILURE;
  2878. }
  2879. else
  2880. return EXIT_SUCCESS;
  2881. }
  2882. BOOL
  2883. TestInstallLikeWindowsSetup(
  2884. PCWSTR wsAssemblyManifest,
  2885. PCWSTR wsCodebase
  2886. )
  2887. {
  2888. BOOL fSuccess = FALSE;
  2889. FN_TRACE_WIN32(fSuccess);
  2890. PSXS_BEGIN_ASSEMBLY_INSTALL sxsBeginAssemblyInstall = NULL;
  2891. PSXS_INSTALL_W_ROUTINE sxsInstallW = NULL;
  2892. PSXS_END_ASSEMBLY_INSTALL sxsEndAssemblyInstall = NULL;
  2893. SXS_INSTALLW InstallParameters = {sizeof(InstallParameters)};
  2894. SXS_INSTALL_REFERENCEW InstallReference = {sizeof(InstallReference)};
  2895. LoadSxs();
  2896. GetSxsProc("SxsBeginAssemblyInstall", &sxsBeginAssemblyInstall);
  2897. GetSxsProc("SxsInstallW", &sxsInstallW);
  2898. GetSxsProc("SxsEndAssemblyInstall", &sxsEndAssemblyInstall);
  2899. IFW32FALSE_EXIT(
  2900. (*sxsBeginAssemblyInstall)(
  2901. SXS_BEGIN_ASSEMBLY_INSTALL_FLAG_NOT_TRANSACTIONAL
  2902. | SXS_BEGIN_ASSEMBLY_INSTALL_FLAG_NO_VERIFY
  2903. | SXS_BEGIN_ASSEMBLY_INSTALL_FLAG_REPLACE_EXISTING,
  2904. NULL,
  2905. NULL,
  2906. NULL,
  2907. NULL,
  2908. &InstallParameters.pvInstallCookie));
  2909. InstallReference.guidScheme = SXS_INSTALL_REFERENCE_SCHEME_OSINSTALL;
  2910. InstallReference.lpNonCanonicalData = L"Foom";
  2911. InstallParameters.dwFlags |= SXS_INSTALL_FLAG_CODEBASE_URL_VALID
  2912. | SXS_INSTALL_FLAG_FROM_DIRECTORY
  2913. | SXS_INSTALL_FLAG_FROM_DIRECTORY_RECURSIVE
  2914. | SXS_INSTALL_FLAG_REFRESH_PROMPT_VALID
  2915. | SXS_INSTALL_FLAG_INSTALL_COOKIE_VALID
  2916. | SXS_INSTALL_FLAG_REFERENCE_VALID
  2917. ;
  2918. InstallParameters.lpCodebaseURL = wsCodebase;
  2919. InstallParameters.lpRefreshPrompt = L"like..Windows CD..";
  2920. InstallParameters.lpManifestPath = wsAssemblyManifest;
  2921. InstallParameters.lpReference = &InstallReference;
  2922. IFW32FALSE_EXIT((*sxsInstallW)(&InstallParameters));
  2923. IFW32FALSE_EXIT(
  2924. (*sxsEndAssemblyInstall)(
  2925. InstallParameters.pvInstallCookie,
  2926. SXS_END_ASSEMBLY_INSTALL_FLAG_COMMIT,
  2927. NULL));
  2928. InstallParameters.pvInstallCookie = NULL;
  2929. fSuccess = TRUE;
  2930. Exit:
  2931. if (InstallParameters.pvInstallCookie != NULL)
  2932. {
  2933. CSxsPreserveLastError ple;
  2934. (void) (*sxsEndAssemblyInstall)(InstallParameters.pvInstallCookie, SXS_END_ASSEMBLY_INSTALL_FLAG_ABORT, NULL);
  2935. ple.Restore();
  2936. }
  2937. if (!fSuccess)
  2938. {
  2939. fprintf(stderr, "%s failed!\n", __FUNCTION__);
  2940. return EXIT_FAILURE;
  2941. }
  2942. else
  2943. return EXIT_SUCCESS;
  2944. }
  2945. //#define ASM_CPUID { __asm __emit 0fh __asm __emit 0a2h }
  2946. #define ASM_CPUID { __asm cpuid }
  2947. #define ASM_RDTSC { __asm rdtsc }
  2948. inline VOID GetCpuIdLag(LARGE_INTEGER *ref)
  2949. {
  2950. #if !defined(_WIN64)
  2951. LARGE_INTEGER temp, temp2;
  2952. _asm
  2953. {
  2954. cpuid
  2955. cpuid
  2956. cpuid
  2957. cpuid
  2958. cpuid
  2959. rdtsc
  2960. mov temp.LowPart, eax
  2961. mov temp.HighPart, edx
  2962. cpuid
  2963. rdtsc
  2964. mov temp2.LowPart, eax
  2965. mov temp2.HighPart, edx
  2966. }
  2967. ref->QuadPart = temp2.QuadPart - temp.QuadPart;
  2968. #else
  2969. ref->QuadPart = 0;
  2970. #endif
  2971. }
  2972. BOOL
  2973. TestOpeningStuff(PCWSTR wsSourceName, PCWSTR wsType, PCWSTR wsCount)
  2974. {
  2975. BOOL fSuccess = FALSE;
  2976. LARGE_INTEGER llStartCount, llEndCount, llCountsPerSec, llTotalSizeSoFar;
  2977. LARGE_INTEGER CpuIdLag;
  2978. BYTE bBuffer[65536];
  2979. SIZE_T cNumTries = _wtol(wsCount);
  2980. double dCountsPerSecond, dSeconds, dCountsPerIteration, dSecondsPerIteration;
  2981. int iFinalIterationsPerSecond;
  2982. GetCpuIdLag(&CpuIdLag);
  2983. llTotalSizeSoFar.QuadPart = 0;
  2984. {
  2985. FUSION_PERF_INFO PerfInfo[2];
  2986. HANDLE hFile;
  2987. for (int i = 0; i < 5000; i++)
  2988. {
  2989. PERFINFOTIME(&PerfInfo[0], hFile = ::CreateFileW(wsSourceName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL));
  2990. PERFINFOTIME(&PerfInfo[1], ::CloseHandle(hFile));
  2991. }
  2992. FusionpReportPerfInfo(
  2993. FUSIONPERF_DUMP_TO_STDOUT |
  2994. FUSIONPERF_DUMP_ALL_STATISTICS |
  2995. FUSIONPERF_DUMP_ALL_SOURCEINFO,
  2996. PerfInfo,
  2997. NUMBER_OF(PerfInfo));
  2998. }
  2999. //
  3000. // Map the DLL as a resource a few thousand times.
  3001. //
  3002. if ((wsType[0] == L'd') || (wsType[0] == L's'))
  3003. {
  3004. FUSION_PERF_INFO PerfInfo[7];
  3005. HMODULE hDllModule;
  3006. HRSRC hManifestResource;
  3007. HGLOBAL hResource;
  3008. PVOID pvResourceData;
  3009. SIZE_T cbResourceSize;
  3010. for (SIZE_T i = 0; i < cNumTries; i++)
  3011. {
  3012. PERFINFOTIME(&PerfInfo[0], hDllModule = ::LoadLibraryExW(wsSourceName, NULL, DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE));
  3013. PERFINFOTIME(&PerfInfo[1], hManifestResource = ::FindResourceW(hDllModule, L"#1", MAKEINTRESOURCEW(RT_MANIFEST)));
  3014. PERFINFOTIME(&PerfInfo[2], hResource = ::LoadResource(hDllModule, hManifestResource));
  3015. PERFINFOTIME(&PerfInfo[3], pvResourceData = ::LockResource(hResource));
  3016. PERFINFOTIME(&PerfInfo[4], cbResourceSize = ::SizeofResource(hDllModule, hManifestResource));
  3017. PERFINFOTIME(&PerfInfo[5],
  3018. { for (SIZE_T i2 = 0; i2 < cbResourceSize; i2++)
  3019. bBuffer[i2] = ((PBYTE)pvResourceData)[i2]; }
  3020. );
  3021. PERFINFOTIME(&PerfInfo[6], FreeLibrary(hDllModule))
  3022. }
  3023. FusionpReportPerfInfo(
  3024. FUSIONPERF_DUMP_TO_STDOUT |
  3025. FUSIONPERF_DUMP_ALL_STATISTICS |
  3026. FUSIONPERF_DUMP_ALL_SOURCEINFO,
  3027. PerfInfo,
  3028. NUMBER_OF(PerfInfo));
  3029. }
  3030. else if (wsType[0] == L'x')
  3031. {
  3032. HANDLE hFile;
  3033. HANDLE hFileMapping;
  3034. PVOID pvFileData;
  3035. SIZE_T cbFileSize;
  3036. FUSION_PERF_INFO PerfInfo[9];
  3037. for (SIZE_T i = 0; i < cNumTries; i++)
  3038. {
  3039. PERFINFOTIME(&PerfInfo[0], hFile = ::CreateFileW(wsSourceName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL));
  3040. PERFINFOTIME(&PerfInfo[1], cbFileSize = ::GetFileSize(hFile, 0));
  3041. PERFINFOTIME(&PerfInfo[2], hFileMapping = ::CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL));
  3042. PERFINFOTIME(&PerfInfo[3], pvFileData = ::MapViewOfFile(hFileMapping, FILE_MAP_READ, 0, 0, 0));
  3043. PERFINFOTIME(&PerfInfo[4], { for (SIZE_T i2 = 0; i2 < cbFileSize; i2++)
  3044. PERFINFOTIME(&PerfInfo[8], bBuffer[i2] = ((PBYTE)pvFileData)[i2]); });
  3045. PERFINFOTIME(&PerfInfo[5], ::UnmapViewOfFile(pvFileData));
  3046. PERFINFOTIME(&PerfInfo[6], ::CloseHandle(hFileMapping));
  3047. PERFINFOTIME(&PerfInfo[7], ::CloseHandle(hFile));
  3048. }
  3049. FusionpReportPerfInfo(
  3050. FUSIONPERF_DUMP_TO_STDOUT |
  3051. FUSIONPERF_DUMP_ALL_STATISTICS |
  3052. FUSIONPERF_DUMP_ALL_SOURCEINFO,
  3053. PerfInfo,
  3054. NUMBER_OF(PerfInfo));
  3055. }
  3056. else if (wsType[0] == L'r')
  3057. {
  3058. BYTE bTempBlock[8192];
  3059. ULONG cbReadCount;
  3060. FUSION_PERF_INFO PerfInfo[3];
  3061. for (SIZE_T i = 0; i < cNumTries; i++)
  3062. {
  3063. CResourceStream RStream;
  3064. QueryPerformanceCounter(&llStartCount);
  3065. PERFINFOTIME(&PerfInfo[0], RStream.Initialize(wsSourceName, MAKEINTRESOURCEW(RT_MANIFEST)));
  3066. PERFINFOTIME(&PerfInfo[1], RStream.Read(bTempBlock, sizeof(bTempBlock), &cbReadCount));
  3067. PERFINFOTIME(&PerfInfo[2],
  3068. for (SIZE_T i2 = 0; i2 < cbReadCount; i2++)
  3069. {
  3070. bBuffer[i2] = bTempBlock[i2];
  3071. }
  3072. );
  3073. wprintf(L"%s", bBuffer);
  3074. QueryPerformanceCounter(&llEndCount);
  3075. llTotalSizeSoFar.QuadPart += llEndCount.QuadPart - llStartCount.QuadPart;
  3076. }
  3077. for (int i = 0; i < NUMBER_OF(PerfInfo); i++)
  3078. {
  3079. FusionpDumpPerfInfo(FUSIONPERF_DUMP_TO_STDOUT, PerfInfo + i);
  3080. }
  3081. }
  3082. else if (wsType[0] == L'f')
  3083. {
  3084. BYTE bTempBlock[8192];
  3085. ULONG cbReadCount;
  3086. for (SIZE_T i = 0; i < cNumTries; i++)
  3087. {
  3088. CFileStream RStream;
  3089. QueryPerformanceCounter(&llStartCount);
  3090. RStream.OpenForRead(
  3091. wsSourceName,
  3092. CImpersonationData(),
  3093. FILE_SHARE_READ,
  3094. OPEN_EXISTING,
  3095. FILE_FLAG_SEQUENTIAL_SCAN);
  3096. RStream.Read(bTempBlock, sizeof(bTempBlock), &cbReadCount);
  3097. for (SIZE_T i2 = 0; i2 < cbReadCount; i2++)
  3098. {
  3099. bBuffer[i2] = bTempBlock[i2];
  3100. }
  3101. QueryPerformanceCounter(&llEndCount);
  3102. llTotalSizeSoFar.QuadPart += llEndCount.QuadPart - llStartCount.QuadPart;
  3103. }
  3104. }
  3105. QueryPerformanceFrequency(&llCountsPerSec);
  3106. dCountsPerIteration = (double)llTotalSizeSoFar.QuadPart / cNumTries;
  3107. dCountsPerSecond = (double)llCountsPerSec.QuadPart;
  3108. dSeconds = (double)llTotalSizeSoFar.QuadPart / dCountsPerSecond;
  3109. dSecondsPerIteration = dCountsPerIteration / dCountsPerSecond;
  3110. iFinalIterationsPerSecond = static_cast<int>(1.0 / dSecondsPerIteration);
  3111. fwprintf(
  3112. stdout,
  3113. L"Completed %d runs: %d attempts per second available\n",
  3114. cNumTries,
  3115. iFinalIterationsPerSecond);
  3116. fSuccess = TRUE;
  3117. return fSuccess;
  3118. }
  3119. BOOL
  3120. TestVerifyFileSignature(PCWSTR wsFilename)
  3121. {
  3122. WINTRUST_FILE_INFO fInfo;
  3123. WINTRUST_DATA wtData;
  3124. GUID guidTrustType = WINTRUST_ACTION_GENERIC_VERIFY_V2;
  3125. HRESULT hResult = E_FAIL;
  3126. PWSTR pwszMessageText = NULL;
  3127. ZeroMemory(&wtData, sizeof(wtData));
  3128. ZeroMemory(&fInfo, sizeof(fInfo));
  3129. fInfo.cbStruct = sizeof(fInfo);
  3130. fInfo.pcwszFilePath = wsFilename;
  3131. fInfo.hFile = NULL;
  3132. wtData.cbStruct = sizeof(wtData);
  3133. wtData.dwUIChoice = WTD_UI_ALL;
  3134. wtData.fdwRevocationChecks = WTD_REVOKE_WHOLECHAIN;
  3135. wtData.dwUnionChoice = WTD_CHOICE_FILE;
  3136. wtData.pFile = &fInfo;
  3137. hResult = WinVerifyTrust(0, &guidTrustType, &wtData);
  3138. if (FAILED(hResult))
  3139. {
  3140. ::FormatMessageW(
  3141. FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER,
  3142. NULL,
  3143. hResult,
  3144. 0,
  3145. (PWSTR)&pwszMessageText,
  3146. 500,
  3147. NULL);
  3148. fwprintf(stdout, L"Error: %ls (code 0x%08x)\n", pwszMessageText, hResult);
  3149. LocalFree(pwszMessageText);
  3150. }
  3151. else
  3152. {
  3153. fwprintf(stdout, L"File signature(s) are valid.");
  3154. }
  3155. return TRUE;
  3156. }
  3157. __inline
  3158. ULONGLONG
  3159. GetCycleCount(void)
  3160. {
  3161. #if defined(_X86_)
  3162. __asm {
  3163. RDTSC
  3164. }
  3165. #else
  3166. return 0;
  3167. #endif // defined(_X86_)
  3168. }
  3169. BOOL TestMessagePerf(int argc, wchar_t **argv, int *piNext)
  3170. {
  3171. ATOM a;
  3172. WNDCLASSEXW wc;
  3173. ULONGLONG cc1, cc2, cc3, cc4;
  3174. ULONG i, t;
  3175. HWND hwnd;
  3176. MSG m;
  3177. ULONG mcount;
  3178. HANDLE hActCtx = NULL;
  3179. ULONG_PTR ulCookie;
  3180. wc.cbSize = sizeof(wc);
  3181. wc.style = 0;
  3182. wc.lpfnWndProc = &TestMessagePerfWndProc;
  3183. wc.cbClsExtra = 0;
  3184. wc.cbWndExtra = 0;
  3185. wc.hInstance = NULL;
  3186. wc.hIcon = NULL;
  3187. wc.hCursor = NULL;
  3188. wc.hbrBackground = NULL;
  3189. wc.lpszMenuName = NULL;
  3190. wc.lpszClassName = L"SxsMsgPerfTest";
  3191. wc.hIconSm = NULL;
  3192. printf("Beginning message perf test...\n");
  3193. a = ::RegisterClassExW(&wc);
  3194. if (a == NULL)
  3195. {
  3196. printf("RegisterClassExW() failed; ::GetLastError = %d\n", ::GetLastError());
  3197. return FALSE;
  3198. }
  3199. if (argv[*piNext][0] != L'*')
  3200. {
  3201. ACTCTXW ac;
  3202. ac.cbSize = sizeof(ac);
  3203. ac.dwFlags = 0;
  3204. ac.lpSource = argv[*piNext];
  3205. hActCtx = ::CreateActCtxW(&ac);
  3206. if (hActCtx == INVALID_HANDLE_VALUE)
  3207. {
  3208. printf("CreateActCtxW() failed; ::GetLastError() = %d\n", ::GetLastError());
  3209. goto ErrorExit;
  3210. }
  3211. }
  3212. if (!ActivateActCtx(hActCtx, &ulCookie))
  3213. {
  3214. printf("ActivateActCtx() failed; ::GetLastError() = %d\n", ::GetLastError());
  3215. goto ErrorExit;
  3216. }
  3217. (*piNext)++;
  3218. hwnd = ::CreateWindowW(
  3219. (LPCWSTR) a,
  3220. L"PerfTestWindow",
  3221. WS_VISIBLE,
  3222. 0, // x
  3223. 0, // y
  3224. 100, // width
  3225. 100, // height
  3226. NULL, // hwndParent
  3227. NULL, // hMenu
  3228. NULL, // hInstance
  3229. NULL); // lpParam
  3230. if (hwnd == NULL)
  3231. return FALSE;
  3232. t = _wtoi(argv[*piNext]);
  3233. (*piNext)++;
  3234. mcount = 0;
  3235. cc3 = 0;
  3236. cc4 = 0;
  3237. for (i=0; i<t; i++)
  3238. {
  3239. if (!PostMessageW(hwnd, WM_USER, 0, 0))
  3240. {
  3241. printf("PostMessageW() failed; ::GetLastError() = %d\n", ::GetLastError());
  3242. goto ErrorExit;
  3243. }
  3244. cc1 = GetCycleCount();
  3245. while (::PeekMessage(&m, hwnd, 0, 0, PM_REMOVE))
  3246. {
  3247. mcount++;
  3248. ::TranslateMessage(&m);
  3249. ::DispatchMessage(&m);
  3250. }
  3251. cc2 = GetCycleCount();
  3252. // accumulate the time spend just processing the message...
  3253. cc3 = cc3 + (cc2 - cc1);
  3254. }
  3255. printf("%lu messages in %I64u cycles\n", mcount, cc3);
  3256. printf(" avg cycles/msg: %I64u\n", static_cast<ULONGLONG>((cc3 / static_cast<ULONGLONG>(mcount))));
  3257. return TRUE;
  3258. ErrorExit:
  3259. return FALSE;
  3260. }
  3261. LRESULT CALLBACK TestMessagePerfWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  3262. {
  3263. return DefWindowProc(hwnd, uMsg, wParam, lParam);
  3264. }
  3265. void
  3266. TestTrickyMultipleAssemblyCacheItems(PCWSTR pvManifest)
  3267. {
  3268. PFNCreateAssemblyCacheItem pCreateAssemblyCacheItem;
  3269. PFNCreateAssemblyCache pCreateAssemblyCache;
  3270. CSmartRef<IAssemblyCache> AssemblyCache;
  3271. CSmartRef<IAssemblyCacheItem> AssemblyCacheItems[2];
  3272. CStringBuffer sbManifestName;
  3273. HRESULT hr;
  3274. LoadSxs();
  3275. GetSxsProc("CreateAssemblyCache", &pCreateAssemblyCache);
  3276. GetSxsProc("CreateAssemblyCacheItem", &pCreateAssemblyCacheItem);
  3277. sbManifestName.Win32Assign(pvManifest, wcslen(pvManifest));
  3278. for (int i = 0; i < 2; i++)
  3279. {
  3280. CSmartRef<IStream> pStream;
  3281. CSmartRef<IAssemblyCacheItem> AssemblyItemTemp;
  3282. CStringBuffer TempStreamName;
  3283. hr = pCreateAssemblyCacheItem(
  3284. &AssemblyItemTemp,
  3285. NULL,
  3286. NULL,
  3287. NULL,
  3288. 0,
  3289. 0);
  3290. //
  3291. // Manifest
  3292. //
  3293. hr = AssemblyItemTemp->CreateStream(0, pvManifest, STREAM_FORMAT_WIN32_MANIFEST, 0, &pStream, NULL);
  3294. TempStreamName.Win32Assign(sbManifestName);
  3295. hr = Helper_WriteStream(&TempStreamName, pStream);
  3296. pStream.Release();
  3297. //
  3298. // Dll
  3299. //
  3300. sbManifestName.Win32ChangePathExtension(L".dll", 4, eAddIfNoExtension);
  3301. hr = AssemblyItemTemp->CreateStream(0, static_cast<PCWSTR>(TempStreamName), STREAM_FORMAT_WIN32_MODULE, 0, &pStream, NULL);
  3302. hr = Helper_WriteStream(&TempStreamName, pStream);
  3303. pStream.Release();
  3304. hr = AssemblyItemTemp->Commit(0, NULL);
  3305. AssemblyCacheItems[i] = AssemblyItemTemp;
  3306. }
  3307. /*
  3308. hr = pCreateAssemblyCache(&AssemblyCache, 0);
  3309. hr = AssemblyCache->MarkAssembliesVisible((IUnknown**)AssemblyCacheItems, 2, 0);
  3310. */
  3311. }
  3312. void
  3313. TestSfcScanKickoff()
  3314. {
  3315. SXSP_DEBUG_FUNCTION pfn;
  3316. BOOL fSuccess = FALSE;
  3317. LoadSxs();
  3318. GetSxsProc(SXSP_DEBUG_ORDINAL, &pfn);
  3319. fSuccess = (*pfn)(SXS_DEBUG_SFC_SCANNER, 0, NULL, NULL);
  3320. }
  3321. void
  3322. GenerateStrongNameAndPublicKey(PCWSTR wsCertificate)
  3323. {
  3324. BOOL bSuccess = FALSE;
  3325. CStringBuffer sbStrings[3];
  3326. PCCERT_CONTEXT pContext = NULL;
  3327. SXSP_DEBUG_FUNCTION pfn;
  3328. HCERTSTORE hCertStore = NULL;
  3329. hCertStore = CertOpenStore(
  3330. CERT_STORE_PROV_FILENAME,
  3331. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  3332. NULL,
  3333. CERT_STORE_OPEN_EXISTING_FLAG,
  3334. (void*)wsCertificate);
  3335. LoadSxs();
  3336. GetSxsProc(SXSP_DEBUG_ORDINAL, &pfn);
  3337. while (pContext = CertEnumCertificatesInStore(hCertStore, pContext))
  3338. {
  3339. bSuccess = (*pfn)(SXS_DEBUG_GET_STRONGNAME, 0, (PCWSTR)pContext, (PVOID)sbStrings);
  3340. wprintf(L"Signer display name: %ls\n\tPublic Key: %ls\n\tPublic Key Token: %ls\n",
  3341. static_cast<PCWSTR>(sbStrings[0]),
  3342. static_cast<PCWSTR>(sbStrings[1]),
  3343. static_cast<PCWSTR>(sbStrings[2]));
  3344. }
  3345. bSuccess = TRUE;
  3346. if (pContext) CertFreeCertificateContext(pContext);
  3347. if (hCertStore) CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG);
  3348. }
  3349. BOOL CALLBACK
  3350. DumpResourceWorker(
  3351. HMODULE hModule,
  3352. PCWSTR lpszType,
  3353. PWSTR lpszName,
  3354. LONG_PTR lParam
  3355. )
  3356. {
  3357. HGLOBAL hGlobal;
  3358. HRSRC hResource;
  3359. PVOID pvData;
  3360. SIZE_T cbResource;
  3361. hResource = ::FindResourceW(hModule, lpszName, lpszType);
  3362. hGlobal = ::LoadResource(hModule, hResource);
  3363. pvData = ::LockResource(hGlobal);
  3364. if (lpszName < (PCWSTR)0xFFFF)
  3365. {
  3366. wprintf(L"----\nResource id: %p\n", lpszName);
  3367. }
  3368. else
  3369. {
  3370. wprintf(L"----\nResource name: %ls\n", lpszName);
  3371. }
  3372. cbResource = ::SizeofResource(hModule, hResource);
  3373. for (SIZE_T i = 0; i < cbResource; i++)
  3374. {
  3375. wprintf(L"%c", ((char*)pvData)[i]);
  3376. }
  3377. wprintf(L"\n");
  3378. return TRUE;
  3379. }
  3380. BOOL
  3381. TestDumpContainedManifests(PCWSTR wsFilename)
  3382. {
  3383. HMODULE hThing;
  3384. hThing = ::LoadLibraryExW(wsFilename, NULL, LOAD_LIBRARY_AS_DATAFILE);
  3385. if ((hThing == NULL) || (hThing == INVALID_HANDLE_VALUE))
  3386. {
  3387. wprintf(L"Bad mojo: can't open %ls for enumeration.\n", wsFilename);
  3388. return FALSE;
  3389. }
  3390. if (!::EnumResourceNamesW(hThing, MAKEINTRESOURCEW(RT_MANIFEST), DumpResourceWorker, NULL))
  3391. {
  3392. if (GetLastError() == ERROR_RESOURCE_TYPE_NOT_FOUND)
  3393. {
  3394. wprintf(L"No manifests found in %ls\n", wsFilename);
  3395. }
  3396. else
  3397. {
  3398. wprintf(L"Bad mojo: can't enumerate resources from %ls, error=0x%08x\n",
  3399. wsFilename,
  3400. ::GetLastError());
  3401. }
  3402. }
  3403. ::FreeLibrary(hThing);
  3404. return TRUE;
  3405. }
  3406. BOOL TestGenerateStringWithIdenticalHash(WCHAR iString[33])
  3407. {
  3408. #define START_VALUE 1
  3409. #define STR_LEN 32
  3410. #define HASH_SEED 65599
  3411. #define MAGIC_ARRAY {1, 1, -1, -1, -1, -1, 1, 1, -1, -1, 1, 1, 1, 1, -1, -1,-1, -1, 1, 1, 1, 1, -1, -1, 1, 1, -1, -1, -1, -1, 1, 1} ;
  3412. #define UPPER(ch) if (ch >=L'a' && ch <= L'z') ch = ch- L'a' + L'A';
  3413. WCHAR oString[STR_LEN + 1];
  3414. DWORD i, nLen, a[STR_LEN];
  3415. ULONG hash1, hash2;
  3416. WCHAR ch;
  3417. a[0] = a[1] = START_VALUE;
  3418. nLen = 2;
  3419. while(nLen < STR_LEN) {
  3420. for(i = nLen; i < nLen*2; i++)
  3421. a[i] = static_cast<ULONG>(-static_cast<LONG>(a[i-nLen]));
  3422. nLen *= 2;
  3423. }
  3424. oString[32] = iString[32] = L'\0';
  3425. // generate the new string
  3426. for (i = 0; i< 32; i++)
  3427. oString[i] = static_cast<WCHAR>(iString[i] + a[i]);
  3428. // verify that these two string have the same hash
  3429. hash1 = 0 ;
  3430. for (i = 0 ; i<STR_LEN; i++) {
  3431. ch = iString[i];
  3432. UPPER(ch);
  3433. hash1 = hash1*HASH_SEED + ch;
  3434. }
  3435. hash2 = 0 ;
  3436. for (i = 0 ; i<STR_LEN; i++){
  3437. ch = oString[i];
  3438. UPPER(ch);
  3439. hash2 = hash2*HASH_SEED + ch;
  3440. }
  3441. return (hash1 == hash2)? TRUE : FALSE;
  3442. #undef START_VALUE
  3443. #undef STR_LEN
  3444. #undef HASH_SEED
  3445. }
  3446. BOOL TestAssemblyIdentityHash()
  3447. {
  3448. SXSP_DEBUG_FUNCTION pfn = NULL;
  3449. BOOL fSuccess = FALSE;
  3450. LoadSxs();
  3451. GetSxsProc(SXSP_DEBUG_ORDINAL, &pfn);
  3452. fSuccess = (*pfn)(SXS_DEBUG_ASSEMBLY_IDENTITY_HASH, 0, 0, NULL);
  3453. if (! fSuccess){
  3454. fprintf(stderr, "%s failed!\n", __FUNCTION__);
  3455. return EXIT_FAILURE;
  3456. }
  3457. else
  3458. return EXIT_SUCCESS;
  3459. }
  3460. const static WCHAR Beta2Manifest[] =
  3461. L"<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
  3462. L" <assemblyIdentity type=\"win32\" name=\"cards\" version=\"2.0.0.0\" processorArchitecture=\"X86\" language=\"en-us\" />"
  3463. L" <file name=\"cards.dll\"/>"
  3464. L"</assembly>;"
  3465. ;
  3466. // check whether the handle counter of csrss has changed dramatically after running this code.....
  3467. VOID TestCreateActctxLeakHandles(DWORD dwCallCounter)
  3468. {
  3469. int result = -1;
  3470. BOOL fSuccess;
  3471. for (DWORD i =0 ; i < dwCallCounter ; i ++)
  3472. {
  3473. HANDLE ActivationContextHandle = ::CreateActivationContextFromStringW(InheritManifest);
  3474. if (ActivationContextHandle == INVALID_HANDLE_VALUE) {
  3475. result = i ;
  3476. break;
  3477. }
  3478. ULONG_PTR Cookie;
  3479. ActivateActCtx(ActivationContextHandle, &Cookie);
  3480. HINSTANCE hInstanceKernel32 = ::GetModuleHandleW(L"KERNEL32.DLL");
  3481. PQUERYACTCTXW_FUNC pQueryActCtxW = (PQUERYACTCTXW_FUNC) ::GetProcAddress(hInstanceKernel32, "QueryActCtxW");
  3482. SIZE_T CbWritten;
  3483. if (pQueryActCtxW != NULL)
  3484. {
  3485. for ( ULONG ulInfoClass = ActivationContextBasicInformation; ulInfoClass <= FileInformationInAssemblyOfAssemblyInActivationContext; ulInfoClass ++)
  3486. {
  3487. switch (ulInfoClass) {
  3488. case ActivationContextBasicInformation :
  3489. break;
  3490. case ActivationContextDetailedInformation :
  3491. {
  3492. struct
  3493. {
  3494. ACTIVATION_CONTEXT_DETAILED_INFORMATION acdi;
  3495. WCHAR Buffer[_MAX_PATH * 3]; // manifest, policy and appdir
  3496. } Data;
  3497. ULONG index = 0 ;
  3498. fSuccess = (*pQueryActCtxW)(0, ActivationContextHandle, &index, ulInfoClass, &Data, sizeof(Data), &CbWritten);
  3499. fprintf(stderr, "\ncall QueryActCtxW with ActivationContextDetailedInformation\n" );
  3500. if (fSuccess)
  3501. {
  3502. fprintf(stderr, "1st string: %ls\n", Data.acdi.lpAppDirPath);
  3503. fprintf(stderr, "2nd string: %ls\n", Data.acdi.lpRootManifestPath);
  3504. }
  3505. else
  3506. fprintf(stderr, "QueryActCtxW() failed; ::GetLastError() = %d\n", ::GetLastError());
  3507. }
  3508. break;
  3509. case AssemblyDetailedInformationInActivationContext:
  3510. {
  3511. struct
  3512. {
  3513. ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION acdi;
  3514. WCHAR Buffer[_MAX_PATH * 4];
  3515. } Data;
  3516. ULONG AssemblyIndex = 1;
  3517. fSuccess = (*pQueryActCtxW)(0, ActivationContextHandle, &AssemblyIndex, ulInfoClass, &Data, sizeof(Data), &CbWritten);
  3518. fprintf(stderr, "\ncall QueryActCtxW with AssemblyDetailedInformationInActivationContext\n" );
  3519. if (fSuccess)
  3520. {
  3521. fprintf(stderr, "Encoded assembly Identity: %ls\n", Data.acdi.lpAssemblyEncodedAssemblyIdentity);
  3522. fprintf(stderr, "manifest path: %ls\n", Data.acdi.lpAssemblyManifestPath);
  3523. fprintf(stderr, "policy path: %ls\n", Data.acdi.lpAssemblyPolicyPath);
  3524. fprintf(stderr, "Assembly Directory: %ls\n", Data.acdi.lpAssemblyDirectoryName);
  3525. }
  3526. else
  3527. fprintf(stderr, "QueryActCtxW() failed; ::GetLastError() = %d\n", ::GetLastError());
  3528. }
  3529. break;
  3530. case FileInformationInAssemblyOfAssemblyInActivationContext:
  3531. {
  3532. struct
  3533. {
  3534. ASSEMBLY_DLL_REDIRECTION_DETAILED_INFORMATION acdi;
  3535. WCHAR Buffer[_MAX_PATH * 2];
  3536. } Data;
  3537. ACTIVATION_CONTEXT_QUERY_INDEX index;
  3538. index.ulAssemblyIndex = 1;
  3539. index.ulFileIndexInAssembly = 0;
  3540. fSuccess = (*pQueryActCtxW)(0, ActivationContextHandle, &index, ulInfoClass, &Data, sizeof(Data), &CbWritten);
  3541. fprintf(stderr, "\ncall QueryActCtxW with FileInformationInAssemblyOfAssemblyInActivationContext\n" );
  3542. if (fSuccess)
  3543. {
  3544. fprintf(stderr, "file name: %ls\n", Data.acdi.lpFileName);
  3545. fprintf(stderr, "file path: %ls\n", Data.acdi.lpFilePath);
  3546. }
  3547. else
  3548. fprintf(stderr, "QueryActCtxW() failed; ::GetLastError() = %d\n", ::GetLastError());
  3549. }
  3550. } // end of switch
  3551. }// end of for
  3552. }
  3553. DeactivateActCtx(0, Cookie);
  3554. // CloseHandle(ActivationContextHandle);
  3555. }
  3556. return;
  3557. }
  3558. BOOL TestSystemDefaultActivationContextGeneration()
  3559. {
  3560. SXSP_DEBUG_FUNCTION pfn = NULL;
  3561. BOOL fSuccess = FALSE;
  3562. LoadSxs();
  3563. GetSxsProc(SXSP_DEBUG_ORDINAL, &pfn);
  3564. fSuccess = (*pfn)(SXS_DEBUG_SYSTEM_DEFAULT_ACTCTX_GENERATION, 0, NULL, NULL);
  3565. if (! fSuccess){
  3566. fprintf(stderr, "%s failed!\n", __FUNCTION__);
  3567. return EXIT_FAILURE;
  3568. }
  3569. else
  3570. return EXIT_SUCCESS;
  3571. }
  3572. CHAR g_AsyncIOBuffer[16384];
  3573. struct AsyncIOBlock
  3574. {
  3575. OVERLAPPED ol_input;
  3576. OVERLAPPED ol_output;
  3577. HANDLE hInputFile;
  3578. HANDLE hOutputFile;
  3579. } g_AsyncIOBlock;
  3580. bool g_AsyncIODone = false;
  3581. DWORD g_AsyncIOError = ERROR_SUCCESS;
  3582. VOID CALLBACK AsyncReadCompleted(
  3583. DWORD dwErrorCode,
  3584. DWORD dwBytesTransferred,
  3585. LPOVERLAPPED ol
  3586. );
  3587. VOID CALLBACK AsyncWriteCompleted(
  3588. DWORD dwErrorCode,
  3589. DWORD dwBytesTransferred,
  3590. LPOVERLAPPED ol
  3591. );
  3592. VOID CALLBACK AsyncReadCompleted(
  3593. DWORD dwErrorCode,
  3594. DWORD dwBytesTransferred,
  3595. LPOVERLAPPED ol
  3596. )
  3597. {
  3598. if (dwErrorCode != ERROR_SUCCESS)
  3599. {
  3600. fprintf(stderr, "Error passed to AsyncReadCompleted(); error code = %ul; bytes transferred = %ul\n", dwErrorCode, dwBytesTransferred);
  3601. g_AsyncIOError = dwErrorCode;
  3602. g_AsyncIODone = true;
  3603. }
  3604. else
  3605. {
  3606. g_AsyncIOBlock.ol_input.Offset += dwBytesTransferred;
  3607. if (!::WriteFileEx(g_AsyncIOBlock.hOutputFile, g_AsyncIOBuffer, dwBytesTransferred, &g_AsyncIOBlock.ol_output, &AsyncWriteCompleted))
  3608. {
  3609. g_AsyncIOError = ::GetLastError();
  3610. fprintf(stderr, "WriteFileEx() failed; ::GetLastError() = %d\n", g_AsyncIOError);
  3611. g_AsyncIODone = true;
  3612. }
  3613. }
  3614. }
  3615. VOID CALLBACK AsyncWriteCompleted(
  3616. DWORD dwErrorCode,
  3617. DWORD dwBytesTransferred,
  3618. LPOVERLAPPED ol
  3619. )
  3620. {
  3621. if (dwErrorCode != ERROR_SUCCESS)
  3622. {
  3623. fprintf(stderr, "Error passed to AsyncWriteCompleted(); error code = %ul; dwBytesTransferred = %ul\n", dwErrorCode, dwBytesTransferred);
  3624. g_AsyncIOError = dwErrorCode;
  3625. g_AsyncIODone = true;
  3626. }
  3627. else
  3628. {
  3629. g_AsyncIOBlock.ol_output.Offset += dwBytesTransferred;
  3630. if (!::ReadFileEx(g_AsyncIOBlock.hInputFile, g_AsyncIOBuffer, sizeof(g_AsyncIOBuffer), &g_AsyncIOBlock.ol_input, &AsyncReadCompleted))
  3631. {
  3632. g_AsyncIOError = ::GetLastError();
  3633. if (g_AsyncIOError != ERROR_HANDLE_EOF)
  3634. fprintf(stderr, "ReadFileEx() failed; ::GetLastError() = %d\n", g_AsyncIOError);
  3635. else
  3636. g_AsyncIOError = ERROR_SUCCESS;
  3637. g_AsyncIODone = true;
  3638. }
  3639. }
  3640. }
  3641. BOOL
  3642. TestAsyncIO(int argc, wchar_t **argv, int *piNext)
  3643. {
  3644. HANDLE hFileIn;
  3645. HANDLE hFileOut;
  3646. HANDLE hActCtx = NULL;
  3647. ULONG_PTR cookie = 0;
  3648. PCWSTR pszManifest;
  3649. PCWSTR pszInputFile;
  3650. PCWSTR pszOutputFile;
  3651. ACTCTXW acw;
  3652. pszManifest = argv[(*piNext)++];
  3653. pszInputFile = argv[(*piNext)++];
  3654. pszOutputFile = argv[(*piNext)++];
  3655. if (wcscmp(pszManifest, L"-") != 0)
  3656. {
  3657. acw.cbSize = sizeof(acw);
  3658. acw.dwFlags = 0;
  3659. acw.lpSource = pszManifest;
  3660. hActCtx = ::CreateActCtxW(&acw);
  3661. if (hActCtx == INVALID_HANDLE_VALUE)
  3662. {
  3663. fprintf(stderr, "CreateActCtxW() on %ls failed; ::GetLastError() = %d\n", pszManifest, ::GetLastError());
  3664. return EXIT_FAILURE;
  3665. }
  3666. }
  3667. hFileIn = ::CreateFileW(pszInputFile, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
  3668. if (hFileIn == INVALID_HANDLE_VALUE)
  3669. {
  3670. fprintf(stderr, "CreateFileW() on %ls failed; ::GetLastError() = %d\n", pszInputFile, ::GetLastError());
  3671. return EXIT_FAILURE;
  3672. }
  3673. hFileOut = ::CreateFileW(pszOutputFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING, NULL);
  3674. if (hFileOut == INVALID_HANDLE_VALUE)
  3675. {
  3676. fprintf(stderr, "CreateFileW() on %ls failed; ::GetLastError() = %d\n", pszOutputFile, ::GetLastError());
  3677. return EXIT_FAILURE;
  3678. }
  3679. ActivateActCtx(hActCtx, &cookie);
  3680. g_AsyncIOBlock.ol_input.Offset = 0;
  3681. g_AsyncIOBlock.ol_input.OffsetHigh = 0;
  3682. g_AsyncIOBlock.ol_output.Offset = 0;
  3683. g_AsyncIOBlock.ol_output.OffsetHigh = 0;
  3684. g_AsyncIOBlock.hInputFile = hFileIn;
  3685. g_AsyncIOBlock.hOutputFile = hFileOut;
  3686. if (!::ReadFileEx(hFileIn, &g_AsyncIOBuffer, sizeof(g_AsyncIOBuffer), &g_AsyncIOBlock.ol_input, &AsyncReadCompleted))
  3687. {
  3688. fprintf(stderr, "First ReadFileEx() failed; ::GetLastError() = %d\n", ::GetLastError());
  3689. return EXIT_FAILURE;
  3690. }
  3691. while (!g_AsyncIODone)
  3692. {
  3693. ::SleepEx(1000, TRUE);
  3694. }
  3695. if (g_AsyncIOError != ERROR_SUCCESS)
  3696. {
  3697. fprintf(stderr, "Async IO test failed; win32 error code = %d\n", g_AsyncIOError);
  3698. return EXIT_FAILURE;
  3699. }
  3700. CloseHandle(hFileIn);
  3701. CloseHandle(hFileOut);
  3702. return EXIT_SUCCESS;
  3703. }
  3704. static
  3705. DWORD
  3706. WINAPI
  3707. TestThreadInheritLeakThreadProc(
  3708. LPVOID lpParameter
  3709. )
  3710. {
  3711. // Don't need to do anything...
  3712. return 1;
  3713. }
  3714. int
  3715. TestThreadInheritLeak()
  3716. {
  3717. HANDLE ActivationContextHandle = ::CreateActivationContextFromStringW(InheritManifest);
  3718. DWORD dwThreadId;
  3719. ULONG_PTR ulpCookie;
  3720. HANDLE hThread = NULL;
  3721. ::ActivateActCtx(ActivationContextHandle, &ulpCookie);
  3722. hThread = ::CreateThread(NULL, 0, &TestThreadInheritLeakThreadProc, NULL, 0, &dwThreadId);
  3723. if (hThread == NULL)
  3724. {
  3725. fprintf(stderr, "CreateThread() failed with ::GetLastError = %d\n", ::GetLastError());
  3726. return EXIT_FAILURE;
  3727. }
  3728. WaitForSingleObject(hThread, INFINITE);
  3729. fprintf(stderr, "Created thread %lu\n", dwThreadId);
  3730. ::DeactivateActCtx(0, ulpCookie);
  3731. ::ReleaseActCtx(ActivationContextHandle);
  3732. return EXIT_SUCCESS;
  3733. }
  3734. BOOL
  3735. TestNewCatalogSignerThingy(
  3736. PCWSTR CatalogName
  3737. )
  3738. {
  3739. SXSP_DEBUG_FUNCTION pfn = NULL;
  3740. BOOL fSuccess = FALSE;
  3741. LoadSxs();
  3742. GetSxsProc(SXSP_DEBUG_ORDINAL, &pfn);
  3743. fSuccess = (*pfn)(SXS_DEBUG_CATALOG_SIGNER_CHECK, 0, CatalogName, NULL);
  3744. return fSuccess;
  3745. }
  3746. HMODULE MyHandle;
  3747. WCHAR MyModuleFullPath[MAX_PATH];
  3748. WCHAR MyModuleFullPathWithoutExtension[MAX_PATH];
  3749. /*
  3750. see \\scratch\scratch\JayK\exedll for a slightly different approach
  3751. */
  3752. HANDLE GetExeHandle()
  3753. {
  3754. return GetModuleHandle(NULL);
  3755. }
  3756. extern "C" { extern IMAGE_DOS_HEADER __ImageBase; }
  3757. HMODULE GetMyHandle()
  3758. {
  3759. //Trace("GetMyHandle():%p\n", &__ImageBase);
  3760. return (HMODULE)&__ImageBase;
  3761. }
  3762. BOOL AmITheExe()
  3763. {
  3764. IamExe = (GetExeHandle() == GetMyHandle());
  3765. IamDll = !IamExe;
  3766. return IamExe;
  3767. }
  3768. PCWSTR GetMyModuleFullPath()
  3769. {
  3770. return
  3771. ((MyModuleFullPath[0]
  3772. || ::GetModuleFileNameW(GetMyHandle(), MyModuleFullPath, RTL_NUMBER_OF(MyModuleFullPath))),
  3773. MyModuleFullPath);
  3774. }
  3775. PCWSTR GetMyModuleFullPathWithoutExtension()
  3776. {
  3777. //
  3778. // not thread safe
  3779. //
  3780. wcscpy(MyModuleFullPathWithoutExtension, GetMyModuleFullPath());
  3781. *wcsrchr(MyModuleFullPathWithoutExtension, '.') = 0;
  3782. return MyModuleFullPathWithoutExtension;
  3783. }
  3784. void TestExeDll()
  3785. {
  3786. #if defined(_X86_)
  3787. WCHAR x[MAX_PATH];
  3788. CStringBuffer y;
  3789. Kernel32.GetModuleFileNameW(NULL, x, RTL_NUMBER_OF(x));
  3790. if (!y.Win32Assign(x, StringLength(x)))
  3791. ThrowLastError();
  3792. if (!y.Win32ChangePathExtension(L"dll", 3, eAddIfNoExtension))
  3793. ThrowLastError();
  3794. if (!CopyFileW(x, y, FALSE))
  3795. ThrowLastError();
  3796. SetDllBitInPeImage(y);
  3797. FreeLibrary(LoadLibraryW(y));
  3798. #endif
  3799. }
  3800. void PrintDll()
  3801. {
  3802. //Trace("dll %ls\n", GetMyModuleFullPath());
  3803. }
  3804. void PrintExe()
  3805. {
  3806. //Trace("exe %ls\n", GetMyModuleFullPath());
  3807. }
  3808. extern "C" void __cdecl wmainCRTStartup();
  3809. extern "C" BOOL __stdcall _DllMainCRTStartup(HINSTANCE, DWORD, PVOID);
  3810. extern "C" BOOL __stdcall DllMain(HINSTANCE DllHandle, DWORD Reason, PVOID SemiReserved)
  3811. {
  3812. //Trace("Enter DllMain\n");
  3813. switch (Reason)
  3814. {
  3815. default:
  3816. break;
  3817. case DLL_PROCESS_ATTACH:
  3818. if (
  3819. wcsstr(GetCommandLineW(), L" -tQueryActCtx")
  3820. || wcsstr(GetCommandLineW(), L" -tqueryactctx")
  3821. || wcsstr(GetCommandLineW(), L" /tQueryActCtx")
  3822. || wcsstr(GetCommandLineW(), L" /tqueryactctx")
  3823. )
  3824. {
  3825. TestQueryActCtx();
  3826. }
  3827. }
  3828. //Trace("Exit DllMain\n");
  3829. return TRUE;
  3830. }
  3831. #if defined(_X86_)
  3832. extern "C" void __declspec(naked) Entry()
  3833. // This works for .dlls or .exes.
  3834. // void ExeMain(void)
  3835. // BOOL __stdcall DllMain(HINSTANCE dll, DWORD reason, void* reserved)
  3836. {
  3837. static const char* DllReason[] =
  3838. {
  3839. "DllProcessDetach %ls\n",
  3840. "DllProcessAttach %ls\n",
  3841. "DllThreadAttach %ls\n",
  3842. "DllThreadDetach %ls\n"
  3843. };
  3844. __asm {
  3845. //int 3
  3846. call AmITheExe
  3847. test eax,eax
  3848. jne Lexe
  3849. //Ldll:
  3850. call GetMyModuleFullPath
  3851. push eax
  3852. mov eax, [esp+12]
  3853. mov eax, DllReason[eax*4]
  3854. push eax
  3855. call Trace
  3856. add esp,8
  3857. jmp _DllMainCRTStartup
  3858. Lexe:
  3859. call PrintExe
  3860. jmp wmainCRTStartup
  3861. }
  3862. }
  3863. #else
  3864. extern "C" void Entry()
  3865. {
  3866. wmainCRTStartup();
  3867. }
  3868. #endif
  3869. BOOL TestSxsSfcUI()
  3870. {
  3871. SXSP_DEBUG_FUNCTION pfn = NULL;
  3872. BOOL fSuccess = FALSE;
  3873. LoadSxs();
  3874. GetSxsProc(SXSP_DEBUG_ORDINAL, &pfn);
  3875. fSuccess = (*pfn)(SXS_DEBUG_SFC_UI_TEST, 0, 0, NULL);
  3876. if (! fSuccess){
  3877. fprintf(stderr, "%s failed!\n", __FUNCTION__);
  3878. return EXIT_FAILURE;
  3879. }
  3880. else
  3881. return EXIT_SUCCESS;
  3882. return fSuccess;
  3883. }
  3884. void TestGetModuleHandleEx()
  3885. {
  3886. HMODULE p;
  3887. BOOL f;
  3888. HMODULE q;
  3889. unsigned u;
  3890. #define GetModuleHandleExA pfnGetModuleHandleExA
  3891. #define GetModuleHandleExW pfnGetModuleHandleExW
  3892. HMODULE kernel32 = GetModuleHandleW(L"Kernel32");
  3893. PGET_MODULE_HANDLE_EXA GetModuleHandleExA = reinterpret_cast<PGET_MODULE_HANDLE_EXA>(GetProcAddress(kernel32, "GetModuleHandleExA"));
  3894. PGET_MODULE_HANDLE_EXW GetModuleHandleExW = reinterpret_cast<PGET_MODULE_HANDLE_EXW>(GetProcAddress(kernel32, "GetModuleHandleExW"));
  3895. if (GetModuleHandleExA == NULL || GetModuleHandleExW == NULL)
  3896. {
  3897. return;
  3898. }
  3899. union
  3900. {
  3901. CHAR BufferA[MAX_PATH];
  3902. WCHAR BufferW[MAX_PATH];
  3903. };
  3904. BufferA[0] = 0;
  3905. GetWindowsDirectoryA(BufferA, MAX_PATH);
  3906. std::string windowsA = BufferA;
  3907. std::string systemA = windowsA + "System32";
  3908. BufferW[0] = 0;
  3909. GetWindowsDirectoryW(BufferW, MAX_PATH);
  3910. std::wstring windowsW = BufferW;
  3911. std::wstring systemW = windowsW + L"System32";
  3912. #define PIN GET_MODULE_HANDLE_EX_FLAG_PIN
  3913. #define NOCHANGE GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT
  3914. #define ADDRESS GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
  3915. #define X(x) SetLastError(NO_ERROR); p = x; printf("%s:%p,%d\n", #x, p, ::GetLastError());
  3916. #define Y(x) SetLastError(NO_ERROR); f = x; printf("%s:%s,%p,%d\n", #x, "false\0true"+f*6, p, ::GetLastError());
  3917. printf("first some basic GetModuleHandle testing\n\n");
  3918. X(GetModuleHandleA(NULL));
  3919. X(GetModuleHandleW(NULL));
  3920. X(GetModuleHandleA("ntdll.dll"));
  3921. X(GetModuleHandleW(L"ntdll.dll"));
  3922. X(GetModuleHandleA("ntdll"));
  3923. X(GetModuleHandleW(L"ntdll"));
  3924. X(GetModuleHandleA("c:\\ntdll"));
  3925. X(GetModuleHandleW(L"c:\\ntdll"));
  3926. X(GetModuleHandleA((systemA + "\\ntdll").c_str()));
  3927. X(GetModuleHandleW((systemW + L"\\ntdll").c_str()));
  3928. X(GetModuleHandleA((systemA + "\\ntdll.dll").c_str()));
  3929. X(GetModuleHandleW((systemW + L"\\ntdll.dll").c_str()));
  3930. X(GetModuleHandleA("sxs"));
  3931. X(GetModuleHandleW(L"sxs.dll"));
  3932. printf("\n\nnow show that FreeLibrary \"works\", GetModuleHandle honors it\n\n");
  3933. X(LoadLibraryA("Sxs.dll"));
  3934. X(GetModuleHandleA("sxs"));
  3935. X(GetModuleHandleW(L"sxs.dll"));
  3936. Y(FreeLibrary(p = GetModuleHandleA("Sxs.dll")));
  3937. X(GetModuleHandleA("sxs"));
  3938. X(GetModuleHandleW(L"sxs.dll"));
  3939. X(LoadLibraryW(L"Sxs.dll"));
  3940. Y(GetModuleHandleExA(0, NULL, &p));
  3941. Y(GetModuleHandleExW(0, NULL, &p));
  3942. printf("\n\nsome invalid parameters (%d)\n\n", ERROR_INVALID_PARAMETER);
  3943. Y(GetModuleHandleExA(PIN | NOCHANGE, "sxs", &p));
  3944. Y(GetModuleHandleExW(PIN | NOCHANGE, L"sxs", &p));
  3945. Y(GetModuleHandleExA(PIN | NOCHANGE, "ntdll", &p));
  3946. Y(GetModuleHandleExW(PIN | NOCHANGE, L"ntdll", &p));
  3947. printf("\n\nshow NOCHANGE's equiv to regular\n\n");
  3948. Y(GetModuleHandleExA(NOCHANGE, "sxs", &p));
  3949. Y(GetModuleHandleExW(NOCHANGE, L"sxs", &p));
  3950. Y(FreeLibrary(p = GetModuleHandleA("Sxs.dll")));
  3951. Y(GetModuleHandleExA(NOCHANGE, "sxs", &p));
  3952. Y(GetModuleHandleExW(NOCHANGE, L"sxs", &p));
  3953. printf("\n\nshow PIN works\n\n");
  3954. X(LoadLibraryW(L"Sxs.dll"));
  3955. Y(GetModuleHandleExA(PIN, "sxs", &p));
  3956. Y(FreeLibrary(p = GetModuleHandleA("Sxs.dll")));
  3957. Y(GetModuleHandleExW(0, L"sxs", &(q = p)));
  3958. Y(GetModuleHandleExW(0, L"c:\\sxs", &p));
  3959. printf("\n\nshow the VirtualQuery form\n\n");
  3960. Y(GetModuleHandleExA(ADDRESS, "sxs", &p)); // string, actually in .exe
  3961. Y(GetModuleHandleExW(ADDRESS, L"c:\\sxs", &p));
  3962. Y(GetModuleHandleExA(ADDRESS, reinterpret_cast<LPCSTR>(q), &p));
  3963. Y(GetModuleHandleExW(ADDRESS, reinterpret_cast<LPCWSTR>(q), &p));
  3964. printf("\n\nsome more invalid parameters (%d)\n\n", ERROR_INVALID_PARAMETER);
  3965. Y(GetModuleHandleExA(0, NULL, NULL));
  3966. Y(GetModuleHandleExW(0, NULL, NULL));
  3967. printf("\n\nshow that static loads can't be unloaded\n\n");
  3968. for (u = 0 ; u < 4 ; ++u)
  3969. {
  3970. printf("%#x\n", u);
  3971. Y(FreeLibrary(p = GetModuleHandleA("kernel32")));
  3972. Y(FreeLibrary(p = GetModuleHandleW(L"sxstest.exe")));
  3973. Y(FreeLibrary(p = GetModuleHandleA("msvcrt.dll")));
  3974. }
  3975. printf("\n\ntry all flag combinations, including invalids ones\n\n");
  3976. for (u = 0 ; u <= (PIN | ADDRESS | NOCHANGE) ; ++u)
  3977. {
  3978. printf("%#x\n", u);
  3979. p = NULL;
  3980. Y( GetModuleHandleExA(u, NULL, NULL)); p = NULL;
  3981. Y( GetModuleHandleExW(u, NULL, NULL)); p = NULL;
  3982. Y( GetModuleHandleExA(u, NULL, &p)); p = NULL;
  3983. Y( GetModuleHandleExW(u, NULL, &p)); p = NULL;
  3984. if (u & ADDRESS)
  3985. {
  3986. Y( GetModuleHandleExA(u, "", NULL)); p = NULL;
  3987. Y( GetModuleHandleExW(u, reinterpret_cast<LPCWSTR>(GetModuleHandleExA), NULL)); p = NULL;
  3988. Y( GetModuleHandleExW(u, reinterpret_cast<LPCWSTR>(atexit), NULL)); p = NULL;
  3989. Y( GetModuleHandleExA(u, "", &p)); p = NULL;
  3990. Y( GetModuleHandleExW(u, reinterpret_cast<LPCWSTR>(GetModuleHandleExA), &p)); p = NULL;
  3991. Y( GetModuleHandleExW(u, reinterpret_cast<LPCWSTR>(atexit), &p)); p = NULL;
  3992. }
  3993. else
  3994. {
  3995. Y( GetModuleHandleExA(u, "foo32", NULL)); p = NULL;
  3996. Y( GetModuleHandleExW(u, L"kernel32", NULL)); p = NULL;
  3997. Y( GetModuleHandleExA(u, "foo32", &p)); p = NULL;
  3998. Y( GetModuleHandleExW(u, L"kernel32", &p)); p = NULL;
  3999. }
  4000. }
  4001. printf("\n\ntry all bits of flags, should be mostly invalid (%d)\n\n", ERROR_INVALID_PARAMETER);
  4002. for (u = 0 ; u < RTL_BITS_OF(u) ; ++u)
  4003. {
  4004. printf("%#x\n", u);
  4005. Y(GetModuleHandleExW(1<<u, L"kernel32", &p));
  4006. }
  4007. printf("\n\nPIN | ADDRESS wasn't covered\n\n", ERROR_INVALID_PARAMETER);
  4008. X(GetModuleHandleW(L"shell32"));
  4009. X(q = LoadLibraryA("shell32"));
  4010. Y(FreeLibrary(GetModuleHandleA("shell32")));
  4011. Y(GetModuleHandleExW(PIN | ADDRESS, reinterpret_cast<LPCWSTR>(q), &p));
  4012. X(q = LoadLibraryW(L"shell32"));
  4013. Y(GetModuleHandleExW(PIN | ADDRESS, reinterpret_cast<LPCWSTR>(q) + 100, &p));
  4014. Y(FreeLibrary(q)); Y(FreeLibrary(q)); Y(FreeLibrary(q));
  4015. X(GetModuleHandleW(L"shell32.dll"));
  4016. Y(GetModuleHandleExW(ADDRESS, reinterpret_cast<LPCWSTR>(q) + 1000, &p));
  4017. #undef X
  4018. #undef Y
  4019. #undef PIN
  4020. #undef NOCHANGE
  4021. #undef ADDRESS
  4022. }
  4023. void
  4024. TestGetFullPathName(
  4025. PCWSTR s
  4026. )
  4027. {
  4028. WCHAR FullPath[MAX_PATH * 2];
  4029. PWSTR FilePart = L"";
  4030. DWORD dw;
  4031. DWORD dwError;
  4032. SetLastError(NO_ERROR);
  4033. dw = GetFullPathNameW(s, RTL_NUMBER_OF(FullPath), FullPath, &FilePart);
  4034. dwError = ::GetLastError();
  4035. printf(
  4036. "GetFullPathNameW(%ls):%lu,lastError=%lu,filePart=%ls\n",
  4037. FullPath,
  4038. dw,
  4039. dwError,
  4040. FilePart
  4041. );
  4042. }
  4043. void
  4044. TestCreateFile(
  4045. PCWSTR s
  4046. )
  4047. {
  4048. HANDLE handle;
  4049. DWORD dwError;
  4050. SetLastError(NO_ERROR);
  4051. handle = CreateFileW(
  4052. s,
  4053. 0,
  4054. FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
  4055. NULL,
  4056. OPEN_ALWAYS,
  4057. FILE_ATTRIBUTE_NORMAL,
  4058. NULL
  4059. );
  4060. dwError = ::GetLastError();
  4061. if (handle != INVALID_HANDLE_VALUE)
  4062. CloseHandle(handle);
  4063. printf(
  4064. "CreateFileW(%ls):%p,lastError=%lu\n",
  4065. s,
  4066. handle,
  4067. dwError
  4068. );
  4069. }
  4070. /*
  4071. from base\ntsetup\dll\sxs.c
  4072. */
  4073. VOID
  4074. SxspGetPathBaseName(
  4075. LPCWSTR Path,
  4076. LPWSTR Base
  4077. )
  4078. {
  4079. LPCWSTR Dot = wcsrchr(Path, '.');
  4080. LPCWSTR Slash = wcsrchr(Path, '\\');
  4081. //
  4082. // beware \foo.txt\bar
  4083. // beware \bar
  4084. // beware bar
  4085. // beware .bar
  4086. // beware \.bar
  4087. //
  4088. *Base = 0;
  4089. if (Slash == NULL)
  4090. Slash = Path;
  4091. else
  4092. Slash += 1;
  4093. if (Dot == NULL || Dot < Slash)
  4094. Dot = Path + StringLength(Path);
  4095. CopyMemory(Base, Slash, (Dot - Slash) * sizeof(*Base));
  4096. Base[Dot - Slash] = 0;
  4097. }
  4098. VOID
  4099. TestGetPathBaseName(
  4100. LPCWSTR Path
  4101. )
  4102. {
  4103. WCHAR Base[MAX_PATH];
  4104. SxspGetPathBaseName(Path, Base);
  4105. printf("\"%ls\" -> \"%ls\"\n", Path, Base);
  4106. }
  4107. void TestVersion()
  4108. {
  4109. printf(
  4110. "Windows NT %lu.%lu.%lu\n",
  4111. FusionpGetWindowsNtMajorVersion(),
  4112. FusionpGetWindowsNtMinorVersion(),
  4113. FusionpGetWindowsNtBuildVersion()
  4114. );
  4115. }
  4116. void TestGetProcessImageFileName()
  4117. {
  4118. UNICODE_STRING s;
  4119. FusionpGetProcessImageFileName(&s);
  4120. printf("%wZ\n", &s);
  4121. }
  4122. BOOL TestErrorInfra1() { FN_PROLOG_WIN32; IFW32FALSE_ORIGINATE_AND_EXIT(LoadLibraryA("1")); FN_EPILOG; }
  4123. BOOL TestErrorInfra2() { FN_PROLOG_WIN32; IFW32NULL_EXIT(LoadLibraryA(" 2 ")); FN_EPILOG; }
  4124. BOOL TestErrorInfra3() { FN_PROLOG_WIN32; IFFAILED_CONVERTHR_HRTOWIN32_EXIT_TRACE(E_FAIL | 3); FN_EPILOG; }
  4125. BOOL TestErrorInfra4() { FN_PROLOG_WIN32; IFCOMFAILED_EXIT(E_FAIL | 4); FN_EPILOG; }
  4126. BOOL TestErrorInfra5() { FN_PROLOG_WIN32; IFCOMFAILED_ORIGINATE_AND_EXIT(E_FAIL | 5); FN_EPILOG; }
  4127. BOOL TestErrorInfra6() { FN_PROLOG_WIN32; IFREGFAILED_EXIT(6); FN_EPILOG; }
  4128. BOOL TestErrorInfra7() { FN_PROLOG_WIN32; IFREGFAILED_ORIGINATE_AND_EXIT(7); FN_EPILOG; }
  4129. HRESULT TestErrorInfra8() { FN_PROLOG_HR; IFW32FALSE_ORIGINATE_AND_EXIT(LoadLibraryA("8")); FN_EPILOG; }
  4130. HRESULT TestErrorInfra9() { FN_PROLOG_HR; IFW32NULL_EXIT(LoadLibraryA("!@# 9 \\")); FN_EPILOG; }
  4131. HRESULT TestErrorInfra10() { FN_PROLOG_HR; IFFAILED_CONVERTHR_HRTOWIN32_EXIT_TRACE(E_FAIL | 10); FN_EPILOG; }
  4132. HRESULT TestErrorInfra11() { FN_PROLOG_HR; IFCOMFAILED_EXIT(E_FAIL | 11); FN_EPILOG; }
  4133. HRESULT TestErrorInfra12() { FN_PROLOG_HR; IFCOMFAILED_ORIGINATE_AND_EXIT(E_FAIL | 12); FN_EPILOG; }
  4134. HRESULT TestErrorInfra13() { FN_PROLOG_HR; IFREGFAILED_EXIT(13); FN_EPILOG; }
  4135. HRESULT TestErrorInfra14() { FN_PROLOG_HR; IFREGFAILED_ORIGINATE_AND_EXIT(14); FN_EPILOG; }
  4136. void TestErrorInfra()
  4137. {
  4138. #define X(x) DbgPrint("%s\n", #x); x()
  4139. X(TestErrorInfra1);
  4140. X(TestErrorInfra2);
  4141. X(TestErrorInfra3);
  4142. X(TestErrorInfra4);
  4143. X(TestErrorInfra5);
  4144. X(TestErrorInfra7);
  4145. X(TestErrorInfra8);
  4146. X(TestErrorInfra9);
  4147. X(TestErrorInfra10);
  4148. X(TestErrorInfra11);
  4149. X(TestErrorInfra12);
  4150. X(TestErrorInfra13);
  4151. X(TestErrorInfra14);
  4152. #undef X
  4153. }
  4154. void TestQueryActCtx3(
  4155. ULONG Flags,
  4156. HANDLE ActCtxHandle
  4157. )
  4158. {
  4159. SIZE_T BytesWrittenOrRequired = 0;
  4160. BYTE QueryBuffer[4][4096];
  4161. ACTIVATION_CONTEXT_QUERY_INDEX QueryIndex = { 0 };
  4162. PACTIVATION_CONTEXT_BASIC_INFORMATION BasicInfo = reinterpret_cast<PACTIVATION_CONTEXT_BASIC_INFORMATION>(&QueryBuffer[0]);
  4163. PASSEMBLY_DLL_REDIRECTION_DETAILED_INFORMATION DllRedir = reinterpret_cast<PASSEMBLY_DLL_REDIRECTION_DETAILED_INFORMATION>(&QueryBuffer[1]);
  4164. PACTIVATION_CONTEXT_DETAILED_INFORMATION ContextDetailed = reinterpret_cast<PACTIVATION_CONTEXT_DETAILED_INFORMATION>(&QueryBuffer[2]);
  4165. PACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION AssemblyDetailed = reinterpret_cast<PACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION>(&QueryBuffer[3]);
  4166. CStringBuffer decimalContext;
  4167. RtlZeroMemory(&QueryBuffer, sizeof(QueryBuffer));
  4168. if (IS_SPECIAL_ACTCTX(ActCtxHandle))
  4169. decimalContext.Win32Format(L" (%Id)", reinterpret_cast<LONG_PTR>(ActCtxHandle));
  4170. #define QueryFailed(x,n) Trace("%s:%ld:QueryActCtx(%s) failed %lu\n", __FUNCTION__, ULONG(n), x, GetLastError())
  4171. if (!QueryActCtxW(
  4172. Flags,
  4173. ActCtxHandle,
  4174. NULL,
  4175. ActivationContextBasicInformation,
  4176. &QueryBuffer,
  4177. sizeof(QueryBuffer),
  4178. &BytesWrittenOrRequired
  4179. ))
  4180. QueryFailed("ActivationContextBasicInformation", __LINE__ - 1);
  4181. else
  4182. {
  4183. if (IS_SPECIAL_ACTCTX(BasicInfo->hActCtx))
  4184. decimalContext.Win32Format(L" (%Id)", reinterpret_cast<LONG_PTR>(BasicInfo->hActCtx));
  4185. Trace(
  4186. "BytesWrittenOrRequired : 0x%lx\n"
  4187. "BasicInfo->hActCtx : %p%ls\n"
  4188. "BasicInfo->Flags : 0x%lx\n",
  4189. BytesWrittenOrRequired,
  4190. BasicInfo->hActCtx,
  4191. static_cast<PCWSTR>(decimalContext),
  4192. BasicInfo->Flags
  4193. );
  4194. }
  4195. Flags = (Flags & ~QUERY_ACTCTX_FLAG_NO_ADDREF);
  4196. if (!QueryActCtxW(Flags, ActCtxHandle, NULL, ActivationContextDetailedInformation, ContextDetailed, 4096, &BytesWrittenOrRequired))
  4197. QueryFailed("ActivationContextDetailedInformation", __LINE__ - 1);
  4198. else
  4199. {
  4200. Trace(
  4201. "BytesWrittenOrRequired : 0x%lx\n"
  4202. "ContextDetailed->dwFlags : 0x%lx\n"
  4203. "ContextDetailed->ulFormatVersion : 0x%lx\n"
  4204. "ContextDetailed->ulAssemblyCount : 0x%lx\n"
  4205. "ContextDetailed->ulRootManifestPathType : 0x%lx\n"
  4206. "ContextDetailed->ulRootManifestPathChars : 0x%lx\n"
  4207. "ContextDetailed->ulRootConfigurationPathType : 0x%lx\n"
  4208. "ContextDetailed->ulRootConfigurationPathChars : 0x%lx\n"
  4209. "ContextDetailed->ulAppDirPathType : 0x%lx\n"
  4210. "ContextDetailed->ulAppDirPathChars : 0x%lx\n"
  4211. "ContextDetailed->lpRootManifestPath : %ls\n"
  4212. "ContextDetailed->lpRootConfigurationPath : %ls\n"
  4213. "ContextDetailed->lpAppDirPath : %ls\n"
  4214. ,
  4215. BytesWrittenOrRequired,
  4216. ContextDetailed->dwFlags,
  4217. ContextDetailed->ulFormatVersion,
  4218. ContextDetailed->ulAssemblyCount,
  4219. ContextDetailed->ulRootManifestPathType,
  4220. ContextDetailed->ulRootManifestPathChars,
  4221. ContextDetailed->ulRootConfigurationPathType,
  4222. ContextDetailed->ulRootConfigurationPathChars,
  4223. ContextDetailed->ulAppDirPathType,
  4224. ContextDetailed->ulAppDirPathChars,
  4225. ContextDetailed->lpRootManifestPath,
  4226. ContextDetailed->lpRootConfigurationPath,
  4227. ContextDetailed->lpAppDirPath
  4228. );
  4229. }
  4230. {
  4231. ULONG AssemblyIndex = 0;
  4232. ULONG FileInAssemblyIndex = 0;
  4233. //
  4234. // 0 produces ERROR_INTERNAL_ERROR
  4235. //
  4236. for (AssemblyIndex = 0 ; AssemblyIndex <= ContextDetailed->ulAssemblyCount ; AssemblyIndex += 1)
  4237. {
  4238. if (!QueryActCtxW(Flags, ActCtxHandle, &AssemblyIndex, AssemblyDetailedInformationInActivationContext, AssemblyDetailed, 4096, &BytesWrittenOrRequired))
  4239. {
  4240. Trace(
  4241. "%s(%lu):QueryActCtx(Flags=0x%lx, ActCtxHandle=%p%ls, AssemblyIndex=0x%lx, AssemblyDetailedInformationInActivationContext) LastError=%lu (%ls)\n",
  4242. __FUNCTION__,
  4243. __LINE__ - 1,
  4244. Flags,
  4245. ActCtxHandle,
  4246. static_cast<PCWSTR>(decimalContext),
  4247. AssemblyIndex,
  4248. ::FusionpGetLastWin32Error(),
  4249. ::FusionpThreadUnsafeGetLastWin32ErrorMessageW()
  4250. );
  4251. }
  4252. else
  4253. {
  4254. Trace(
  4255. "AssemblyIndex : 0x%lx\n"
  4256. "BytesWrittenOrRequired : 0x%lx\n"
  4257. "AssemblyDetailed->ulFlags : 0x%lx\n"
  4258. "AssemblyDetailed->ulEncodedAssemblyIdentityLength : 0x%lx\n"
  4259. "AssemblyDetailed->ulManifestPathType : 0x%lx\n"
  4260. "AssemblyDetailed->ulManifestPathLength : 0x%lx\n"
  4261. "AssemblyDetailed->liManifestLastWriteTime : 0x%I64x\n"
  4262. "AssemblyDetailed->ulPolicyPathType : 0x%lx\n"
  4263. "AssemblyDetailed->ulPolicyPathLength : 0x%lx\n"
  4264. "AssemblyDetailed->liPolicyLastWriteTime : 0x%I64x\n"
  4265. "AssemblyDetailed->ulMetadataSatelliteRosterIndex : 0x%lx\n"
  4266. "AssemblyDetailed->ulManifestVersionMajor : 0x%lx\n"
  4267. "AssemblyDetailed->ulManifestVersionMinor : 0x%lx\n"
  4268. "AssemblyDetailed->ulPolicyVersionMajor : 0x%lx\n"
  4269. "AssemblyDetailed->ulPolicyVersionMinor : 0x%lx\n"
  4270. "AssemblyDetailed->ulAssemblyDirectoryNameLength : 0x%lx\n"
  4271. "AssemblyDetailed->lpAssemblyEncodedAssemblyIdentity : %ls\n"
  4272. "AssemblyDetailed->lpAssemblyManifestPath : %ls\n"
  4273. "AssemblyDetailed->lpAssemblyPolicyPath : %ls\n"
  4274. "AssemblyDetailed->lpAssemblyDirectoryName : %ls\n"
  4275. "AssemblyDetailed->ulFileCount : 0x%lx\n"
  4276. ,
  4277. AssemblyIndex,
  4278. BytesWrittenOrRequired,
  4279. AssemblyDetailed->ulFlags,
  4280. AssemblyDetailed->ulEncodedAssemblyIdentityLength,
  4281. AssemblyDetailed->ulManifestPathType,
  4282. AssemblyDetailed->ulManifestPathLength,
  4283. AssemblyDetailed->liManifestLastWriteTime.QuadPart,
  4284. AssemblyDetailed->ulPolicyPathType,
  4285. AssemblyDetailed->ulPolicyPathLength,
  4286. AssemblyDetailed->liPolicyLastWriteTime.QuadPart,
  4287. AssemblyDetailed->ulMetadataSatelliteRosterIndex,
  4288. AssemblyDetailed->ulManifestVersionMajor,
  4289. AssemblyDetailed->ulManifestVersionMinor,
  4290. AssemblyDetailed->ulPolicyVersionMajor,
  4291. AssemblyDetailed->ulPolicyVersionMinor,
  4292. AssemblyDetailed->ulAssemblyDirectoryNameLength,
  4293. AssemblyDetailed->lpAssemblyEncodedAssemblyIdentity,
  4294. AssemblyDetailed->lpAssemblyManifestPath,
  4295. AssemblyDetailed->lpAssemblyPolicyPath,
  4296. AssemblyDetailed->lpAssemblyDirectoryName,
  4297. AssemblyDetailed->ulFileCount
  4298. );
  4299. QueryIndex.ulAssemblyIndex = AssemblyIndex;
  4300. SetLastError(NO_ERROR);
  4301. if (AssemblyDetailed->ulFileCount == 0)
  4302. {
  4303. Trace("AssemblyDetailed->ulFileCount is 0, working around bug, setting it to 4.\n");
  4304. AssemblyDetailed->ulFileCount = 4; // bug workaround
  4305. }
  4306. for (FileInAssemblyIndex = 0 ; FileInAssemblyIndex != AssemblyDetailed->ulFileCount ; FileInAssemblyIndex += 1)
  4307. {
  4308. QueryIndex.ulFileIndexInAssembly = FileInAssemblyIndex;
  4309. if (!QueryActCtxW(Flags, ActCtxHandle, &QueryIndex, FileInformationInAssemblyOfAssemblyInActivationContext, DllRedir, 4096, &BytesWrittenOrRequired))
  4310. {
  4311. Trace(
  4312. "%s(%lu):QueryActCtx(Flags=0x%lx, ActCtxHandle=%p%ls, QueryIndex={ulAssemblyIndex=0x%lx, ulFileIndexInAssembly=0x%lx}, FileInformationInAssemblyOfAssemblyInActivationContext) LastError=%lu (%ls)\n",
  4313. __FUNCTION__,
  4314. __LINE__,
  4315. Flags,
  4316. ActCtxHandle,
  4317. static_cast<PCWSTR>(decimalContext),
  4318. QueryIndex.ulAssemblyIndex,
  4319. QueryIndex.ulFileIndexInAssembly,
  4320. ::FusionpGetLastWin32Error(),
  4321. ::FusionpThreadUnsafeGetLastWin32ErrorMessageW()
  4322. );
  4323. //break;
  4324. }
  4325. else
  4326. {
  4327. Trace(
  4328. "AssemblyIndex : 0x%lx\n"
  4329. "FileIndex : 0x%lx\n"
  4330. "BytesWrittenOrRequired : 0x%lx\n"
  4331. "DllRedir[0x%lx,0x%lx]->ulFlags : 0x%lx\n"
  4332. "DllRedir[0x%lx,0x%lx]->ulFilenameLength : 0x%lx\n"
  4333. "DllRedir[0x%lx,0x%lx]->ulPathLength : 0x%lx\n"
  4334. "DllRedir[0x%lx,0x%lx]->lpFileName : %ls\n"
  4335. "DllRedir[0x%lx,0x%lx]->lpFilePath : %ls\n"
  4336. ,
  4337. AssemblyIndex,
  4338. FileInAssemblyIndex,
  4339. BytesWrittenOrRequired,
  4340. AssemblyIndex, FileInAssemblyIndex, DllRedir->ulFlags,
  4341. AssemblyIndex, FileInAssemblyIndex, DllRedir->ulFilenameLength,
  4342. AssemblyIndex, FileInAssemblyIndex, DllRedir->ulPathLength,
  4343. AssemblyIndex, FileInAssemblyIndex, DllRedir->lpFileName,
  4344. AssemblyIndex, FileInAssemblyIndex, DllRedir->lpFilePath
  4345. );
  4346. }
  4347. }
  4348. }
  4349. }
  4350. }
  4351. }
  4352. void TestQueryActCtx2()
  4353. {
  4354. {
  4355. CFusionActCtxHandle LogonuiActCtxHandle;
  4356. {
  4357. WCHAR LogonuiManifest[MAX_PATH * 2];
  4358. ACTCTXW LogonuiActCtx = {sizeof(LogonuiActCtx)};
  4359. LogonuiManifest[0] = 0;
  4360. GetSystemDirectoryW(LogonuiManifest, MAX_PATH);
  4361. wcscat(LogonuiManifest, L"\\logonui.exe.manifest");
  4362. LogonuiActCtx.lpSource = LogonuiManifest;
  4363. LogonuiActCtxHandle.Win32Create(&LogonuiActCtx);
  4364. }
  4365. {
  4366. CFusionActCtxScope LogonuiActCtxScope;
  4367. LogonuiActCtxScope.Win32Activate(LogonuiActCtxHandle);
  4368. TestQueryActCtx3(QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX | QUERY_ACTCTX_FLAG_NO_ADDREF, NULL);
  4369. }
  4370. TestQueryActCtx3(QUERY_ACTCTX_FLAG_NO_ADDREF, LogonuiActCtxHandle);
  4371. }
  4372. TestQueryActCtx3(QUERY_ACTCTX_FLAG_NO_ADDREF, ACTCTX_EMPTY);
  4373. TestQueryActCtx3(QUERY_ACTCTX_FLAG_NO_ADDREF, ACTCTX_SYSTEM_DEFAULT);
  4374. }
  4375. void TestQueryActCtx()
  4376. {
  4377. WCHAR ExePath[MAX_PATH];
  4378. CStringBuffer DllPath;
  4379. HMODULE hmod = NULL;
  4380. WCHAR buffer[200];
  4381. if (IamExe)
  4382. {
  4383. if (!Kernel32.GetModuleFileNameW(NULL, ExePath, RTL_NUMBER_OF(ExePath)))
  4384. ThrowLastError();
  4385. if (!DllPath.Win32Format(L"%ls.dll", ExePath))
  4386. ThrowLastError();
  4387. ::CopyFileW(ExePath, DllPath, FALSE);
  4388. }
  4389. if (IamDll)
  4390. {
  4391. hmod = NULL;
  4392. hmod = (HMODULE)RtlPcToFileHeader(InitCommonControls, (PVOID*)&hmod);
  4393. wcscpy(buffer, L"FAILED");
  4394. if (hmod != NULL)
  4395. Kernel32.GetModuleFileNameW(hmod, buffer, RTL_NUMBER_OF(buffer));
  4396. Trace("from dll static dep: %p %ls\n", hmod, buffer);
  4397. #if defined(ISOLATION_AWARE_ENABLED)
  4398. hmod = IsolationAwareLoadLibraryW(L"comctl32.dll");
  4399. LastError = ::GetLastError();
  4400. wcscpy(buffer, L"FAILED");
  4401. if (hmod != NULL)
  4402. Kernel32.GetModuleFileNameW(hmod, buffer, RTL_NUMBER_OF(buffer));
  4403. Trace("from dll IsolationAwareLoadLibraryW: %p %ls\n", hmod, buffer);
  4404. #endif
  4405. hmod = LoadLibraryW(L"comctl32.dll");
  4406. LastError = ::GetLastError();
  4407. wcscpy(buffer, L"FAILED");
  4408. if (hmod != NULL)
  4409. Kernel32.GetModuleFileNameW(hmod, buffer, RTL_NUMBER_OF(buffer));
  4410. Trace("from dll LoadLibraryW: %p %ls\n", hmod, buffer);
  4411. return;
  4412. }
  4413. {
  4414. hmod = NULL;
  4415. hmod = (HMODULE)RtlPcToFileHeader(InitCommonControls, (PVOID*)&hmod);
  4416. wcscpy(buffer, L"FAILED");
  4417. if (hmod != NULL)
  4418. Kernel32.GetModuleFileNameW(hmod, buffer, RTL_NUMBER_OF(buffer));
  4419. Trace("from exe static dep: %p %ls\n", hmod, buffer);
  4420. #if defined(ISOLATION_AWARE_ENABLED)
  4421. hmod = IsolationAwareLoadLibraryW(L"comctl32.dll");
  4422. LastError = ::GetLastError();
  4423. wcscpy(buffer, L"FAILED");
  4424. if (hmod != NULL)
  4425. Kernel32.GetModuleFileNameW(hmod, buffer, RTL_NUMBER_OF(buffer));
  4426. Trace("from exe IsolationAwareLoadLibraryW: %p %ls\n", hmod, buffer);
  4427. #endif
  4428. hmod = LoadLibraryW(L"comctl32.dll");
  4429. LastError = ::GetLastError();
  4430. wcscpy(buffer, L"FAILED");
  4431. if (hmod != NULL)
  4432. Kernel32.GetModuleFileNameW(hmod, buffer, RTL_NUMBER_OF(buffer));
  4433. Trace("from exe LoadLibraryW: %p %ls\n", hmod, buffer);
  4434. }
  4435. SetDllBitInPeImage(DllPath);
  4436. Trace("Enter LoadLibraryW\n");
  4437. hmod = LoadLibraryW(DllPath);
  4438. LastError = ::GetLastError();
  4439. Trace("Exit LoadLibraryW\n");
  4440. void (*pfn)(void) = reinterpret_cast<void (*)(void)>(GetProcAddress(hmod, "TestQueryActCtx"));
  4441. Trace("Enter non DllMain call to TestQueryActCtx\n");
  4442. pfn();
  4443. Trace("Exit non DllMain call to TestQueryActCtx\n");
  4444. FreeLibrary(hmod);
  4445. DeleteFileW(DllPath);
  4446. }
  4447. DWORD WINAPI Test64kThreadMain(void* pv)
  4448. {
  4449. LONG_PTR i = 0;
  4450. HANDLE h = 0;
  4451. ULONG_PTR cookie = 0;
  4452. LONG_PTR j = reinterpret_cast<LONG_PTR>(pv);
  4453. GetCurrentActCtx(&h);
  4454. ActivateActCtx(h, &cookie);
  4455. printf("%Id ", cookie);
  4456. if (cookie == 0) printf("cookie 0\n");
  4457. ActivateActCtx(h, &cookie);
  4458. printf("%Id ", cookie);
  4459. if (cookie == 0) printf("cookie 0\n");
  4460. __try
  4461. {
  4462. for (i = 0 ; i < j ; ++i)
  4463. {
  4464. if (!ActivateActCtx(h, &cookie))
  4465. printf("activate error %lu\n", ::GetLastError());
  4466. else
  4467. {
  4468. if (cookie == 0) printf("cookie 0\n");
  4469. //printf("%Id ", cookie);
  4470. if (!DeactivateActCtx(0, cookie))
  4471. printf("deactivate error %lu\n", ::GetLastError());
  4472. }
  4473. }
  4474. }
  4475. __except(printf("exception %lx\n", GetExceptionCode()),EXCEPTION_EXECUTE_HANDLER)
  4476. {
  4477. }
  4478. printf("final cookie value %Id\n", cookie);
  4479. return 0;
  4480. }
  4481. void Test64k()
  4482. {
  4483. HANDLE h = 0;
  4484. ULONG_PTR cookie = 0;
  4485. DWORD threadId = 0;
  4486. LONG_PTR i = 0;
  4487. LONG_PTR j = 0;
  4488. HANDLE thread = 0;
  4489. GetCurrentActCtx(&h);
  4490. ActivateActCtx(h, &cookie);
  4491. if (cookie == 0) printf("cookie 0\n");
  4492. printf("%Id ", cookie);
  4493. ActivateActCtx(h, &cookie);
  4494. if (cookie == 0) printf("cookie 0\n");
  4495. printf("%Id ", cookie);
  4496. for (j = 0 ; j < 0xfff0 ; ++j)
  4497. {
  4498. if (!ActivateActCtx(h, &cookie))
  4499. printf("activate error %lu\n", ::GetLastError());
  4500. else
  4501. {
  4502. if (cookie == 0) printf("cookie 0\n");
  4503. if (!DeactivateActCtx(0, cookie))
  4504. printf("deactivate error %lu\n", ::GetLastError());
  4505. }
  4506. }
  4507. for ( ; j < 0xffff + 0xf ; ++j)
  4508. {
  4509. if (!ActivateActCtx(h, &cookie))
  4510. printf("activate error %lu\n", ::GetLastError());
  4511. printf("%Id ", cookie);
  4512. if (cookie == 0) printf("cookie 0\n");
  4513. thread = CreateThread(NULL, 0, Test64kThreadMain, reinterpret_cast<void*>(j), 0, &threadId);
  4514. }
  4515. WaitForSingleObject(thread, INFINITE);
  4516. }
  4517. void TestDotLocalSingleInstancing()
  4518. {
  4519. FILE* File = 0;
  4520. HMODULE DllHandle = 0;
  4521. {
  4522. WCHAR DotLocal[MAX_PATH];
  4523. if (!Kernel32.GetModuleFileNameW(GetMyHandle(), DotLocal, NUMBER_OF(DotLocal) - sizeof(".local")))
  4524. ThrowLastError();
  4525. wcscat(DotLocal, L".local");
  4526. File = _wfopen(DotLocal, L"w");
  4527. fprintf(File, "\n");
  4528. fclose(File);
  4529. }
  4530. {
  4531. WCHAR System32Mshtml[MAX_PATH];
  4532. WCHAR LocalMshtml[MAX_PATH];
  4533. WCHAR ResultingMshtml[MAX_PATH];
  4534. if (!GetSystemDirectoryW(System32Mshtml, NUMBER_OF(System32Mshtml) - sizeof("\\Mshtml.dll")))
  4535. ThrowLastError();
  4536. wcscat(System32Mshtml, L"\\Mshtml.dll");
  4537. if (!Kernel32.GetModuleFileNameW(GetMyHandle(), LocalMshtml, NUMBER_OF(LocalMshtml) - sizeof("\\Mshtml.dll")))
  4538. ThrowLastError();
  4539. *wcsrchr(LocalMshtml, '\\') = 0;
  4540. wcscat(LocalMshtml, L"\\Mshtml.dll");
  4541. //DllHandle = LoadLibraryW(L"Mshtml.dll");
  4542. //Trace("LoadLibrary(Mshtml): %p\n", DllHandle);
  4543. if (!CopyFileW(System32Mshtml, LocalMshtml, FALSE))
  4544. ThrowLastError();
  4545. Trace("copy %ls -> %ls\n", System32Mshtml, LocalMshtml);
  4546. ULONG i;
  4547. for (i = 0 ; i != 4 ; i += 1)
  4548. {
  4549. DllHandle = LoadLibraryW(System32Mshtml);
  4550. wcscpy(ResultingMshtml, L"FAILED");
  4551. if (DllHandle != NULL)
  4552. Kernel32.GetModuleFileNameW(DllHandle, ResultingMshtml, RTL_NUMBER_OF(ResultingMshtml));
  4553. Trace("LoadLibrary(%ls): %p %ls\n", System32Mshtml, DllHandle, ResultingMshtml);
  4554. }
  4555. }
  4556. }
  4557. void
  4558. TestCreateActCtx(
  4559. int n,
  4560. wchar_t **args
  4561. )
  4562. {
  4563. ACTCTXW acw;
  4564. int i;
  4565. WCHAR rgwchSource[MAX_PATH];
  4566. PCWSTR pszResource;
  4567. HANDLE hActCtx;
  4568. DWORD dwLastError;
  4569. for (i=0; i<n; i++)
  4570. {
  4571. PCWSTR arg = args[i];
  4572. PCWSTR semi = wcschr(arg, L';');
  4573. memset(&acw, 0, sizeof(acw));
  4574. acw.cbSize = sizeof(acw);
  4575. if (semi == NULL)
  4576. {
  4577. acw.lpSource = arg;
  4578. }
  4579. else
  4580. {
  4581. int cch = (int) (semi - arg);
  4582. if (cch >= NUMBER_OF(rgwchSource))
  4583. cch = NUMBER_OF(rgwchSource) - 1;
  4584. memcpy(rgwchSource, arg, cch * sizeof(WCHAR));
  4585. rgwchSource[cch] = L'\0';
  4586. if (semi[1] == L'#')
  4587. {
  4588. wchar_t *pszDummy;
  4589. pszResource = MAKEINTRESOURCEW(wcstoul(semi+1, &pszDummy, 10));
  4590. }
  4591. else
  4592. {
  4593. pszResource = semi+1;
  4594. }
  4595. acw.lpSource = rgwchSource;
  4596. acw.lpResourceName = pszResource;
  4597. acw.dwFlags |= ACTCTX_FLAG_RESOURCE_NAME_VALID;
  4598. }
  4599. hActCtx = ::CreateActCtxW(&acw);
  4600. dwLastError = ::GetLastError();
  4601. printf("CreateActCtxW() on \"%ls\" returned %p\n", arg, hActCtx);
  4602. if (hActCtx == INVALID_HANDLE_VALUE)
  4603. {
  4604. printf(" ::GetLastError() = %lu\n", dwLastError);
  4605. }
  4606. ::ReleaseActCtx(hActCtx);
  4607. }
  4608. }
  4609. const char comctlv6manifest[]=
  4610. "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"
  4611. "<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
  4612. "<assemblyIdentity"
  4613. " name=\"Microsoft.Windows.Shell.notepad\""
  4614. " processorArchitecture=\"x86\""
  4615. " version=\"5.1.0.0\""
  4616. " type=\"win32\"/>"
  4617. "<dependency>"
  4618. " <dependentAssembly>"
  4619. " <assemblyIdentity"
  4620. " type=\"win32\""
  4621. " name=\"Microsoft.Windows.Common-Controls\""
  4622. " version=\"6.0.0.0\""
  4623. " processorArchitecture=\"x86\""
  4624. " publicKeyToken=\"6595b64144ccf1df\""
  4625. " language=\"*\""
  4626. " />"
  4627. " </dependentAssembly>"
  4628. "</dependency>"
  4629. "</assembly>"
  4630. ;
  4631. const char comctlv5manifest[]=
  4632. "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"
  4633. "<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
  4634. "<assemblyIdentity"
  4635. " name=\"Microsoft.Windows.Shell.notepad\""
  4636. " processorArchitecture=\"x86\""
  4637. " version=\"5.1.0.0\""
  4638. " type=\"win32\"/>"
  4639. "</assembly>"
  4640. ;
  4641. void TestCreateActctxAdminOverride()
  4642. {
  4643. WCHAR exe[MAX_PATH];
  4644. WCHAR dll[MAX_PATH];
  4645. WCHAR comctl[MAX_PATH];
  4646. WCHAR manifest[MAX_PATH];
  4647. ACTCTXW Actctx = {sizeof(Actctx)};
  4648. FILE* File = NULL;
  4649. ULONG_PTR ulCookie = 0;
  4650. HMODULE DllHandle = 0;
  4651. HANDLE ActctxHandle;
  4652. GUID Guid = { 0 };
  4653. wcscpy(exe, GetMyModuleFullPath());
  4654. wcscpy(dll, GetMyModuleFullPath());
  4655. wcscat(dll, L".dll");
  4656. CopyFileW(exe, dll, FALSE);
  4657. SetDllBitInPeImage(dll);
  4658. #if 0
  4659. wcscpy(String, GetMyModuleFullPath());
  4660. wcscat(String, L".Manifest");
  4661. DeleteFileW(String);
  4662. Trace("DeleteFile(%ls)\n", String);
  4663. wcscpy(String, GetMyModuleFullPath());
  4664. wcscat(String, L".2.Manifest");
  4665. DeleteFileW(String);
  4666. Trace("DeleteFile(%ls)\n", String);
  4667. wcscpy(String, GetMyModuleFullPath());
  4668. wcscat(String, L".3.Manifest");
  4669. DeleteFileW(String);
  4670. Trace("DeleteFile(%ls)\n", String);
  4671. #endif
  4672. Actctx.lpSource = dll;
  4673. /*
  4674. ActctxHandle = CreateActCtxW(&Actctx);
  4675. if (ActctxHandle == INVALID_HANDLE_VALUE)
  4676. return;
  4677. Trace("CreateActCtxW succeeded\n");
  4678. */
  4679. //
  4680. // manfile is number to put in the manifest file name, 0 for none
  4681. // good is what the contents of the file are, 0=>bad, 1=>v5, 2=>v6
  4682. // res is what resource id to ask for
  4683. //
  4684. for (int manfile = 0 ; manfile != 4 ; manfile += 1)
  4685. {
  4686. WCHAR Number[RTL_BITS_OF(ULONG_PTR) + 3];
  4687. for (int good = 0 ; good != 3 ; good += 1)
  4688. {
  4689. for (int res = -1 ; res != 4 ; res += 1)
  4690. {
  4691. Trace("---------------------------------------------------------------\n");
  4692. Trace("resourceid is %d%s\n", res, (res != -1) ? "" : " (flag not set)");
  4693. if (res != -1)
  4694. {
  4695. Actctx.lpResourceName = MAKEINTRESOURCEW(res);
  4696. Actctx.dwFlags |= ACTCTX_FLAG_RESOURCE_NAME_VALID;
  4697. Actctx.lpResourceName = MAKEINTRESOURCEW(res);
  4698. }
  4699. else
  4700. {
  4701. Actctx.dwFlags &= ~ACTCTX_FLAG_RESOURCE_NAME_VALID;
  4702. }
  4703. for (int delman = 0 ; delman != 4 ; delman += 1)
  4704. {
  4705. Number[0] = 0;
  4706. if (delman)
  4707. swprintf(Number, L".%d", delman);
  4708. swprintf(manifest, L"%ls%ls%ls%ls", GetMyModuleFullPathWithoutExtension(), L".dll", Number, L".Manifest");
  4709. /*
  4710. CoCreateGuid(&Guid);
  4711. swprintf(String3, L"%ls%I64x%I64x", GetMyModuleFullPath(), *reinterpret_cast<__int64*>(&Guid), *(1+reinterpret_cast<__int64*>(&Guid)));
  4712. if (!MoveFileW(String, String3) && ::GetLastError() != ERROR_FILE_NOT_FOUND)
  4713. Trace("MoveFile(%ls -> %ls) FAILED %d\n", String, String3, ::GetLastError());
  4714. else
  4715. ;//Trace("MoveFile(%ls -> %ls)\n", String, String3);
  4716. */
  4717. if (!DeleteFileW(manifest) && ::GetLastError() != ERROR_FILE_NOT_FOUND)
  4718. Trace("DeleteFile(%ls) FAILED %d\n", manifest, ::GetLastError());
  4719. else
  4720. ;//Trace("DeleteFile(%ls)\n", String3);
  4721. }
  4722. Number[0] = 0;
  4723. if (manfile != 0)
  4724. {
  4725. swprintf(Number, L".%d", manfile);
  4726. }
  4727. swprintf(manifest, L"%ls%ls%ls%ls", GetMyModuleFullPathWithoutExtension(), L".dll", Number, L".Manifest");
  4728. //Trace("fopen(%ls)\n", String);
  4729. File = _wfopen(manifest, L"w+");
  4730. if (File == NULL)
  4731. {
  4732. perror("fopen");
  4733. }
  4734. switch (good)
  4735. {
  4736. case 0:
  4737. fprintf(File, "bad");
  4738. Trace("%ls is bad\n", manifest);
  4739. break;
  4740. case 1:
  4741. fprintf(File, "%s", comctlv5manifest);
  4742. Trace("%ls is comctlv5manifest\n", manifest);
  4743. break;
  4744. case 2:
  4745. fprintf(File, "%s", comctlv6manifest);
  4746. Trace("%ls is comctlv6manifest\n", manifest);
  4747. break;
  4748. }
  4749. fclose(File);
  4750. ActctxHandle = CreateActCtxW(&Actctx);
  4751. if (ActctxHandle == INVALID_HANDLE_VALUE)
  4752. {
  4753. Trace("CreateActCtxW failed %d\n", ::GetLastError());
  4754. ulCookie = 0;
  4755. }
  4756. else
  4757. {
  4758. Trace("CreateActCtxW succeeded %p\n", ActctxHandle);
  4759. ActivateActCtx(ActctxHandle, &ulCookie);
  4760. }
  4761. __try
  4762. {
  4763. PWSTR filePart;
  4764. comctl[0] = 0;
  4765. SearchPathW(NULL, L"comctl32.dll", NULL, RTL_NUMBER_OF(comctl), comctl, &filePart);
  4766. }
  4767. __finally
  4768. {
  4769. if (ActctxHandle != INVALID_HANDLE_VALUE)
  4770. DeactivateActCtx(0, ulCookie);
  4771. }
  4772. Trace("SearchPathW(comctl32.dll): %ls\n", comctl);
  4773. }
  4774. }
  4775. }
  4776. }
  4777. void TestCreateActctxLikeCreateProcess()
  4778. {
  4779. #if defined(ACTCTX_FLAG_LIKE_CREATEPROCESS)
  4780. WCHAR comctl[MAX_PATH];
  4781. WCHAR manifest[MAX_PATH];
  4782. ACTCTXW Actctx = {sizeof(Actctx)};
  4783. FILE* File = NULL;
  4784. ULONG_PTR ulCookie = 0;
  4785. HMODULE DllHandle = 0;
  4786. HANDLE ActctxHandle;
  4787. PWSTR filePart;
  4788. Actctx.lpSource = GetMyModuleFullPath();
  4789. Actctx.dwFlags = ACTCTX_FLAG_LIKE_CREATEPROCESS;
  4790. wcscpy(manifest, GetMyModuleFullPath());
  4791. wcscat(manifest, L".Manifest");
  4792. DeleteFileW(manifest);
  4793. //Trace("DeleteFile(%ls)\n", manifest);
  4794. ActctxHandle = CreateActCtxW(&Actctx);
  4795. if (ActctxHandle == INVALID_HANDLE_VALUE)
  4796. {
  4797. Trace("CreateActCtxW failed %d\n", ::GetLastError());
  4798. ulCookie = 0;
  4799. }
  4800. else
  4801. {
  4802. Trace("CreateActCtxW succeeded %p\n", ActctxHandle);
  4803. ActivateActCtx(ActctxHandle, &ulCookie);
  4804. }
  4805. __try
  4806. {
  4807. comctl[0] = 0;
  4808. SearchPathW(NULL, L"comctl32.dll", NULL, RTL_NUMBER_OF(comctl), comctl, &filePart);
  4809. }
  4810. __finally
  4811. {
  4812. if (ActctxHandle != INVALID_HANDLE_VALUE)
  4813. DeactivateActCtx(0, ulCookie);
  4814. }
  4815. Trace("SearchPathW(comctl32.dll): %ls\n", comctl);
  4816. File = _wfopen(manifest, L"w");
  4817. fprintf(File, "%s", comctlv5manifest);
  4818. fclose(File);
  4819. Trace("%ls == comctlv5manifest\n", manifest);
  4820. ActctxHandle = CreateActCtxW(&Actctx);
  4821. if (ActctxHandle == INVALID_HANDLE_VALUE)
  4822. {
  4823. Trace("CreateActCtxW failed %d\n", ::GetLastError());
  4824. ulCookie = 0;
  4825. }
  4826. else
  4827. {
  4828. Trace("CreateActCtxW succeeded %p\n", ActctxHandle);
  4829. ActivateActCtx(ActctxHandle, &ulCookie);
  4830. }
  4831. __try
  4832. {
  4833. comctl[0] = 0;
  4834. SearchPathW(NULL, L"comctl32.dll", NULL, RTL_NUMBER_OF(comctl), comctl, &filePart);
  4835. }
  4836. __finally
  4837. {
  4838. if (ActctxHandle != INVALID_HANDLE_VALUE)
  4839. DeactivateActCtx(0, ulCookie);
  4840. }
  4841. Trace("SearchPathW(comctl32.dll): %ls\n", comctl);
  4842. File = _wfopen(manifest, L"w");
  4843. fprintf(File, "%ls", comctlv6manifest);
  4844. fclose(File);
  4845. Trace("%ls == comctlv6manifest\n", manifest);
  4846. ActctxHandle = CreateActCtxW(&Actctx);
  4847. if (ActctxHandle == INVALID_HANDLE_VALUE)
  4848. {
  4849. Trace("CreateActCtxW failed %d\n", ::GetLastError());
  4850. ulCookie = 0;
  4851. }
  4852. else
  4853. {
  4854. Trace("CreateActCtxW succeeded %p\n", ActctxHandle);
  4855. ActivateActCtx(ActctxHandle, &ulCookie);
  4856. }
  4857. __try
  4858. {
  4859. comctl[0] = 0;
  4860. SearchPathW(NULL, L"comctl32.dll", NULL, RTL_NUMBER_OF(comctl), comctl, &filePart);
  4861. }
  4862. __finally
  4863. {
  4864. if (ActctxHandle != INVALID_HANDLE_VALUE)
  4865. DeactivateActCtx(0, ulCookie);
  4866. }
  4867. Trace("SearchPathW(comctl32.dll): %ls\n", comctl);
  4868. #endif
  4869. }
  4870. void
  4871. TestQueryManifestInformationBasic(
  4872. PCWSTR pszManifest
  4873. )
  4874. {
  4875. PSXS_QUERY_MANIFEST_INFORMATION pfn = NULL;
  4876. LoadSxs();
  4877. struct {
  4878. SXS_MANIFEST_INFORMATION_BASIC mib;
  4879. WCHAR rgwchSpaceForIdentity[1024];
  4880. WCHAR rgwchSpaceForDirName[1024];
  4881. } buff;
  4882. GetSxsProc("SxsQueryManifestInformation", &pfn);
  4883. if (!(*pfn)(0, pszManifest, SXS_QUERY_MANIFEST_INFORMATION_INFOCLASS_BASIC, 0, sizeof(buff), &buff, NULL)) {
  4884. fprintf(stderr, "%s failed!\n", __FUNCTION__);
  4885. }
  4886. }
  4887. void TestImage()
  4888. {
  4889. PIMAGE_RESOURCE_DIRECTORY ImageResourceDirectory = (PIMAGE_RESOURCE_DIRECTORY)4;
  4890. PIMAGE_RESOURCE_DIRECTORY_ENTRY ImageResourceDirectoryEntry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)4;;
  4891. printf("ImageResourceDirectory %p\n", ImageResourceDirectory);
  4892. printf("ImageResourceDirectory + 1 %p\n", ImageResourceDirectory + 1);
  4893. printf("ImageResourceDirectoryEntry %p\n", ImageResourceDirectoryEntry);
  4894. printf("ImageResourceDirectoryEntry + 1 %p\n", ImageResourceDirectoryEntry + 1);
  4895. }
  4896. class CSxsTestCleanup : public CCleanupBase
  4897. {
  4898. public:
  4899. VOID DeleteYourself() { }
  4900. ~CSxsTestCleanup() { }
  4901. };
  4902. #define private public
  4903. #include "sxsprotect.h"
  4904. #undef private
  4905. void TestInterlockedAlignment()
  4906. {
  4907. __declspec(align(16)) SLIST_HEADER SlistHeader;
  4908. RtlInitializeSListHead(&SlistHeader);
  4909. CSxsTestCleanup* pc = new CSxsTestCleanup();
  4910. printf("%p\n", pc);
  4911. printf("%p\n", static_cast<SINGLE_LIST_ENTRY*>(pc));
  4912. SxspAtExit(pc);
  4913. CProtectionRequestRecord* pr = new CProtectionRequestRecord;
  4914. printf("%p\n", pr);
  4915. printf("%p\n", &pr->m_ListHeader);
  4916. CStringListEntry* psle = new CStringListEntry;
  4917. printf("%p\n", psle);
  4918. printf("%p\n", static_cast<SINGLE_LIST_ENTRY*>(psle));
  4919. RtlInterlockedPushEntrySList(&SlistHeader, pc);
  4920. RtlInterlockedPushEntrySList(&SlistHeader, psle);
  4921. RtlQueryDepthSList(&SlistHeader);
  4922. RtlInterlockedPopEntrySList(&SlistHeader);
  4923. RtlInterlockedFlushSList(&SlistHeader);
  4924. // untested: RtlInterlockedPushListSList
  4925. RtlInterlockedPushEntrySList(&pr->m_ListHeader, pc);
  4926. RtlInterlockedPushEntrySList(&pr->m_ListHeader, psle);
  4927. RtlQueryDepthSList(&pr->m_ListHeader);
  4928. RtlInterlockedPopEntrySList(&pr->m_ListHeader);
  4929. RtlInterlockedFlushSList(&pr->m_ListHeader);
  4930. // untested: RtlInterlockedPushListSList
  4931. printf("success\n");
  4932. }
  4933. void TestCreateActctxWindowsShellManifest()
  4934. {
  4935. WCHAR WindowsShellManifestFileName[MAX_PATH];
  4936. ACTCTXW ActCtx = { sizeof(ActCtx) };
  4937. HANDLE ActCtxHandle = 0;
  4938. WindowsShellManifestFileName[0] = 0;
  4939. GetWindowsDirectoryW(WindowsShellManifestFileName, NUMBER_OF(WindowsShellManifestFileName) - 64);
  4940. wcscat(WindowsShellManifestFileName, L"\\WindowsShell.Manifest");
  4941. ActCtx.lpSource = WindowsShellManifestFileName;
  4942. ActCtxHandle = CreateActCtxW(&ActCtx);
  4943. Trace("TestCreateActctxWindowsShellManifest: %p, %lu\n", ActCtxHandle, ::GetLastError());
  4944. ReleaseActCtx(ActCtxHandle);
  4945. }
  4946. class CObjectTypes
  4947. {
  4948. protected:
  4949. std::vector<BYTE> m_ByteBuffer;
  4950. PSYSTEM_OBJECTTYPE_INFORMATION m_TypedBuffer;
  4951. public:
  4952. };
  4953. void TestCreateGlobalEvent()
  4954. {
  4955. if (!::CreateEventW(NULL, FALSE, FALSE, L"MGRIER"))
  4956. return;
  4957. Sleep(500000);
  4958. }
  4959. class CObjectSnapshot
  4960. {
  4961. protected:
  4962. //
  4963. // This interface is not very good, but it's easy..the entries
  4964. // are of variable size...
  4965. //
  4966. std::vector<BYTE> m_ByteBuffer;
  4967. SIZE_T m_Size;
  4968. //
  4969. // Some operations, like sorting, require us to move all the string data
  4970. // out of the elements. We do not manage this data in a lossless way.
  4971. //
  4972. // Ultimately, you may benefit from copying/transforming the data completely.
  4973. //
  4974. std::vector<BYTE> m_StringData;
  4975. public:
  4976. SIZE_T size() const { return m_Size; }
  4977. class iterator;
  4978. class const_iterator
  4979. {
  4980. protected:
  4981. const SYSTEM_OBJECT_INFORMATION* m_p;
  4982. public:
  4983. ~const_iterator() { }
  4984. void operator=(const const_iterator& x) { m_p = x.m_p; }
  4985. const_iterator(const const_iterator& x) : m_p(x.m_p) { }
  4986. const_iterator(const BYTE* p = NULL) : m_p(reinterpret_cast<const SYSTEM_OBJECT_INFORMATION*>(p)) { }
  4987. //void operator=(const iterator& x);
  4988. //const_iterator(const iterator& x);
  4989. bool operator==(const const_iterator& i) const
  4990. {
  4991. return (m_p == i.m_p);
  4992. }
  4993. bool operator!=(const const_iterator& i) const
  4994. {
  4995. return (m_p != i.m_p);
  4996. }
  4997. const SYSTEM_OBJECT_INFORMATION& operator*() const { return *m_p; }
  4998. void operator++()
  4999. {
  5000. if (m_p != NULL)
  5001. {
  5002. if (m_p->NextEntryOffset != 0)
  5003. m_p = reinterpret_cast<const SYSTEM_OBJECT_INFORMATION*>(reinterpret_cast<const BYTE*>(m_p) + m_p->NextEntryOffset);
  5004. else
  5005. m_p = NULL; // end
  5006. }
  5007. }
  5008. const_iterator operator++(int)
  5009. {
  5010. const_iterator tmp = *this;
  5011. ++*this;;
  5012. return tmp;
  5013. }
  5014. };
  5015. class iterator : public const_iterator
  5016. {
  5017. private:
  5018. void operator=(const const_iterator&);
  5019. public:
  5020. ~iterator() { }
  5021. iterator(BYTE* p = NULL) : const_iterator(p) { }
  5022. SYSTEM_OBJECT_INFORMATION& operator*() { return const_cast<SYSTEM_OBJECT_INFORMATION&>(*m_p); }
  5023. };
  5024. const_iterator begin() const { return const_iterator(&m_ByteBuffer[0]); }
  5025. iterator begin() { return iterator(&m_ByteBuffer[0]); }
  5026. const_iterator end() const { return const_iterator(); }
  5027. iterator end() { return iterator(); }
  5028. void swap(CObjectSnapshot& x)
  5029. {
  5030. std::swap(m_ByteBuffer, x.m_ByteBuffer);
  5031. std::swap(m_Size, x.m_Size);
  5032. }
  5033. CObjectSnapshot() { }
  5034. ~CObjectSnapshot() { }
  5035. };
  5036. class CHandleSnapshot
  5037. {
  5038. protected:
  5039. std::vector<BYTE> m_ByteBuffer;
  5040. PSYSTEM_HANDLE_INFORMATION_EX m_TypedBuffer;
  5041. public:
  5042. SIZE_T size() const { return m_TypedBuffer->NumberOfHandles; }
  5043. SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX* begin() { return &m_TypedBuffer->Handles[0]; }
  5044. const SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX* begin() const { return &m_TypedBuffer->Handles[0]; }
  5045. SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX* end() { return begin() + size(); }
  5046. const SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX* end() const { return begin() + size(); }
  5047. SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX& operator[](size_t index) { return *(begin() + index); }
  5048. const SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX& operator[](size_t index) const { return *(begin() + index); }
  5049. void reserve(SIZE_T n)
  5050. {
  5051. resize(n); // since there's no constructor..
  5052. }
  5053. void resize(SIZE_T n)
  5054. {
  5055. m_ByteBuffer.resize(sizeof(SYSTEM_HANDLE_INFORMATION_EX) + (n - 1) * sizeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX));
  5056. Resync();
  5057. m_TypedBuffer->NumberOfHandles = n;
  5058. }
  5059. void swap(CHandleSnapshot& x)
  5060. {
  5061. std::swap(m_ByteBuffer, x.m_ByteBuffer);
  5062. x.Resync();
  5063. Resync();
  5064. }
  5065. CHandleSnapshot() : m_TypedBuffer(NULL) { }
  5066. ~CHandleSnapshot() { }
  5067. void GetHandlesForCurrentProcess()
  5068. {
  5069. GetHandlesForProcess(GetCurrentProcessId());
  5070. }
  5071. void GetHandlesForProcess(ULONG_PTR pid)
  5072. {
  5073. GetHandlesForSystem();
  5074. FilterByProcessId(pid);
  5075. }
  5076. void GetHandlesForSystem()
  5077. {
  5078. //
  5079. // the actual needed size can be very large, over 256k
  5080. //
  5081. ULONG Size = 0;
  5082. m_TypedBuffer = NULL;
  5083. m_ByteBuffer.resize(sizeof(SYSTEM_HANDLE_INFORMATION_EX));
  5084. NTSTATUS Status = NtQuerySystemInformation(SystemExtendedHandleInformation, &m_ByteBuffer[0], static_cast<ULONG>(m_ByteBuffer.size()), &Size);
  5085. while (Status == STATUS_INFO_LENGTH_MISMATCH && Size != 0)
  5086. {
  5087. //
  5088. // since it is transient, let's be safe and double it
  5089. //
  5090. m_ByteBuffer.resize(Size * 2);
  5091. Status = NtQuerySystemInformation(SystemExtendedHandleInformation, &m_ByteBuffer[0], static_cast<ULONG>(m_ByteBuffer.size()), &Size);
  5092. }
  5093. if (!NT_SUCCESS(Status))
  5094. {
  5095. Trace("NtQuerySystemInformation failed 0x%lx\n", Status);
  5096. return;
  5097. }
  5098. m_ByteBuffer.resize(Size);
  5099. m_TypedBuffer = reinterpret_cast<PSYSTEM_HANDLE_INFORMATION_EX>(&m_ByteBuffer[0]);
  5100. Trace("%Id total handles system-wide\n", m_TypedBuffer->NumberOfHandles);
  5101. }
  5102. void FilterByProcessId(ULONG_PTR pid)
  5103. {
  5104. SIZE_T Scan = 0;
  5105. SIZE_T Keep = 0;
  5106. for (Scan = 0 ; Scan != m_TypedBuffer->NumberOfHandles ; Scan += 1)
  5107. {
  5108. if (m_TypedBuffer->Handles[Scan].UniqueProcessId == pid)
  5109. {
  5110. if (Keep != Scan)
  5111. m_TypedBuffer->Handles[Keep] = m_TypedBuffer->Handles[Scan]; // struct copy
  5112. Keep += 1;
  5113. }
  5114. }
  5115. m_TypedBuffer->NumberOfHandles = Keep;
  5116. }
  5117. void Resync()
  5118. {
  5119. m_TypedBuffer = reinterpret_cast<PSYSTEM_HANDLE_INFORMATION_EX>(&m_ByteBuffer[0]);
  5120. }
  5121. CHandleSnapshot(const CHandleSnapshot& x) : m_TypedBuffer(NULL)
  5122. {
  5123. this->m_ByteBuffer = x.m_ByteBuffer;
  5124. Resync();
  5125. }
  5126. void operator=(const CHandleSnapshot& x)
  5127. {
  5128. this->m_ByteBuffer = x.m_ByteBuffer;
  5129. Resync();
  5130. }
  5131. class CHandleValueOperatorLessThan
  5132. {
  5133. public:
  5134. bool operator()(const SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX& x, const SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX& y)
  5135. {
  5136. return (x.HandleValue < y.HandleValue);
  5137. }
  5138. };
  5139. void SortByHandleValue()
  5140. {
  5141. std::sort(begin(), end(), CHandleValueOperatorLessThan());
  5142. }
  5143. void operator-=(/*const*/CHandleSnapshot& x)
  5144. {
  5145. SortByHandleValue();
  5146. x.SortByHandleValue();
  5147. CHandleSnapshot temp(*this);
  5148. resize(
  5149. std::set_difference(temp.begin(), temp.end(), x.begin(), x.end(), begin(), CHandleValueOperatorLessThan())
  5150. - begin());
  5151. }
  5152. void Dump()
  5153. {
  5154. }
  5155. };
  5156. class CHandleSnapshots
  5157. {
  5158. public:
  5159. void Begin() { m_Begin.GetHandlesForCurrentProcess(); }
  5160. void End() { m_End.GetHandlesForCurrentProcess(); m_Diff = m_Begin; m_Diff -= m_End; }
  5161. CHandleSnapshot m_Begin;
  5162. CHandleSnapshot m_End;
  5163. CHandleSnapshot m_Diff;
  5164. };
  5165. void Pause()
  5166. {
  5167. Trace("Press a key to continue\n");
  5168. getchar();
  5169. }
  5170. void TestHandleLeaks()
  5171. {
  5172. WCHAR WindowsDirectory[MAX_PATH];
  5173. ULONG i = 0;
  5174. CFusionFile DevNull;
  5175. //SECURITY_ATTRIBUTES SecurityAttributes = { sizeof(SecurityAttributes), NULL, TRUE};
  5176. WindowsDirectory[0] = 0;
  5177. DevNull = CreateFileW(L"nul:", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
  5178. NULL/*&SecurityAttributes*/, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  5179. if (DevNull == INVALID_HANDLE_VALUE)
  5180. Trace("Open(nul:) failed %ld\n", ::GetLastError());
  5181. GetWindowsDirectoryW(WindowsDirectory, NUMBER_OF(WindowsDirectory) - 64);
  5182. {
  5183. const WCHAR SubFunction[] = L"CreateActCtx";
  5184. CHandleSnapshots handleSnapshots;
  5185. handleSnapshots.Begin();
  5186. Trace("%s Begin %ls : %Id handles\n", __FUNCTION__, SubFunction, handleSnapshots.m_Begin.size());
  5187. {
  5188. WCHAR WindowsShellManifestFileName[MAX_PATH];
  5189. ACTCTXW ActCtx = { sizeof(ActCtx) };
  5190. HANDLE ActCtxHandle = 0;
  5191. WindowsShellManifestFileName[0] = 0;
  5192. wcscpy(WindowsShellManifestFileName, WindowsDirectory);
  5193. wcscat(WindowsShellManifestFileName, L"\\WindowsShell.Manifest");
  5194. ActCtx.lpSource = WindowsShellManifestFileName;
  5195. for (i = 0 ; i != 100 ; ++i)
  5196. {
  5197. HANDLE ActCtxHandle = CreateActCtxW(&ActCtx);
  5198. if (ActCtxHandle == INVALID_HANDLE_VALUE)
  5199. Trace("TestCreateActctxWindowsShellManifest: %p, %lu\n", ActCtxHandle, ::GetLastError());
  5200. else
  5201. ReleaseActCtx(ActCtxHandle);
  5202. }
  5203. }
  5204. handleSnapshots.End();
  5205. Trace("%s End %ls : %Id handles\n", __FUNCTION__, SubFunction, handleSnapshots.m_End.size());
  5206. if (handleSnapshots.m_Diff.size() != 0)
  5207. {
  5208. Trace("%s Diff %ls : %Id handles\n", __FUNCTION__, SubFunction, handleSnapshots.m_Diff.size());
  5209. }
  5210. }
  5211. Pause();
  5212. {
  5213. const WCHAR SubFunction[] = L"CreateActCtx + LoadLibrary(comctl32)";
  5214. CHandleSnapshots handleSnapshots;
  5215. handleSnapshots.Begin();
  5216. Trace("%s Begin %ls : %Id handles\n", __FUNCTION__, SubFunction, handleSnapshots.m_Begin.size());
  5217. {
  5218. WCHAR WindowsShellManifestFileName[MAX_PATH];
  5219. ACTCTXW ActCtx = { sizeof(ActCtx) };
  5220. HANDLE ActCtxHandle = 0;
  5221. WindowsShellManifestFileName[0] = 0;
  5222. wcscpy(WindowsShellManifestFileName, WindowsDirectory);
  5223. wcscat(WindowsShellManifestFileName, L"\\WindowsShell.Manifest");
  5224. ActCtx.lpSource = WindowsShellManifestFileName;
  5225. for (i = 0 ; i != 100 ; ++i)
  5226. {
  5227. ULONG_PTR ulCookie = 0;
  5228. HANDLE ActCtxHandle = CreateActCtxW(&ActCtx);
  5229. if (ActCtxHandle == INVALID_HANDLE_VALUE)
  5230. Trace("TestCreateActctxWindowsShellManifest: %p, %lu\n", ActCtxHandle, ::GetLastError());
  5231. else
  5232. {
  5233. ActivateActCtx(ActCtxHandle, &ulCookie);
  5234. HMODULE Comctl = LoadLibraryW(L"comctl32.dll");
  5235. if (i == 1)
  5236. {
  5237. CHandleSnapshot handleSnapshot;
  5238. handleSnapshot.GetHandlesForCurrentProcess();
  5239. Trace("Comctl32.dll loaded first time %Id\n", handleSnapshot.size());
  5240. Pause();
  5241. }
  5242. FreeLibrary(Comctl);
  5243. if (i == 1)
  5244. {
  5245. CHandleSnapshot handleSnapshot;
  5246. handleSnapshot.GetHandlesForCurrentProcess();
  5247. Trace("Comctl32.dll unloaded first time %Id\n", handleSnapshot.size());
  5248. Pause();
  5249. }
  5250. if (ulCookie != 0)
  5251. DeactivateActCtx(0, ulCookie);
  5252. ReleaseActCtx(ActCtxHandle);
  5253. if (i == 1)
  5254. {
  5255. CHandleSnapshot handleSnapshot;
  5256. handleSnapshot.GetHandlesForCurrentProcess();
  5257. Trace("Comctl32.dll unloaded + ReleaseActCtxfirst time %Id\n", handleSnapshot.size());
  5258. Pause();
  5259. }
  5260. }
  5261. }
  5262. }
  5263. handleSnapshots.End();
  5264. Trace("%s End %ls : %Id handles\n", __FUNCTION__, SubFunction, handleSnapshots.m_End.size());
  5265. if (handleSnapshots.m_Diff.size() != 0)
  5266. {
  5267. Trace("%s Diff %ls : %Id handles\n", __FUNCTION__, SubFunction, handleSnapshots.m_Diff.size());
  5268. }
  5269. }
  5270. Pause();
  5271. {
  5272. WCHAR Me[MAX_PATH];
  5273. STARTUPINFOW StartupInfo = {sizeof(StartupInfo)};
  5274. PROCESS_INFORMATION ProcessInfo = {0};
  5275. static const WCHAR SubFunction[] = L"CreateProcess";
  5276. Kernel32.GetModuleFileNameW(NULL, Me, NUMBER_OF(Me));
  5277. CHandleSnapshots handleSnapshots;
  5278. handleSnapshots.Begin();
  5279. Trace("%s Begin %ls : %Id handles\n", __FUNCTION__, SubFunction, handleSnapshots.m_Begin.size());
  5280. for (i = 0 ; i != 100 ; ++i)
  5281. {
  5282. StartupInfo.hStdOutput = DevNull;
  5283. StartupInfo.hStdError = DevNull;
  5284. StartupInfo.dwFlags = STARTF_USESTDHANDLES;
  5285. if (!CreateProcessW(Me, NULL, NULL, NULL, FALSE, 0, NULL, NULL, &StartupInfo, &ProcessInfo))
  5286. {
  5287. Trace("CreateProcess failed %ld\n", ::GetLastError());
  5288. }
  5289. else
  5290. {
  5291. WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
  5292. WaitForSingleObject(ProcessInfo.hThread, INFINITE);
  5293. if (!CloseHandle(ProcessInfo.hProcess))
  5294. Trace("CloseHandle(Process %p) failed %ld\n", ProcessInfo.hProcess, ::GetLastError());
  5295. if (!CloseHandle(ProcessInfo.hThread))
  5296. Trace("CloseHandle(Thread %p) failed %ld\n", ProcessInfo.hThread, ::GetLastError());
  5297. }
  5298. }
  5299. handleSnapshots.End();
  5300. Trace("%s End %ls : %Id handles\n", __FUNCTION__, SubFunction, handleSnapshots.m_End.size());
  5301. if (handleSnapshots.m_Diff.size() != 0)
  5302. {
  5303. Trace("%s Diff %ls : %Id handles\n", __FUNCTION__, SubFunction, handleSnapshots.m_Diff.size());
  5304. }
  5305. }
  5306. Pause();
  5307. {
  5308. WCHAR SubFunction[sizeof("LoadLibrary xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")];
  5309. WCHAR DllPath[MAX_PATH];
  5310. ULONG j = 0;
  5311. const static PCWSTR Leaves[] = {
  5312. L"mshtml.dll",
  5313. L"wintrust.dll",
  5314. L"shell32.dll",
  5315. L"crypt32.dll",
  5316. L"msxml.dll",
  5317. L"shdocvw.dll",
  5318. L"msxml2.dll",
  5319. L"msxml3.dll"
  5320. };
  5321. for (j = 0 ; j != NUMBER_OF(Leaves) ; ++j)
  5322. {
  5323. SubFunction[0] = 0;
  5324. wcscat(SubFunction, L"LoadLibrary ");
  5325. wcscat(SubFunction, Leaves[j]);
  5326. DllPath[0] = 0;
  5327. wcscat(DllPath, WindowsDirectory);
  5328. wcscat(DllPath, L"\\system32\\");
  5329. wcscat(DllPath, Leaves[j]);
  5330. CHandleSnapshots handleSnapshots;
  5331. handleSnapshots.Begin();
  5332. Trace("%s Begin %ls : %Id handles\n", __FUNCTION__, SubFunction, handleSnapshots.m_Begin.size());
  5333. for (i = 0 ; i != 20 ; ++i)
  5334. {
  5335. HMODULE DllHandle;
  5336. if ((DllHandle = LoadLibraryW(DllPath)) != NULL)
  5337. FreeLibrary(DllHandle);
  5338. else
  5339. Trace("LoadLibraryW(%ls) failed %ld\n", DllPath, ::GetLastError());
  5340. }
  5341. handleSnapshots.End();
  5342. Trace("%s End %ls : %Id handles\n", __FUNCTION__, SubFunction, handleSnapshots.m_End.size());
  5343. if (handleSnapshots.m_Diff.size() != 0)
  5344. {
  5345. Trace("%s Diff %s : %Id handles\n", __FUNCTION__, SubFunction, handleSnapshots.m_Diff.size());
  5346. }
  5347. }
  5348. }
  5349. Pause();
  5350. }
  5351. #define YET_ANOTHER_PASTE(x,y) x##y
  5352. #define YET_YET_ANOTHER_PASTE(x,y) YET_ANOTHER_PASTE(x,y)
  5353. #define LSXS_PROCESSOR_ARCHITECTURE YET_YET_ANOTHER_PASTE(L, SXS_PROCESSOR_ARCHITECTURE)
  5354. const WCHAR ToolsCrtManifest[]=
  5355. L"<?xml version=\"1.0\" standalone=\"yes\"?>"
  5356. L"<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
  5357. L"<assemblyIdentity"
  5358. L" name=\"Microsoft.Windows.SxsTest.ToolsCrtClient\""
  5359. L" processorArchitecture=\"" LSXS_PROCESSOR_ARCHITECTURE L"\"" /* Note that this only actually exists on x86 */
  5360. L" version=\"5.1.0.0\""
  5361. L" type=\"win32\"/>"
  5362. L"<dependency>"
  5363. L" <dependentAssembly>"
  5364. L" <assemblyIdentity"
  5365. L" type=\"win32\""
  5366. L" name=\"Microsoft.Tools.VisualCPlusPlus.Runtime-Libraries\""
  5367. L" version=\"6.0.0.0\""
  5368. L" processorArchitecture=\"" LSXS_PROCESSOR_ARCHITECTURE L"\""
  5369. L" publicKeyToken=\"6595b64144ccf1df\""
  5370. L" language=\"*\""
  5371. L" />"
  5372. L" </dependentAssembly>"
  5373. L"</dependency>"
  5374. L"</assembly>"
  5375. ;
  5376. const WCHAR WindowsCrtManifest[]=
  5377. L"<?xml version=\"1.0\" standalone=\"yes\"?>"
  5378. L"<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
  5379. L"<assemblyIdentity"
  5380. L" name=\"Microsoft.Windows.SxsTest.WindowsCrtClient\""
  5381. L" processorArchitecture=\"" LSXS_PROCESSOR_ARCHITECTURE L"\""
  5382. L" version=\"5.1.0.0\""
  5383. L" type=\"win32\"/>"
  5384. L"<dependency>"
  5385. L" <dependentAssembly>"
  5386. L" <assemblyIdentity"
  5387. L" type=\"win32\""
  5388. L" name=\"Microsoft.Windows.CPlusPlusRuntime\""
  5389. L" version=\"7.0.0.0\""
  5390. L" processorArchitecture=\"" LSXS_PROCESSOR_ARCHITECTURE L"\""
  5391. L" publicKeyToken=\"6595b64144ccf1df\""
  5392. L" language=\"*\""
  5393. L" />"
  5394. L" </dependentAssembly>"
  5395. L"</dependency>"
  5396. L"</assembly>"
  5397. ;
  5398. void TestCRuntimeAsms()
  5399. {
  5400. CFusionActCtxHandle WindowsCrtActCtxHandle;
  5401. CFusionActCtxHandle ToolsCrtActCtxHandle;
  5402. WindowsCrtActCtxHandle = ::CreateActivationContextFromStringW(WindowsCrtManifest);
  5403. if (WindowsCrtActCtxHandle == INVALID_HANDLE_VALUE)
  5404. ::Trace("CreateActCtx(WindowsCrtManifest %p) failed %ld\n", WindowsCrtManifest, ::GetLastError());
  5405. ToolsCrtActCtxHandle = ::CreateActivationContextFromStringW(ToolsCrtManifest);
  5406. if (ToolsCrtActCtxHandle == INVALID_HANDLE_VALUE)
  5407. ::Trace("CreateActCtx(WindowsCrtManifest %p) failed %ld\n", WindowsCrtManifest, ::GetLastError());
  5408. CFusionActCtxScope ToolsCrtActCtxScope;
  5409. CFusionActCtxScope WindowsCrtActCtxScope;
  5410. if (!WindowsCrtActCtxScope.Win32Activate(WindowsCrtActCtxHandle))
  5411. ::Trace("Activate(WindowsCrtActCtxHandle %p) failed %ld\n", WindowsCrtActCtxHandle, ::GetLastError());
  5412. if (!ToolsCrtActCtxScope.Win32Activate(ToolsCrtActCtxHandle))
  5413. ::Trace("Activate(ToolsCrtActCtxHandle %p) failed %ld\n", ToolsCrtActCtxHandle, ::GetLastError());
  5414. CStringBuffer MsvcrtBuffer;
  5415. CStringBuffer AtlBuffer;
  5416. //::SearchPathW();
  5417. }
  5418. /*
  5419. <comInterfaceExternalProxyStub
  5420. name="IPropertyPage"
  5421. iid="{B196B28D-BAB4-101A-B69C-00AA00341D07}"
  5422. proxyStubClsid32="{B196B286-BAB4-101A-B69C-00AA00341D07}"
  5423. numMethods="14"
  5424. baseInterface="{00000000-0000-0000-C000-000000000046}"
  5425. >
  5426. <comInterfaceExternalProxyStub
  5427. name="IPropertyPage2"
  5428. iid="{01E44665-24AC-101B-84ED-08002B2EC713}"
  5429. proxyStubClsid32="{B196B286-BAB4-101A-B69C-00AA00341D07}"
  5430. numMethods="15"
  5431. baseInterface="{B196B28D-BAB4-101A-B69C-00AA00341D07}"
  5432. >
  5433. <comInterfaceExternalProxyStub
  5434. name="IPropertyNotifySink"
  5435. iid="{9BFBBC02-EFF1-101A-84ED-00AA00341D07}"
  5436. proxyStubClsid32="{B196B286-BAB4-101A-B69C-00AA00341D07}"
  5437. baseInterface="{00000000-0000-0000-C000-00 00 00 00 00 46}"
  5438. numMethods="5"
  5439. >
  5440. */
  5441. #if 0
  5442. BOOL Win32FormatGuid(
  5443. CBaseStringBuffer& buff
  5444. REFGUID guid
  5445. )
  5446. {
  5447. FN_PROLOG_WIN32
  5448. IFW32FALSE_EXIT(this->Win32ResizeBuffer(64));
  5449. IFW32FALSE_EXIT(buff.Win32Format(L"{%08lx-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x}",
  5450. guid.Data1,
  5451. guid.Data2,
  5452. guid.Data3,
  5453. guid.Data4[0], guid.Data4[1],
  5454. guid.Data4[2], guid.Data4[3], guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7],
  5455. ));
  5456. FN_EPILOG
  5457. }
  5458. #endif
  5459. BOOL Win32Append(
  5460. CBaseStringBuffer& s,
  5461. PCWSTR t
  5462. )
  5463. {
  5464. FN_PROLOG_WIN32
  5465. IFW32FALSE_EXIT(s.Win32Append(t, wcslen(t)));
  5466. FN_EPILOG
  5467. }
  5468. typedef struct _FUSIONTESTP_REG_DATA
  5469. {
  5470. #define FUSIONTESTP_REG_TYPE_INTERFACE (1)
  5471. #define FUSIONTESTP_REG_TYPE_CLASS (2)
  5472. ULONG Type;
  5473. PCWSTR Name; // for debugging/tracing purposes (should coincide with InterfaceName)
  5474. PCWSTR Guid;
  5475. union
  5476. {
  5477. struct
  5478. {
  5479. WCHAR InprocServerFilePath[MAX_PATH];
  5480. WCHAR ThreadingModel[64];
  5481. };
  5482. struct
  5483. {
  5484. WCHAR InterfaceName[MAX_PATH];
  5485. WCHAR NumMethods[64];
  5486. WCHAR ProxyStubClsid[64];
  5487. //
  5488. // These usually aren't provided.
  5489. //
  5490. // WCHAR BaseInterface[64];
  5491. // WCHAR OLEViewerIViewerCLSID[64];
  5492. //
  5493. };
  5494. };
  5495. #define FUSIONTESTP_REG_ROOT_CURRENT_USER (1)
  5496. #define FUSIONTESTP_REG_ROOT_LOCAL_MACHINE (2)
  5497. #define FUSIONTESTP_REG_ROOT_CLASSES_ROOT (3)
  5498. ULONG Root;
  5499. //
  5500. // It is perhaps a bit inelegant to put this data here, perhaps not..
  5501. // We are deliberately a bit sloppy on the refcounting of these right now.
  5502. //
  5503. //#define FUSIONTESTP_PLAIN_COM_POINTER(t) CSmartRef<t>
  5504. #define FUSIONTESTP_PLAIN_COM_POINTER(t) t*
  5505. //#define FUSIONTESTP_PLAIN_COM_POINTER(t) void*
  5506. FUSIONTESTP_PLAIN_COM_POINTER(IUnknown) CoCreatedObject;
  5507. //FUSIONTESTP_PLAIN_COM_POINTER(IUnknown) InterfaceIntoObjectInCreatingThread;
  5508. //FUSIONTESTP_PLAIN_COM_POINTER(IUnknown) InterfaceIntoObjectInAnotherThread;
  5509. //WCHAR ModulePathInOtherThread[MAX_PATH]; // expected to be oleaut32.dll, but possibly already unloaded
  5510. //IID InterfaceIdOfObject;
  5511. DWORD GlobalInterfaceTableCookie;
  5512. } FUSIONTESTP_REG_DATA, *PFUSIONTESTP_REG_DATA;
  5513. typedef const FUSIONTESTP_REG_DATA* PCFUSIONTESTP_REG_DATA;
  5514. #if 0
  5515. //
  5516. // In reality, all three MFC classes implement all three interfaces, but let's broaden
  5517. // our minds a bit, ok?
  5518. //
  5519. BOOL
  5520. FusionTestpDynamicallyFindAnyInterfaceIntoObjectExceptIUnknown(
  5521. IUnknown* Object,
  5522. PCFUSIONTESTP_REG_DATA RegData, // too broad of a type really, but ok
  5523. SIZE_T Count,
  5524. FUSIONTESTP_PLAIN_COM_POINTER(IUnknown)& InterfaceIntoObject,
  5525. SIZE_T& InterfaceId
  5526. )
  5527. {
  5528. BOOL Success = FALSE;
  5529. FN_PROLOG_WIN32(Success);
  5530. IID LocalInterfaceId = { 0 };
  5531. FUSIONTESTP_PLAIN_COM_POINTER(IUnknown) LocalInterfaceIntoObject = NULL;
  5532. SIZE_T InterfaceIndex = 0;
  5533. InterfaceIntoObject = LocalInterfaceIntoObject;
  5534. InterfaceId = LocalInterfaceId;
  5535. for ( LocalInterfaceIndex = 0; LocalInterfaceIndex != Count ; LocalInterfaceIndex += 1)
  5536. {
  5537. FUSIONTESTP_REG_DATA* const p = &RegData[LocalInterfaceIndex];
  5538. IFCOMFAILED_EXIT(hr = Ole32.IIDFromString(const_cast<PWSTR>(p->Guid), &InterfaceId));
  5539. if (InterfaceId == IID_IUnknown) // shouldn't happen, but easy enough to handle
  5540. continue;
  5541. hr = Object->QueryInterface(InterfaceId, reinterpret_cast<void**>(&LocalInterfaceIntoObject));
  5542. if (SUCCEEDED(hr))
  5543. {
  5544. ::Trace("%s found interface %ls\n", __FUNCTION__, p->Name);
  5545. InterfaceIntoObject = LocalInterfaceIntoObject;
  5546. InterfaceId = LocalInterfaceId;
  5547. Success = TRUE;
  5548. goto Exit;
  5549. }
  5550. }
  5551. FN_EPILOG
  5552. }
  5553. #endif
  5554. #define OLEAUT_MARSHALER_CLSID_STRING L"{B196B286-BAB4-101A-B69C-00AA00341D07}"
  5555. FUSIONTESTP_REG_DATA FusionTestpMfcRegData[] =
  5556. {
  5557. { FUSIONTESTP_REG_TYPE_CLASS, L"Font Property Page", L"{0BE35200-8F91-11CE-9DE3-00AA004BB851}" },
  5558. { FUSIONTESTP_REG_TYPE_CLASS, L"Color Property Page", L"{0BE35201-8F91-11CE-9DE3-00AA004BB851}" },
  5559. { FUSIONTESTP_REG_TYPE_CLASS, L"Picture Property Page", L"{0BE35202-8F91-11CE-9DE3-00AA004BB851}" },
  5560. { FUSIONTESTP_REG_TYPE_INTERFACE, L"IPropertyPage", L"{B196B28D-BAB4-101A-B69C-00AA00341D07}" },
  5561. { FUSIONTESTP_REG_TYPE_INTERFACE, L"IPropertyPage2", L"{01E44665-24AC-101B-84ED-08002B2EC713}" },
  5562. { FUSIONTESTP_REG_TYPE_INTERFACE, L"IPropertyNotifySink", L"{9BFBBC02-EFF1-101A-84ED-00AA00341D07}" },
  5563. // Leave this registered, since the manifest does not specify a file.
  5564. //{ FUSIONTESTP_REG_TYPE_CLASS, L"oleaut32 marshaller (PSFactoryBuffer)", OLEAUT_MARSHALER_CLSID_STRING }
  5565. };
  5566. FUSIONTESTP_REG_DATA FusionTestpAtlRegData[1];
  5567. const HKEY FusionTestpHkeyRoots[] = { NULL, HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE, HKEY_CLASSES_ROOT };
  5568. const PCWSTR FusionTestpClassStringRoots[] = { NULL, L"Software\\Classes\\CLSID\\", L"Software\\Classes\\CLSID\\", L"CLSID\\" };
  5569. const PCWSTR FusionTestpInterfaceStringRoots[] = { NULL, L"Software\\Classes\\Interface\\", L"Software\\Classes\\Interface\\", L"Interface\\" };
  5570. const PCWSTR* FusionTestpStringRoots[] = { NULL, FusionTestpInterfaceStringRoots, FusionTestpClassStringRoots};
  5571. #define FUSIONTESTP_REG_DELETE (1)
  5572. #define FUSIONTESTP_REG_RESTORE (2)
  5573. #define FUSIONTESTP_REG_BACKUP (3)
  5574. BOOL FusionTestpEnumerateRegistryData(FUSIONTESTP_REG_DATA* RegData, ULONG Count, ULONG Mode)
  5575. {
  5576. BOOL Success = FALSE;
  5577. FN_PROLOG_WIN32(Success);
  5578. for (ULONG i = 0 ; i != Count ; i += 1)
  5579. {
  5580. FUSIONTESTP_REG_DATA* const p = &RegData[i];
  5581. ULONG MinRoot = 0;
  5582. ULONG MaxRoot = 0;
  5583. switch (Mode)
  5584. {
  5585. case FUSIONTESTP_REG_RESTORE:
  5586. case FUSIONTESTP_REG_DELETE:
  5587. MinRoot = p->Root;
  5588. if (MinRoot == 0)
  5589. continue;
  5590. MaxRoot = MinRoot;
  5591. break;
  5592. case FUSIONTESTP_REG_BACKUP:
  5593. MinRoot = 1;
  5594. MaxRoot = 3;
  5595. break;
  5596. }
  5597. //
  5598. // It'd be nice if you could embed the if within a switch..
  5599. //
  5600. for (ULONG root = MinRoot ; root <= MaxRoot ; root += 1)
  5601. {
  5602. CFusionRegKey regKey;
  5603. CFusionRegKey inprocServerKey;
  5604. CStringBuffer stringBuffer;
  5605. CFusionRegKey numMethodsKey;
  5606. CFusionRegKey proxyStubClsidKey;
  5607. DWORD dwSize = 0;
  5608. DWORD dwType = 0;
  5609. CFusionRegKey rootKey(FusionTestpHkeyRoots[root]);
  5610. IFW32FALSE_EXIT(Win32Append(stringBuffer, FusionTestpStringRoots[p->Type][root]));
  5611. IFW32FALSE_EXIT(Win32Append(stringBuffer, p->Guid));
  5612. switch (Mode)
  5613. {
  5614. case FUSIONTESTP_REG_DELETE:
  5615. case FUSIONTESTP_REG_BACKUP:
  5616. rootKey.OpenSubKey(regKey, stringBuffer);
  5617. break;
  5618. case FUSIONTESTP_REG_RESTORE:
  5619. IFW32FALSE_EXIT(rootKey.OpenOrCreateSubKey(regKey, stringBuffer));
  5620. break;
  5621. }
  5622. if (regKey != regKey.GetInvalidValue())
  5623. {
  5624. switch (Mode)
  5625. {
  5626. case FUSIONTESTP_REG_BACKUP:
  5627. p->Root = root;
  5628. break;
  5629. case FUSIONTESTP_REG_DELETE:
  5630. case FUSIONTESTP_REG_RESTORE:
  5631. break;
  5632. }
  5633. switch (p->Type)
  5634. {
  5635. case FUSIONTESTP_REG_TYPE_CLASS:
  5636. switch (Mode)
  5637. {
  5638. case FUSIONTESTP_REG_BACKUP:
  5639. #define FusionTestpQueryRegString(hkey, name, value) \
  5640. do { dwSize = sizeof(value); \
  5641. RegQueryValueExW(hkey, name, NULL, &dwType, reinterpret_cast<BYTE*>(value), &dwSize); \
  5642. } while(false)
  5643. if (regKey.OpenSubKey(inprocServerKey, L"InprocServer32"))
  5644. {
  5645. FusionTestpQueryRegString(inprocServerKey, NULL, p->InprocServerFilePath);
  5646. FusionTestpQueryRegString(inprocServerKey, L"ThreadingModel", p->ThreadingModel);
  5647. }
  5648. break;
  5649. case FUSIONTESTP_REG_RESTORE:
  5650. if (regKey.OpenOrCreateSubKey(inprocServerKey, L"InprocServer32"))
  5651. {
  5652. #define FusionTestpRegStringSize(x) static_cast<ULONG>(((wcslen(x) + 1)*sizeof((x)[0])))
  5653. #define FusionTestpSetRegString(hkey, name, value) \
  5654. do { if (value[0] != 0) \
  5655. RegSetValueExW(hkey, name, NULL, REG_SZ, reinterpret_cast<const BYTE*>(value), FusionTestpRegStringSize(value)); \
  5656. } while(false)
  5657. FusionTestpSetRegString(inprocServerKey, NULL, p->InprocServerFilePath);
  5658. FusionTestpSetRegString(inprocServerKey, L"ThreadingModel", p->ThreadingModel);
  5659. }
  5660. break;
  5661. case FUSIONTESTP_REG_DELETE:
  5662. break;
  5663. }
  5664. break;
  5665. case FUSIONTESTP_REG_TYPE_INTERFACE:
  5666. switch (Mode)
  5667. {
  5668. case FUSIONTESTP_REG_BACKUP:
  5669. FusionTestpQueryRegString(regKey, NULL, p->InterfaceName);
  5670. if (regKey.OpenSubKey(numMethodsKey, L"NumMethods"))
  5671. FusionTestpQueryRegString(numMethodsKey, NULL, p->NumMethods);
  5672. if (regKey.OpenSubKey(proxyStubClsidKey, L"ProxyStubClsid32"))
  5673. FusionTestpQueryRegString(proxyStubClsidKey, NULL, p->ProxyStubClsid);
  5674. break;
  5675. case FUSIONTESTP_REG_RESTORE:
  5676. FusionTestpSetRegString(regKey, NULL, p->InterfaceName);
  5677. if (regKey.OpenOrCreateSubKey(numMethodsKey, L"NumMethods"))
  5678. FusionTestpSetRegString(numMethodsKey, NULL, p->NumMethods);
  5679. if (regKey.OpenOrCreateSubKey(proxyStubClsidKey, L"ProxyStubClsid32"))
  5680. FusionTestpSetRegString(proxyStubClsidKey, NULL, p->ProxyStubClsid);
  5681. case FUSIONTESTP_REG_DELETE:
  5682. break;
  5683. }
  5684. break;
  5685. }
  5686. switch (Mode)
  5687. {
  5688. case FUSIONTESTP_REG_DELETE:
  5689. regKey.DestroyKeyTree();
  5690. break;
  5691. case FUSIONTESTP_REG_BACKUP:
  5692. case FUSIONTESTP_REG_RESTORE:
  5693. break;
  5694. }
  5695. break;
  5696. }
  5697. }
  5698. }
  5699. FN_EPILOG
  5700. }
  5701. #if 0 // Use CoWaitForMultipleHandles instead, it is much safer because it only
  5702. // pumps particular messages.
  5703. void FusionTestpPumpMessages()
  5704. {
  5705. MSG msg;
  5706. BOOL bRet;
  5707. while ((bRet = ::GetMessageW(&msg, NULL, 0, 0)) != 0)
  5708. {
  5709. if (bRet == -1)
  5710. return;
  5711. else
  5712. {
  5713. ::TranslateMessage(&msg);
  5714. if (::IsWindowUnicode(msg.hwnd))
  5715. ::DispatchMessageW(&msg);
  5716. else
  5717. ::DispatchMessage(&msg);
  5718. }
  5719. }
  5720. }
  5721. #endif
  5722. HMODULE FusionTestpHmoduleFromComObject(IUnknown* unk)
  5723. {
  5724. void** ppv = reinterpret_cast<void**>(unk);
  5725. void* pv = *ppv;
  5726. MEMORY_BASIC_INFORMATION MemBasicInfo = { 0 };
  5727. SIZE_T dw = 0;
  5728. if ((dw = Kernel32.VirtualQuery(pv, &MemBasicInfo, sizeof(MemBasicInfo))) == 0
  5729. || (dw < RTL_SIZEOF_THROUGH_FIELD(MEMORY_BASIC_INFORMATION, BaseAddress)))
  5730. {
  5731. ::Trace("VirtualQuery(%p) failed %lu\n", pv, ::GetLastError());
  5732. return NULL;
  5733. }
  5734. return reinterpret_cast<HMODULE>(MemBasicInfo.AllocationBase);
  5735. }
  5736. DWORD WINAPI FusionTestpMfcCreateAndMarshalThreadMain(LPVOID pvShouldBeAbleToMarshal)
  5737. {
  5738. BOOL Success = FALSE;
  5739. FN_PROLOG_WIN32(Success);
  5740. HRESULT hr = 0;
  5741. const bool ShouldBeAbleToMarshal = (pvShouldBeAbleToMarshal != NULL ? true : false);
  5742. Ole32.CoInitialize(NULL);
  5743. //
  5744. // For each interface, make sure we can unmarshal at least one object.
  5745. //
  5746. for (ULONG InterfaceIndex = 0 ; InterfaceIndex != NUMBER_OF(::FusionTestpMfcRegData) ; InterfaceIndex += 1)
  5747. {
  5748. FUSIONTESTP_REG_DATA* const pi = &::FusionTestpMfcRegData[InterfaceIndex];
  5749. switch (pi->Type)
  5750. {
  5751. case FUSIONTESTP_REG_TYPE_CLASS:
  5752. continue;
  5753. case FUSIONTESTP_REG_TYPE_INTERFACE:
  5754. IID InterfaceId = { 0 };
  5755. FUSIONTESTP_PLAIN_COM_POINTER(IUnknown) InterfaceIntoObjectInAnotherThread = NULL;
  5756. IFCOMFAILED_EXIT(hr = Ole32.IIDFromString(const_cast<PWSTR>(pi->Guid), &InterfaceId));
  5757. // nested loop..
  5758. for (ULONG ClassIndex = 0 ;
  5759. ClassIndex != NUMBER_OF(::FusionTestpMfcRegData) ;
  5760. ClassIndex += 1)
  5761. {
  5762. CLSID ClassId = { 0 };
  5763. FUSIONTESTP_REG_DATA* const pc = &::FusionTestpMfcRegData[ClassIndex];
  5764. switch (pc->Type)
  5765. {
  5766. case FUSIONTESTP_REG_TYPE_INTERFACE:
  5767. continue;
  5768. case FUSIONTESTP_REG_TYPE_CLASS:
  5769. WCHAR ModulePathInOtherThread[MAX_PATH];
  5770. ModulePathInOtherThread[0] = 0;
  5771. ASSERT(pc->GlobalInterfaceTableCookie != 0);
  5772. IFCOMFAILED_EXIT(hr = Ole32.CLSIDFromString(const_cast<PWSTR>(pc->Guid), &ClassId));
  5773. hr = g.GlobalInterfaceTable->GetInterfaceFromGlobal(
  5774. pc->GlobalInterfaceTableCookie, InterfaceId,
  5775. reinterpret_cast<void**>(&InterfaceIntoObjectInAnotherThread));
  5776. if (SUCCEEDED(hr))
  5777. {
  5778. IFW32FALSE_EXIT(Kernel32.GetModuleFileNameW(
  5779. ::FusionTestpHmoduleFromComObject(InterfaceIntoObjectInAnotherThread),
  5780. ModulePathInOtherThread, NUMBER_OF(ModulePathInOtherThread)));
  5781. }
  5782. if (SUCCEEDED(hr) && ShouldBeAbleToMarshal)
  5783. {
  5784. Trace("%s SUCCESSfully marshaled interface %ls on class %ls using proxy/stub in %ls\n",
  5785. __FUNCTION__, pi->Name, pc->Name, ModulePathInOtherThread);
  5786. g.Successes += 1;
  5787. }
  5788. else if (SUCCEEDED(hr) && !ShouldBeAbleToMarshal)
  5789. {
  5790. // unexpected success -> ERROR
  5791. Trace("%s FAILED to fail to marshal interface %ls on class %ls (using proxy/stub in %ls)\n",
  5792. __FUNCTION__, pi->Name, pc->Name, ModulePathInOtherThread);
  5793. g.Failures += 1;
  5794. }
  5795. else if (FAILED(hr) && ShouldBeAbleToMarshal)
  5796. {
  5797. // keep looping, try other objects
  5798. }
  5799. else if (FAILED(hr) && !ShouldBeAbleToMarshal)
  5800. {
  5801. // keep looping, make sure none succeed
  5802. //::Trace("%s OK Unable to marshal interface %ls (%ls) 0x%lx (fac 0x%lx code 0x%lx)\n", __FUNCTION__, pi->Name, pi->Guid, hr, HRESULT_FACILITY(hr), HRESULT_CODE(hr));
  5803. }
  5804. break;
  5805. }
  5806. if (InterfaceIntoObjectInAnotherThread != NULL && ShouldBeAbleToMarshal)
  5807. {
  5808. // one successful unmarshal is enough
  5809. break;
  5810. }
  5811. }
  5812. // use the nullness of InterfaceIntoObjectInAnotherThread as a summary of the loop
  5813. if (InterfaceIntoObjectInAnotherThread == NULL && ShouldBeAbleToMarshal)
  5814. {
  5815. ::Trace("%s FAILURE Unable to marshal interface %ls (%ls)\n", __FUNCTION__, pi->Name, pi->Guid);
  5816. g.Failures += 1;
  5817. }
  5818. else if (InterfaceIntoObjectInAnotherThread == NULL && !ShouldBeAbleToMarshal)
  5819. {
  5820. ::Trace("%s GOOD Unable to marshal interface %ls without actctx as expected\n", __FUNCTION__, pi->Name);
  5821. g.Successes += 1;
  5822. }
  5823. break;
  5824. }
  5825. }
  5826. Ole32.CoUninitialize();
  5827. FN_EPILOG
  5828. }
  5829. BOOL TestMfcCreateAndMarshal()
  5830. {
  5831. BOOL Success = FALSE;
  5832. FN_PROLOG_WIN32(Success);
  5833. ULONG i = 0;
  5834. HRESULT hr = 0;
  5835. HANDLE ThreadHandle = 0;
  5836. DWORD Ignored = 0;
  5837. CFusionActCtxHandle ToolsCrtActCtxHandle;
  5838. ::FusionTestpEnumerateRegistryData(::FusionTestpMfcRegData, NUMBER_OF(::FusionTestpMfcRegData), FUSIONTESTP_REG_BACKUP);
  5839. ::FusionTestpEnumerateRegistryData(::FusionTestpMfcRegData, NUMBER_OF(::FusionTestpMfcRegData), FUSIONTESTP_REG_DELETE);
  5840. Ole32.CoInitialize(NULL);
  5841. //
  5842. // Verify that we cannot create any of the classes.
  5843. //
  5844. for (i = 0 ; i != NUMBER_OF(::FusionTestpMfcRegData) ; i += 1)
  5845. {
  5846. CSmartRef<IUnknown> unk;
  5847. CLSID ClassId = { 0 };
  5848. FUSIONTESTP_REG_DATA* const p = &::FusionTestpMfcRegData[i];
  5849. switch (p->Type)
  5850. {
  5851. case FUSIONTESTP_REG_TYPE_INTERFACE:
  5852. break;
  5853. case FUSIONTESTP_REG_TYPE_CLASS:
  5854. IFCOMFAILED_EXIT(hr = Ole32.CLSIDFromString(const_cast<PWSTR>(p->Guid), &ClassId));
  5855. hr = Ole32.CoCreateInstance(ClassId, NULL, CLSCTX_INPROC_SERVER, IID_IUnknown, reinterpret_cast<void**>(&unk));
  5856. if (SUCCEEDED(hr))
  5857. {
  5858. ::Trace("%s BAD, no registry, no actctx CoCreate(%ls) SUCCEEDED, not expected\n", __FUNCTION__, p->Name);
  5859. g.Failures += 1;
  5860. }
  5861. else
  5862. {
  5863. ::Trace("%s GOOD, no registry, no actctx CoCreate(%ls) FAILed 0x%lx, as expected\n", __FUNCTION__, p->Name, hr);
  5864. g.Successes += 1;
  5865. }
  5866. break;
  5867. }
  5868. }
  5869. //
  5870. // Create and activate the context.
  5871. //
  5872. ToolsCrtActCtxHandle = ::CreateActivationContextFromStringW(ToolsCrtManifest);
  5873. if (ToolsCrtActCtxHandle == INVALID_HANDLE_VALUE)
  5874. ::Trace("CreateActCtx(WindowsCrtManifest %p) failed %ld\n", WindowsCrtManifest, ::GetLastError());
  5875. {
  5876. CFusionActCtxScope ToolsCrtActCtxScope;
  5877. if (!ToolsCrtActCtxScope.Win32Activate(ToolsCrtActCtxHandle))
  5878. ::Trace("Activate(ToolsCrtActCtxHandle %p) failed %ld\n", ToolsCrtActCtxHandle, ::GetLastError());
  5879. //
  5880. // Now create each class and print the .dll it came from.
  5881. // And put it in the global interface table for later unmarshalling.
  5882. //
  5883. IFCOMFAILED_EXIT(hr = Ole32.CoCreateInstance(CLSID_StdGlobalInterfaceTable,NULL, CLSCTX_INPROC_SERVER,
  5884. IID_IGlobalInterfaceTable, reinterpret_cast<void**>(&g.GlobalInterfaceTable)));
  5885. for (i = 0 ; i != NUMBER_OF(::FusionTestpMfcRegData) ; i += 1)
  5886. {
  5887. CLSID ClassId = { 0 };
  5888. FUSIONTESTP_REG_DATA* const p = &::FusionTestpMfcRegData[i];
  5889. //
  5890. // We are not supposed to be able to cocreate this here.
  5891. //
  5892. if (FusionpStrCmpI(p->Guid, OLEAUT_MARSHALER_CLSID_STRING) == 0)
  5893. continue;
  5894. switch (p->Type)
  5895. {
  5896. case FUSIONTESTP_REG_TYPE_INTERFACE:
  5897. break;
  5898. case FUSIONTESTP_REG_TYPE_CLASS:
  5899. IFCOMFAILED_EXIT(hr = Ole32.CLSIDFromString(const_cast<PWSTR>(p->Guid), &ClassId));
  5900. hr = Ole32.CoCreateInstance(ClassId, NULL, CLSCTX_INPROC_SERVER, IID_IUnknown,
  5901. reinterpret_cast<void**>(&p->CoCreatedObject));
  5902. if (FAILED(hr))
  5903. {
  5904. Trace("%s Failure: CoCreate(%ls) FAILED\n", __FUNCTION__, p->Name);
  5905. g.Failures += 1;
  5906. }
  5907. else
  5908. {
  5909. WCHAR ComObjectModule[MAX_PATH];
  5910. ComObjectModule[0] = 0;
  5911. IFW32FALSE_EXIT(Kernel32.GetModuleFileNameW(
  5912. ::FusionTestpHmoduleFromComObject(p->CoCreatedObject), ComObjectModule, NUMBER_OF(ComObjectModule)));
  5913. Trace("%s SUCCESSfully cocreated %p of type %ls from %ls with actctx influence\n",
  5914. __FUNCTION__, p->CoCreatedObject, p->Name, ComObjectModule);
  5915. g.Successes += 1;
  5916. #if 0
  5917. //
  5918. // Put it in the global interface table for later marshalling.
  5919. // It does not make sense to use IUnknown here, because ole32 can always
  5920. // marshal IUnknown itself without any proxy/stubs found via the
  5921. // registry or fusion (see also my special message pumper in vsee that
  5922. // takes advantage of this feature...)
  5923. //
  5924. IFW32FALSE_EXIT(
  5925. FusionTestpDynamicallyFindAnyInterfaceIntoObjectExceptIUnknown(
  5926. p->CoCreatedObject,
  5927. ::FusionTestpMfcRegData,
  5928. RTL_NUMBER_OF(::FusionTestpMfcRegData),
  5929. p->InterfaceIntoObjectInCreatingThread,
  5930. p->InterfaceIdOfObject
  5931. ));
  5932. IFCOMFAILED_EXIT(hr = g.GlobalInterfaceTable->RegisterInterfaceInGlobal(
  5933. p->InterfaceIntoObjectInCreatingThread,
  5934. p->InterfaceIdOfObject,
  5935. &p->GlobalInterfaceTableCookie
  5936. ));
  5937. #else
  5938. //
  5939. // It'll still have to look for the proxy/stub at unmarshal time. This is fine.
  5940. //
  5941. IFCOMFAILED_EXIT(hr = g.GlobalInterfaceTable->RegisterInterfaceInGlobal(
  5942. p->CoCreatedObject,
  5943. IID_IUnknown,
  5944. &p->GlobalInterfaceTableCookie
  5945. ));
  5946. #endif
  5947. }
  5948. break;
  5949. }
  5950. }
  5951. }
  5952. {
  5953. CFusionActCtxScope ToolsCrtActCtxScope;
  5954. if (!ToolsCrtActCtxScope.Win32Activate(ToolsCrtActCtxHandle))
  5955. ::Trace("Activate(ToolsCrtActCtxHandle %p) failed %ld\n", ToolsCrtActCtxHandle, ::GetLastError());
  5956. //
  5957. // try marshalling with the actctx activated, it should work (not NULL => expected success==TRUE)
  5958. //
  5959. ThreadHandle = CreateThread(NULL, 0, FusionTestpMfcCreateAndMarshalThreadMain, &Ignored, 0, &Ignored);
  5960. CoWaitForMultipleHandles(0, INFINITE, 1, &ThreadHandle, &Ignored);
  5961. CloseHandle(ThreadHandle);
  5962. }
  5963. #if 0
  5964. //
  5965. // If interfaces are _really_never_ changed, (but doesn't Fusion let you violate that?),
  5966. // this test case isn't valid. COM does caching and prefills caches when you may not expect
  5967. // (like when you put stuff in the GlobalInterfaceTable), and it does not invalidate its caches
  5968. // because of actctx pushes and pops.
  5969. //
  5970. {
  5971. //
  5972. // try marshalling without the actctx activated, it should NOT work (NULL => expected success==FALSE)
  5973. //
  5974. ThreadHandle = CreateThread(NULL, 0, FusionTestpMfcCreateAndMarshalThreadMain, NULL, 0, &Ignored);
  5975. CoWaitForMultipleHandles(0, INFINITE, 1, &ThreadHandle, &Ignored);
  5976. CloseHandle(ThreadHandle);
  5977. }
  5978. #endif
  5979. Ole32.CoUninitialize();
  5980. //::FusionTestpEnumerateRegistryData(::FusionTestpMfcRegData, NUMBER_OF(::FusionTestpMfcRegData), FUSIONTESTP_REG_RESTORE);
  5981. FN_EPILOG
  5982. }
  5983. void TestAtlCreate()
  5984. {
  5985. ::FusionTestpEnumerateRegistryData(FusionTestpAtlRegData, NUMBER_OF(FusionTestpAtlRegData), FUSIONTESTP_REG_BACKUP);
  5986. ::FusionTestpEnumerateRegistryData(FusionTestpAtlRegData, NUMBER_OF(FusionTestpAtlRegData), FUSIONTESTP_REG_DELETE);
  5987. ::FusionTestpEnumerateRegistryData(FusionTestpAtlRegData, NUMBER_OF(FusionTestpAtlRegData), FUSIONTESTP_REG_RESTORE);
  5988. }
  5989. BOOL TestPrivateSha1Impl(
  5990. PCWSTR pcwszDirName
  5991. )
  5992. {
  5993. FN_PROLOG_WIN32
  5994. CFusionArray<BYTE> rgbShaState;
  5995. CFusionFile ffInputFile;
  5996. BYTE bChunkletBuffer[4096];
  5997. CSmallStringBuffer sbHashedString;
  5998. DWORD dwReadData;
  5999. HCRYPTPROV hProvider;
  6000. HCRYPTHASH hHash;
  6001. CFusionHash fHashObject;
  6002. IFW32FALSE_EXIT(fHashObject.Win32Initialize(CALG_SHA1));
  6003. IFW32FALSE_EXIT(ffInputFile.Win32CreateFile(
  6004. pcwszDirName,
  6005. GENERIC_READ,
  6006. FILE_SHARE_READ,
  6007. OPEN_EXISTING));
  6008. IFW32FALSE_EXIT(CryptAcquireContextW(
  6009. &hProvider,
  6010. NULL,
  6011. NULL,
  6012. PROV_RSA_FULL,
  6013. CRYPT_SILENT | CRYPT_VERIFYCONTEXT ));
  6014. IFW32FALSE_EXIT(CryptCreateHash(
  6015. hProvider,
  6016. CALG_SHA1,
  6017. 0,
  6018. 0,
  6019. &hHash ));
  6020. do
  6021. {
  6022. IFW32FALSE_EXIT(::ReadFile(
  6023. ffInputFile,
  6024. bChunkletBuffer,
  6025. sizeof(bChunkletBuffer),
  6026. &dwReadData,
  6027. NULL));
  6028. IFW32FALSE_EXIT(fHashObject.Win32HashData(bChunkletBuffer, dwReadData));
  6029. IFW32FALSE_EXIT(CryptHashData(hHash, bChunkletBuffer, dwReadData, 0));
  6030. }
  6031. while ( dwReadData != 0 );
  6032. IFW32FALSE_EXIT(fHashObject.Win32GetValue(rgbShaState));
  6033. wprintf(L"%ls (private) hashed to ", pcwszDirName);
  6034. for ( SIZE_T n = 0; n < rgbShaState.GetSize(); n++ )
  6035. {
  6036. wprintf(L"%02x", rgbShaState[n]);
  6037. }
  6038. IFW32FALSE_EXIT(CryptGetHashParam(
  6039. hHash,
  6040. HP_HASHVAL,
  6041. bChunkletBuffer,
  6042. &(dwReadData = sizeof(bChunkletBuffer)),
  6043. 0));
  6044. wprintf(L"\n%ls (regular) hashed to ", pcwszDirName);
  6045. for ( SIZE_T n = 0; n < dwReadData; n++ )
  6046. {
  6047. wprintf(L"%02x", bChunkletBuffer[n]);
  6048. }
  6049. IFW32FALSE_EXIT(CryptReleaseContext(hProvider, 0));
  6050. FN_EPILOG
  6051. }
  6052. void TestAlignment()
  6053. {
  6054. CCleanupBase* p = reinterpret_cast<CCleanupBase*>(ULONG_PTR(0xffff0000));
  6055. SINGLE_LIST_ENTRY* q = p;
  6056. printf("%p %Ix\n", q, ULONG_PTR(q) % 16);
  6057. }
  6058. void TestCreateActCtx_PE_flags0()
  6059. {
  6060. WCHAR SyssetupDll[MAX_PATH * 2];
  6061. ACTCTXW ActCtx = {sizeof(ActCtx)};
  6062. CFusionActCtxHandle ActCtxHandle;
  6063. GetSystemDirectoryW(SyssetupDll, MAX_PATH);
  6064. wcscat(SyssetupDll, L"\\syssetup.dll");
  6065. ActCtx.lpSource = SyssetupDll;
  6066. printf("%s\n", ActCtxHandle.Win32Create(&ActCtx) ? "true" : "false");
  6067. }
  6068. void
  6069. TestUninstall(
  6070. PCWSTR ManifestPath,
  6071. PCWSTR ReferenceString
  6072. )
  6073. {
  6074. SXS_UNINSTALLW UninstallParameters = {sizeof(UninstallParameters)};
  6075. SXS_INSTALL_REFERENCEW Reference = {sizeof(Reference)};
  6076. PSXS_UNINSTALL_W_ROUTINE Uninstall = NULL;
  6077. PSXS_QUERY_MANIFEST_INFORMATION QueryManifestInformation;
  6078. BYTE ManifestInformationBuffer[1UL << 16];
  6079. PSXS_MANIFEST_INFORMATION_BASIC ManifestBasicInfo = reinterpret_cast<PSXS_MANIFEST_INFORMATION_BASIC>(&ManifestInformationBuffer);
  6080. DWORD Disposition = 0;
  6081. BOOL Success = FALSE;
  6082. LoadSxs();
  6083. GetSxsProc("SxsUninstallW", &Uninstall);
  6084. GetSxsProc("SxsQueryManifestInformation", &QueryManifestInformation);
  6085. Success = QueryManifestInformation(0, ManifestPath,
  6086. SXS_QUERY_MANIFEST_INFORMATION_INFOCLASS_BASIC, 0, sizeof(ManifestInformationBuffer),
  6087. ManifestBasicInfo, NULL);
  6088. printf("QueryManifestInformation(%ls)->(%ls, %ls)\n", ManifestPath, ManifestBasicInfo->lpIdentity, ManifestBasicInfo->lpShortName);
  6089. UninstallParameters.dwFlags |= SXS_UNINSTALL_FLAG_REFERENCE_VALID;
  6090. UninstallParameters.lpInstallReference = &Reference;
  6091. UninstallParameters.lpAssemblyIdentity = ManifestBasicInfo->lpIdentity;
  6092. Reference.lpIdentifier = ReferenceString;
  6093. Reference.guidScheme = SXS_INSTALL_REFERENCE_SCHEME_OPAQUESTRING;
  6094. Success = Uninstall(&UninstallParameters, &Disposition);
  6095. printf("TestUninstall(%ls, %ls) : %s, 0x%lx\n", ManifestPath, ReferenceString, Success ? "true" : "false", Disposition);
  6096. }
  6097. BOOL
  6098. TestNewSxsInstallAPI(
  6099. PCWSTR pcwszManifest
  6100. )
  6101. {
  6102. BOOL fSuccess = FALSE;
  6103. PSXS_INSTALL_W sxsInstallW = NULL;
  6104. PSXS_UNINSTALL_ASSEMBLYW sxsUninstallW = NULL;
  6105. SXS_INSTALLW Info = {sizeof(Info)};
  6106. SXS_INSTALL_REFERENCEW Reference = {sizeof(Reference)};
  6107. SXS_UNINSTALLW Uninstall = {sizeof(Uninstall)};
  6108. DWORD dwDisposition;
  6109. Info.dwFlags = SXS_INSTALL_FLAG_REPLACE_EXISTING |
  6110. SXS_INSTALL_FLAG_REFERENCE_VALID |
  6111. SXS_INSTALL_FLAG_CODEBASE_URL_VALID |
  6112. SXS_INSTALL_FLAG_LOG_FILE_NAME_VALID;
  6113. Info.lpManifestPath = pcwszManifest;
  6114. Info.lpCodebaseURL = Info.lpManifestPath;
  6115. Info.lpReference = &Reference;
  6116. Info.lpLogFileName = L"c:\\thelogfile";
  6117. DWORD dwAttribute = GetFileAttributesW(pcwszManifest);
  6118. if ( dwAttribute == 0xffffffff) // non-exist
  6119. goto Exit;
  6120. if ( dwAttribute & FILE_ATTRIBUTE_DIRECTORY) // install from a directory recursively
  6121. {
  6122. Info.dwFlags |= SXS_INSTALL_FLAG_FROM_DIRECTORY_RECURSIVE;
  6123. }
  6124. Reference.guidScheme = SXS_INSTALL_REFERENCE_SCHEME_OPAQUESTRING;
  6125. Reference.lpIdentifier = L"Sxs installation";
  6126. LoadSxs();
  6127. GetSxsProc(SXS_INSTALL_W, &sxsInstallW);
  6128. GetSxsProc(SXS_UNINSTALL_ASSEMBLYW, &sxsUninstallW);
  6129. if (!(*sxsInstallW)(&Info))
  6130. {
  6131. goto Exit;
  6132. }
  6133. Uninstall.dwFlags = SXS_UNINSTALL_FLAG_USE_INSTALL_LOG;
  6134. Uninstall.lpInstallLogFile = L"c:\\thelogfile";
  6135. if (!(*sxsUninstallW)(&Uninstall, &dwDisposition))
  6136. {
  6137. goto Exit;
  6138. }
  6139. fSuccess = TRUE;
  6140. Exit:
  6141. if (!fSuccess)
  6142. {
  6143. fprintf(stderr, "%s failed!\n", __FUNCTION__);
  6144. return EXIT_FAILURE;
  6145. }
  6146. else
  6147. return EXIT_SUCCESS;
  6148. }
  6149. VOID
  6150. NTAPI
  6151. SimpleContextNotification(
  6152. IN ULONG NotificationType,
  6153. IN PACTIVATION_CONTEXT ActivationContext,
  6154. IN const VOID *ActivationContextData,
  6155. IN PVOID NotificationContext,
  6156. IN PVOID NotificationData,
  6157. IN OUT PBOOLEAN DisableNotification
  6158. )
  6159. {
  6160. switch (NotificationType)
  6161. {
  6162. case ACTIVATION_CONTEXT_NOTIFICATION_DESTROY:
  6163. RTL_SOFT_VERIFY(NT_SUCCESS(NtUnmapViewOfSection(NtCurrentProcess(), (PVOID) ActivationContextData)));
  6164. break;
  6165. default:
  6166. // Otherwise, we don't need to see this notification ever again.
  6167. *DisableNotification = TRUE;
  6168. break;
  6169. }
  6170. }
  6171. BOOL
  6172. MakeActCtxFromCurrentSxsDll(
  6173. PCWSTR pcwszFileName,
  6174. HANDLE *phActCtx
  6175. )
  6176. {
  6177. FN_PROLOG_WIN32;
  6178. SXS_GENERATE_ACTIVATION_CONTEXT_PARAMETERS Parameters = {0};
  6179. PACTIVATION_CONTEXT pContextCreated = NULL;
  6180. CStringBuffer AssemblyDirectory;
  6181. CFileStream SourceManifestStream;
  6182. PVOID pvMappedSection = NULL;
  6183. NTSTATUS status;
  6184. BOOL (WINAPI *pfnSxsGenerateActivationContext)(PSXS_GENERATE_ACTIVATION_CONTEXT_PARAMETERS Parameters);
  6185. *phActCtx = INVALID_HANDLE_VALUE;
  6186. LoadSxs();
  6187. GetSxsProc("SxsGenerateActivationContext", &pfnSxsGenerateActivationContext);
  6188. IFW32FALSE_EXIT(SourceManifestStream.OpenForRead(pcwszFileName, CImpersonationData(), FILE_SHARE_READ, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN));
  6189. Parameters.Manifest.Path = pcwszFileName;
  6190. Parameters.Manifest.PathType = ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE;
  6191. Parameters.Manifest.Stream = &SourceManifestStream;
  6192. IFW32FALSE_EXIT(AssemblyDirectory.Win32Assign(pcwszFileName, ::wcslen(pcwszFileName)));
  6193. AssemblyDirectory.RemoveLastPathElement();
  6194. Parameters.AssemblyDirectory = AssemblyDirectory;
  6195. Parameters.ProcessorArchitecture = 0;
  6196. Parameters.LangId = GetUserDefaultUILanguage();
  6197. IFW32FALSE_EXIT(pfnSxsGenerateActivationContext(&Parameters));
  6198. IFW32NULL_EXIT(pvMappedSection = MapViewOfFile(Parameters.SectionObjectHandle, FILE_MAP_READ, 0, 0, 0));
  6199. status = RtlCreateActivationContext(
  6200. 0,
  6201. pvMappedSection,
  6202. 0,
  6203. SimpleContextNotification,
  6204. NULL,
  6205. &pContextCreated);
  6206. if (!NT_SUCCESS(status)) {
  6207. ORIGINATE_WIN32_FAILURE_AND_EXIT(RtlCreateActivationContext, RtlNtStatusToDosError(status));
  6208. }
  6209. *phActCtx = pContextCreated;
  6210. FN_EPILOG;
  6211. }
  6212. BOOL SimpleTestFindAndUseSurrogateInformation(PCWSTR filename, PCWSTR GuidToDisplay)
  6213. {
  6214. FN_PROLOG_WIN32;
  6215. SXS_GENERATE_ACTIVATION_CONTEXT_PARAMETERS Parameters = {0};
  6216. BOOL (WINAPI *pfnSxsGenerateActivationContext)(PSXS_GENERATE_ACTIVATION_CONTEXT_PARAMETERS Parameters);
  6217. CFileStream SourceManifestStream;
  6218. CStringBuffer AssemblyDirectory;
  6219. BOOL fCreatedOk = false;
  6220. GUID GuidToFind;
  6221. LoadSxs();
  6222. GetSxsProc("SxsGenerateActivationContext", &pfnSxsGenerateActivationContext);
  6223. IFW32FALSE_EXIT(SxspParseGUID(GuidToDisplay, ::wcslen(GuidToDisplay), GuidToFind));
  6224. IFW32FALSE_EXIT(SourceManifestStream.OpenForRead(filename, CImpersonationData(), FILE_SHARE_READ, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN));
  6225. Parameters.Manifest.Path = filename;
  6226. Parameters.Manifest.PathType = ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE;
  6227. Parameters.Manifest.Stream = &SourceManifestStream;
  6228. IFW32FALSE_EXIT(AssemblyDirectory.Win32Assign(filename, ::wcslen(filename)));
  6229. AssemblyDirectory.RemoveLastPathElement();
  6230. Parameters.AssemblyDirectory = AssemblyDirectory;
  6231. Parameters.ProcessorArchitecture = 0;
  6232. Parameters.LangId = GetUserDefaultUILanguage();
  6233. fCreatedOk = pfnSxsGenerateActivationContext(&Parameters);
  6234. //
  6235. // Spiffy, we've got the thing.
  6236. //
  6237. if (fCreatedOk && (Parameters.SectionObjectHandle != INVALID_HANDLE_VALUE) && (Parameters.SectionObjectHandle != NULL))
  6238. {
  6239. PACTIVATION_CONTEXT pActivationContext = NULL;
  6240. NTSTATUS status;
  6241. ULONG_PTR ulCookie;
  6242. ACTCTX_SECTION_KEYED_DATA Data = { sizeof(Data) };
  6243. // PCACTIVATION_CONTEXT_DATA_CLR_SURROGATE pFoundData;
  6244. /*
  6245. status = RtlCreateActivationContext(
  6246. 0,
  6247. Parameters.SectionObjectHandle,
  6248. 0,
  6249. SimpleContextNotification,
  6250. NULL,
  6251. &pActivationContext);
  6252. */
  6253. if (ActivateActCtx(static_cast<HANDLE>(pActivationContext), &ulCookie))
  6254. {
  6255. status = FindActCtxSectionGuid(
  6256. 0,
  6257. NULL,
  6258. ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES,
  6259. &GuidToFind,
  6260. &Data);
  6261. DeactivateActCtx(0, ulCookie);
  6262. ReleaseActCtx(static_cast<HANDLE>(pActivationContext));
  6263. }
  6264. }
  6265. FN_EPILOG
  6266. }
  6267. void TestFindAndUseSurrogateInformation(PCWSTR pcwsz, PCWSTR GuidToDisplay)
  6268. {
  6269. ACTCTXW actctx = { sizeof(actctx) };
  6270. HANDLE hActCtx = INVALID_HANDLE_VALUE;
  6271. GUID GuidToFind;
  6272. ACTCTX_SECTION_KEYED_DATA Data = { sizeof(Data) };
  6273. PCACTIVATION_CONTEXT_DATA_CLR_SURROGATE pFoundData;
  6274. BOOL status;
  6275. ULONG_PTR ulCookie;
  6276. SxspParseGUID(GuidToDisplay, wcslen(GuidToDisplay), GuidToFind);
  6277. actctx.lpSource = pcwsz;
  6278. hActCtx = CreateActCtxW(&actctx);
  6279. if ((hActCtx == INVALID_HANDLE_VALUE) || (hActCtx == NULL))
  6280. {
  6281. printf("Sorry, can't find file %ls, error %d", pcwsz, ::GetLastError());
  6282. return;
  6283. }
  6284. ActivateActCtx(hActCtx, &ulCookie);
  6285. __try {
  6286. status = FindActCtxSectionGuid(
  6287. 0,
  6288. NULL,
  6289. ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES,
  6290. &GuidToFind,
  6291. &Data);
  6292. pFoundData = (PCACTIVATION_CONTEXT_DATA_CLR_SURROGATE)Data.lpData;
  6293. wprintf(L"The guid %ls maps to assembly '%.*ls', runtime version '%.*ls', module '%.*ls'\n",
  6294. GuidToDisplay,
  6295. pFoundData->TypeNameLength / 2,
  6296. (PCWSTR)(((PBYTE)pFoundData) + pFoundData->TypeNameOffset),
  6297. pFoundData->VersionLength / 2,
  6298. (PCWSTR)(((PBYTE)pFoundData) + pFoundData->VersionOffset));
  6299. }
  6300. __finally
  6301. {
  6302. if (ulCookie != 0)
  6303. DeactivateActCtx(0, ulCookie);
  6304. }
  6305. ReleaseActCtx(hActCtx);
  6306. }
  6307. BOOL
  6308. TestSxsExportedSurrogateStuff(
  6309. PCWSTR pcwszManifest,
  6310. PCWSTR pcwszWhat,
  6311. PCWSTR pcwszData
  6312. )
  6313. {
  6314. FN_PROLOG_WIN32;
  6315. PFN_SXS_FIND_CLR_CLASS_INFO pfnClrClass = NULL;
  6316. PFN_SXS_FIND_CLR_SURROGATE_INFO pfnClrSurrogate = NULL;
  6317. PFN_SXS_LOOKUP_CLR_GUID pfnClrLookup = NULL;
  6318. SIZE_T cbRequired = 0;
  6319. BOOL f = false;
  6320. PVOID pvTargetBuffer = NULL;
  6321. PCSXS_CLR_SURROGATE_INFORMATION pSurrogateInfo = NULL;
  6322. PCSXS_CLR_CLASS_INFORMATION pClassInfo = NULL;
  6323. CFusionActCtxHandle hActCtxCreated;
  6324. CFusionActCtxScope ActivationScope;
  6325. ACTCTXW ActCtxStruct = {sizeof(ActCtxStruct)};
  6326. LoadSxs();
  6327. GetSxsProc(SXS_FIND_CLR_SURROGATE_INFO, &pfnClrSurrogate);
  6328. GetSxsProc(SXS_FIND_CLR_CLASS_INFO, &pfnClrClass);
  6329. GetSxsProc(SXS_LOOKUP_CLR_GUID, &pfnClrLookup);
  6330. IFW32FALSE_EXIT(MakeActCtxFromCurrentSxsDll(pcwszManifest, &hActCtxCreated));
  6331. IFW32FALSE_EXIT(ActivationScope.Win32Activate(hActCtxCreated));
  6332. if (lstrcmpiW(pcwszWhat, L"clrprogid") == 0)
  6333. {
  6334. f = pfnClrClass(
  6335. SXS_FIND_CLR_CLASS_SEARCH_PROGID | SXS_FIND_CLR_CLASS_GET_ALL,
  6336. (PVOID)pcwszData,
  6337. hActCtxCreated,
  6338. NULL, 0, &cbRequired);
  6339. if (!f)
  6340. {
  6341. SIZE_T cbWritten = 0;
  6342. pvTargetBuffer = HeapAlloc(GetProcessHeap(), 0, cbRequired);
  6343. pfnClrClass(
  6344. SXS_FIND_CLR_CLASS_SEARCH_PROGID | SXS_FIND_CLR_CLASS_GET_ALL,
  6345. (PVOID)pcwszData,
  6346. hActCtxCreated,
  6347. pvTargetBuffer,
  6348. cbRequired,
  6349. &cbWritten);
  6350. pClassInfo = (PCSXS_CLR_CLASS_INFORMATION)pvTargetBuffer;
  6351. }
  6352. }
  6353. else if (lstrcmpiW(pcwszWhat, L"clrguid") == 0)
  6354. {
  6355. GUID ParsedGuid;
  6356. IFW32FALSE_EXIT(SxspParseGUID(pcwszData, wcslen(pcwszData), ParsedGuid));
  6357. f = pfnClrClass(
  6358. SXS_FIND_CLR_CLASS_SEARCH_GUID | SXS_FIND_CLR_CLASS_GET_ALL,
  6359. (PVOID)&ParsedGuid,
  6360. hActCtxCreated,
  6361. NULL, 0, &cbRequired);
  6362. if (!f)
  6363. {
  6364. SIZE_T cbWritten = 0;
  6365. pvTargetBuffer = HeapAlloc(GetProcessHeap(), 0, cbRequired);
  6366. pfnClrClass(
  6367. SXS_FIND_CLR_CLASS_SEARCH_GUID | SXS_FIND_CLR_CLASS_GET_ALL,
  6368. (PVOID)&ParsedGuid,
  6369. hActCtxCreated,
  6370. pvTargetBuffer, cbRequired, &cbWritten);
  6371. pClassInfo = (PCSXS_CLR_CLASS_INFORMATION)pvTargetBuffer;
  6372. }
  6373. }
  6374. else if (lstrcmpiW(pcwszWhat, L"lookup") == 0)
  6375. {
  6376. GUID ParsedGuid;
  6377. PCSXS_GUID_INFORMATION_CLR pGuidInfo = NULL;
  6378. IFW32FALSE_EXIT(SxspParseGUID(pcwszData, wcslen(pcwszData), ParsedGuid));
  6379. f = pfnClrLookup(
  6380. SXS_LOOKUP_CLR_GUID_FIND_ANY,
  6381. &ParsedGuid,
  6382. hActCtxCreated,
  6383. NULL,
  6384. 0,
  6385. &cbRequired);
  6386. if (!f)
  6387. {
  6388. SIZE_T cbWritten = 0;
  6389. pvTargetBuffer = HeapAlloc(GetProcessHeap(), 0, cbRequired);
  6390. f = pfnClrLookup(
  6391. SXS_LOOKUP_CLR_GUID_FIND_ANY,
  6392. &ParsedGuid,
  6393. hActCtxCreated,
  6394. pvTargetBuffer,
  6395. cbRequired,
  6396. &cbWritten);
  6397. pGuidInfo = (PCSXS_GUID_INFORMATION_CLR)pvTargetBuffer;
  6398. }
  6399. }
  6400. else if (lstrcmpiW(pcwszWhat, L"surrogate") == 0)
  6401. {
  6402. GUID ParsedGuid;
  6403. IFW32FALSE_EXIT(SxspParseGUID(pcwszData, wcslen(pcwszData), ParsedGuid));
  6404. f = pfnClrSurrogate(
  6405. SXS_FIND_CLR_SURROGATE_USE_ACTCTX | SXS_FIND_CLR_SURROGATE_GET_ALL,
  6406. &ParsedGuid,
  6407. hActCtxCreated,
  6408. NULL, 0, &cbRequired);
  6409. if (!f)
  6410. {
  6411. SIZE_T cbWritten = 0;
  6412. pvTargetBuffer = HeapAlloc(GetProcessHeap(), 0, cbRequired);
  6413. pfnClrSurrogate(
  6414. SXS_FIND_CLR_SURROGATE_USE_ACTCTX | SXS_FIND_CLR_SURROGATE_GET_ALL,
  6415. &ParsedGuid,
  6416. hActCtxCreated,
  6417. pvTargetBuffer, cbRequired, &cbWritten);
  6418. pSurrogateInfo = (PCSXS_CLR_SURROGATE_INFORMATION)pvTargetBuffer;
  6419. }
  6420. }
  6421. FN_EPILOG;
  6422. }