windows-nt/Source/XPSP1/NT/base/win32/fusion/tests/sxstest/sxstest.cpp
2020-09-26 16:20:57 +08:00

7414 lines
227 KiB
C++

#include "stdinc.h" // actually from dll\whistler directory
/*-----------------------------------------------------------------------------
Side X ("by") Side Test
-----------------------------------------------------------------------------*/
#include "nt.h"
#include "ntrtl.h"
#include "nturtl.h"
#include "windows.h"
#include "fusionlastwin32error.h"
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#pragma warning(push)
#pragma warning(disable: 4511)
#pragma warning(disable: 4512)
#pragma warning(disable: 4663)
#include <yvals.h>
#pragma warning(disable: 4663)
#include <string>
#include <deque>
#include <vector>
#pragma warning(pop)
#include "FusionBuffer.h"
#include "fusion.h"
#include "sxsasmname.h"
#include "util.h"
#include "filestream.cpp"
#include "sxsapi.h"
#include "fusiontrace.h"
#include "cresourcestream.cpp"
#include "cmemorystream.cpp"
#include "wintrust.h"
#include "softpub.h"
#include "perfclocking.h"
#include "strongname.h"
#include "fusionversion.h"
#include <setupapi.h>
#include <string>
#include "commctrl.h"
#include <algorithm>
#include "fusionsha1.h"
#include "cguid.h"
#include "winbasep.h"
#undef LoadLibraryA
#undef LoadLibraryW
#undef LoadLibraryExA
#undef LoadLibraryExW
#undef InitCommonControls
BOOL IamExe;
BOOL IamDll;
extern "C" { void (__cdecl * _aexit_rtn)(int); }
void __cdecl Trace(const char* FormatString, ...)
{
char buffer[2000];
va_list args;
va_start(args, FormatString);
_vsnprintf(buffer, RTL_NUMBER_OF(buffer), FormatString, args);
buffer[RTL_NUMBER_OF(buffer) - 1] = 0;
for (PSTR s = buffer ; *s != 0 ; )
{
PSTR t = strchr(s, '\n');
if (t != NULL)
*t = 0;
printf("stdout : %s\n", s);
OutputDebugStringA("debugger: ");
OutputDebugStringA(s);
OutputDebugStringA("\n");
if (t != NULL)
s = t + 1;
}
va_end(args);
}
typedef BOOL (WINAPI * PSXSPGENERATEMANIFESTPATHONASSEMBLYIDENTITY)(
PWSTR str, // input string, must have name, version, langid and processorarchitecture
PWSTR psz, // output string, like x86_cards_strongname,.......
SIZE_T * pCch, // IN : length of psz, OUT : used
PASSEMBLY_IDENTITY *ppAssemblyIdentity // could be NULL
);
/*-----------------------------------------------------------------------------
work around the fact that SxsHeap doesn't let us use a non debug operator new
-----------------------------------------------------------------------------*/
template <typename T>
class Allocator : public std::allocator<T>
{
public:
pointer allocate(size_type n, const void*)
{
return reinterpret_cast<pointer>(malloc(n * sizeof(T)));
}
char* _Charalloc(size_type n)
{
return reinterpret_cast<char*>(malloc(n));
}
void deallocate(void* p, size_type)
{
free(p);
}
};
#define SXSTEST_BEGIN_INSTALL (0x4000000000000000i64)
#define SXSTEST_INSTALL (0x2000000000000000i64)
#define SXSTEST_END_INSTALL (0x1000000000000000i64)
#define SXSTEST_INSTALL_MY_QUEUE (0x0800000000000000i64)
#define SXSTEST_INSTALL_SETUPAPI_QUEUE (0x0400000000000000i64)
#define SXSTEST_END_OF_FLAGS (0x0200000000000000i64)
#define SXSTEST_THREADS (0x0100000000000000i64)
#define SXSTEST_CREATEPROCESS (0x0080000000000000i64)
inline int PRINTABLE(int ch) { return isprint(ch) ? ch : '.'; }
void PrintIfAnyCriticalSectionsHeld(const char* file, int line, const char* function)
#define PrintIfAnyCriticalSectionsHeld() PrintIfAnyCriticalSectionsHeld(__FILE__, __LINE__, __FUNCTION__)
{
const DWORD dwLastError = ::GetLastError();
PTEB teb;
teb = NtCurrentTeb();
if (teb->CountOfOwnedCriticalSections != 0)
{
DbgPrint("%s(%d):%s teb->CountOfOwnedCriticalSections %d\n", file, line, function, teb->CountOfOwnedCriticalSections);
}
SetLastError(dwLastError);
}
static
VOID
PrintBlob(
FILE *pf,
PVOID Data,
SIZE_T Length,
PCWSTR PerLinePrefix
);
BOOL TestLeakMemory(DWORD Amount);
BOOL TestAssemblyProbing(int argc, wchar_t **argv, int *piNext);
BOOL TestDirectoryChangeWatcher(int argc, wchar_t **argv, int *piNext);
BOOL TestXMLParsing(int argc, wchar_t **argv, int *piNext);
BOOL TestMultiAct(int argc, wchar_t **argv);
BOOL TestManifestSchema(int argc, wchar_t **argv, int *piNext);
BOOL TestDirect(int argc, wchar_t **argv, int *piNext);
void TestWin32(wchar_t** argv);
BOOL TestAct(int argc, wchar_t **argv, int *piNext);
BOOL TestInstall(PCWSTR manifest, __int64 flags, DWORD beginInstallFlags, DWORD installFlags, DWORD endInstallFlags);
int TestDiffDir(PCWSTR dir1, PCWSTR dir2);
BOOL TestSearchPath(int argc, wchar_t** argv, int* piNext);
BOOL TestMSIInstall(int argc, wchar_t** argv, int* piNext);
int TestDirWalk(PCWSTR root, PWSTR filter);
BOOL TestLoadLibrary(int argc, wchar_t** argv, int* piNext);
int TestAssemblyName(VOID);
int TestPrecomiledManifest(PCWSTR szFileName);
int TestPCMTime(PCWSTR manifestFilename);
int TestCreateProcess(wchar_t** argv);
int TestCreateProcess2(wchar_t** argv);
BOOL TestInstallPrivateAssembly(int argc, wchar_t** argv, int* piNext);
BOOL TestManifestProbing(int argc, wchar_t** argv, int* piNext);
int TestCreateMultiLevelDirectory(PCWSTR dirs);
BOOL TestXMLDOM(PCWSTR xmlfilename);
BOOL TestFusionArray(PCWSTR, PCWSTR);
BOOL TestGeneratePathFromIdentityAttributeString(PCWSTR str);
BOOL TestRefreshAssembly(PCWSTR wsAssembly);
BOOL TestInstallWithInstallInfo(PCWSTR wsAssemblyManifest, PCWSTR wsReference);
BOOL TestOpeningStuff(PCWSTR wsSourceName, PCWSTR wsType, PCWSTR wsCount);
BOOL TestVerifyFileSignature(PCWSTR wsFilename);
BOOL TestInstallLikeWindowsSetup(PCWSTR szDirectory, PCWSTR szCodebase);
BOOL TestDumpContainedManifests(PCWSTR wsFilename);
BOOL TestGenerateStringWithIdenticalHash(WCHAR iString[33]);
BOOL TestAssemblyIdentityHash();
void TestInherit();
void TestNoInherit();
void TestEmpty();
BOOL TestMessagePerf(int argc, wchar_t **arg, int *piNext);
LRESULT CALLBACK TestMessagePerfWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
void TestTrickyMultipleAssemblyCacheItems(PCWSTR);
void TestSfcScanKickoff();
void GenerateStrongNameAndPublicKey(PCWSTR wsCertificate);
VOID TestCreateActctxLeakHandles(DWORD num);
BOOL TestSystemDefaultActivationContextGeneration();
BOOL TestAsyncIO(int argc, wchar_t **argv, int *piNext);
void TestRefCount();
void TestGuidSort();
void TestStringSort();
BOOL TestNewCatalogSignerThingy(PCWSTR pcwszCatalog);
void TestExeDll();
int TestThreadInheritLeak();
BOOL TestSxsSfcUI();
void TestGetModuleHandleEx();
void TestGetFullPathName(PCWSTR);
void TestCreateFile(PCWSTR);
void TestGetPathBaseName(LPCWSTR Path);
PCSTR PrintPathToString(RTL_PATH_TYPE);
void TestPathType(PCWSTR*);
void TestVersion();
void TestGetProcessImageFileName();
void TestErrorInfra();
void TestQueryActCtx();
void TestQueryActCtx2();
void Test64k();
void TestDotLocalSingleInstancing();
void TestCreateActCtx(int nCreations, wchar_t **rgCreations);
void TestCreateActctxLikeCreateProcess();
void TestCreateActctxAdminOverride();
void TestQueryManifestInformationBasic(PCWSTR pszManifest);
void TestCreateActctxWindowsShellManifest();
void TestCreateGlobalEvent();
void TestHandleLeaks(void);
void TestCRuntimeAsms(void);
BOOL TestMfcCreateAndMarshal(void);
void TestAtlCreate(void);
void TestAlignment(void);
BOOL TestPrivateSha1Impl(PCWSTR pcwszDirName);
BOOL TestNewSxsInstallAPI(PCWSTR pcwszManifest);
void TestImage(void);
void TestInterlockedAlignment(void);
void TestCreateActCtx_PE_flags0(void);
void TestUninstall(PCWSTR ManifestPath, PCWSTR ReferenceString);
PCWSTR GetLastErrorMessage();
BOOL SimpleTestFindAndUseSurrogateInformation(PCWSTR filename, PCWSTR GuidToDisplay);
BOOL TestSxsExportedSurrogateStuff(PCWSTR pcwszManifest, PCWSTR pcwszWhat, PCWSTR pcwszData);
DWORD LastError;
static void LoadSxs();
static int Main(int argc, wchar_t** argv);
static void SetLastOperation(const wchar_t* format, ...);
static const wchar_t* GetLastOperation(const wchar_t* format, ...);
static int Usage(const char* argv0);
template <typename PFN> void GetSxsProc(PCSTR name, PFN* ppfn);
template <typename PFN> void GetSxsProc(int name, PFN* ppfn);
SXSP_DEBUG_FUNCTION pfnSxspDebug = NULL;
BOOL ParseProcessorArchitecture(int argc, wchar_t** argv, int* piCurrent);
BOOL ParseLangId(int argc, wchar_t** argv, int* piCurrent);
PCWSTR FusionpThreadUnsafeGetLastWin32ErrorMessageW()
{
CSxsPreserveLastError ple;
static WCHAR LastErrorMessage[4096];
LastErrorMessage[0] = 0;
::FormatMessageW(
FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
::FusionpGetLastWin32Error(),
0,
LastErrorMessage,
RTL_NUMBER_OF(LastErrorMessage),
NULL);
if (LastErrorMessage[0] != 0)
{
PWSTR p = LastErrorMessage + ::StringLength(LastErrorMessage) - 1;
while (p != LastErrorMessage && (*p == '\n' || *p == '\r' || *p == ' ' || *p == '\t'))
{
*p-- = 0;
}
}
ple.Restore();
return LastErrorMessage;
}
void __stdcall ThrowLastError(DWORD error = ::GetLastError())
{
RaiseException(error, 0, 0, NULL);
//throw HRESULT_FROM_WIN32(error);
}
void __stdcall ThrowWin32(ULONG_PTR error = ::GetLastError())
{
ThrowLastError(static_cast<DWORD>(error));
}
void __stdcall CheckHresult(HRESULT hr)
{
if (FAILED(hr))
throw hr;
}
void SetDllBitInPeImage(PCWSTR Path)
/*++
.exes and .dlls are the same format except one bit in the headers distinguishes them.
--*/
{
CFusionFile File;
CFileMapping FileMapping;
CMappedViewOfFile MappedViewOfFile;
if (!File.Win32CreateFile(Path, GENERIC_READ | GENERIC_WRITE, 0, OPEN_EXISTING))
ThrowLastError();
if (!FileMapping.Win32CreateFileMapping(File, PAGE_READWRITE))
ThrowLastError();
if (!MappedViewOfFile.Win32MapViewOfFile(FileMapping, FILE_MAP_WRITE))
ThrowLastError();
PIMAGE_NT_HEADERS NtHeaders = RtlImageNtHeader(static_cast<PVOID>(MappedViewOfFile));
if (NtHeaders == NULL)
ThrowLastError(ERROR_BAD_EXE_FORMAT);
// This is correct for PE32 or PE32+.
NtHeaders->FileHeader.Characteristics |= IMAGE_FILE_DLL;
if (!MappedViewOfFile.Win32Close())
ThrowLastError();
if (!FileMapping.Win32Close())
ThrowLastError();
if (!File.Win32Close())
ThrowLastError();
}
PCSTR PrintPathToString(RTL_PATH_TYPE PathType)
{
switch (PathType)
{
#define X(x) case x: return #x;
X(RtlPathTypeUnknown)
X(RtlPathTypeUncAbsolute)
X(RtlPathTypeDriveAbsolute)
X(RtlPathTypeDriveRelative)
X(RtlPathTypeRooted)
X(RtlPathTypeRelative)
X(RtlPathTypeLocalDevice)
X(RtlPathTypeRootLocalDevice)
#undef X
default:
return "unknown";
}
}
void TestPathType(const PCWSTR* argv)
{
if (*argv != NULL)
{
while (*argv != NULL)
{
RTL_PATH_TYPE PathType = SxspDetermineDosPathNameType(*argv);
printf("%ls -> %s\n", *argv, PrintPathToString(PathType));
argv += 1;
}
}
else
{
const static PCWSTR args[] =
{
L"a",
L"\\a",
L"\\\\a",
L"\\\\\\a",
L"a:",
L"a:\\",
L"\\?",
L"\\.",
L"\\\\?",
L"\\\\.",
L"\\\\?\\",
L"\\\\.\\",
L"\\\\?\\a",
L"\\\\.\\a",
L"\\\\?\\a:",
L"\\\\.\\a:",
L"\\\\?\\a:\\",
L"\\\\.\\a:\\",
L"\\\\?\\unc",
L"\\\\.\\unc",
L"\\\\?\\unc\\",
L"\\\\.\\unc\\",
NULL
};
TestPathType(args);
}
}
class CUnknown : public IUnknown
{
public:
virtual HRESULT __stdcall QueryInterface(const IID& iid, void** ppv)
{
return E_NOINTERFACE;
}
virtual ULONG __stdcall AddRef()
{
return 1;
}
virtual ULONG __stdcall Release()
{
return 1;
}
};
struct G
{
HINSTANCE sxsDll;
USHORT wProcessorArchitecture;
LANGID wLangId;
HANDLE MainThread;
INT NumberOfThreads;
HANDLE Threads[MAXIMUM_WAIT_OBJECTS];
HANDLE ThreadExitEvent;
wchar_t lastOperation[256];
CUnknown unknown;
CSmartRef<IGlobalInterfaceTable> GlobalInterfaceTable;
//
// the start of some automation / record keeping..
//
ULONG Failures;
ULONG Successes;
} g;
const static struct
{
DWORD (WINAPI* GetModuleFileNameW)(HMODULE, LPWSTR, DWORD);
SIZE_T (WINAPI* VirtualQuery)(LPCVOID, PMEMORY_BASIC_INFORMATION, SIZE_T);
}
Kernel32 =
{
GetModuleFileNameW,
VirtualQuery
};
const static struct
{
HRESULT (WINAPI* IIDFromString)(LPOLESTR, LPIID);
HRESULT (WINAPI* CLSIDFromString)(LPOLESTR, LPIID);
HRESULT (WINAPI* CoCreateInstance)(REFCLSID, LPUNKNOWN, DWORD, REFIID, LPVOID*);
HRESULT (WINAPI* CoInitialize)(LPVOID);
void (WINAPI* CoUninitialize)();
}
Ole32 =
{
IIDFromString,
CLSIDFromString,
CoCreateInstance,
CoInitialize,
CoUninitialize
};
void
ManifestStringToTempFile(
PCWSTR ManifestString,
CBaseStringBuffer &rTempFilePath
)
{
CFusionFile File;
WCHAR xTempFilePath[MAX_PATH];
WCHAR TempDirectory[MAX_PATH];
const static WCHAR NativeUnicodeByteOrderMark = 0xfeff;
DWORD BytesWritten;
//if (!::GetTempPathW(NUMBER_OF(TempDirectory), TempDirectory))
// ThrowLastError();
::GetModuleFileNameW(NULL, TempDirectory, NUMBER_OF(TempDirectory));
*wcsrchr(TempDirectory, '\\') = 0;
::Trace("TempDirectory:%ls\n", TempDirectory);
if (!::GetTempFileNameW(TempDirectory, L"", 0, xTempFilePath))
::ThrowLastError();
rTempFilePath.Win32Assign(xTempFilePath, wcslen(xTempFilePath));
::Trace("xTempFilePath:%ls\n", xTempFilePath);
::Trace("TempFilePath:%ls\n", static_cast<PCWSTR>(xTempFilePath));
if (!File.Win32CreateFile(rTempFilePath, GENERIC_WRITE, 0, CREATE_ALWAYS))
::ThrowLastError();
if (!::WriteFile(File, &NativeUnicodeByteOrderMark, sizeof(NativeUnicodeByteOrderMark), &BytesWritten, NULL))
::ThrowLastError();
if (!::WriteFile(File, ManifestString, static_cast<DWORD>(sizeof(*ManifestString) * StringLength(ManifestString)), &BytesWritten, NULL))
::ThrowLastError();
}
HANDLE
CreateActivationContextFromStringW(
PCWSTR ManifestString
)
{
CStringBuffer TempFilePath;
::ManifestStringToTempFile(ManifestString, TempFilePath);
ACTCTXW ActivationContextCreate = { sizeof(ActivationContextCreate) };
ActivationContextCreate.lpSource = TempFilePath;
HANDLE ActivationContextHandle = ::CreateActCtxW(&ActivationContextCreate);
DWORD Error = ::GetLastError();
::DeleteFileW(TempFilePath);
if (ActivationContextHandle == INVALID_HANDLE_VALUE)
::ThrowLastError(Error);
return ActivationContextHandle;
}
int Usage(const wchar_t* argv0)
{
std::wstring strargv0 = argv0;
fprintf(stderr,
"%ls",
(
L"Usage: \n"
L" " + strargv0 + L" [install-flags] manifest-or-image-with-manifest-resource-path\n"
L" " + strargv0 + L" [-pa processor-architecture] [-langid langid] -d manifest-path ...\n"
L" " + strargv0 + L" [-pa processor-architecture] [-langid langid] -p manifest-path ...\n"
L" " + strargv0 + L" [-pa processor-architecture] [-langid langid] -w32 manifest-path ...\n"
L" " + strargv0 + L" [-pa processor-architecture] [-langid langid] -msi msi-script...\n"
L" " + strargv0 + L" -tcreateprocess ...\n"
L" " + strargv0 + L" -tsearchpath ...\n"
L" " + strargv0 + L" -tcreateprocess ...\n"
L" " + strargv0 + L" -tempty test pushing a special empty context ...\n"
L" " + strargv0 + L" -tinherit test the usual default inheritance ...\n"
L" " + strargv0 + L" -tnoinherit test the noinherit bit ...\n"
L" " + strargv0 + L" [-threads n] create n threads for some tests ...\n"
L" " + strargv0 + L" probably other choices, use the source\n"
L"\n"
L"install-flags:\n"
L" -i\n"
L" -install\n"
L" -install-my-queue\n"
L" -install-setupapi-queue\n"
L" -install-from-resource\n"
L" -install-move\n"
L" -install-my-queue\n"
L" -install-setupapi-queue [requires debugger]\n"
L" -install-from-resource\n"
).c_str()
);
return EXIT_FAILURE;
}
const wchar_t* GetLastOperation()
{
return g.lastOperation;
}
void SetLastOperation(const wchar_t* format, ...)
{
va_list args;
g.lastOperation[0] = 0;
g.lastOperation[NUMBER_OF(g.lastOperation) - 1] = 0;
va_start(args, format);
_vsnwprintf(g.lastOperation, NUMBER_OF(g.lastOperation) - 1, format, args);
va_end(args);
}
HANDLE DuplicateHandle(HANDLE handle)
{
HANDLE newHandle = NULL;
if (!DuplicateHandle(GetCurrentProcess(), handle, GetCurrentProcess(), &newHandle, 0, FALSE, DUPLICATE_SAME_ACCESS))
{
ThrowLastError();
}
return newHandle;
}
__int64 IsFlag(PCWSTR arg)
{
const static struct
{
WCHAR name[32];
__int64 value;
} flags[] =
{
{ L"i", SXSTEST_BEGIN_INSTALL},
{ L"install", SXSTEST_BEGIN_INSTALL},
{ L"install-my-queue", SXSTEST_INSTALL_MY_QUEUE },
{ L"install-setupapi-queue", SXSTEST_INSTALL_SETUPAPI_QUEUE },
{ L"install-from-resource", SXS_INSTALL_ASSEMBLY_FLAG_FROM_RESOURCE | SXSTEST_INSTALL},
{ L"install-move", SXS_INSTALL_ASSEMBLY_FLAG_MOVE | SXSTEST_INSTALL },
{ L"install-dir", SXS_INSTALL_ASSEMBLY_FLAG_FROM_DIRECTORY | SXSTEST_INSTALL},
{ L"install-dir-recursive", SXS_INSTALL_ASSEMBLY_FLAG_FROM_DIRECTORY_RECURSIVE | SXSTEST_INSTALL},
{ L"install-no-verify", SXS_INSTALL_ASSEMBLY_FLAG_NO_VERIFY | SXSTEST_INSTALL},
{ L"install-no-transact", SXS_INSTALL_ASSEMBLY_FLAG_NOT_TRANSACTIONAL | SXSTEST_INSTALL},
{ L"install-replace-existing", SXS_INSTALL_ASSEMBLY_FLAG_REPLACE_EXISTING | SXSTEST_INSTALL},
{ L"begin-install-replace-existing", SXS_BEGIN_ASSEMBLY_INSTALL_FLAG_REPLACE_EXISTING | SXSTEST_BEGIN_INSTALL},
{ L"begin-install-from-resource", SXS_BEGIN_ASSEMBLY_INSTALL_FLAG_FROM_RESOURCE | SXSTEST_BEGIN_INSTALL},
{ L"begin-install-move", SXS_BEGIN_ASSEMBLY_INSTALL_FLAG_MOVE | SXSTEST_BEGIN_INSTALL },
{ L"begin-install-dir", SXS_BEGIN_ASSEMBLY_INSTALL_FLAG_FROM_DIRECTORY | SXSTEST_BEGIN_INSTALL},
{ L"begin-install-dir-recursive", SXS_BEGIN_ASSEMBLY_INSTALL_FLAG_FROM_DIRECTORY_RECURSIVE | SXSTEST_BEGIN_INSTALL},
{ L"begin-install-no-verify", SXS_BEGIN_ASSEMBLY_INSTALL_FLAG_NO_VERIFY | SXSTEST_BEGIN_INSTALL},
{ L"begin-install-no-transact", SXS_BEGIN_ASSEMBLY_INSTALL_FLAG_NOT_TRANSACTIONAL | SXSTEST_BEGIN_INSTALL},
{ L"end-install-no-verify", SXS_END_ASSEMBLY_INSTALL_FLAG_NO_VERIFY | SXSTEST_END_INSTALL},
{ L"threads", SXSTEST_THREADS },
{ L"-", SXSTEST_END_OF_FLAGS }
};
if (*arg == '-')
{
arg += 1;
for (ULONG i = 0 ; i != NUMBER_OF(flags) ; ++i)
{
if (_wcsicmp(flags[i].name, arg) == 0)
return flags[i].value;
}
}
return 0;
}
DWORD __stdcall ThreadMain(PVOID)
{
//
// We run stuff in other threads via QueueUserAPC.
//
__try
{
WaitForSingleObjectEx(g.ThreadExitEvent, INFINITE, TRUE);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
#if DBG
if (IsDebuggerPresent())
{
FUSION_DEBUG_BREAK();
}
#endif
QueueUserAPC(ThrowWin32, g.MainThread, GetExceptionCode());
}
return 0;
}
void CreateThreads()
{
INT i;
g.MainThread = DuplicateHandle(GetCurrentThread());
g.ThreadExitEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
if (g.ThreadExitEvent == NULL)
{
ThrowLastError();
}
for (i = 0 ; i < g.NumberOfThreads ; i++)
{
g.Threads[i] = CreateThread(NULL, 0, ThreadMain, NULL, 0, NULL);
if (g.Threads[i] == NULL)
{
int error = ::GetLastError();
if (i > 2)
{
fprintf(stderr, "Only able to created %d threads, error=%d, continuing\n", i, error);
g.NumberOfThreads = i;
break;
}
fprintf(stderr, "Unable to create threads, error=%d, terminating\n", error);
ThrowWin32(error);
}
}
}
void
GetFlags(
wchar_t**& argv,
__int64& flags,
DWORD& beginInstallFlags,
DWORD& installFlags,
DWORD& endInstallFlags
)
{
__int64 flag;
while (flag = IsFlag(argv[1]))
{
++argv;
if (flag & SXSTEST_END_OF_FLAGS)
{
break;
}
else if (flag & SXSTEST_BEGIN_INSTALL)
{
beginInstallFlags |= flag;
}
else if (flag & SXSTEST_INSTALL)
{
installFlags |= flag;
}
else if (flag & SXSTEST_END_INSTALL)
{
endInstallFlags |= flag;
}
else if (flag & SXSTEST_THREADS)
{
g.NumberOfThreads = _wtoi(*++argv);
if (g.NumberOfThreads > NUMBER_OF(g.Threads))
{
g.NumberOfThreads = NUMBER_OF(g.Threads);
}
}
// always set flags because normal installation is 0 now
flags |= flag;
}
}
VOID
FusionpSetSystemSetupInProgress(bool f)
{
CFusionRegKey Regkey;
CFusionRegKey RegkeyLocalMachine(HKEY_LOCAL_MACHINE);
if (!RegkeyLocalMachine.OpenSubKey(Regkey, L"System\\Setup", KEY_ALL_ACCESS))
return;
Regkey.SetValue(L"SystemSetupInProgress", f ? 1 : 0);
}
extern "C"
BOOL
WINAPI
SxsDllMain(
HINSTANCE hInst,
DWORD dwReason,
PVOID pvReserved
);
int Main(int argc, wchar_t** argv)
{
int i = 0;
__int64 flags = 0;
//__int64 flag = 0;
DWORD beginInstallFlags = 0;
DWORD installFlags = 0;
DWORD endInstallFlags = 0;
wchar_t* argv0 = argv[0];
g.wProcessorArchitecture = SxspGetSystemProcessorArchitecture();
g.wLangId = ::GetUserDefaultLangID();
if (argc > 1)
{
FusionpSetSystemSetupInProgress(false);
__try
{
__try
{
if (!SxsDllMain(GetModuleHandle(NULL), DLL_PROCESS_ATTACH, NULL))
ThrowLastError();
GetFlags(argv, flags, beginInstallFlags, installFlags, endInstallFlags);
i = 1;
// consume global flags...
for (;;)
{
if (::FusionpStrCmpI(argv[i], L"-pa") == 0)
{
if (!ParseProcessorArchitecture(argc, argv, &i))
goto Exit;
}
else if (::FusionpStrCmpI(argv[i], L"-langid") == 0)
{
if (!ParseLangId(argc, argv, &i))
goto Exit;
}
else
break;
}
if (false) { }
else if (::FusionpStrCmpI(argv[i], L"-id") == 0)
{
DWORD index = 0;
if (argv[3]){ // have an index present
index = argv[3][0] - L'0';
}
i = TestGeneratePathFromIdentityAttributeString(argv[2]);
}
else if (::FusionpStrCmpI(argv[i], L"-tPathType") == 0)
{
TestPathType(argv + i + 1);
}
else if (::FusionpStrCmpI(argv[i], L"-systemdefault") == 0)
{
i = TestSystemDefaultActivationContextGeneration();
}
else if (::FusionpStrCmpI(argv[i], L"-dom") == 0)
{
i = TestXMLDOM(argv[2]);
}
else if (::FusionpStrCmpI(argv[i], L"-hash") == 0)
{
i = TestGenerateStringWithIdenticalHash(argv[2]);
}
else if (::FusionpStrCmpI(argv[i], L"-tasyncio") == 0)
{
i++;
i = TestAsyncIO(argc, argv, &i);
}
else if (::FusionpStrCmpI(argv[i], L"-assemblyidentityhash") == 0)
{
i = TestAssemblyIdentityHash();
}
else if (::FusionpStrCmpI(argv[i], L"-array") == 0)
{
i = TestFusionArray(argv[2], argv[3]);
}
else if (::FusionpStrCmpI(argv[i], L"-diffdir") == 0)
{
i = TestDiffDir(argv[i + 1], argv[i + 2]);
}
else if (::FusionpStrCmpI(argv[1], L"-pcm") == 0)
{
i = TestPrecomiledManifest(argv[2]);
}
else if (::FusionpStrCmpI(argv[1], L"-testpcm") == 0)
{
i = TestPCMTime(argv[2]);
}
else if (::FusionpStrCmpI(argv[1], L"-cd") == 0)
{
i = TestCreateMultiLevelDirectory(argv[2]);
}
else if (!::FusionpStrCmpI(argv[i], L"-manifests"))
{
TestDumpContainedManifests(argv[++i]);
}
else if (::FusionpStrCmpI(argv[1], L"-dirwalk") == 0)
{
i = TestDirWalk(argv[i + 1], argv[i + 2]);
}
else if (::FusionpStrCmpI(argv[1], L"-tmultiact") == 0)
{
i = TestMultiAct(argc, argv);
}
else if (flags)
{
PrintIfAnyCriticalSectionsHeld();
i = TestInstall(argv[i], flags, beginInstallFlags, installFlags, endInstallFlags);
PrintIfAnyCriticalSectionsHeld();
}
else if (!::FusionpStrCmpI(argv[i], L"-sfcui"))
{
if ( !TestSxsSfcUI() )
goto Exit;
i++;
}
else if ( !FusionpStrCmpI( argv[i], L"-installwithinfo" ) )
{
TestInstallWithInstallInfo(
( i + 1 < argc ) ? argv[i + 1] : NULL,
( i + 2 < argc ) ? argv[i+2] : NULL);
i += 2;
}
else if (!::FusionpStrCmpI(argv[i], L"-multicache"))
{
TestTrickyMultipleAssemblyCacheItems(argv[i + 1]);
i++;
}
else if (::FusionpStrCmpI(argv[i], L"-d") == 0)
{
if (!TestDirect(argc, argv, &i))
goto Exit;
}
else if (::FusionpStrCmpI(argv[i], L"-probe") == 0)
{
i++;
argv[i] = L"foo,type=\"win32\",processorArchitecture=\"x86\",version=\"6.0.0.0\",publicKeyToken=\"6595b64144ccf1df\"";
if (!TestAssemblyProbing(argc, argv, &i))
goto Exit;
}
else if (::FusionpStrCmpI(argv[i], L"-dirchanges") == 0)
{
if (!TestDirectoryChangeWatcher(argc, argv, &i))
goto Exit;
}
else if (::FusionpStrCmpI(argv[i], L"-newinstall") == 0)
{
if (!TestNewSxsInstallAPI(argv[++i]))
goto Exit;
}
else if (::FusionpStrCmpI(argv[i], L"-tuninstall") == 0
|| ::FusionpStrCmpI(argv[i], L"-uninstall") == 0)
{
TestUninstall(argv[i + 1], argv[i + 2]);
goto Exit;
}
else if (::FusionpStrCmpI(argv[i], L"-probemanifest") == 0)
{
if (!TestManifestProbing(argc, argv, &i))
goto Exit;
}
else if (::FusionpStrCmpI(argv[i], L"-p") == 0)
{
if (!TestXMLParsing(argc, argv, &i))
goto Exit;
}
else if (::FusionpStrCmpI(argv[i], L"-w32") == 0)
{
TestWin32(argv + i + 1);
}
else if (::FusionpStrCmpI(argv[i], L"-msi") == 0)
{
if (!TestMSIInstall(argc, argv, &i))
goto Exit;
}
else if (::FusionpStrCmpI(argv[i], L"-mp") == 0)
{
if (!TestManifestSchema(argc, argv, &i))
goto Exit;
}
else if (::FusionpStrCmpI(argv[i], L"-act") == 0)
{
if (!TestAct(argc, argv, &i))
goto Exit;
}
else if (::FusionpStrCmpI(argv[i], L"-shatest") == 0)
{
if (!TestPrivateSha1Impl(argv[++i]))
goto Exit;
}
else if (::FusionpStrCmpI(argv[1], L"-am") == 0)
{
i = TestAssemblyName();
}
else if (::FusionpStrCmpI(argv[i], L"-tsurrogates") == 0)
{
if (!SimpleTestFindAndUseSurrogateInformation(argv[i+1], argv[i+2]))
goto Exit;
i += 2;
}
else if (::FusionpStrCmpI(argv[i], L"-clrhelpers") == 0)
{
if (!TestSxsExportedSurrogateStuff(argv[i+1], argv[i+2], argv[i+3]))
goto Exit;
i += 3;
}
else if (::FusionpStrCmpI(argv[i], L"-tsearchpath") == 0)
{
if (!TestSearchPath(argc, argv, &i))
goto Exit;
}
else if (!::FusionpStrCmpI(argv[i], L"-testmapping"))
{
if (!TestOpeningStuff(argv[i+1], argv[i+2], argv[i+3]))
goto Exit;
i += 3;
}
else if (!::FusionpStrCmpI(argv[i], L"-validatefile"))
{
if (!TestVerifyFileSignature(argv[++i]))
goto Exit;
}
else if (::FusionpStrCmpI(argv[i], L"-tloadlibrary") == 0)
{
if (!TestLoadLibrary(argc, argv, &i))
goto Exit;
}
else if (!::FusionpStrCmpI(argv[i], L"-refresh"))
{
if (!TestRefreshAssembly(argv[i+1]))
goto Exit;
}
else if (::FusionpStrCmpI(argv[i], L"-leak") == 0)
{
//
// We dump a little bit of memory
//
UINT iAmount = 0;
iAmount = _wtoi(argv[++i]);
if (!TestLeakMemory(iAmount))
goto Exit;
}
else if (::FusionpStrCmpI(argv[i], L"-tcreateprocess") == 0)
{
if (!TestCreateProcess(argv + i + 1))
goto Exit;
}
else if (::FusionpStrCmpI(argv[i], L"-tcreateprocess2") == 0)
{
if (!TestCreateProcess2(argv + i + 1))
goto Exit;
}
else if (::FusionpStrCmpI(argv[i], L"-tinherit") == 0)
{
TestInherit();
}
else if (::FusionpStrCmpI(argv[i], L"-tnoinherit") == 0)
{
TestNoInherit();
}
else if (::FusionpStrCmpI(argv[i], L"-tempty") == 0)
{
TestEmpty();
}
else if (::FusionpStrCmpI(argv[i], L"-ttsappcmp") == 0)
{
TestCreateGlobalEvent();
}
else if (::FusionpStrCmpI(argv[i], L"-tmsgperf") == 0)
{
i++;
if (!TestMessagePerf(argc, argv, &i))
goto Exit;
}
else if (::FusionpStrCmpI(argv[i], L"-twinsetup") == 0)
{
FusionpSetSystemSetupInProgress(true);
if (!TestInstallLikeWindowsSetup(argv[i + 1], (argv[i + 2] != NULL) ? argv[i + 2] : argv[i + 1]))
goto Exit;
i += 3;
}
else if (!::FusionpStrCmpI(argv[i], L"-sfcscan"))
{
TestSfcScanKickoff();
}
else if (!::FusionpStrCmpI(argv[i], L"-certinfo"))
{
GenerateStrongNameAndPublicKey(argv[++i]);
}
else if (::FusionpStrCmpI(argv[i], L"-thandle") == 0)
{
DWORD iAmount = 0;
iAmount = _wtoi(argv[++i]);
TestCreateActctxLeakHandles(iAmount);
}
else if (::FusionpStrCmpI(argv[i], L"-catsigner") == 0)
{
TestNewCatalogSignerThingy(argv[++i]);
}
else if (::FusionpStrCmpI(argv[i], L"-trefcount") == 0)
{
TestRefCount();
}
else if (::FusionpStrCmpI(argv[i], L"-ttileak") == 0)
{
TestThreadInheritLeak();
}
else if (::FusionpStrCmpI(argv[i], L"-tguidsort") == 0)
{
TestGuidSort();
}
else if (::FusionpStrCmpI(argv[i], L"-tstringsort") == 0)
{
TestStringSort();
}
else if (::FusionpStrCmpI(argv[i], L"-tExeDll") == 0)
{
TestExeDll();
}
else if (FusionpStrCmpI(argv[i], L"-tExitProcess") == 0)
{
LoadSxs();
GetSxsProc(SXSP_DEBUG_ORDINAL, &pfnSxspDebug);
pfnSxspDebug(SXS_DEBUG_EXIT_PROCESS, 0, 0, NULL);
}
else if (FusionpStrCmpI(argv[i], L"-tTerminateProcess") == 0)
{
LoadSxs();
GetSxsProc(SXSP_DEBUG_ORDINAL, &pfnSxspDebug);
pfnSxspDebug(SXS_DEBUG_TERMINATE_PROCESS, 0, 0, NULL);
}
else if (FusionpStrCmpI(argv[i], L"-tLastError") == 0)
{
::SetLastError(123);
printf("%lu\n", FusionpGetLastWin32Error());
printf("%lu\n", ::GetLastError());
::FusionpSetLastWin32Error(456);
printf("%lu\n", FusionpGetLastWin32Error());
printf("%lu\n", ::GetLastError());
}
else if (FusionpStrCmpI(argv[i], L"-tGetModuleHandleEx") == 0)
{
TestGetModuleHandleEx();
}
else if (FusionpStrCmpI(argv[i], L"-tGetFullPathName") == 0)
{
TestGetFullPathName(argv[i + 1]);
}
else if (FusionpStrCmpI(argv[i], L"-tCreateFile") == 0)
{
TestCreateFile(argv[i + 1]);
}
else if (FusionpStrCmpI(argv[i], L"-tGetPathBaseName") == 0)
{
TestGetPathBaseName(argv[i + 1]);
}
else if (FusionpStrCmpI(argv[i], L"-tVersion") == 0)
{
TestVersion();
}
else if (FusionpStrCmpI(argv[i], L"-tGetProcessImageFileName") == 0)
{
TestGetProcessImageFileName();
}
else if (FusionpStrCmpI(argv[i], L"-tErrorInfra") == 0)
{
TestErrorInfra();
}
else if (FusionpStrCmpI(argv[i], L"-tQueryActCtx") == 0)
TestQueryActCtx();
else if (FusionpStrCmpI(argv[i], L"-tQueryActCtx2") == 0)
TestQueryActCtx2();
else if (FusionpStrCmpI(argv[i], L"-tqmib") == 0)
{
TestQueryManifestInformationBasic(argv[i+1]);
}
else if (FusionpStrCmpI(argv[i], L"-t64k") == 0)
{
Test64k();
}
else if (FusionpStrCmpI(argv[i], L"-tcreateactctx") == 0)
{
TestCreateActCtx(argc - (i + 1), &argv[i+1]);
}
else if (FusionpStrCmpI(argv[i], L"-TestCreateActCtx_PE_flags0") == 0)
{
TestCreateActCtx_PE_flags0();
}
else if (FusionpStrCmpI(argv[i], L"-tDotLocalSingleInstancing") == 0)
{
TestDotLocalSingleInstancing();
}
else if (FusionpStrCmpI(argv[i], L"-tCreateActctxLikeCreateProcess") == 0)
{
TestCreateActctxLikeCreateProcess();
}
else if (FusionpStrCmpI(argv[i], L"-tCreateActctxLikeCreateProcess") == 0)
{
TestCreateActctxLikeCreateProcess();
}
else if (FusionpStrCmpI(argv[i], L"-tCreateActctxAdminOverride") == 0)
{
TestCreateActctxAdminOverride();
}
else if (FusionpStrCmpI(argv[i], L"-tCreateActctxWindowsShellManifest") == 0)
{
TestCreateActctxWindowsShellManifest();
}
else if (FusionpStrCmpI(argv[i], L"-tHandleLeak") == 0)
{
//for (ULONG i = 0 ; i != 5 ; i += 1)
TestHandleLeaks();
}
else if (FusionpStrCmpI(argv[i], L"-tMfcCreateAndMarshal") == 0)
{
TestMfcCreateAndMarshal();
}
else if (FusionpStrCmpI(argv[i], L"-tAtlCreate") == 0)
{
TestAtlCreate();
}
else if (FusionpStrCmpI(argv[i], L"-TestAlignment") == 0)
{
TestAlignment();
}
else if (FusionpStrCmpI(argv[i], L"-DoNothingJustSeeIfItRuns") == 0)
{
printf("%wZ ran successfully\n", &NtCurrentPeb()->ProcessParameters->ImagePathName);
}
else if (FusionpStrCmpI(argv[i], L"-TestImage") == 0)
{
TestImage();
}
else if (FusionpStrCmpI(argv[i], L"-TestInterlockedAlignment") == 0)
{
TestInterlockedAlignment();
}
else
{
i = Usage(argv0);
}
if (g.ThreadExitEvent)
{
SetEvent(g.ThreadExitEvent);
WaitForMultipleObjectsEx(g.NumberOfThreads, g.Threads, TRUE, INFINITE, TRUE);
}
if (g.sxsDll != NULL)
{
FreeLibrary(g.sxsDll);
}
}
__finally
{
FusionpSetSystemSetupInProgress(false);
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
#if DBG
if (IsDebuggerPresent())
{
FUSION_DEBUG_BREAK();
}
#endif
i = GetExceptionCode();
WCHAR message[128];
DWORD flags = FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM;
FormatMessageW(flags, NULL, i, 0, message, NUMBER_OF(message), NULL);
PWSTR end = message + wcslen(message);
while (end != message && isspace(*(end - 1)))
{
--end;
}
*end = 0;
::Trace("%ls failed, %d, %#x, %ls", g.lastOperation, i, i, message);
}
PTEB teb;
teb = NtCurrentTeb();
if (teb->CountOfOwnedCriticalSections != 0)
{
DbgPrint("teb->CountOfOwnedCriticalSections %d\n", teb->CountOfOwnedCriticalSections);
//ASSERT(teb->CountOfOwnedCriticalSections == 0);
}
return i ? EXIT_SUCCESS : EXIT_FAILURE;
}
return Usage(argv[0]);
Exit:
return ::GetLastError();
}
extern "C" int __cdecl wmain(int argc, wchar_t** argv)
{
// NtCurrentTeb()->CountOfOwnedCriticalSections = 0;
PrintIfAnyCriticalSectionsHeld();
int i = Main(argc, argv);
PrintIfAnyCriticalSectionsHeld();
return i;
}
int TestDiffDir(PCWSTR dir1, PCWSTR dir2)
{
CFusionDirectoryDifference diff;
CStringBuffer buf1;
CStringBuffer buf2;
BOOL fSuccess = FALSE;
if (!buf1.Win32Assign(dir1, ::wcslen(dir1)))
goto Exit;
if (!buf2.Win32Assign(dir2, ::wcslen(dir2)))
goto Exit;
if (!::FusionpCompareDirectoriesSizewiseRecursively(&diff, buf1, buf2))
goto Exit;
diff.DbgPrint(buf1, buf2);
fSuccess = TRUE;
Exit:
return fSuccess ? EXIT_SUCCESS : EXIT_FAILURE;
}
PCWSTR GetUser()
{
static bool fInited;
static WCHAR userName[MAX_PATH];
if (!fInited)
{
DWORD size = NUMBER_OF(userName);
userName[0] = 0;
userName[1] = 0;
GetUserNameW(userName, &size);
if (userName[1] == '-')
{
wmemcpy(userName, 2+userName, 1+wcslen(2+userName));
}
fInited = true;
}
return userName;
}
void UserBreakPoint(PCWSTR user)
{
if (::IsDebuggerPresent() && _wcsicmp(GetUser(), user) == 0)
{
ASSERT2_NTC(FALSE, __FUNCTION__);
}
}
void LoadSxs()
{
WCHAR ExePath[MAX_PATH];
if (g.sxsDll == NULL)
{
SetLastOperation(L"LoadLibrary(SXS.DLL)");
// sxstest is often run from nt\base\win32\fusion\tests\sxstest\whistler\obj\i386\sxstest.exe; try loading sxs.dll
// via a relative path first
g.sxsDll = ::LoadLibraryW(L"..\\..\\..\\..\\..\\dll\\whistler\\obj\\i386\\SXS.DLL");
if (g.sxsDll == NULL)
{
GetModuleFileNameW(NULL, ExePath, NUMBER_OF(ExePath));
wcscpy(1 + wcsrchr(ExePath, '\\'), L"SXS.DLL");
g.sxsDll = ::LoadLibraryW(ExePath);
}
if (g.sxsDll == NULL)
g.sxsDll = ::LoadLibraryW(L"SXS.DLL");
if (g.sxsDll == NULL)
ThrowLastError();
UserBreakPoint(L"JayKrell");
}
}
template <typename PFN>
void GetSxsProc(int name, PFN* ppfn)
{
SetLastOperation(L"GetProcAddress(#%d)", name);
if (!(*ppfn = reinterpret_cast<PFN>(GetProcAddress(g.sxsDll, reinterpret_cast<PCSTR>(IntToPtr(name))))))
{
ThrowLastError();
}
}
template <typename PFN>
void GetSxsProc(PCSTR name, PFN* ppfn)
{
SetLastOperation(L"GetProcAddress(%hs)", name);
if (!(*ppfn = reinterpret_cast<PFN>(GetProcAddress(g.sxsDll, name))))
{
ThrowLastError();
}
}
class CCopyQueueElement : public std::pair<std::wstring, std::wstring>
{
typedef std::pair<std::wstring, std::wstring> Base;
public:
CCopyQueueElement() { }
CCopyQueueElement(const first_type& source, const second_type& target)
:
Base(source, target)
{
}
first_type& Source() { return first; }
const first_type& Source() const { return first; }
second_type& Target() { return second; }
const second_type& Target() const { return second; }
};
template <typename T> class StdDeque : public std::deque<T, Allocator<T> > { };
template <typename T> class StdVector : public std::vector<T, Allocator<T> > { };
class CCopyQueue : public StdDeque<CCopyQueueElement>
{
typedef StdDeque<CCopyQueueElement> Base;
public:
BOOL Callback(
PSXS_INSTALLATION_FILE_COPY_CALLBACK_PARAMETERS parameters
)
{
push_back(value_type(parameters->pSourceFile, parameters->pDestinationFile));
parameters->nDisposition = SXS_INSTALLATION_FILE_COPY_DISPOSITION_FILE_QUEUED;
return TRUE;
}
static BOOL WINAPI StaticCallback(
PSXS_INSTALLATION_FILE_COPY_CALLBACK_PARAMETERS parameters
)
{
CCopyQueue* pThis = reinterpret_cast<CCopyQueue*>(parameters->pvContext);
BOOL fResult = pThis->Callback(parameters);
return fResult;
}
BOOL Flush()
{
BOOL fSuccess = FALSE;
for (; !empty() ; pop_back())
{
const std::wstring& target = back().Target();
const std::wstring targetDir = target.substr(0, target.find_last_of('\\'));
FusionpCreateDirectories(targetDir.c_str(), ::wcslen(targetDir.c_str()));
if (!CopyFileW(back().Source().c_str(), target.c_str(), TRUE))
{
goto Exit;
}
}
fSuccess = TRUE;
Exit:
return fSuccess;
}
};
int
TestInstall(
PCWSTR manifest,
__int64 flags,
DWORD beginInstallFlags,
DWORD installFlags,
DWORD endInstallFlags
)
{
PrintIfAnyCriticalSectionsHeld();
BOOL fSuccess = FALSE;
PVOID installCookie = NULL;
PSXS_BEGIN_ASSEMBLY_INSTALL sxsBeginAssemblyInstall = NULL;
PSXS_INSTALL_ASSEMBLY_W sxsInstallAssemblyW = NULL;
PSXS_END_ASSEMBLY_INSTALL sxsEndAssemblyInstall = NULL;
CCopyQueue copyQueue;
BOOL fCleanup = FALSE;
SXS_INSTALL_SOURCE_INFO SxsInstallInfo = {0};
PSXS_INSTALLATION_FILE_COPY_CALLBACK callback = NULL;
PVOID context = NULL;
HSPFILEQ hSetupCopyQueue = INVALID_HANDLE_VALUE;
PVOID pDefaultSetupCopyQueueContext = NULL;
LoadSxs();
GetSxsProc("SxsBeginAssemblyInstall", &sxsBeginAssemblyInstall);
GetSxsProc("SxsInstallAssemblyW", &sxsInstallAssemblyW);
GetSxsProc("SxsEndAssemblyInstall", &sxsEndAssemblyInstall);
if (flags & SXSTEST_INSTALL_MY_QUEUE)
{
callback = &CCopyQueue::StaticCallback;
context = &copyQueue;
}
else if (flags & SXSTEST_INSTALL_SETUPAPI_QUEUE)
{
callback = SXS_INSTALLATION_FILE_COPY_CALLBACK_SETUP_COPY_QUEUE;
if (INVALID_HANDLE_VALUE == (hSetupCopyQueue = SetupOpenFileQueue()))
{
goto Exit;
}
context = hSetupCopyQueue; // random non NULL, step through, then stop debugging
#if DBG
FUSION_DEBUG_BREAK();
#endif
}
PrintIfAnyCriticalSectionsHeld();
if (!(*sxsBeginAssemblyInstall)(
beginInstallFlags,
callback,
context,
NULL, // ImpersonationCallback,
NULL, // ImpersonationContext,
&installCookie))
{
goto Exit;
}
fCleanup = TRUE;
PrintIfAnyCriticalSectionsHeld();
memset(&SxsInstallInfo, 0, sizeof(SxsInstallInfo));
SxsInstallInfo.cbSize = sizeof(SxsInstallInfo);
SxsInstallInfo.dwFlags = SXSINSTALLSOURCE_INSTALLING_SETUP | SXSINSTALLSOURCE_HAS_CODEBASE;
SxsInstallInfo.pcwszCodebaseName = manifest;
fSuccess = sxsInstallAssemblyW(
installCookie,
installFlags | SXS_INSTALL_ASSEMBLY_FLAG_FROM_DIRECTORY_RECURSIVE | SXS_INSTALL_ASSEMBLY_FLAG_INCLUDE_CODEBASE,
manifest,
&SxsInstallInfo);
PrintIfAnyCriticalSectionsHeld();
fSuccess = copyQueue.Flush();
Exit:
if (fCleanup)
{
if (flags & SXSTEST_INSTALL_SETUPAPI_QUEUE)
{
if (!(pDefaultSetupCopyQueueContext = ::SetupInitDefaultQueueCallback(NULL)))
{
fSuccess = FALSE;
}
if (fSuccess && !::SetupCommitFileQueue(NULL,
hSetupCopyQueue,
SetupDefaultQueueCallback,
pDefaultSetupCopyQueueContext))
{
fSuccess = FALSE;
}
if (hSetupCopyQueue != INVALID_HANDLE_VALUE)
{
::SetupCloseFileQueue(hSetupCopyQueue);
hSetupCopyQueue = NULL;
}
}
sxsEndAssemblyInstall(installCookie, endInstallFlags | (fSuccess ? SXS_END_ASSEMBLY_INSTALL_FLAG_COMMIT : SXS_END_ASSEMBLY_INSTALL_FLAG_ABORT), NULL);
}
PrintIfAnyCriticalSectionsHeld();
if (!fSuccess)
{
fprintf(stderr, "%s failed!\n", __FUNCTION__);
return EXIT_FAILURE;
}
else
return EXIT_SUCCESS;
}
BOOL
TestManifestSchema(
int argc,
wchar_t** argv,
int* piNext
)
{
SXSP_DEBUG_FUNCTION& pfn = pfnSxspDebug;
BOOL fSuccess = FALSE;
int i = (*piNext) + 1;
if (i >= argc)
{
fprintf(stderr, "%S: Missing parameter after \"%S\"\n", argv[0], argv[i-1]);
goto Exit;
}
LoadSxs();
GetSxsProc(SXSP_DEBUG_ORDINAL, &pfn);
fSuccess = (*pfn)(SXS_DEBUG_CHECK_MANIFEST_SCHEMA, 0, argv[i++], NULL);
if (!fSuccess)
{
fprintf(stderr, "%s failed!\n", __FUNCTION__);
goto Exit;
}
*piNext = i;
fSuccess = TRUE;
Exit:
return fSuccess;
}
BOOL
TestXMLParsing(
int argc,
wchar_t** argv,
int* piNext)
{
SXSP_DEBUG_FUNCTION pfn = NULL;
BOOL fSuccess = FALSE;
int i = (*piNext) + 1;
if (i >= argc)
{
fprintf(stderr, "%S: missing parameter after \"%S\"\n", argv[0], argv[i-1]);
goto Exit;
}
LoadSxs();
GetSxsProc(SXSP_DEBUG_ORDINAL, &pfn);
fSuccess = (*pfn)(SXS_DEBUG_XML_PARSER, 0, argv[i], NULL);
if (!fSuccess)
{
fprintf(stderr, "%s failed!\n", __FUNCTION__);
goto Exit;
}
*piNext = i + 1;
fSuccess = TRUE;
Exit:
return fSuccess;
}
BOOL
TestDirect(
int argc,
wchar_t** argv,
int* piNext)
{
SXSP_DEBUG_FUNCTION pfn = NULL;
BOOL fSuccess = FALSE;
int i = (*piNext) + 1;
if (i >= argc)
{
fprintf(stderr, "%S: missing parameter after \"%S\"\n", argv[0], argv[i-1]);
goto Exit;
}
LoadSxs();
GetSxsProc(SXSP_DEBUG_ORDINAL, &pfn);
fSuccess = (*pfn)(SXS_DEBUG_DLL_REDIRECTION, 0, argv[i], NULL);
if (!fSuccess)
{
fprintf(stderr, "%s failed!\n", __FUNCTION__);
goto Exit;
}
*piNext = i + 1;
fSuccess = TRUE;
Exit:
return fSuccess;
}
VOID
PrintBlob(
FILE *pf,
PVOID Data,
SIZE_T Length,
PCWSTR PerLinePrefix
)
{
ULONG Offset = 0;
if (PerLinePrefix == NULL)
PerLinePrefix = L"";
// we'll output in 8-byte chunks as shown:
//
// [prefix]Binary section %p (%d bytes)
// [prefix] 00000000: xx-xx-xx-xx-xx-xx-xx-xx (........)
// [prefix] 00000008: xx-xx-xx-xx-xx-xx-xx-xx (........)
// [prefix] 00000010: xx-xx-xx-xx-xx-xx-xx-xx (........)
//
while (Length >= 8)
{
BYTE *pb = (BYTE *) (((ULONG_PTR) Data) + Offset);
fprintf(
pf,
"%S %08lx: %02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x (%c%c%c%c%c%c%c%c)\n",
PerLinePrefix,
Offset,
pb[0], pb[1], pb[2], pb[3], pb[4], pb[5], pb[6], pb[7],
PRINTABLE(pb[0]),
PRINTABLE(pb[1]),
PRINTABLE(pb[2]),
PRINTABLE(pb[3]),
PRINTABLE(pb[4]),
PRINTABLE(pb[5]),
PRINTABLE(pb[6]),
PRINTABLE(pb[7]));
Offset += 8;
Length -= 8;
}
if (Length != 0)
{
CStringBuffer buffTemp;
bool First = true;
ULONG i;
BYTE *pb = (BYTE *) (((ULONG_PTR) Data) + Offset);
buffTemp.Win32ResizeBuffer(48, eDoNotPreserveBufferContents);
buffTemp.Win32Format(L" %08lx: ", Offset);
for (i=0; i<8; i++)
{
if (Length > 0)
{
if (!First)
buffTemp.Win32Append("-", 1);
else
First = false;
buffTemp.Win32FormatAppend(L"%02x", pb[i]);
Length--;
}
else
{
buffTemp.Win32Append(" ", 3);
}
}
buffTemp.Win32Append(" (", 2);
i = 0;
while (Length != 0)
{
CHAR chTemp = static_cast<CHAR>(PRINTABLE(pb[i]));
i++;
buffTemp.Win32Append(&chTemp, 1);
Length--;
}
buffTemp.Win32Append(L")", 1);
fprintf(
pf,
"%S%S\n",
PerLinePrefix,
static_cast<PCWSTR>(buffTemp));
}
}
void __stdcall TestWin32Apc(ULONG_PTR arg)
{
ACTCTXW ac = {sizeof(ac)};
int error = 0;
PWSTR source = reinterpret_cast<PWSTR>(arg);
HANDLE hActCtx = NULL;
BOOL fSuccess = FALSE;
ac.lpSource = source;
PWSTR pound = wcschr(source, '#');
if (pound != NULL)
{
*pound = 0;
ac.lpResourceName = pound + 1;
ac.dwFlags |= ACTCTX_FLAG_RESOURCE_NAME_VALID;
}
ac.wProcessorArchitecture = g.wProcessorArchitecture;
ac.wLangId = g.wLangId;
hActCtx = ::CreateActCtxW(&ac);
if (hActCtx == INVALID_HANDLE_VALUE)
{
error = ::GetLastError();
fwprintf(stderr, L"CreateActCtxW(%ls) failed; ::GetLastError() = %d\n", source, error);
goto Exit;
}
//fSuccess = ::ReleaseActCtx(hActCtx);
fSuccess = TRUE;
hActCtx = NULL;
if (!fSuccess)
{
error = ::GetLastError();
goto Exit;
}
Exit:
if (error)
ThrowWin32(error);
}
void
TestWin32(
wchar_t** argv
)
{
CreateThreads();
int i = 0;
for (i = 0 ; argv[i] ; ++i)
{
if (g.NumberOfThreads)
{
if (!QueueUserAPC(TestWin32Apc, g.Threads[i % g.NumberOfThreads], reinterpret_cast<ULONG_PTR>(argv[i])))
{
fprintf(stderr, "QueueUserAPC() failed\n");
ThrowWin32(((ULONG_PTR) (LONG_PTR) -1));
}
}
else
{
TestWin32Apc(reinterpret_cast<ULONG_PTR>(argv[i]));
}
}
}
#if BETA1
const static WCHAR InheritManifest[] =
L"<assembly manifestversion=\"1.0\" name=\"InheritManifest\">"
L"<dependency assemblyname=\"Microsoft-Visual-CPlusPlus-Runtime-Libraries\" version=\"6.0.0.0\" language=\"0000\"/>"
L"</assembly>"
;
#else // suppose to be BETA2 or later
const static WCHAR InheritManifest[] =
L"<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
L"<assemblyIdentity type=\"win32\" name=\"Microsoft.Windows.SystemCompatibleAssembly\" version=\"1.0.0.0\" processorArchitecture=\"x86\" />"
L"<description>System Compatible Default</description> "
L"<dependency> <dependentAssembly>"
L"<assemblyIdentity type=\"win32\" name=\"Microsoft.Tools.VisualCPlusPlus.Runtime-Libraries\" version=\"6.0.0.0\" language=\"*\" processorArchitecture=\"x86\" publicKeyToken=\"6595b64144ccf1df\" />"
L"</dependentAssembly> </dependency></assembly>"
;
#endif
const static WCHAR NoInheritManifest[] =
L"<assembly manifestversion=\"1.0\" name=\"InheritManifest\">"
L"<dependency assemblyname=\"Microsoft-Visual-CPlusPlus-Runtime-Libraries\" version=\"6.0.0.0\" language=\"0000\"/>"
L"<noinherit/>"
L"</assembly>"
;
const static WCHAR RefCountManifest[] =
L"<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
L"<assemblyIdentity type=\"win32\" name=\"Microsoft.Windows.SxsTest.RefCount\" version=\"1.0.0.0\" processorArchitecture=\"x86\" />"
L"<description>blah</description> "
L"<dependency><dependentAssembly>"
//L"<assemblyIdentity type=\"win32\" name=\"Microsoft.Windows.SxsTest1\" version=\"1.0.0.0\" language=\"*\" processorArchitecture=\"x86\" publicKeyToken=\"6595b64144ccf1df\" />"
L"<assemblyIdentity type=\"win32\" name=\"Microsoft.Tools.VisualCPlusPlus.Runtime-Libraries\" version=\"6.0.0.0\" language=\"*\" processorArchitecture=\"x86\" publicKeyToken=\"6595b64144ccf1df\" />"
L"</dependentAssembly> </dependency></assembly>"
;
// to test the empty actctx, we push this, probe, push empty, probe
const static PCWSTR DependentOnMsvc6Manifest = InheritManifest;
WCHAR SearchPathResult[MAX_PATH];
void ProbeContext(const char* Function, PCWSTR Dll = L"msvcrt.dll")
{
SearchPathResult[0] = 0;
SearchPathW(NULL, Dll, NULL, NUMBER_OF(SearchPathResult), SearchPathResult, NULL);
DbgPrint("%s %ls\n", Function, SearchPathResult);
}
DWORD CALLBACK InheritThreadMain(VOID*)
{
ProbeContext(__FUNCTION__);
return 0;
}
DWORD CALLBACK NoinheritThreadMain(VOID*)
{
ProbeContext(__FUNCTION__);
return 0;
}
void TestInherit()
{
ProbeContext(__FUNCTION__);
HANDLE ActivationContextHandle = ::CreateActivationContextFromStringW(InheritManifest);
ULONG_PTR Cookie;
ActivateActCtx(ActivationContextHandle, &Cookie);
ProbeContext(__FUNCTION__);
DWORD ThreadId;
WaitForSingleObject(CreateThread(NULL, 0, InheritThreadMain, NULL, 0, &ThreadId), INFINITE);
}
void TestNoInherit()
{
ProbeContext(__FUNCTION__);
HANDLE ActivationContextHandle = ::CreateActivationContextFromStringW(NoInheritManifest);
ULONG_PTR Cookie;
ActivateActCtx(ActivationContextHandle, &Cookie);
ProbeContext(__FUNCTION__);
DWORD ThreadId;
WaitForSingleObject(CreateThread(NULL, 0, NoinheritThreadMain, NULL, 0, &ThreadId), INFINITE);
}
void TestEmpty()
{
ProbeContext(__FUNCTION__);
HANDLE ActivationContextHandle = ::CreateActivationContextFromStringW(DependentOnMsvc6Manifest);
ULONG_PTR Cookie1, Cookie2;
ActivateActCtx(ActivationContextHandle, &Cookie1);
ProbeContext(__FUNCTION__);
ActivateActCtx(ACTCTX_EMPTY, &Cookie2);
ProbeContext(__FUNCTION__);
DeactivateActCtx(0, Cookie2);
ProbeContext(__FUNCTION__);
DeactivateActCtx(0, Cookie1);
ProbeContext(__FUNCTION__);
}
#if 0
#define SXSTEST_NTOPENFILE_RET NTSTATUS
#define SXSTEST_NTOPENFILE_CALL NTAPI
#define SXSTEST_NTOPENFILE_ARG_NAMES_TYPES \
(\
OUT PHANDLE FileHandle, \
IN ACCESS_MASK DesiredAccess, \
IN POBJECT_ATTRIBUTES ObjectAttributes, \
OUT PIO_STATUS_BLOCK IoStatusBlock, \
IN ULONG ShareAccess, \
IN ULONG OpenOptions \
)
#define SXSTEST_NTCREATEFILE_RET NTSTATUS
#define SXSTEST_NTCREATEFILE_CALL NTAPI
#define SXSTEST_NTCREATEFILE_ARG_NAMES_TYPES \
(\
OUT PHANDLE FileHandle, \
IN ACCESS_MASK DesiredAccess, \
IN POBJECT_ATTRIBUTES ObjectAttributes, \
OUT PIO_STATUS_BLOCK IoStatusBlock, \
IN PLARGE_INTEGER AllocationSize OPTIONAL, \
IN ULONG FileAttributes, \
IN ULONG ShareAccess, \
IN ULONG CreateDisposition, \
IN ULONG CreateOptions, \
IN PVOID EaBuffer OPTIONAL, \
IN ULONG EaLength \
)
SXSTEST_NTCREATEFILE_RET (SXSTEST_NTCREATEFILE_CALL* SxsTestDynamicNtCreateFileTrampoline)(...);
SXSTEST_NTCREATEFILE_RET
DETOUR_TRAMPOLINE(
SXSTEST_NTCREATEFILE_RET SXSTEST_NTCREATEFILE_CALL SxsTestNtCreateFileTrampoline SXSTEST_NTCREATEFILE_ARG_NAMES_TYPES,
NtCreateFile
);
DETOUR_TRAMPOLINE(
SXSTEST_NTOPENFILE_RET SXSTEST_NTOPENFILE_CALL SxsTestNtOpenFileTrampoline SXSTEST_NTCREATEFILE_ARG_NAMES_TYPES,
NtOpenFile
);
#endif
void TestRefCount()
{
//
// 1) newly created actctx has refcount==1
// 2) activated actctx has refcount==1
// 3) load a library with no deps with actctx, refcount==2
// 4) freelibrary, refcount==1
// directory of library is closed
// 5) release actctx refcount==0
//
// First order, just step through the code to look at the refcount.
// Second order, "detour" like crazy and look at the memory
// (including detouring away RtlFreeHeap, NtUnmapViewOfSection)
//
HANDLE ActivationContextHandle = ::CreateActivationContextFromStringW(RefCountManifest);
ULONG_PTR Cookie1;
ActivateActCtx(ActivationContextHandle, &Cookie1);
FreeLibrary(LoadLibraryW(L"msvcrt.dll"));
DeactivateActCtx(0, Cookie1);
ReleaseActCtx(ActivationContextHandle);
#if 0
WCHAR RenameDirectorySource[MAX_PATH];
WCHAR RenameDirectoryDestination[MAX_PATH];
//
// Try to rename the directory.
//
DbgPrint("dll was loaded from %ls, now see if we can rename that directory\n", SearchPathResult);
wcscpy(RenameDirectorySource, SearchPathResult);
*wcsrchr(SearchPathResult, '\\') = 0;
wcscpy(RenameDirectoryDestination, RenameDirectorySource);
wcscpy(wcsrchr(RenameDirectoryDestination, '\\'), L"blah");
BOOL Success = MoveFileW(RenameDirectorySource, RenameDirectoryDestination);
int Error = ::GetLastError();
DbgPrint("MoveFile(%ls -> %ls) %s, Error=%d\n",
RenameDirectorySource, RenameDirectoryDestination, Success ? "succeeded" : "failed", Error);
#endif
}
GUID Guids[100];
WCHAR GuidStrings[100][64];
void FormatGuid(WCHAR* String, const GUID& Guid)
{
swprintf(
String,
L"%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
Guid.Data1,
Guid.Data2,
Guid.Data3,
Guid.Data4[0], Guid.Data4[1], Guid.Data4[2], Guid.Data4[3],
Guid.Data4[4], Guid.Data4[5], Guid.Data4[6], Guid.Data4[7]);
}
extern "C" HRESULT __stdcall
DllGetClassObject(
REFCLSID rclsid, //CLSID for the class object
REFIID riid, //Reference to the identifier of the interface
// that communicates with the class object
LPVOID * ppv //Address of output variable that receives the
// interface pointer requested in riid
)
{
WCHAR GuidString[64];
FormatGuid(GuidString, rclsid);
printf("%s : {%ls}\n", __FUNCTION__, GuidString);
if (riid == IID_IUnknown)
{
*ppv = &g.unknown;
return S_OK;
}
else
{
return E_NOINTERFACE;
}
}
void TestGuidSort()
{
const int MAX = 100;
FN_TRACE_SMART_TLS();
CStringBuffer Manifest;
int i = 0;
Ole32.CoInitialize(NULL);
Manifest.Win32ResizeBuffer(1 << 15, eDoNotPreserveBufferContents);
Manifest.Win32Format(
L"<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\"> \
<assemblyIdentity \
type=\"win32\" \
name=\"Microsoft.Windows.SxsTest.GuidSort\" \
version=\"1.0.0.0\" \
processorArchitecture=\"x86\" \
publicKeyToken=\"6595b64144ccf1df\" \
/> \
<file name=\"sxstest.exe\">");
for (i = 0 ; i < MAX ; ++i)
{
GUID& Guid = Guids[i];
CoCreateGuid(&Guid);
FormatGuid(GuidStrings[i], Guid);
if (!Manifest.Win32FormatAppend(
L"\n<comClass description=\"a%d\" clsid=\"{%ls}\"/>",
i,
static_cast<PCWSTR>(GuidStrings[i])))
ThrowLastError();
}
if (!Manifest.Win32FormatAppend(L"\n</file>\n</assembly>"))
ThrowLastError();
//LoadSxs();
//GetSxsProc(SXSP_DEBUG_ORDINAL, &pfn);
//fSuccess = (*pfn)(SXS_DEBUG_DLL_REDIRECTION, 0, argv[i], NULL);
printf("%ls\n", static_cast<PCWSTR>(Manifest));
HANDLE ActivationContextHandle = ::CreateActivationContextFromStringW(Manifest);
ULONG_PTR Cookie1;
ActivateActCtx(ActivationContextHandle, &Cookie1);
for (i = 0 ; i < MAX ; ++i)
{
HRESULT hr;
PVOID pv = NULL;
hr = Ole32.CoCreateInstance(Guids[i], NULL, CLSCTX_INPROC, IID_IUnknown, &pv);
printf("CoCreateInstance({%ls}): %08lx%s%s%s\n",
GuidStrings[i],
static_cast<unsigned long>(hr),
( (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND))
|| hr == REGDB_E_CLASSNOTREG
|| (hr == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER))
|| (hr == E_NOINTERFACE)
) ? "(" : "",
(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND))
? "ERROR_FILE_NOT_FOUND"
: (hr == REGDB_E_CLASSNOTREG)
? "REGDB_E_CLASSNOTREG"
: (hr == ERROR_INVALID_PARAMETER)
? "ERROR_INVALID_PARAMETER"
: (hr == E_NOINTERFACE)
? "E_NOINTERFACE (ok)"
: "",
( hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)
|| hr == REGDB_E_CLASSNOTREG
|| hr == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER))
|| hr == E_NOINTERFACE
? ")" : "");
}
DeactivateActCtx(0, Cookie1);
ReleaseActCtx(ActivationContextHandle);
}
void TestStringSort()
{
/*
Mike says this takes between 2 and 7 to visit the code.
*/
const int MAX = 50;
FN_TRACE_SMART_TLS();
WCHAR ExePath[MAX_PATH];
CStringBuffer DllPaths[MAX];
CStringBuffer Manifest;
int i = 0;
if (!Kernel32.GetModuleFileNameW(NULL, ExePath, RTL_NUMBER_OF(ExePath)))
ThrowLastError();
if (!Manifest.Win32ResizeBuffer(1 << 15, eDoNotPreserveBufferContents))
ThrowLastError();
if (!Manifest.Win32Format(
L"<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\"> \
<assemblyIdentity \
type=\"win32\" \
name=\"Microsoft.Windows.SxsTest.StringSort\" \
version=\"1.0.0.0\" \
processorArchitecture=\"x86\" \
publicKeyToken=\"6595b64144ccf1df\" \
/> \
<file name=\"sxstest.exe\"/>"))
ThrowLastError();
for (i = 0 ; i < MAX ; ++i)
{
if (!DllPaths[i].Win32Format(L"%ls.%d.dll", ExePath, i))
ThrowLastError();
if (!::CopyFileW(ExePath, DllPaths[i], FALSE))
ThrowLastError();
SetDllBitInPeImage(DllPaths[i]);
if (!Manifest.Win32FormatAppend(L"\n<file name=\"%ls\"/>\n", 1 + wcsrchr(static_cast<PCWSTR>(DllPaths[i]), '\\')))
ThrowLastError();
}
if (!Manifest.Win32FormatAppend(L"\n</assembly>"))
ThrowLastError();
//LoadSxs();
//GetSxsProc(SXSP_DEBUG_ORDINAL, &pfn);
//fSuccess = (*pfn)(SXS_DEBUG_DLL_REDIRECTION, 0, argv[i], NULL);
printf("%ls\n", static_cast<PCWSTR>(Manifest));
HANDLE ActivationContextHandle = ::CreateActivationContextFromStringW(Manifest);
ULONG_PTR Cookie1;
ActivateActCtx(ActivationContextHandle, &Cookie1);
for (i = 0 ; i < MAX ; ++i)
{
HMODULE h;
PCWSTR DllName = 1 + wcsrchr(DllPaths[i], '\\');
h = ::LoadLibraryW(DllName);
printf("LoadLibrary(%ls):%p, LastError=%d\n",
DllName,
h,
::GetLastError());
//FreeLibrary(h);
::DeleteFileW(DllPaths[i]);
}
DeactivateActCtx(0, Cookie1);
ReleaseActCtx(ActivationContextHandle);
}
int
TestSearchPathHelper1(
PCSTR RunId,
PCWSTR Path,
PCWSTR File,
PCWSTR Extension,
bool GetFilePart,
ULONG cch
)
{
WCHAR Buffer[65536]; // we know that the underlying code can never use a buffer this big
PWSTR FilePart = NULL;
PWSTR *lpFilePart = (GetFilePart ? &FilePart : NULL);
SetLastError(ERROR_GEN_FAILURE);
ULONG Result = ::SearchPathW(
Path,
File,
Extension,
0,
NULL,
lpFilePart);
printf("SearchPath() RunId = %s (Path %s; File %s; Extension %s; GetFilePart %s; cch = %lu; buffer=null) result = %lu ::GetLastError() = %u; FilePart = %s %u\n",
RunId,
Path ? "present" : "null",
File ? "present" : "null",
Extension ? "present" : "null",
GetFilePart ? "true" : "false",
0,
Result,
::GetLastError(),
FilePart ? "present" : "null",
FilePart ? (FilePart - Buffer) : 0);
SetLastError(ERROR_GEN_FAILURE);
FilePart = NULL;
ULONG NewResult = ::SearchPathW(
Path,
File,
Extension,
Result,
Buffer,
lpFilePart);
printf("SearchPath() RunId = %s (Path %s; File %s; Extension %s; GetFilePart %s; cch = %lu) result = %lu ::GetLastError() = %u; FilePart = %s %u\n",
RunId,
Path ? "present" : "null",
File ? "present" : "null",
Extension ? "present" : "null",
GetFilePart ? "true" : "false",
Result,
NewResult,
::GetLastError(),
FilePart ? "present" : "null",
FilePart ? (FilePart - Buffer) : 0);
SetLastError(ERROR_GEN_FAILURE);
FilePart = NULL;
Result = ::SearchPathW(
Path,
File,
Extension,
cch,
Buffer,
lpFilePart);
printf("SearchPath() RunId = %s (Path %s; File %s; Extension %s; GetFilePart %s; cch = %lu) result = %lu ::GetLastError() = %u; FilePart = %s %u\n",
RunId,
Path ? "present" : "null",
File ? "present" : "null",
Extension ? "present" : "null",
GetFilePart ? "true" : "false",
cch,
Result,
::GetLastError(),
FilePart ? "present" : "null",
FilePart ? (FilePart - Buffer) : 0);
return EXIT_SUCCESS;
}
int
TestSearchPathHelper2(
PCSTR RunId,
PCWSTR Path,
PCWSTR File,
PCWSTR Extension,
ULONG cch
)
{
TestSearchPathHelper1(RunId, NULL, File, NULL, true, cch);
TestSearchPathHelper1(RunId, NULL, File, NULL, false, cch);
TestSearchPathHelper1(RunId, Path, File, NULL, true, cch);
TestSearchPathHelper1(RunId, Path, File, NULL, false, cch);
TestSearchPathHelper1(RunId, NULL, File, Extension, true, cch);
TestSearchPathHelper1(RunId, NULL, File, Extension, false, cch);
TestSearchPathHelper1(RunId, Path, File, Extension, true, cch);
TestSearchPathHelper1(RunId, Path, File, Extension, false, cch);
return EXIT_SUCCESS;
}
int
TestSearchPathHelper3(
PCSTR RunId,
PCWSTR Path,
PCWSTR File,
PCWSTR Extension
)
{
ULONG i;
for (i=0; i<5; i++)
TestSearchPathHelper2(RunId, Path, File, Extension, i);
for (i=MAX_PATH-5; i<(MAX_PATH+5); i++)
TestSearchPathHelper2(RunId, Path, File, Extension, i);
for (i=32760; i<32770; i++)
TestSearchPathHelper2(RunId, Path, File, Extension, i);
return EXIT_SUCCESS;
}
BOOL
TestSearchPath(
int argc,
wchar_t** argv,
int* piNext
)
{
ULONG i;
PWSTR PathToSearch = (PWSTR) malloc(100000* sizeof(WCHAR));
int iNext = (*piNext) + 1;
PathToSearch[0] = L'C';
PathToSearch[1] = L'\\';
for (i=2; i<60000; i++)
PathToSearch[i] = L'X';
wcscpy(&PathToSearch[i], L";C:\\");
TestSearchPathHelper3("1.0", L"C:\\DirectoryDoesNotExist;C:\\", L"boot.ini", L".ini");
TestSearchPathHelper3("1.1", L"C:\\DirectoryDoesNotExist;C:\\", L"boot.", L".ini");
TestSearchPathHelper3("1.2", L"C:\\DirectoryDoesNotExist;C:\\", L"boot", L".ini");
TestSearchPathHelper3("1.3", L"C:\\DirectoryDoesNotExist;C:\\", L"doesnotexist.doesnotexist", L".ini");
TestSearchPathHelper3("1.4", L"C:\\DirectoryDoesNotExist;C:\\", L"d:\\readme.txt", L".ini");
TestSearchPathHelper3("1.5", L"C:\\DirectoryDoesNotExist;C:\\", L"kernel32.dll", L".dll");
TestSearchPathHelper3("1.6", L"C:\\DirectoryDoesNotExist;C:\\", L"kernel32.", L".dll");
TestSearchPathHelper3("1.7", L"C:\\DirectoryDoesNotExist;C:\\", L"kernel32", L".dll");
TestSearchPathHelper3("1.8", L"C:\\DirectoryDoesNotExist;C:\\", L"kernel32.dll", L".ini");
TestSearchPathHelper3("1.9", L"C:\\DirectoryDoesNotExist;C:\\", L"kernel32.", L".ini");
TestSearchPathHelper3("1.10", L"C:\\DirectoryDoesNotExist;C:\\", L"kernel32", L".ini");
TestSearchPathHelper3("2.0", L"C:\\;C:\\DirectoryDoesNotExist", L"boot.ini", L".ini");
TestSearchPathHelper3("2.1", L"C:\\;C:\\DirectoryDoesNotExist", L"boot.", L".ini");
TestSearchPathHelper3("2.2", L"C:\\;C:\\DirectoryDoesNotExist", L"boot", L".ini");
TestSearchPathHelper3("2.3", L"C:\\;C:\\DirectoryDoesNotExist", L"doesnotexist.doesnotexist", L".ini");
TestSearchPathHelper3("2.4", L"C:\\;C:\\DirectoryDoesNotExist", L"d:\\readme.txt", L".ini");
TestSearchPathHelper3("2.5", L"C:\\;C:\\DirectoryDoesNotExist", L"kernel32.dll", L".dll");
TestSearchPathHelper3("2.6", L"C:\\;C:\\DirectoryDoesNotExist", L"kernel32.", L".dll");
TestSearchPathHelper3("2.7", L"C:\\;C:\\DirectoryDoesNotExist", L"kernel32", L".dll");
TestSearchPathHelper3("2.8", L"C:\\;C:\\DirectoryDoesNotExist", L"kernel32.dll", L".ini");
TestSearchPathHelper3("2.9", L"C:\\;C:\\DirectoryDoesNotExist", L"kernel32.", L".ini");
TestSearchPathHelper3("2.10", L"C:\\;C:\\DirectoryDoesNotExist", L"kernel32", L".ini");
TestSearchPathHelper3("3.0", PathToSearch, L"boot.ini", L".ini");
TestSearchPathHelper3("3.1", PathToSearch, L"boot", L".ini");
TestSearchPathHelper3("3.1", PathToSearch, L"boot.", L".ini");
TestSearchPathHelper3("3.2", PathToSearch, L"doesnotexist.doesnotexist", L".ini");
TestSearchPathHelper3("3.3", PathToSearch, L"d:\\readme.txt", L".ini");
*piNext = iNext;
return EXIT_SUCCESS;
}
BOOL
TestAct(
int argc,
wchar_t** argv,
int* piNext)
{
ULONG i, c;
ULONG_PTR *prgCookies = NULL;
HANDLE hActCtx = NULL;
CHAR buffer[1024];
int iNext = (*piNext + 1);
BOOL fSuccess = FALSE;
if (iNext >= argc)
{
fprintf(stderr, "%S: missing parameter after \"%S\"\n", argv[0], argv[iNext - 1]);
goto Exit;
}
WideCharToMultiByte(CP_ACP, 0, argv[iNext++], -1, buffer, NUMBER_OF(buffer), NULL, NULL);
ACTCTXA ac;
ac.cbSize = sizeof(ac);
ac.dwFlags = 0;
ac.lpSource = buffer;
ac.wProcessorArchitecture = g.wProcessorArchitecture;
ac.wLangId = g.wLangId;
hActCtx = ::CreateActCtxA(&ac);
if (hActCtx == INVALID_HANDLE_VALUE)
{
fprintf(stderr, "CreateActCtxA() failed; ::GetLastError() = %d\n", ::GetLastError());
return EXIT_FAILURE;
}
c = 0;
if (argc > iNext)
c = _wtoi(argv[iNext++]);
if (c == 0)
c = 100;
prgCookies = NEW(ULONG_PTR[c]);
if (prgCookies == NULL)
{
fprintf(stderr, "Unable to allocate %lu cookies.\n", c);
goto Exit;
}
for (i=0; i<c; i++)
{
if (!ActivateActCtx(hActCtx, &prgCookies[i]))
{
fprintf(stderr, "Attempt to activate to depth %lu failed; ::GetLastError() = %d\n", i, ::GetLastError());
goto Exit;
}
}
for (i=0; i<c; i++)
{
ULONG j = (c - i) - 1;
DeactivateActCtx(0, prgCookies[j]);
}
ReleaseActCtx(hActCtx);
fSuccess = TRUE;
*piNext = iNext;
Exit:
delete []prgCookies;
return fSuccess;
}
HRESULT Helper_WriteStream(CBaseStringBuffer * pFileNameBuf,
IStream *pStream)
{
HRESULT hr = NOERROR;
LPBYTE pBuf[0x4000];
DWORD cbBuf = 0x4000;
DWORD dwWritten = 0;
DWORD cbRead = 0;
HANDLE hf = INVALID_HANDLE_VALUE;
hf = ::CreateFileW(static_cast<PCWSTR>(*pFileNameBuf), GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if (hf == INVALID_HANDLE_VALUE){
hr = HRESULT_FROM_WIN32 (GetLastError());
goto Exit;
}
while (::ReadFile(hf, pBuf, cbBuf, &cbRead, NULL) && cbRead){
hr = pStream->Write(pBuf, cbRead, &dwWritten);
if (FAILED(hr))
goto Exit;
}
if (! SUCCEEDED(hr =pStream->Commit(0)))
goto Exit;
CloseHandle(hf);
Exit:
return hr;
}
BOOL
TestMSIInstall(
int argc,
wchar_t** argv,
int* piNext
)
{
BOOL fSuccess = FALSE;
FN_TRACE_WIN32(fSuccess);
CSmartRef<IAssemblyCache> pCache;
CSmartRef<IAssemblyCacheItem> ppCacheItem[4];
CSmartRef<IStream> pStream;
PFNCreateAssemblyCache pCreateAssemblyCache = NULL;
CStringBuffer SourceFilePathBuf;
CStringBuffer SourceFileNameBuf;
CHAR buf[1024];
FILE* fp = NULL;
LPSTR p1, pbuf ;
int i, cAsm;
int iArg = (*piNext) + 1;
if (iArg >= argc)
{
fprintf(stderr, "%S: missing parameter after \"%S\"\n", argv[0], argv[iArg-1]);
goto Exit;
}
LoadSxs();
GetSxsProc("CreateAssemblyCache", &pCreateAssemblyCache);
IFCOMFAILED_EXIT(pCreateAssemblyCache(&pCache, 0));
WideCharToMultiByte(CP_ACP, 0, argv[iArg], -1, buf, NUMBER_OF(buf), NULL, NULL);
fp = fopen(buf, "r");
if (!fp) {
fprintf(stderr, "%S: Error opening script file \"%S\"\n", argv[0], argv[iArg]);
goto Exit;
}
cAsm = 0;
while (! feof(fp)) {
if (! fgets(buf, 80, fp)) { // end of file or error
if (ferror(fp)){ // error occur
fprintf(stderr, "%S: Error occur while reading the script file\n", argv[0]);
goto Exit;
}
else{ // end of file
fprintf(stderr, "%S: end of script file\n", argv[0]);
break;
}
}
// trim the string
i = 0 ;
while (buf[i] == ' ') i++; // skip the whitespace at the beginning of the line
pbuf = buf + i ; // pointer to the first un-whitespace char in the line
i = 0 ;
while (pbuf[i] != '\n') i++;
pbuf[i] = '\0';
p1 = NULL;
p1 = strchr(pbuf, ' ');
if (p1 == NULL) { // instruction line
if (strcmp(pbuf, "BeginAsmCacheItem") == 0) {
IFCOMFAILED_EXIT(pCache->CreateAssemblyCacheItem(0, NULL, &ppCacheItem[cAsm], NULL));
}else
if (strcmp(pbuf, "EndAsmCacheItem") == 0) {
IFCOMFAILED_EXIT(ppCacheItem[cAsm]->Commit(0, NULL));
cAsm ++;
}
}
else
{ // get the first word of the line
*p1 = '\0';
p1++; // p1 points to the filename now
IFW32FALSE_EXIT(SourceFileNameBuf.Win32Assign(p1, ::strlen(p1)));
if (strcmp(pbuf,"SourceFilePath") == 0) { // fullpath of source files, which would be in a CD
IFW32FALSE_EXIT(SourceFilePathBuf.Win32Assign(p1, ::strlen(p1)));
SourceFilePathBuf.Win32EnsureTrailingPathSeparator();
}else
if (strcmp(pbuf, "FILE") == 0) {
IFCOMFAILED_EXIT(ppCacheItem[cAsm]->CreateStream(0, SourceFileNameBuf, STREAM_FORMAT_WIN32_MODULE, 0, &pStream, NULL));
IFW32FALSE_EXIT(SourceFileNameBuf.Win32Assign(SourceFilePathBuf, ::wcslen(SourceFilePathBuf)));
IFW32FALSE_EXIT(SourceFileNameBuf.Win32Append(p1, ::strlen(p1))); // containing full-path of the source file
IFCOMFAILED_EXIT(Helper_WriteStream(&SourceFileNameBuf, pStream));
pStream.Release(); // stream should be released since writtingfile has been done
}else
if (strcmp(pbuf, "MANIFEST") == 0) {
IFCOMFAILED_EXIT(ppCacheItem[cAsm]->CreateStream(0, SourceFileNameBuf, STREAM_FORMAT_WIN32_MANIFEST, 0, &pStream, NULL));
IFW32FALSE_EXIT(SourceFileNameBuf.Win32Assign(SourceFilePathBuf, SourceFilePathBuf.Cch())); // containing full-path of the source file
IFW32FALSE_EXIT(SourceFileNameBuf.Win32Append(p1, ::strlen(p1)));
IFCOMFAILED_EXIT(Helper_WriteStream(&SourceFileNameBuf, pStream));
pStream.Release(); // stream should be released since writtingfile has been done
}
} // end of else
}// end of while
fSuccess = TRUE;
*piNext = iArg;
Exit:
fp ? fclose(fp) : 0;
return fSuccess;
}
CDirWalk::ECallbackResult
DirWalkCallback(
CDirWalk::ECallbackReason reason,
CDirWalk* dirWalk,
DWORD dwFlags
)
{
PCWSTR parent = dirWalk->m_strParent;
PCWSTR leaf = dirWalk->m_fileData.cFileName;
if (reason == CDirWalk::eFile)
printf("file %lu, %ls, %ls\n", reason, parent, leaf);
else
printf("directory %lu, %ls\n", reason, parent);
return CDirWalk::eKeepWalking;
}
int
TestDirWalk(
PCWSTR root,
PWSTR filter
)
{
CDirWalk dirWalk;
StdVector<std::wstring> vstrFilter;
StdVector<PCWSTR> vstrFilter2;
PWSTR filterTok;
if (filterTok = wcstok(filter, L";"))
{
do
{
vstrFilter.push_back(filterTok);
vstrFilter2.push_back(vstrFilter.back().c_str());
} while (filterTok = wcstok(NULL, L";"));
}
dirWalk.m_fileFiltersBegin = &*vstrFilter2.begin();
dirWalk.m_fileFiltersEnd = &*vstrFilter2.end();
dirWalk.m_strParent.Win32Assign(root, ::wcslen(root));
dirWalk.m_callback = DirWalkCallback;
dirWalk.Walk();
return 0;
}
int
TestMultiAct(
int argc,
wchar_t **argv
)
{
HANDLE h1, h2;
ACTCTXW acw;
memset(&acw, 0, sizeof(acw));
acw.cbSize = sizeof(acw);
acw.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID;
acw.lpSource = argv[2];
acw.lpResourceName = MAKEINTRESOURCEW(1);
h1 = ::CreateActCtxW(&acw);
if (h1 == INVALID_HANDLE_VALUE)
{
fprintf(stderr, "1st CreateActCtxW() failed; ::GetLastError() = %d\n", ::GetLastError());
return EXIT_FAILURE;
}
h2 = ::CreateActCtxW(&acw);
if (h2 == INVALID_HANDLE_VALUE)
{
fprintf(stderr, "2nd CreateActCtxW() failed; ::GetLastError() = %d\n", ::GetLastError());
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
BOOL
ParseProcessorArchitecture(
int argc,
wchar_t** argv,
int* piCurrent
)
{
BOOL fSuccess = FALSE;
int i = *piCurrent;
i++;
if (i >= argc)
{
fprintf(stderr, "%S: missing parameter after %S\n", argv[0], argv[i - 1]);
goto Exit;
}
if (::FusionpStrCmpI(argv[i], L"x86") == 0)
g.wProcessorArchitecture = PROCESSOR_ARCHITECTURE_INTEL;
else if (::FusionpStrCmpI(argv[i], L"i386") == 0)
g.wProcessorArchitecture = PROCESSOR_ARCHITECTURE_INTEL;
else if (::FusionpStrCmpI(argv[i], L"ia64") == 0)
g.wProcessorArchitecture = PROCESSOR_ARCHITECTURE_IA64;
else if (::FusionpStrCmpI(argv[i], L"alpha64") == 0)
g.wProcessorArchitecture = PROCESSOR_ARCHITECTURE_ALPHA64;
else
{
fprintf(stderr, "%S: invalid -pa value \"%S\"\n", argv[0], argv[i]);
goto Exit;
}
*piCurrent = i + 1;
fSuccess = TRUE;
Exit:
return fSuccess;
}
BOOL
ParseLangId(
int argc,
wchar_t** argv,
int* piCurrent
)
{
BOOL fSuccess = FALSE;
int i = *piCurrent;
i++;
if (i >= argc)
{
fprintf(stderr, "%S: missing parameter after %S\n", argv[0], argv[i - 1]);
goto Exit;
}
swscanf(argv[i], L"%hx", &g.wLangId);
*piCurrent = i + 1;
fSuccess = TRUE;
Exit:
return fSuccess;
}
BOOL
TestLoadLibrary(
int argc,
wchar_t** argv,
int* piNext
)
{
int i = (*piNext) + 1;
HINSTANCE hInstance = NULL;
BOOL fExpectedToFail = FALSE;
BOOL fSuccess = FALSE;
while (i < argc)
{
if (::FusionpStrCmpI(argv[i], L"-fail-") == 0)
fExpectedToFail = TRUE;
else if (::FusionpStrCmpI(argv[i], L"-succeed-") == 0)
fExpectedToFail = FALSE;
else
{
hInstance = LoadLibraryW(argv[i]);
if (hInstance == NULL)
{
if (!fExpectedToFail)
{
fprintf(stderr, "%S: Failed to LoadLibraryW(\"%S\"); ::GetLastError() = %d\n", argv[0], argv[i], ::GetLastError());
}
}
else
{
if (fExpectedToFail)
{
WCHAR LibraryPath[4096];
Kernel32.GetModuleFileNameW(hInstance, LibraryPath, NUMBER_OF(LibraryPath));
fprintf(stderr, "%S: LoadLibraryW(\"%S\") was supposed to fail, but instead we got \"%S\"\n", argv[0], argv[i], LibraryPath);
}
::FreeLibrary(hInstance);
hInstance = NULL;
}
}
i++;
}
fSuccess = TRUE;
// Exit:
return fSuccess;
}
int TestAssemblyName()
{
SXSP_DEBUG_FUNCTION pfn = NULL;
BOOL fSuccess = FALSE;
LoadSxs();
GetSxsProc(SXSP_DEBUG_ORDINAL, &pfn);
fSuccess = (*pfn)(SXS_DEBUG_ASSEMBLYNAME_CONVERSION, 0, NULL, NULL);
if (! fSuccess){
fprintf(stderr, "%s failed!\n", __FUNCTION__);
return EXIT_FAILURE;
}
else
return EXIT_SUCCESS;
}
int TestPrecomiledManifest(PCWSTR manifestFileName)
{
SXSP_DEBUG_FUNCTION pfn = NULL;
BOOL fSuccess = FALSE;
LoadSxs();
GetSxsProc(SXSP_DEBUG_ORDINAL, &pfn);
fSuccess = (*pfn)(SXS_DEBUG_PRECOMPILED_MANIFEST, 0, manifestFileName, NULL);
if (! fSuccess){
fprintf(stderr, "%s failed!\n", __FUNCTION__);
return EXIT_FAILURE;
}
else
return EXIT_SUCCESS;
}
int TestPCMTime(PCWSTR manifestFilename)
{
SXSP_DEBUG_FUNCTION pfn = NULL;
BOOL fSuccess = FALSE;
LoadSxs();
GetSxsProc(SXSP_DEBUG_ORDINAL, &pfn);
fSuccess = (*pfn)(SXS_DEBUG_TIME_PCM, 0, manifestFilename, NULL);
if (! fSuccess)
{
fprintf(stderr, "%s failed!\n", __FUNCTION__);
return EXIT_FAILURE;
}
else
return EXIT_SUCCESS;
}
int TestCreateMultiLevelDirectory(PCWSTR dirs)
{
SXSP_DEBUG_FUNCTION pfn = NULL;
BOOL fSuccess = FALSE;
LoadSxs();
GetSxsProc(SXSP_DEBUG_ORDINAL, &pfn);
fSuccess = (*pfn)(SXS_DEBUG_CREAT_MULTILEVEL_DIRECTORY, 0, dirs, NULL);
if (! fSuccess)
{
fprintf(stderr, "%s failed!\n", __FUNCTION__);
return EXIT_FAILURE;
}
else
return EXIT_SUCCESS;
}
BOOL
TestLeakMemory(
DWORD dwAmount
)
{
SXSP_DEBUG_FUNCTION pfn = NULL;
BOOL fSuccess = FALSE;
if (dwAmount < 1) {
fprintf(stderr, "%s got a bad parameter, %d; rectifying to 1.\n", __FUNCTION__, dwAmount);
dwAmount = 1;
}
LoadSxs();
GetSxsProc(SXSP_DEBUG_ORDINAL, &pfn);
fSuccess = (*pfn)(SXS_DEBUG_FORCE_LEAK, 0, NULL, (PDWORD)&dwAmount);
if (! fSuccess)
{
fprintf(stderr, "%s failed to leak %d bytes of memory!\n", __FUNCTION__, dwAmount);
return EXIT_FAILURE;
}
else
{
fprintf(stdout, "%s leaked %d bytes of memory.\n", __FUNCTION__, dwAmount);
return EXIT_SUCCESS;
}
}
BOOL
TestManifestProbing(
int argc,
wchar_t **argv,
int *piNext
)
{
SXSP_DEBUG_FUNCTION pfn = NULL;
BOOL fSuccess = FALSE;
LoadSxs();
GetSxsProc(SXSP_DEBUG_ORDINAL, &pfn);
fSuccess = (*pfn)(SXS_DEBUG_PROBE_MANIFST, 0, NULL, NULL);
if (! fSuccess){
fprintf(stderr, "%s failed!\n", __FUNCTION__);
return EXIT_FAILURE;
}
else
return EXIT_SUCCESS;
}
BOOL
TestAssemblyProbing(
int argc,
wchar_t **argv,
int *piNext
)
{
PSXS_PROBE_ASSEMBLY_INSTALLATION pfn;
BOOL fSuccess = FALSE;
DWORD dwDisposition = 0;
LoadSxs();
GetSxsProc(SXS_PROBE_ASSEMBLY_INSTALLATION, &pfn);
fSuccess = (*pfn)(0, argv[*piNext], &dwDisposition);
return (fSuccess ? EXIT_SUCCESS : EXIT_FAILURE);
}
int TestCreateProcess2(wchar_t** argv)
{
STARTUPINFOW StartupInfo = { sizeof(StartupInfo) };
PROCESS_INFORMATION ProcessInformation = {0};
*argv += wcsspn(*argv, L" \t\r\n");
BOOL f = ::CreateProcessW(
*argv,
NULL,
NULL,
NULL,
FALSE,
0,
NULL,
NULL,
&StartupInfo,
&ProcessInformation);
printf("CreateProcess(%S) returned %s\n", *argv, f ? "True" : "False");
return EXIT_SUCCESS;
}
int TestCreateProcess(wchar_t** argv)
{
CUnicodeStringBuffer CommandLine;
STARTUPINFOW StartupInfo = { sizeof(StartupInfo) };
PROCESS_INFORMATION ProcessInformation = {0};
while (*argv)
{
CommandLine.Win32Append(L" ", 1);
CommandLine.Win32Append(*argv, ::wcslen(*argv));
argv++;
}
CUnicodeStringBufferAccessor MutableCommandLine(&CommandLine);
BOOL f = ::CreateProcessW(
NULL,
MutableCommandLine,
NULL,
NULL,
FALSE,
0,
NULL,
NULL,
&StartupInfo,
&ProcessInformation);
printf("CreateProcess(%S) returned %s\n", static_cast<PCWSTR>(MutableCommandLine), f ? "True" : "False");
return EXIT_SUCCESS;
}
////////////////////////////////////////////////////////////////////////////
// XMLDOM Helper function:
////////////////////////////////////////////////////////////////////////////
HRESULT XMLDOMHelper_WalkTree(IXMLDOMNode* node, int level)
{
IXMLDOMNode* pChild, *pNext;
BSTR nodeName;
IXMLDOMNamedNodeMap* pattrs;
node->get_nodeName(&nodeName);
for (int i = 0; i < level; i++)
printf(" ");
printf("%S",nodeName);
SysFreeString(nodeName);
if (SUCCEEDED(node->get_attributes(&pattrs)) && pattrs != NULL)
{
pattrs->nextNode(&pChild);
while (pChild)
{
BSTR name;
pChild->get_nodeName(&name);
printf(" %S='", name);
::SysFreeString(name);
VARIANT value;
pChild->get_nodeValue(&value);
if (value.vt == VT_BSTR)
{
printf("%S", V_BSTR(&value));
}
printf("'");
VariantClear(&value);
pChild->Release();
pattrs->nextNode(&pChild);
}
pattrs->Release();
}
printf("\n");
node->get_firstChild(&pChild);
while (pChild)
{
XMLDOMHelper_WalkTree(pChild, level+1);
pChild->get_nextSibling(&pNext);
pChild->Release();
pChild = pNext;
}
return S_OK;
}
////////////////////////////////////////////////////////////////////////////
// XMLDOM Helper function:
////////////////////////////////////////////////////////////////////////////
HRESULT XMLDOMHelper_ReportError(IXMLDOMParseError *pXMLError)
{
long line, linePos;
LONG errorCode;
BSTR pBURL = NULL, pBReason = NULL;
HRESULT hr;
hr = pXMLError->get_line(&line);
if (FAILED(hr))
goto Exit;
hr = pXMLError->get_linepos(&linePos);
if (FAILED(hr))
goto Exit;
hr = pXMLError->get_errorCode(&errorCode);
if (FAILED(hr))
goto Exit;
hr = pXMLError->get_url(&pBURL);
if (FAILED(hr))
goto Exit;
hr = pXMLError->get_reason(&pBReason);
if (FAILED(hr))
goto Exit;
fprintf(stderr, "%S", pBReason);
if (line > 0)
{
fprintf(stderr, "Error on line %d, position %d in \"%S\".\n",
line, linePos, pBURL);
}
hr= E_FAIL;
Exit:
SysFreeString(pBURL);
SysFreeString(pBReason);
return hr;
}
////////////////////////////////////////////////////////////////////////////
// XMLDOM Helper function: Check load results
////////////////////////////////////////////////////////////////////////////
HRESULT XMLDOMHelper_CheckLoad(IXMLDOMDocument* pDoc)
{
// And since we don't have the VARIANT_BOOL from load we
// need to check the parse Error errorCode property to see
// if everything went ok.
IXMLDOMParseError *pXMLError = NULL;
LONG errorCode;
HRESULT hr = NOERROR;
hr = pDoc->get_parseError(&pXMLError);
if (FAILED(hr))
goto Exit;
hr = pXMLError->get_errorCode(&errorCode);
if (FAILED(hr))
goto Exit;
if (errorCode != 0){
hr = XMLDOMHelper_ReportError(pXMLError);
goto Exit;
}
hr = NOERROR;
Exit:
if (pXMLError)
pXMLError->Release();
return hr;
}
////////////////////////////////////////////////////////////////////////////
// XMLDOM Helper function:
////////////////////////////////////////////////////////////////////////////
HRESULT XMLDOMHelper_LoadDocumentSync(IXMLDOMDocument *pDoc, BSTR pBURL)
{
IXMLDOMParseError *pXMLError = NULL;
VARIANT vURL;
VARIANT_BOOL vb;
HRESULT hr;
hr = pDoc->put_async(VARIANT_FALSE);
if (FAILED(hr))
goto Exit;
// Load xml document from the given URL or file path
VariantInit(&vURL);
vURL.vt = VT_BSTR;
V_BSTR(&vURL) = pBURL;
hr = pDoc->load(vURL, &vb);
if (FAILED(hr))
goto Exit;
hr = XMLDOMHelper_CheckLoad(pDoc);
if (FAILED(hr))
goto Exit;
hr = NOERROR;
Exit:
if (pXMLError)
pXMLError->Release();
return hr;
}
BOOL TestXMLDOM(PCWSTR pswzXMLFileName)
{
HRESULT hr = S_OK;
IXMLDOMDocument *pDoc = NULL;
IXMLDOMNode* pNode = NULL;
BSTR pBURL = NULL;
Ole32.CoInitialize(NULL);
// Create an empty XML document
hr = Ole32.CoCreateInstance(CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER,
IID_IXMLDOMDocument, (void**)&pDoc);
if (FAILED(hr))
goto Exit;
pBURL = SysAllocString(pswzXMLFileName);
hr = XMLDOMHelper_LoadDocumentSync(pDoc, pBURL);
if (FAILED(hr))
goto Exit;
// Now walk the loaded XML document dumping the node names to stdout.
hr = pDoc->QueryInterface(IID_IXMLDOMNode,(void**)&pNode);
if (FAILED(hr))
goto Exit;
hr = XMLDOMHelper_WalkTree(pNode,0);
if (FAILED(hr))
goto Exit;
hr = NOERROR;
Exit:
if (pDoc) pDoc->Release();
SysFreeString(pBURL);
if (pNode) pNode->Release();
Ole32.CoUninitialize();
return hr == 0 ? 0 : 1;
}
BOOL TestFusionArray(PCWSTR dir1, PCWSTR dir2)
{
SXSP_DEBUG_FUNCTION pfn = NULL;
BOOL fSuccess = FALSE;
LoadSxs();
GetSxsProc(SXSP_DEBUG_ORDINAL, &pfn);
fSuccess = (*pfn)(SXS_DEBUG_FUSION_ARRAY, 0, dir1, (PVOID)dir2);
if (! fSuccess){
fprintf(stderr, "%s failed!\n", __FUNCTION__);
return EXIT_FAILURE;
}
else
return EXIT_SUCCESS;
}
BOOL TestGeneratePathFromIdentityAttributeString(PCWSTR str)
{
PSXSPGENERATEMANIFESTPATHONASSEMBLYIDENTITY pfn = NULL;
BOOL fSuccess = FALSE;
WCHAR folderName[5000];
SIZE_T cch = NUMBER_OF(folderName);
LoadSxs();
GetSxsProc("SxspGenerateManifestPathOnAssemblyIdentity", &pfn);
fSuccess = (*pfn)((PWSTR) str, folderName, &cch, NULL);
if (! fSuccess)
{
fprintf(stderr, "%s failed!\n", __FUNCTION__);
return EXIT_FAILURE;
}
else
{
wprintf(L"Folder name returned is %s\n", folderName);
return EXIT_SUCCESS;
}
}
BOOL
TestDirectoryChangeWatcher(
int argc,
wchar_t **argv,
int *piNext
)
{
SXSP_DEBUG_FUNCTION pfn;
BOOL fSuccess;
LoadSxs();
GetSxsProc(SXSP_DEBUG_ORDINAL, &pfn);
fSuccess = (*pfn)(SXS_DEBUG_DIRECTORY_WATCHER, 0, NULL, NULL);
return (fSuccess ? EXIT_SUCCESS : EXIT_FAILURE);
}
BOOL
TestRefreshAssembly(
PCWSTR wsAssemblyManifest
)
{
BOOL fSuccess = FALSE;
PSXS_INSTALL_ASSEMBLY_W sxsInstallAssemblyW = NULL;
LoadSxs();
GetSxsProc("SxsInstallAssemblyW", &sxsInstallAssemblyW);
if (!sxsInstallAssemblyW(
NULL,
SXS_INSTALL_ASSEMBLY_FLAG_REPLACE_EXISTING,
wsAssemblyManifest,
NULL))
{
fwprintf(
stderr,
L"Failed reinstalling assembly '%ls', 0x%08X\n",
wsAssemblyManifest,
::GetLastError());
}
else
{
fSuccess = TRUE;
}
return fSuccess;
}
BOOL
TestInstallWithInstallInfo(
PCWSTR wsAssemblyManifest,
PCWSTR wsReferenceString
)
{
#define SXS_TEST
BOOL fSuccess = FALSE;
FN_TRACE_WIN32(fSuccess);
PSXS_INSTALL_W_ROUTINE sxsInstallW = NULL;
SXS_INSTALLW InstallParameters = {sizeof(InstallParameters)};
SXS_INSTALL_REFERENCEW InstallReference = {sizeof(InstallReference)};
LoadSxs();
GetSxsProc("SxsInstallW", &sxsInstallW);
InstallParameters.dwFlags =
//SXS_INSTALL_FLAG_MOVE |
SXS_INSTALL_FLAG_REPLACE_EXISTING |
SXS_INSTALL_FLAG_CODEBASE_URL_VALID |
SXS_INSTALL_FLAG_REFERENCE_VALID |
SXS_INSTALL_FLAG_REFRESH_PROMPT_VALID;
InstallParameters.lpCodebaseURL = wsAssemblyManifest;
InstallParameters.lpManifestPath = wsAssemblyManifest;
InstallParameters.lpReference = &InstallReference;
InstallParameters.lpRefreshPrompt = L"boop";
InstallReference.guidScheme = SXS_INSTALL_REFERENCE_SCHEME_OPAQUESTRING;
InstallReference.lpIdentifier = wsReferenceString ? wsReferenceString : L"TempRef";
if (!(*sxsInstallW)(&InstallParameters))
{
goto Exit;
}
fSuccess = TRUE;
Exit:
if (!fSuccess)
{
fprintf(stderr, "%s failed!\n", __FUNCTION__);
return EXIT_FAILURE;
}
else
return EXIT_SUCCESS;
}
BOOL
TestInstallLikeWindowsSetup(
PCWSTR wsAssemblyManifest,
PCWSTR wsCodebase
)
{
BOOL fSuccess = FALSE;
FN_TRACE_WIN32(fSuccess);
PSXS_BEGIN_ASSEMBLY_INSTALL sxsBeginAssemblyInstall = NULL;
PSXS_INSTALL_W_ROUTINE sxsInstallW = NULL;
PSXS_END_ASSEMBLY_INSTALL sxsEndAssemblyInstall = NULL;
SXS_INSTALLW InstallParameters = {sizeof(InstallParameters)};
SXS_INSTALL_REFERENCEW InstallReference = {sizeof(InstallReference)};
LoadSxs();
GetSxsProc("SxsBeginAssemblyInstall", &sxsBeginAssemblyInstall);
GetSxsProc("SxsInstallW", &sxsInstallW);
GetSxsProc("SxsEndAssemblyInstall", &sxsEndAssemblyInstall);
IFW32FALSE_EXIT(
(*sxsBeginAssemblyInstall)(
SXS_BEGIN_ASSEMBLY_INSTALL_FLAG_NOT_TRANSACTIONAL
| SXS_BEGIN_ASSEMBLY_INSTALL_FLAG_NO_VERIFY
| SXS_BEGIN_ASSEMBLY_INSTALL_FLAG_REPLACE_EXISTING,
NULL,
NULL,
NULL,
NULL,
&InstallParameters.pvInstallCookie));
InstallReference.guidScheme = SXS_INSTALL_REFERENCE_SCHEME_OSINSTALL;
InstallReference.lpNonCanonicalData = L"Foom";
InstallParameters.dwFlags |= SXS_INSTALL_FLAG_CODEBASE_URL_VALID
| SXS_INSTALL_FLAG_FROM_DIRECTORY
| SXS_INSTALL_FLAG_FROM_DIRECTORY_RECURSIVE
| SXS_INSTALL_FLAG_REFRESH_PROMPT_VALID
| SXS_INSTALL_FLAG_INSTALL_COOKIE_VALID
| SXS_INSTALL_FLAG_REFERENCE_VALID
;
InstallParameters.lpCodebaseURL = wsCodebase;
InstallParameters.lpRefreshPrompt = L"like..Windows CD..";
InstallParameters.lpManifestPath = wsAssemblyManifest;
InstallParameters.lpReference = &InstallReference;
IFW32FALSE_EXIT((*sxsInstallW)(&InstallParameters));
IFW32FALSE_EXIT(
(*sxsEndAssemblyInstall)(
InstallParameters.pvInstallCookie,
SXS_END_ASSEMBLY_INSTALL_FLAG_COMMIT,
NULL));
InstallParameters.pvInstallCookie = NULL;
fSuccess = TRUE;
Exit:
if (InstallParameters.pvInstallCookie != NULL)
{
CSxsPreserveLastError ple;
(void) (*sxsEndAssemblyInstall)(InstallParameters.pvInstallCookie, SXS_END_ASSEMBLY_INSTALL_FLAG_ABORT, NULL);
ple.Restore();
}
if (!fSuccess)
{
fprintf(stderr, "%s failed!\n", __FUNCTION__);
return EXIT_FAILURE;
}
else
return EXIT_SUCCESS;
}
//#define ASM_CPUID { __asm __emit 0fh __asm __emit 0a2h }
#define ASM_CPUID { __asm cpuid }
#define ASM_RDTSC { __asm rdtsc }
inline VOID GetCpuIdLag(LARGE_INTEGER *ref)
{
#if !defined(_WIN64)
LARGE_INTEGER temp, temp2;
_asm
{
cpuid
cpuid
cpuid
cpuid
cpuid
rdtsc
mov temp.LowPart, eax
mov temp.HighPart, edx
cpuid
rdtsc
mov temp2.LowPart, eax
mov temp2.HighPart, edx
}
ref->QuadPart = temp2.QuadPart - temp.QuadPart;
#else
ref->QuadPart = 0;
#endif
}
BOOL
TestOpeningStuff(PCWSTR wsSourceName, PCWSTR wsType, PCWSTR wsCount)
{
BOOL fSuccess = FALSE;
LARGE_INTEGER llStartCount, llEndCount, llCountsPerSec, llTotalSizeSoFar;
LARGE_INTEGER CpuIdLag;
BYTE bBuffer[65536];
SIZE_T cNumTries = _wtol(wsCount);
double dCountsPerSecond, dSeconds, dCountsPerIteration, dSecondsPerIteration;
int iFinalIterationsPerSecond;
GetCpuIdLag(&CpuIdLag);
llTotalSizeSoFar.QuadPart = 0;
{
FUSION_PERF_INFO PerfInfo[2];
HANDLE hFile;
for (int i = 0; i < 5000; i++)
{
PERFINFOTIME(&PerfInfo[0], hFile = ::CreateFileW(wsSourceName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL));
PERFINFOTIME(&PerfInfo[1], ::CloseHandle(hFile));
}
FusionpReportPerfInfo(
FUSIONPERF_DUMP_TO_STDOUT |
FUSIONPERF_DUMP_ALL_STATISTICS |
FUSIONPERF_DUMP_ALL_SOURCEINFO,
PerfInfo,
NUMBER_OF(PerfInfo));
}
//
// Map the DLL as a resource a few thousand times.
//
if ((wsType[0] == L'd') || (wsType[0] == L's'))
{
FUSION_PERF_INFO PerfInfo[7];
HMODULE hDllModule;
HRSRC hManifestResource;
HGLOBAL hResource;
PVOID pvResourceData;
SIZE_T cbResourceSize;
for (SIZE_T i = 0; i < cNumTries; i++)
{
PERFINFOTIME(&PerfInfo[0], hDllModule = ::LoadLibraryExW(wsSourceName, NULL, DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE));
PERFINFOTIME(&PerfInfo[1], hManifestResource = ::FindResourceW(hDllModule, L"#1", MAKEINTRESOURCEW(RT_MANIFEST)));
PERFINFOTIME(&PerfInfo[2], hResource = ::LoadResource(hDllModule, hManifestResource));
PERFINFOTIME(&PerfInfo[3], pvResourceData = ::LockResource(hResource));
PERFINFOTIME(&PerfInfo[4], cbResourceSize = ::SizeofResource(hDllModule, hManifestResource));
PERFINFOTIME(&PerfInfo[5],
{ for (SIZE_T i2 = 0; i2 < cbResourceSize; i2++)
bBuffer[i2] = ((PBYTE)pvResourceData)[i2]; }
);
PERFINFOTIME(&PerfInfo[6], FreeLibrary(hDllModule))
}
FusionpReportPerfInfo(
FUSIONPERF_DUMP_TO_STDOUT |
FUSIONPERF_DUMP_ALL_STATISTICS |
FUSIONPERF_DUMP_ALL_SOURCEINFO,
PerfInfo,
NUMBER_OF(PerfInfo));
}
else if (wsType[0] == L'x')
{
HANDLE hFile;
HANDLE hFileMapping;
PVOID pvFileData;
SIZE_T cbFileSize;
FUSION_PERF_INFO PerfInfo[9];
for (SIZE_T i = 0; i < cNumTries; i++)
{
PERFINFOTIME(&PerfInfo[0], hFile = ::CreateFileW(wsSourceName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL));
PERFINFOTIME(&PerfInfo[1], cbFileSize = ::GetFileSize(hFile, 0));
PERFINFOTIME(&PerfInfo[2], hFileMapping = ::CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL));
PERFINFOTIME(&PerfInfo[3], pvFileData = ::MapViewOfFile(hFileMapping, FILE_MAP_READ, 0, 0, 0));
PERFINFOTIME(&PerfInfo[4], { for (SIZE_T i2 = 0; i2 < cbFileSize; i2++)
PERFINFOTIME(&PerfInfo[8], bBuffer[i2] = ((PBYTE)pvFileData)[i2]); });
PERFINFOTIME(&PerfInfo[5], ::UnmapViewOfFile(pvFileData));
PERFINFOTIME(&PerfInfo[6], ::CloseHandle(hFileMapping));
PERFINFOTIME(&PerfInfo[7], ::CloseHandle(hFile));
}
FusionpReportPerfInfo(
FUSIONPERF_DUMP_TO_STDOUT |
FUSIONPERF_DUMP_ALL_STATISTICS |
FUSIONPERF_DUMP_ALL_SOURCEINFO,
PerfInfo,
NUMBER_OF(PerfInfo));
}
else if (wsType[0] == L'r')
{
BYTE bTempBlock[8192];
ULONG cbReadCount;
FUSION_PERF_INFO PerfInfo[3];
for (SIZE_T i = 0; i < cNumTries; i++)
{
CResourceStream RStream;
QueryPerformanceCounter(&llStartCount);
PERFINFOTIME(&PerfInfo[0], RStream.Initialize(wsSourceName, MAKEINTRESOURCEW(RT_MANIFEST)));
PERFINFOTIME(&PerfInfo[1], RStream.Read(bTempBlock, sizeof(bTempBlock), &cbReadCount));
PERFINFOTIME(&PerfInfo[2],
for (SIZE_T i2 = 0; i2 < cbReadCount; i2++)
{
bBuffer[i2] = bTempBlock[i2];
}
);
wprintf(L"%s", bBuffer);
QueryPerformanceCounter(&llEndCount);
llTotalSizeSoFar.QuadPart += llEndCount.QuadPart - llStartCount.QuadPart;
}
for (int i = 0; i < NUMBER_OF(PerfInfo); i++)
{
FusionpDumpPerfInfo(FUSIONPERF_DUMP_TO_STDOUT, PerfInfo + i);
}
}
else if (wsType[0] == L'f')
{
BYTE bTempBlock[8192];
ULONG cbReadCount;
for (SIZE_T i = 0; i < cNumTries; i++)
{
CFileStream RStream;
QueryPerformanceCounter(&llStartCount);
RStream.OpenForRead(
wsSourceName,
CImpersonationData(),
FILE_SHARE_READ,
OPEN_EXISTING,
FILE_FLAG_SEQUENTIAL_SCAN);
RStream.Read(bTempBlock, sizeof(bTempBlock), &cbReadCount);
for (SIZE_T i2 = 0; i2 < cbReadCount; i2++)
{
bBuffer[i2] = bTempBlock[i2];
}
QueryPerformanceCounter(&llEndCount);
llTotalSizeSoFar.QuadPart += llEndCount.QuadPart - llStartCount.QuadPart;
}
}
QueryPerformanceFrequency(&llCountsPerSec);
dCountsPerIteration = (double)llTotalSizeSoFar.QuadPart / cNumTries;
dCountsPerSecond = (double)llCountsPerSec.QuadPart;
dSeconds = (double)llTotalSizeSoFar.QuadPart / dCountsPerSecond;
dSecondsPerIteration = dCountsPerIteration / dCountsPerSecond;
iFinalIterationsPerSecond = static_cast<int>(1.0 / dSecondsPerIteration);
fwprintf(
stdout,
L"Completed %d runs: %d attempts per second available\n",
cNumTries,
iFinalIterationsPerSecond);
fSuccess = TRUE;
return fSuccess;
}
BOOL
TestVerifyFileSignature(PCWSTR wsFilename)
{
WINTRUST_FILE_INFO fInfo;
WINTRUST_DATA wtData;
GUID guidTrustType = WINTRUST_ACTION_GENERIC_VERIFY_V2;
HRESULT hResult = E_FAIL;
PWSTR pwszMessageText = NULL;
ZeroMemory(&wtData, sizeof(wtData));
ZeroMemory(&fInfo, sizeof(fInfo));
fInfo.cbStruct = sizeof(fInfo);
fInfo.pcwszFilePath = wsFilename;
fInfo.hFile = NULL;
wtData.cbStruct = sizeof(wtData);
wtData.dwUIChoice = WTD_UI_ALL;
wtData.fdwRevocationChecks = WTD_REVOKE_WHOLECHAIN;
wtData.dwUnionChoice = WTD_CHOICE_FILE;
wtData.pFile = &fInfo;
hResult = WinVerifyTrust(0, &guidTrustType, &wtData);
if (FAILED(hResult))
{
::FormatMessageW(
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER,
NULL,
hResult,
0,
(PWSTR)&pwszMessageText,
500,
NULL);
fwprintf(stdout, L"Error: %ls (code 0x%08x)\n", pwszMessageText, hResult);
LocalFree(pwszMessageText);
}
else
{
fwprintf(stdout, L"File signature(s) are valid.");
}
return TRUE;
}
__inline
ULONGLONG
GetCycleCount(void)
{
#if defined(_X86_)
__asm {
RDTSC
}
#else
return 0;
#endif // defined(_X86_)
}
BOOL TestMessagePerf(int argc, wchar_t **argv, int *piNext)
{
ATOM a;
WNDCLASSEXW wc;
ULONGLONG cc1, cc2, cc3, cc4;
ULONG i, t;
HWND hwnd;
MSG m;
ULONG mcount;
HANDLE hActCtx = NULL;
ULONG_PTR ulCookie;
wc.cbSize = sizeof(wc);
wc.style = 0;
wc.lpfnWndProc = &TestMessagePerfWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = NULL;
wc.hIcon = NULL;
wc.hCursor = NULL;
wc.hbrBackground = NULL;
wc.lpszMenuName = NULL;
wc.lpszClassName = L"SxsMsgPerfTest";
wc.hIconSm = NULL;
printf("Beginning message perf test...\n");
a = ::RegisterClassExW(&wc);
if (a == NULL)
{
printf("RegisterClassExW() failed; ::GetLastError = %d\n", ::GetLastError());
return FALSE;
}
if (argv[*piNext][0] != L'*')
{
ACTCTXW ac;
ac.cbSize = sizeof(ac);
ac.dwFlags = 0;
ac.lpSource = argv[*piNext];
hActCtx = ::CreateActCtxW(&ac);
if (hActCtx == INVALID_HANDLE_VALUE)
{
printf("CreateActCtxW() failed; ::GetLastError() = %d\n", ::GetLastError());
goto ErrorExit;
}
}
if (!ActivateActCtx(hActCtx, &ulCookie))
{
printf("ActivateActCtx() failed; ::GetLastError() = %d\n", ::GetLastError());
goto ErrorExit;
}
(*piNext)++;
hwnd = ::CreateWindowW(
(LPCWSTR) a,
L"PerfTestWindow",
WS_VISIBLE,
0, // x
0, // y
100, // width
100, // height
NULL, // hwndParent
NULL, // hMenu
NULL, // hInstance
NULL); // lpParam
if (hwnd == NULL)
return FALSE;
t = _wtoi(argv[*piNext]);
(*piNext)++;
mcount = 0;
cc3 = 0;
cc4 = 0;
for (i=0; i<t; i++)
{
if (!PostMessageW(hwnd, WM_USER, 0, 0))
{
printf("PostMessageW() failed; ::GetLastError() = %d\n", ::GetLastError());
goto ErrorExit;
}
cc1 = GetCycleCount();
while (::PeekMessage(&m, hwnd, 0, 0, PM_REMOVE))
{
mcount++;
::TranslateMessage(&m);
::DispatchMessage(&m);
}
cc2 = GetCycleCount();
// accumulate the time spend just processing the message...
cc3 = cc3 + (cc2 - cc1);
}
printf("%lu messages in %I64u cycles\n", mcount, cc3);
printf(" avg cycles/msg: %I64u\n", static_cast<ULONGLONG>((cc3 / static_cast<ULONGLONG>(mcount))));
return TRUE;
ErrorExit:
return FALSE;
}
LRESULT CALLBACK TestMessagePerfWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
void
TestTrickyMultipleAssemblyCacheItems(PCWSTR pvManifest)
{
PFNCreateAssemblyCacheItem pCreateAssemblyCacheItem;
PFNCreateAssemblyCache pCreateAssemblyCache;
CSmartRef<IAssemblyCache> AssemblyCache;
CSmartRef<IAssemblyCacheItem> AssemblyCacheItems[2];
CStringBuffer sbManifestName;
HRESULT hr;
LoadSxs();
GetSxsProc("CreateAssemblyCache", &pCreateAssemblyCache);
GetSxsProc("CreateAssemblyCacheItem", &pCreateAssemblyCacheItem);
sbManifestName.Win32Assign(pvManifest, wcslen(pvManifest));
for (int i = 0; i < 2; i++)
{
CSmartRef<IStream> pStream;
CSmartRef<IAssemblyCacheItem> AssemblyItemTemp;
CStringBuffer TempStreamName;
hr = pCreateAssemblyCacheItem(
&AssemblyItemTemp,
NULL,
NULL,
NULL,
0,
0);
//
// Manifest
//
hr = AssemblyItemTemp->CreateStream(0, pvManifest, STREAM_FORMAT_WIN32_MANIFEST, 0, &pStream, NULL);
TempStreamName.Win32Assign(sbManifestName);
hr = Helper_WriteStream(&TempStreamName, pStream);
pStream.Release();
//
// Dll
//
sbManifestName.Win32ChangePathExtension(L".dll", 4, eAddIfNoExtension);
hr = AssemblyItemTemp->CreateStream(0, static_cast<PCWSTR>(TempStreamName), STREAM_FORMAT_WIN32_MODULE, 0, &pStream, NULL);
hr = Helper_WriteStream(&TempStreamName, pStream);
pStream.Release();
hr = AssemblyItemTemp->Commit(0, NULL);
AssemblyCacheItems[i] = AssemblyItemTemp;
}
/*
hr = pCreateAssemblyCache(&AssemblyCache, 0);
hr = AssemblyCache->MarkAssembliesVisible((IUnknown**)AssemblyCacheItems, 2, 0);
*/
}
void
TestSfcScanKickoff()
{
SXSP_DEBUG_FUNCTION pfn;
BOOL fSuccess = FALSE;
LoadSxs();
GetSxsProc(SXSP_DEBUG_ORDINAL, &pfn);
fSuccess = (*pfn)(SXS_DEBUG_SFC_SCANNER, 0, NULL, NULL);
}
void
GenerateStrongNameAndPublicKey(PCWSTR wsCertificate)
{
BOOL bSuccess = FALSE;
CStringBuffer sbStrings[3];
PCCERT_CONTEXT pContext = NULL;
SXSP_DEBUG_FUNCTION pfn;
HCERTSTORE hCertStore = NULL;
hCertStore = CertOpenStore(
CERT_STORE_PROV_FILENAME,
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
NULL,
CERT_STORE_OPEN_EXISTING_FLAG,
(void*)wsCertificate);
LoadSxs();
GetSxsProc(SXSP_DEBUG_ORDINAL, &pfn);
while (pContext = CertEnumCertificatesInStore(hCertStore, pContext))
{
bSuccess = (*pfn)(SXS_DEBUG_GET_STRONGNAME, 0, (PCWSTR)pContext, (PVOID)sbStrings);
wprintf(L"Signer display name: %ls\n\tPublic Key: %ls\n\tPublic Key Token: %ls\n",
static_cast<PCWSTR>(sbStrings[0]),
static_cast<PCWSTR>(sbStrings[1]),
static_cast<PCWSTR>(sbStrings[2]));
}
bSuccess = TRUE;
if (pContext) CertFreeCertificateContext(pContext);
if (hCertStore) CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG);
}
BOOL CALLBACK
DumpResourceWorker(
HMODULE hModule,
PCWSTR lpszType,
PWSTR lpszName,
LONG_PTR lParam
)
{
HGLOBAL hGlobal;
HRSRC hResource;
PVOID pvData;
SIZE_T cbResource;
hResource = ::FindResourceW(hModule, lpszName, lpszType);
hGlobal = ::LoadResource(hModule, hResource);
pvData = ::LockResource(hGlobal);
if (lpszName < (PCWSTR)0xFFFF)
{
wprintf(L"----\nResource id: %p\n", lpszName);
}
else
{
wprintf(L"----\nResource name: %ls\n", lpszName);
}
cbResource = ::SizeofResource(hModule, hResource);
for (SIZE_T i = 0; i < cbResource; i++)
{
wprintf(L"%c", ((char*)pvData)[i]);
}
wprintf(L"\n");
return TRUE;
}
BOOL
TestDumpContainedManifests(PCWSTR wsFilename)
{
HMODULE hThing;
hThing = ::LoadLibraryExW(wsFilename, NULL, LOAD_LIBRARY_AS_DATAFILE);
if ((hThing == NULL) || (hThing == INVALID_HANDLE_VALUE))
{
wprintf(L"Bad mojo: can't open %ls for enumeration.\n", wsFilename);
return FALSE;
}
if (!::EnumResourceNamesW(hThing, MAKEINTRESOURCEW(RT_MANIFEST), DumpResourceWorker, NULL))
{
if (GetLastError() == ERROR_RESOURCE_TYPE_NOT_FOUND)
{
wprintf(L"No manifests found in %ls\n", wsFilename);
}
else
{
wprintf(L"Bad mojo: can't enumerate resources from %ls, error=0x%08x\n",
wsFilename,
::GetLastError());
}
}
::FreeLibrary(hThing);
return TRUE;
}
BOOL TestGenerateStringWithIdenticalHash(WCHAR iString[33])
{
#define START_VALUE 1
#define STR_LEN 32
#define HASH_SEED 65599
#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} ;
#define UPPER(ch) if (ch >=L'a' && ch <= L'z') ch = ch- L'a' + L'A';
WCHAR oString[STR_LEN + 1];
DWORD i, nLen, a[STR_LEN];
ULONG hash1, hash2;
WCHAR ch;
a[0] = a[1] = START_VALUE;
nLen = 2;
while(nLen < STR_LEN) {
for(i = nLen; i < nLen*2; i++)
a[i] = static_cast<ULONG>(-static_cast<LONG>(a[i-nLen]));
nLen *= 2;
}
oString[32] = iString[32] = L'\0';
// generate the new string
for (i = 0; i< 32; i++)
oString[i] = static_cast<WCHAR>(iString[i] + a[i]);
// verify that these two string have the same hash
hash1 = 0 ;
for (i = 0 ; i<STR_LEN; i++) {
ch = iString[i];
UPPER(ch);
hash1 = hash1*HASH_SEED + ch;
}
hash2 = 0 ;
for (i = 0 ; i<STR_LEN; i++){
ch = oString[i];
UPPER(ch);
hash2 = hash2*HASH_SEED + ch;
}
return (hash1 == hash2)? TRUE : FALSE;
#undef START_VALUE
#undef STR_LEN
#undef HASH_SEED
}
BOOL TestAssemblyIdentityHash()
{
SXSP_DEBUG_FUNCTION pfn = NULL;
BOOL fSuccess = FALSE;
LoadSxs();
GetSxsProc(SXSP_DEBUG_ORDINAL, &pfn);
fSuccess = (*pfn)(SXS_DEBUG_ASSEMBLY_IDENTITY_HASH, 0, 0, NULL);
if (! fSuccess){
fprintf(stderr, "%s failed!\n", __FUNCTION__);
return EXIT_FAILURE;
}
else
return EXIT_SUCCESS;
}
const static WCHAR Beta2Manifest[] =
L"<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
L" <assemblyIdentity type=\"win32\" name=\"cards\" version=\"2.0.0.0\" processorArchitecture=\"X86\" language=\"en-us\" />"
L" <file name=\"cards.dll\"/>"
L"</assembly>;"
;
// check whether the handle counter of csrss has changed dramatically after running this code.....
VOID TestCreateActctxLeakHandles(DWORD dwCallCounter)
{
int result = -1;
BOOL fSuccess;
for (DWORD i =0 ; i < dwCallCounter ; i ++)
{
HANDLE ActivationContextHandle = ::CreateActivationContextFromStringW(InheritManifest);
if (ActivationContextHandle == INVALID_HANDLE_VALUE) {
result = i ;
break;
}
ULONG_PTR Cookie;
ActivateActCtx(ActivationContextHandle, &Cookie);
HINSTANCE hInstanceKernel32 = ::GetModuleHandleW(L"KERNEL32.DLL");
PQUERYACTCTXW_FUNC pQueryActCtxW = (PQUERYACTCTXW_FUNC) ::GetProcAddress(hInstanceKernel32, "QueryActCtxW");
SIZE_T CbWritten;
if (pQueryActCtxW != NULL)
{
for ( ULONG ulInfoClass = ActivationContextBasicInformation; ulInfoClass <= FileInformationInAssemblyOfAssemblyInActivationContext; ulInfoClass ++)
{
switch (ulInfoClass) {
case ActivationContextBasicInformation :
break;
case ActivationContextDetailedInformation :
{
struct
{
ACTIVATION_CONTEXT_DETAILED_INFORMATION acdi;
WCHAR Buffer[_MAX_PATH * 3]; // manifest, policy and appdir
} Data;
ULONG index = 0 ;
fSuccess = (*pQueryActCtxW)(0, ActivationContextHandle, &index, ulInfoClass, &Data, sizeof(Data), &CbWritten);
fprintf(stderr, "\ncall QueryActCtxW with ActivationContextDetailedInformation\n" );
if (fSuccess)
{
fprintf(stderr, "1st string: %ls\n", Data.acdi.lpAppDirPath);
fprintf(stderr, "2nd string: %ls\n", Data.acdi.lpRootManifestPath);
}
else
fprintf(stderr, "QueryActCtxW() failed; ::GetLastError() = %d\n", ::GetLastError());
}
break;
case AssemblyDetailedInformationInActivationContext:
{
struct
{
ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION acdi;
WCHAR Buffer[_MAX_PATH * 4];
} Data;
ULONG AssemblyIndex = 1;
fSuccess = (*pQueryActCtxW)(0, ActivationContextHandle, &AssemblyIndex, ulInfoClass, &Data, sizeof(Data), &CbWritten);
fprintf(stderr, "\ncall QueryActCtxW with AssemblyDetailedInformationInActivationContext\n" );
if (fSuccess)
{
fprintf(stderr, "Encoded assembly Identity: %ls\n", Data.acdi.lpAssemblyEncodedAssemblyIdentity);
fprintf(stderr, "manifest path: %ls\n", Data.acdi.lpAssemblyManifestPath);
fprintf(stderr, "policy path: %ls\n", Data.acdi.lpAssemblyPolicyPath);
fprintf(stderr, "Assembly Directory: %ls\n", Data.acdi.lpAssemblyDirectoryName);
}
else
fprintf(stderr, "QueryActCtxW() failed; ::GetLastError() = %d\n", ::GetLastError());
}
break;
case FileInformationInAssemblyOfAssemblyInActivationContext:
{
struct
{
ASSEMBLY_DLL_REDIRECTION_DETAILED_INFORMATION acdi;
WCHAR Buffer[_MAX_PATH * 2];
} Data;
ACTIVATION_CONTEXT_QUERY_INDEX index;
index.ulAssemblyIndex = 1;
index.ulFileIndexInAssembly = 0;
fSuccess = (*pQueryActCtxW)(0, ActivationContextHandle, &index, ulInfoClass, &Data, sizeof(Data), &CbWritten);
fprintf(stderr, "\ncall QueryActCtxW with FileInformationInAssemblyOfAssemblyInActivationContext\n" );
if (fSuccess)
{
fprintf(stderr, "file name: %ls\n", Data.acdi.lpFileName);
fprintf(stderr, "file path: %ls\n", Data.acdi.lpFilePath);
}
else
fprintf(stderr, "QueryActCtxW() failed; ::GetLastError() = %d\n", ::GetLastError());
}
} // end of switch
}// end of for
}
DeactivateActCtx(0, Cookie);
// CloseHandle(ActivationContextHandle);
}
return;
}
BOOL TestSystemDefaultActivationContextGeneration()
{
SXSP_DEBUG_FUNCTION pfn = NULL;
BOOL fSuccess = FALSE;
LoadSxs();
GetSxsProc(SXSP_DEBUG_ORDINAL, &pfn);
fSuccess = (*pfn)(SXS_DEBUG_SYSTEM_DEFAULT_ACTCTX_GENERATION, 0, NULL, NULL);
if (! fSuccess){
fprintf(stderr, "%s failed!\n", __FUNCTION__);
return EXIT_FAILURE;
}
else
return EXIT_SUCCESS;
}
CHAR g_AsyncIOBuffer[16384];
struct AsyncIOBlock
{
OVERLAPPED ol_input;
OVERLAPPED ol_output;
HANDLE hInputFile;
HANDLE hOutputFile;
} g_AsyncIOBlock;
bool g_AsyncIODone = false;
DWORD g_AsyncIOError = ERROR_SUCCESS;
VOID CALLBACK AsyncReadCompleted(
DWORD dwErrorCode,
DWORD dwBytesTransferred,
LPOVERLAPPED ol
);
VOID CALLBACK AsyncWriteCompleted(
DWORD dwErrorCode,
DWORD dwBytesTransferred,
LPOVERLAPPED ol
);
VOID CALLBACK AsyncReadCompleted(
DWORD dwErrorCode,
DWORD dwBytesTransferred,
LPOVERLAPPED ol
)
{
if (dwErrorCode != ERROR_SUCCESS)
{
fprintf(stderr, "Error passed to AsyncReadCompleted(); error code = %ul; bytes transferred = %ul\n", dwErrorCode, dwBytesTransferred);
g_AsyncIOError = dwErrorCode;
g_AsyncIODone = true;
}
else
{
g_AsyncIOBlock.ol_input.Offset += dwBytesTransferred;
if (!::WriteFileEx(g_AsyncIOBlock.hOutputFile, g_AsyncIOBuffer, dwBytesTransferred, &g_AsyncIOBlock.ol_output, &AsyncWriteCompleted))
{
g_AsyncIOError = ::GetLastError();
fprintf(stderr, "WriteFileEx() failed; ::GetLastError() = %d\n", g_AsyncIOError);
g_AsyncIODone = true;
}
}
}
VOID CALLBACK AsyncWriteCompleted(
DWORD dwErrorCode,
DWORD dwBytesTransferred,
LPOVERLAPPED ol
)
{
if (dwErrorCode != ERROR_SUCCESS)
{
fprintf(stderr, "Error passed to AsyncWriteCompleted(); error code = %ul; dwBytesTransferred = %ul\n", dwErrorCode, dwBytesTransferred);
g_AsyncIOError = dwErrorCode;
g_AsyncIODone = true;
}
else
{
g_AsyncIOBlock.ol_output.Offset += dwBytesTransferred;
if (!::ReadFileEx(g_AsyncIOBlock.hInputFile, g_AsyncIOBuffer, sizeof(g_AsyncIOBuffer), &g_AsyncIOBlock.ol_input, &AsyncReadCompleted))
{
g_AsyncIOError = ::GetLastError();
if (g_AsyncIOError != ERROR_HANDLE_EOF)
fprintf(stderr, "ReadFileEx() failed; ::GetLastError() = %d\n", g_AsyncIOError);
else
g_AsyncIOError = ERROR_SUCCESS;
g_AsyncIODone = true;
}
}
}
BOOL
TestAsyncIO(int argc, wchar_t **argv, int *piNext)
{
HANDLE hFileIn;
HANDLE hFileOut;
HANDLE hActCtx = NULL;
ULONG_PTR cookie = 0;
PCWSTR pszManifest;
PCWSTR pszInputFile;
PCWSTR pszOutputFile;
ACTCTXW acw;
pszManifest = argv[(*piNext)++];
pszInputFile = argv[(*piNext)++];
pszOutputFile = argv[(*piNext)++];
if (wcscmp(pszManifest, L"-") != 0)
{
acw.cbSize = sizeof(acw);
acw.dwFlags = 0;
acw.lpSource = pszManifest;
hActCtx = ::CreateActCtxW(&acw);
if (hActCtx == INVALID_HANDLE_VALUE)
{
fprintf(stderr, "CreateActCtxW() on %ls failed; ::GetLastError() = %d\n", pszManifest, ::GetLastError());
return EXIT_FAILURE;
}
}
hFileIn = ::CreateFileW(pszInputFile, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if (hFileIn == INVALID_HANDLE_VALUE)
{
fprintf(stderr, "CreateFileW() on %ls failed; ::GetLastError() = %d\n", pszInputFile, ::GetLastError());
return EXIT_FAILURE;
}
hFileOut = ::CreateFileW(pszOutputFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING, NULL);
if (hFileOut == INVALID_HANDLE_VALUE)
{
fprintf(stderr, "CreateFileW() on %ls failed; ::GetLastError() = %d\n", pszOutputFile, ::GetLastError());
return EXIT_FAILURE;
}
ActivateActCtx(hActCtx, &cookie);
g_AsyncIOBlock.ol_input.Offset = 0;
g_AsyncIOBlock.ol_input.OffsetHigh = 0;
g_AsyncIOBlock.ol_output.Offset = 0;
g_AsyncIOBlock.ol_output.OffsetHigh = 0;
g_AsyncIOBlock.hInputFile = hFileIn;
g_AsyncIOBlock.hOutputFile = hFileOut;
if (!::ReadFileEx(hFileIn, &g_AsyncIOBuffer, sizeof(g_AsyncIOBuffer), &g_AsyncIOBlock.ol_input, &AsyncReadCompleted))
{
fprintf(stderr, "First ReadFileEx() failed; ::GetLastError() = %d\n", ::GetLastError());
return EXIT_FAILURE;
}
while (!g_AsyncIODone)
{
::SleepEx(1000, TRUE);
}
if (g_AsyncIOError != ERROR_SUCCESS)
{
fprintf(stderr, "Async IO test failed; win32 error code = %d\n", g_AsyncIOError);
return EXIT_FAILURE;
}
CloseHandle(hFileIn);
CloseHandle(hFileOut);
return EXIT_SUCCESS;
}
static
DWORD
WINAPI
TestThreadInheritLeakThreadProc(
LPVOID lpParameter
)
{
// Don't need to do anything...
return 1;
}
int
TestThreadInheritLeak()
{
HANDLE ActivationContextHandle = ::CreateActivationContextFromStringW(InheritManifest);
DWORD dwThreadId;
ULONG_PTR ulpCookie;
HANDLE hThread = NULL;
::ActivateActCtx(ActivationContextHandle, &ulpCookie);
hThread = ::CreateThread(NULL, 0, &TestThreadInheritLeakThreadProc, NULL, 0, &dwThreadId);
if (hThread == NULL)
{
fprintf(stderr, "CreateThread() failed with ::GetLastError = %d\n", ::GetLastError());
return EXIT_FAILURE;
}
WaitForSingleObject(hThread, INFINITE);
fprintf(stderr, "Created thread %lu\n", dwThreadId);
::DeactivateActCtx(0, ulpCookie);
::ReleaseActCtx(ActivationContextHandle);
return EXIT_SUCCESS;
}
BOOL
TestNewCatalogSignerThingy(
PCWSTR CatalogName
)
{
SXSP_DEBUG_FUNCTION pfn = NULL;
BOOL fSuccess = FALSE;
LoadSxs();
GetSxsProc(SXSP_DEBUG_ORDINAL, &pfn);
fSuccess = (*pfn)(SXS_DEBUG_CATALOG_SIGNER_CHECK, 0, CatalogName, NULL);
return fSuccess;
}
HMODULE MyHandle;
WCHAR MyModuleFullPath[MAX_PATH];
WCHAR MyModuleFullPathWithoutExtension[MAX_PATH];
/*
see \\scratch\scratch\JayK\exedll for a slightly different approach
*/
HANDLE GetExeHandle()
{
return GetModuleHandle(NULL);
}
extern "C" { extern IMAGE_DOS_HEADER __ImageBase; }
HMODULE GetMyHandle()
{
//Trace("GetMyHandle():%p\n", &__ImageBase);
return (HMODULE)&__ImageBase;
}
BOOL AmITheExe()
{
IamExe = (GetExeHandle() == GetMyHandle());
IamDll = !IamExe;
return IamExe;
}
PCWSTR GetMyModuleFullPath()
{
return
((MyModuleFullPath[0]
|| ::GetModuleFileNameW(GetMyHandle(), MyModuleFullPath, RTL_NUMBER_OF(MyModuleFullPath))),
MyModuleFullPath);
}
PCWSTR GetMyModuleFullPathWithoutExtension()
{
//
// not thread safe
//
wcscpy(MyModuleFullPathWithoutExtension, GetMyModuleFullPath());
*wcsrchr(MyModuleFullPathWithoutExtension, '.') = 0;
return MyModuleFullPathWithoutExtension;
}
void TestExeDll()
{
#if defined(_X86_)
WCHAR x[MAX_PATH];
CStringBuffer y;
Kernel32.GetModuleFileNameW(NULL, x, RTL_NUMBER_OF(x));
if (!y.Win32Assign(x, StringLength(x)))
ThrowLastError();
if (!y.Win32ChangePathExtension(L"dll", 3, eAddIfNoExtension))
ThrowLastError();
if (!CopyFileW(x, y, FALSE))
ThrowLastError();
SetDllBitInPeImage(y);
FreeLibrary(LoadLibraryW(y));
#endif
}
void PrintDll()
{
//Trace("dll %ls\n", GetMyModuleFullPath());
}
void PrintExe()
{
//Trace("exe %ls\n", GetMyModuleFullPath());
}
extern "C" void __cdecl wmainCRTStartup();
extern "C" BOOL __stdcall _DllMainCRTStartup(HINSTANCE, DWORD, PVOID);
extern "C" BOOL __stdcall DllMain(HINSTANCE DllHandle, DWORD Reason, PVOID SemiReserved)
{
//Trace("Enter DllMain\n");
switch (Reason)
{
default:
break;
case DLL_PROCESS_ATTACH:
if (
wcsstr(GetCommandLineW(), L" -tQueryActCtx")
|| wcsstr(GetCommandLineW(), L" -tqueryactctx")
|| wcsstr(GetCommandLineW(), L" /tQueryActCtx")
|| wcsstr(GetCommandLineW(), L" /tqueryactctx")
)
{
TestQueryActCtx();
}
}
//Trace("Exit DllMain\n");
return TRUE;
}
#if defined(_X86_)
extern "C" void __declspec(naked) Entry()
// This works for .dlls or .exes.
// void ExeMain(void)
// BOOL __stdcall DllMain(HINSTANCE dll, DWORD reason, void* reserved)
{
static const char* DllReason[] =
{
"DllProcessDetach %ls\n",
"DllProcessAttach %ls\n",
"DllThreadAttach %ls\n",
"DllThreadDetach %ls\n"
};
__asm {
//int 3
call AmITheExe
test eax,eax
jne Lexe
//Ldll:
call GetMyModuleFullPath
push eax
mov eax, [esp+12]
mov eax, DllReason[eax*4]
push eax
call Trace
add esp,8
jmp _DllMainCRTStartup
Lexe:
call PrintExe
jmp wmainCRTStartup
}
}
#else
extern "C" void Entry()
{
wmainCRTStartup();
}
#endif
BOOL TestSxsSfcUI()
{
SXSP_DEBUG_FUNCTION pfn = NULL;
BOOL fSuccess = FALSE;
LoadSxs();
GetSxsProc(SXSP_DEBUG_ORDINAL, &pfn);
fSuccess = (*pfn)(SXS_DEBUG_SFC_UI_TEST, 0, 0, NULL);
if (! fSuccess){
fprintf(stderr, "%s failed!\n", __FUNCTION__);
return EXIT_FAILURE;
}
else
return EXIT_SUCCESS;
return fSuccess;
}
void TestGetModuleHandleEx()
{
HMODULE p;
BOOL f;
HMODULE q;
unsigned u;
#define GetModuleHandleExA pfnGetModuleHandleExA
#define GetModuleHandleExW pfnGetModuleHandleExW
HMODULE kernel32 = GetModuleHandleW(L"Kernel32");
PGET_MODULE_HANDLE_EXA GetModuleHandleExA = reinterpret_cast<PGET_MODULE_HANDLE_EXA>(GetProcAddress(kernel32, "GetModuleHandleExA"));
PGET_MODULE_HANDLE_EXW GetModuleHandleExW = reinterpret_cast<PGET_MODULE_HANDLE_EXW>(GetProcAddress(kernel32, "GetModuleHandleExW"));
if (GetModuleHandleExA == NULL || GetModuleHandleExW == NULL)
{
return;
}
union
{
CHAR BufferA[MAX_PATH];
WCHAR BufferW[MAX_PATH];
};
BufferA[0] = 0;
GetWindowsDirectoryA(BufferA, MAX_PATH);
std::string windowsA = BufferA;
std::string systemA = windowsA + "System32";
BufferW[0] = 0;
GetWindowsDirectoryW(BufferW, MAX_PATH);
std::wstring windowsW = BufferW;
std::wstring systemW = windowsW + L"System32";
#define PIN GET_MODULE_HANDLE_EX_FLAG_PIN
#define NOCHANGE GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT
#define ADDRESS GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
#define X(x) SetLastError(NO_ERROR); p = x; printf("%s:%p,%d\n", #x, p, ::GetLastError());
#define Y(x) SetLastError(NO_ERROR); f = x; printf("%s:%s,%p,%d\n", #x, "false\0true"+f*6, p, ::GetLastError());
printf("first some basic GetModuleHandle testing\n\n");
X(GetModuleHandleA(NULL));
X(GetModuleHandleW(NULL));
X(GetModuleHandleA("ntdll.dll"));
X(GetModuleHandleW(L"ntdll.dll"));
X(GetModuleHandleA("ntdll"));
X(GetModuleHandleW(L"ntdll"));
X(GetModuleHandleA("c:\\ntdll"));
X(GetModuleHandleW(L"c:\\ntdll"));
X(GetModuleHandleA((systemA + "\\ntdll").c_str()));
X(GetModuleHandleW((systemW + L"\\ntdll").c_str()));
X(GetModuleHandleA((systemA + "\\ntdll.dll").c_str()));
X(GetModuleHandleW((systemW + L"\\ntdll.dll").c_str()));
X(GetModuleHandleA("sxs"));
X(GetModuleHandleW(L"sxs.dll"));
printf("\n\nnow show that FreeLibrary \"works\", GetModuleHandle honors it\n\n");
X(LoadLibraryA("Sxs.dll"));
X(GetModuleHandleA("sxs"));
X(GetModuleHandleW(L"sxs.dll"));
Y(FreeLibrary(p = GetModuleHandleA("Sxs.dll")));
X(GetModuleHandleA("sxs"));
X(GetModuleHandleW(L"sxs.dll"));
X(LoadLibraryW(L"Sxs.dll"));
Y(GetModuleHandleExA(0, NULL, &p));
Y(GetModuleHandleExW(0, NULL, &p));
printf("\n\nsome invalid parameters (%d)\n\n", ERROR_INVALID_PARAMETER);
Y(GetModuleHandleExA(PIN | NOCHANGE, "sxs", &p));
Y(GetModuleHandleExW(PIN | NOCHANGE, L"sxs", &p));
Y(GetModuleHandleExA(PIN | NOCHANGE, "ntdll", &p));
Y(GetModuleHandleExW(PIN | NOCHANGE, L"ntdll", &p));
printf("\n\nshow NOCHANGE's equiv to regular\n\n");
Y(GetModuleHandleExA(NOCHANGE, "sxs", &p));
Y(GetModuleHandleExW(NOCHANGE, L"sxs", &p));
Y(FreeLibrary(p = GetModuleHandleA("Sxs.dll")));
Y(GetModuleHandleExA(NOCHANGE, "sxs", &p));
Y(GetModuleHandleExW(NOCHANGE, L"sxs", &p));
printf("\n\nshow PIN works\n\n");
X(LoadLibraryW(L"Sxs.dll"));
Y(GetModuleHandleExA(PIN, "sxs", &p));
Y(FreeLibrary(p = GetModuleHandleA("Sxs.dll")));
Y(GetModuleHandleExW(0, L"sxs", &(q = p)));
Y(GetModuleHandleExW(0, L"c:\\sxs", &p));
printf("\n\nshow the VirtualQuery form\n\n");
Y(GetModuleHandleExA(ADDRESS, "sxs", &p)); // string, actually in .exe
Y(GetModuleHandleExW(ADDRESS, L"c:\\sxs", &p));
Y(GetModuleHandleExA(ADDRESS, reinterpret_cast<LPCSTR>(q), &p));
Y(GetModuleHandleExW(ADDRESS, reinterpret_cast<LPCWSTR>(q), &p));
printf("\n\nsome more invalid parameters (%d)\n\n", ERROR_INVALID_PARAMETER);
Y(GetModuleHandleExA(0, NULL, NULL));
Y(GetModuleHandleExW(0, NULL, NULL));
printf("\n\nshow that static loads can't be unloaded\n\n");
for (u = 0 ; u < 4 ; ++u)
{
printf("%#x\n", u);
Y(FreeLibrary(p = GetModuleHandleA("kernel32")));
Y(FreeLibrary(p = GetModuleHandleW(L"sxstest.exe")));
Y(FreeLibrary(p = GetModuleHandleA("msvcrt.dll")));
}
printf("\n\ntry all flag combinations, including invalids ones\n\n");
for (u = 0 ; u <= (PIN | ADDRESS | NOCHANGE) ; ++u)
{
printf("%#x\n", u);
p = NULL;
Y( GetModuleHandleExA(u, NULL, NULL)); p = NULL;
Y( GetModuleHandleExW(u, NULL, NULL)); p = NULL;
Y( GetModuleHandleExA(u, NULL, &p)); p = NULL;
Y( GetModuleHandleExW(u, NULL, &p)); p = NULL;
if (u & ADDRESS)
{
Y( GetModuleHandleExA(u, "", NULL)); p = NULL;
Y( GetModuleHandleExW(u, reinterpret_cast<LPCWSTR>(GetModuleHandleExA), NULL)); p = NULL;
Y( GetModuleHandleExW(u, reinterpret_cast<LPCWSTR>(atexit), NULL)); p = NULL;
Y( GetModuleHandleExA(u, "", &p)); p = NULL;
Y( GetModuleHandleExW(u, reinterpret_cast<LPCWSTR>(GetModuleHandleExA), &p)); p = NULL;
Y( GetModuleHandleExW(u, reinterpret_cast<LPCWSTR>(atexit), &p)); p = NULL;
}
else
{
Y( GetModuleHandleExA(u, "foo32", NULL)); p = NULL;
Y( GetModuleHandleExW(u, L"kernel32", NULL)); p = NULL;
Y( GetModuleHandleExA(u, "foo32", &p)); p = NULL;
Y( GetModuleHandleExW(u, L"kernel32", &p)); p = NULL;
}
}
printf("\n\ntry all bits of flags, should be mostly invalid (%d)\n\n", ERROR_INVALID_PARAMETER);
for (u = 0 ; u < RTL_BITS_OF(u) ; ++u)
{
printf("%#x\n", u);
Y(GetModuleHandleExW(1<<u, L"kernel32", &p));
}
printf("\n\nPIN | ADDRESS wasn't covered\n\n", ERROR_INVALID_PARAMETER);
X(GetModuleHandleW(L"shell32"));
X(q = LoadLibraryA("shell32"));
Y(FreeLibrary(GetModuleHandleA("shell32")));
Y(GetModuleHandleExW(PIN | ADDRESS, reinterpret_cast<LPCWSTR>(q), &p));
X(q = LoadLibraryW(L"shell32"));
Y(GetModuleHandleExW(PIN | ADDRESS, reinterpret_cast<LPCWSTR>(q) + 100, &p));
Y(FreeLibrary(q)); Y(FreeLibrary(q)); Y(FreeLibrary(q));
X(GetModuleHandleW(L"shell32.dll"));
Y(GetModuleHandleExW(ADDRESS, reinterpret_cast<LPCWSTR>(q) + 1000, &p));
#undef X
#undef Y
#undef PIN
#undef NOCHANGE
#undef ADDRESS
}
void
TestGetFullPathName(
PCWSTR s
)
{
WCHAR FullPath[MAX_PATH * 2];
PWSTR FilePart = L"";
DWORD dw;
DWORD dwError;
SetLastError(NO_ERROR);
dw = GetFullPathNameW(s, RTL_NUMBER_OF(FullPath), FullPath, &FilePart);
dwError = ::GetLastError();
printf(
"GetFullPathNameW(%ls):%lu,lastError=%lu,filePart=%ls\n",
FullPath,
dw,
dwError,
FilePart
);
}
void
TestCreateFile(
PCWSTR s
)
{
HANDLE handle;
DWORD dwError;
SetLastError(NO_ERROR);
handle = CreateFileW(
s,
0,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL
);
dwError = ::GetLastError();
if (handle != INVALID_HANDLE_VALUE)
CloseHandle(handle);
printf(
"CreateFileW(%ls):%p,lastError=%lu\n",
s,
handle,
dwError
);
}
/*
from base\ntsetup\dll\sxs.c
*/
VOID
SxspGetPathBaseName(
LPCWSTR Path,
LPWSTR Base
)
{
LPCWSTR Dot = wcsrchr(Path, '.');
LPCWSTR Slash = wcsrchr(Path, '\\');
//
// beware \foo.txt\bar
// beware \bar
// beware bar
// beware .bar
// beware \.bar
//
*Base = 0;
if (Slash == NULL)
Slash = Path;
else
Slash += 1;
if (Dot == NULL || Dot < Slash)
Dot = Path + StringLength(Path);
CopyMemory(Base, Slash, (Dot - Slash) * sizeof(*Base));
Base[Dot - Slash] = 0;
}
VOID
TestGetPathBaseName(
LPCWSTR Path
)
{
WCHAR Base[MAX_PATH];
SxspGetPathBaseName(Path, Base);
printf("\"%ls\" -> \"%ls\"\n", Path, Base);
}
void TestVersion()
{
printf(
"Windows NT %lu.%lu.%lu\n",
FusionpGetWindowsNtMajorVersion(),
FusionpGetWindowsNtMinorVersion(),
FusionpGetWindowsNtBuildVersion()
);
}
void TestGetProcessImageFileName()
{
UNICODE_STRING s;
FusionpGetProcessImageFileName(&s);
printf("%wZ\n", &s);
}
BOOL TestErrorInfra1() { FN_PROLOG_WIN32; IFW32FALSE_ORIGINATE_AND_EXIT(LoadLibraryA("1")); FN_EPILOG; }
BOOL TestErrorInfra2() { FN_PROLOG_WIN32; IFW32NULL_EXIT(LoadLibraryA(" 2 ")); FN_EPILOG; }
BOOL TestErrorInfra3() { FN_PROLOG_WIN32; IFFAILED_CONVERTHR_HRTOWIN32_EXIT_TRACE(E_FAIL | 3); FN_EPILOG; }
BOOL TestErrorInfra4() { FN_PROLOG_WIN32; IFCOMFAILED_EXIT(E_FAIL | 4); FN_EPILOG; }
BOOL TestErrorInfra5() { FN_PROLOG_WIN32; IFCOMFAILED_ORIGINATE_AND_EXIT(E_FAIL | 5); FN_EPILOG; }
BOOL TestErrorInfra6() { FN_PROLOG_WIN32; IFREGFAILED_EXIT(6); FN_EPILOG; }
BOOL TestErrorInfra7() { FN_PROLOG_WIN32; IFREGFAILED_ORIGINATE_AND_EXIT(7); FN_EPILOG; }
HRESULT TestErrorInfra8() { FN_PROLOG_HR; IFW32FALSE_ORIGINATE_AND_EXIT(LoadLibraryA("8")); FN_EPILOG; }
HRESULT TestErrorInfra9() { FN_PROLOG_HR; IFW32NULL_EXIT(LoadLibraryA("!@# 9 \\")); FN_EPILOG; }
HRESULT TestErrorInfra10() { FN_PROLOG_HR; IFFAILED_CONVERTHR_HRTOWIN32_EXIT_TRACE(E_FAIL | 10); FN_EPILOG; }
HRESULT TestErrorInfra11() { FN_PROLOG_HR; IFCOMFAILED_EXIT(E_FAIL | 11); FN_EPILOG; }
HRESULT TestErrorInfra12() { FN_PROLOG_HR; IFCOMFAILED_ORIGINATE_AND_EXIT(E_FAIL | 12); FN_EPILOG; }
HRESULT TestErrorInfra13() { FN_PROLOG_HR; IFREGFAILED_EXIT(13); FN_EPILOG; }
HRESULT TestErrorInfra14() { FN_PROLOG_HR; IFREGFAILED_ORIGINATE_AND_EXIT(14); FN_EPILOG; }
void TestErrorInfra()
{
#define X(x) DbgPrint("%s\n", #x); x()
X(TestErrorInfra1);
X(TestErrorInfra2);
X(TestErrorInfra3);
X(TestErrorInfra4);
X(TestErrorInfra5);
X(TestErrorInfra7);
X(TestErrorInfra8);
X(TestErrorInfra9);
X(TestErrorInfra10);
X(TestErrorInfra11);
X(TestErrorInfra12);
X(TestErrorInfra13);
X(TestErrorInfra14);
#undef X
}
void TestQueryActCtx3(
ULONG Flags,
HANDLE ActCtxHandle
)
{
SIZE_T BytesWrittenOrRequired = 0;
BYTE QueryBuffer[4][4096];
ACTIVATION_CONTEXT_QUERY_INDEX QueryIndex = { 0 };
PACTIVATION_CONTEXT_BASIC_INFORMATION BasicInfo = reinterpret_cast<PACTIVATION_CONTEXT_BASIC_INFORMATION>(&QueryBuffer[0]);
PASSEMBLY_DLL_REDIRECTION_DETAILED_INFORMATION DllRedir = reinterpret_cast<PASSEMBLY_DLL_REDIRECTION_DETAILED_INFORMATION>(&QueryBuffer[1]);
PACTIVATION_CONTEXT_DETAILED_INFORMATION ContextDetailed = reinterpret_cast<PACTIVATION_CONTEXT_DETAILED_INFORMATION>(&QueryBuffer[2]);
PACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION AssemblyDetailed = reinterpret_cast<PACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION>(&QueryBuffer[3]);
CStringBuffer decimalContext;
RtlZeroMemory(&QueryBuffer, sizeof(QueryBuffer));
if (IS_SPECIAL_ACTCTX(ActCtxHandle))
decimalContext.Win32Format(L" (%Id)", reinterpret_cast<LONG_PTR>(ActCtxHandle));
#define QueryFailed(x,n) Trace("%s:%ld:QueryActCtx(%s) failed %lu\n", __FUNCTION__, ULONG(n), x, GetLastError())
if (!QueryActCtxW(
Flags,
ActCtxHandle,
NULL,
ActivationContextBasicInformation,
&QueryBuffer,
sizeof(QueryBuffer),
&BytesWrittenOrRequired
))
QueryFailed("ActivationContextBasicInformation", __LINE__ - 1);
else
{
if (IS_SPECIAL_ACTCTX(BasicInfo->hActCtx))
decimalContext.Win32Format(L" (%Id)", reinterpret_cast<LONG_PTR>(BasicInfo->hActCtx));
Trace(
"BytesWrittenOrRequired : 0x%lx\n"
"BasicInfo->hActCtx : %p%ls\n"
"BasicInfo->Flags : 0x%lx\n",
BytesWrittenOrRequired,
BasicInfo->hActCtx,
static_cast<PCWSTR>(decimalContext),
BasicInfo->Flags
);
}
Flags = (Flags & ~QUERY_ACTCTX_FLAG_NO_ADDREF);
if (!QueryActCtxW(Flags, ActCtxHandle, NULL, ActivationContextDetailedInformation, ContextDetailed, 4096, &BytesWrittenOrRequired))
QueryFailed("ActivationContextDetailedInformation", __LINE__ - 1);
else
{
Trace(
"BytesWrittenOrRequired : 0x%lx\n"
"ContextDetailed->dwFlags : 0x%lx\n"
"ContextDetailed->ulFormatVersion : 0x%lx\n"
"ContextDetailed->ulAssemblyCount : 0x%lx\n"
"ContextDetailed->ulRootManifestPathType : 0x%lx\n"
"ContextDetailed->ulRootManifestPathChars : 0x%lx\n"
"ContextDetailed->ulRootConfigurationPathType : 0x%lx\n"
"ContextDetailed->ulRootConfigurationPathChars : 0x%lx\n"
"ContextDetailed->ulAppDirPathType : 0x%lx\n"
"ContextDetailed->ulAppDirPathChars : 0x%lx\n"
"ContextDetailed->lpRootManifestPath : %ls\n"
"ContextDetailed->lpRootConfigurationPath : %ls\n"
"ContextDetailed->lpAppDirPath : %ls\n"
,
BytesWrittenOrRequired,
ContextDetailed->dwFlags,
ContextDetailed->ulFormatVersion,
ContextDetailed->ulAssemblyCount,
ContextDetailed->ulRootManifestPathType,
ContextDetailed->ulRootManifestPathChars,
ContextDetailed->ulRootConfigurationPathType,
ContextDetailed->ulRootConfigurationPathChars,
ContextDetailed->ulAppDirPathType,
ContextDetailed->ulAppDirPathChars,
ContextDetailed->lpRootManifestPath,
ContextDetailed->lpRootConfigurationPath,
ContextDetailed->lpAppDirPath
);
}
{
ULONG AssemblyIndex = 0;
ULONG FileInAssemblyIndex = 0;
//
// 0 produces ERROR_INTERNAL_ERROR
//
for (AssemblyIndex = 0 ; AssemblyIndex <= ContextDetailed->ulAssemblyCount ; AssemblyIndex += 1)
{
if (!QueryActCtxW(Flags, ActCtxHandle, &AssemblyIndex, AssemblyDetailedInformationInActivationContext, AssemblyDetailed, 4096, &BytesWrittenOrRequired))
{
Trace(
"%s(%lu):QueryActCtx(Flags=0x%lx, ActCtxHandle=%p%ls, AssemblyIndex=0x%lx, AssemblyDetailedInformationInActivationContext) LastError=%lu (%ls)\n",
__FUNCTION__,
__LINE__ - 1,
Flags,
ActCtxHandle,
static_cast<PCWSTR>(decimalContext),
AssemblyIndex,
::FusionpGetLastWin32Error(),
::FusionpThreadUnsafeGetLastWin32ErrorMessageW()
);
}
else
{
Trace(
"AssemblyIndex : 0x%lx\n"
"BytesWrittenOrRequired : 0x%lx\n"
"AssemblyDetailed->ulFlags : 0x%lx\n"
"AssemblyDetailed->ulEncodedAssemblyIdentityLength : 0x%lx\n"
"AssemblyDetailed->ulManifestPathType : 0x%lx\n"
"AssemblyDetailed->ulManifestPathLength : 0x%lx\n"
"AssemblyDetailed->liManifestLastWriteTime : 0x%I64x\n"
"AssemblyDetailed->ulPolicyPathType : 0x%lx\n"
"AssemblyDetailed->ulPolicyPathLength : 0x%lx\n"
"AssemblyDetailed->liPolicyLastWriteTime : 0x%I64x\n"
"AssemblyDetailed->ulMetadataSatelliteRosterIndex : 0x%lx\n"
"AssemblyDetailed->ulManifestVersionMajor : 0x%lx\n"
"AssemblyDetailed->ulManifestVersionMinor : 0x%lx\n"
"AssemblyDetailed->ulPolicyVersionMajor : 0x%lx\n"
"AssemblyDetailed->ulPolicyVersionMinor : 0x%lx\n"
"AssemblyDetailed->ulAssemblyDirectoryNameLength : 0x%lx\n"
"AssemblyDetailed->lpAssemblyEncodedAssemblyIdentity : %ls\n"
"AssemblyDetailed->lpAssemblyManifestPath : %ls\n"
"AssemblyDetailed->lpAssemblyPolicyPath : %ls\n"
"AssemblyDetailed->lpAssemblyDirectoryName : %ls\n"
"AssemblyDetailed->ulFileCount : 0x%lx\n"
,
AssemblyIndex,
BytesWrittenOrRequired,
AssemblyDetailed->ulFlags,
AssemblyDetailed->ulEncodedAssemblyIdentityLength,
AssemblyDetailed->ulManifestPathType,
AssemblyDetailed->ulManifestPathLength,
AssemblyDetailed->liManifestLastWriteTime.QuadPart,
AssemblyDetailed->ulPolicyPathType,
AssemblyDetailed->ulPolicyPathLength,
AssemblyDetailed->liPolicyLastWriteTime.QuadPart,
AssemblyDetailed->ulMetadataSatelliteRosterIndex,
AssemblyDetailed->ulManifestVersionMajor,
AssemblyDetailed->ulManifestVersionMinor,
AssemblyDetailed->ulPolicyVersionMajor,
AssemblyDetailed->ulPolicyVersionMinor,
AssemblyDetailed->ulAssemblyDirectoryNameLength,
AssemblyDetailed->lpAssemblyEncodedAssemblyIdentity,
AssemblyDetailed->lpAssemblyManifestPath,
AssemblyDetailed->lpAssemblyPolicyPath,
AssemblyDetailed->lpAssemblyDirectoryName,
AssemblyDetailed->ulFileCount
);
QueryIndex.ulAssemblyIndex = AssemblyIndex;
SetLastError(NO_ERROR);
if (AssemblyDetailed->ulFileCount == 0)
{
Trace("AssemblyDetailed->ulFileCount is 0, working around bug, setting it to 4.\n");
AssemblyDetailed->ulFileCount = 4; // bug workaround
}
for (FileInAssemblyIndex = 0 ; FileInAssemblyIndex != AssemblyDetailed->ulFileCount ; FileInAssemblyIndex += 1)
{
QueryIndex.ulFileIndexInAssembly = FileInAssemblyIndex;
if (!QueryActCtxW(Flags, ActCtxHandle, &QueryIndex, FileInformationInAssemblyOfAssemblyInActivationContext, DllRedir, 4096, &BytesWrittenOrRequired))
{
Trace(
"%s(%lu):QueryActCtx(Flags=0x%lx, ActCtxHandle=%p%ls, QueryIndex={ulAssemblyIndex=0x%lx, ulFileIndexInAssembly=0x%lx}, FileInformationInAssemblyOfAssemblyInActivationContext) LastError=%lu (%ls)\n",
__FUNCTION__,
__LINE__,
Flags,
ActCtxHandle,
static_cast<PCWSTR>(decimalContext),
QueryIndex.ulAssemblyIndex,
QueryIndex.ulFileIndexInAssembly,
::FusionpGetLastWin32Error(),
::FusionpThreadUnsafeGetLastWin32ErrorMessageW()
);
//break;
}
else
{
Trace(
"AssemblyIndex : 0x%lx\n"
"FileIndex : 0x%lx\n"
"BytesWrittenOrRequired : 0x%lx\n"
"DllRedir[0x%lx,0x%lx]->ulFlags : 0x%lx\n"
"DllRedir[0x%lx,0x%lx]->ulFilenameLength : 0x%lx\n"
"DllRedir[0x%lx,0x%lx]->ulPathLength : 0x%lx\n"
"DllRedir[0x%lx,0x%lx]->lpFileName : %ls\n"
"DllRedir[0x%lx,0x%lx]->lpFilePath : %ls\n"
,
AssemblyIndex,
FileInAssemblyIndex,
BytesWrittenOrRequired,
AssemblyIndex, FileInAssemblyIndex, DllRedir->ulFlags,
AssemblyIndex, FileInAssemblyIndex, DllRedir->ulFilenameLength,
AssemblyIndex, FileInAssemblyIndex, DllRedir->ulPathLength,
AssemblyIndex, FileInAssemblyIndex, DllRedir->lpFileName,
AssemblyIndex, FileInAssemblyIndex, DllRedir->lpFilePath
);
}
}
}
}
}
}
void TestQueryActCtx2()
{
{
CFusionActCtxHandle LogonuiActCtxHandle;
{
WCHAR LogonuiManifest[MAX_PATH * 2];
ACTCTXW LogonuiActCtx = {sizeof(LogonuiActCtx)};
LogonuiManifest[0] = 0;
GetSystemDirectoryW(LogonuiManifest, MAX_PATH);
wcscat(LogonuiManifest, L"\\logonui.exe.manifest");
LogonuiActCtx.lpSource = LogonuiManifest;
LogonuiActCtxHandle.Win32Create(&LogonuiActCtx);
}
{
CFusionActCtxScope LogonuiActCtxScope;
LogonuiActCtxScope.Win32Activate(LogonuiActCtxHandle);
TestQueryActCtx3(QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX | QUERY_ACTCTX_FLAG_NO_ADDREF, NULL);
}
TestQueryActCtx3(QUERY_ACTCTX_FLAG_NO_ADDREF, LogonuiActCtxHandle);
}
TestQueryActCtx3(QUERY_ACTCTX_FLAG_NO_ADDREF, ACTCTX_EMPTY);
TestQueryActCtx3(QUERY_ACTCTX_FLAG_NO_ADDREF, ACTCTX_SYSTEM_DEFAULT);
}
void TestQueryActCtx()
{
WCHAR ExePath[MAX_PATH];
CStringBuffer DllPath;
HMODULE hmod = NULL;
WCHAR buffer[200];
if (IamExe)
{
if (!Kernel32.GetModuleFileNameW(NULL, ExePath, RTL_NUMBER_OF(ExePath)))
ThrowLastError();
if (!DllPath.Win32Format(L"%ls.dll", ExePath))
ThrowLastError();
::CopyFileW(ExePath, DllPath, FALSE);
}
if (IamDll)
{
hmod = NULL;
hmod = (HMODULE)RtlPcToFileHeader(InitCommonControls, (PVOID*)&hmod);
wcscpy(buffer, L"FAILED");
if (hmod != NULL)
Kernel32.GetModuleFileNameW(hmod, buffer, RTL_NUMBER_OF(buffer));
Trace("from dll static dep: %p %ls\n", hmod, buffer);
#if defined(ISOLATION_AWARE_ENABLED)
hmod = IsolationAwareLoadLibraryW(L"comctl32.dll");
LastError = ::GetLastError();
wcscpy(buffer, L"FAILED");
if (hmod != NULL)
Kernel32.GetModuleFileNameW(hmod, buffer, RTL_NUMBER_OF(buffer));
Trace("from dll IsolationAwareLoadLibraryW: %p %ls\n", hmod, buffer);
#endif
hmod = LoadLibraryW(L"comctl32.dll");
LastError = ::GetLastError();
wcscpy(buffer, L"FAILED");
if (hmod != NULL)
Kernel32.GetModuleFileNameW(hmod, buffer, RTL_NUMBER_OF(buffer));
Trace("from dll LoadLibraryW: %p %ls\n", hmod, buffer);
return;
}
{
hmod = NULL;
hmod = (HMODULE)RtlPcToFileHeader(InitCommonControls, (PVOID*)&hmod);
wcscpy(buffer, L"FAILED");
if (hmod != NULL)
Kernel32.GetModuleFileNameW(hmod, buffer, RTL_NUMBER_OF(buffer));
Trace("from exe static dep: %p %ls\n", hmod, buffer);
#if defined(ISOLATION_AWARE_ENABLED)
hmod = IsolationAwareLoadLibraryW(L"comctl32.dll");
LastError = ::GetLastError();
wcscpy(buffer, L"FAILED");
if (hmod != NULL)
Kernel32.GetModuleFileNameW(hmod, buffer, RTL_NUMBER_OF(buffer));
Trace("from exe IsolationAwareLoadLibraryW: %p %ls\n", hmod, buffer);
#endif
hmod = LoadLibraryW(L"comctl32.dll");
LastError = ::GetLastError();
wcscpy(buffer, L"FAILED");
if (hmod != NULL)
Kernel32.GetModuleFileNameW(hmod, buffer, RTL_NUMBER_OF(buffer));
Trace("from exe LoadLibraryW: %p %ls\n", hmod, buffer);
}
SetDllBitInPeImage(DllPath);
Trace("Enter LoadLibraryW\n");
hmod = LoadLibraryW(DllPath);
LastError = ::GetLastError();
Trace("Exit LoadLibraryW\n");
void (*pfn)(void) = reinterpret_cast<void (*)(void)>(GetProcAddress(hmod, "TestQueryActCtx"));
Trace("Enter non DllMain call to TestQueryActCtx\n");
pfn();
Trace("Exit non DllMain call to TestQueryActCtx\n");
FreeLibrary(hmod);
DeleteFileW(DllPath);
}
DWORD WINAPI Test64kThreadMain(void* pv)
{
LONG_PTR i = 0;
HANDLE h = 0;
ULONG_PTR cookie = 0;
LONG_PTR j = reinterpret_cast<LONG_PTR>(pv);
GetCurrentActCtx(&h);
ActivateActCtx(h, &cookie);
printf("%Id ", cookie);
if (cookie == 0) printf("cookie 0\n");
ActivateActCtx(h, &cookie);
printf("%Id ", cookie);
if (cookie == 0) printf("cookie 0\n");
__try
{
for (i = 0 ; i < j ; ++i)
{
if (!ActivateActCtx(h, &cookie))
printf("activate error %lu\n", ::GetLastError());
else
{
if (cookie == 0) printf("cookie 0\n");
//printf("%Id ", cookie);
if (!DeactivateActCtx(0, cookie))
printf("deactivate error %lu\n", ::GetLastError());
}
}
}
__except(printf("exception %lx\n", GetExceptionCode()),EXCEPTION_EXECUTE_HANDLER)
{
}
printf("final cookie value %Id\n", cookie);
return 0;
}
void Test64k()
{
HANDLE h = 0;
ULONG_PTR cookie = 0;
DWORD threadId = 0;
LONG_PTR i = 0;
LONG_PTR j = 0;
HANDLE thread = 0;
GetCurrentActCtx(&h);
ActivateActCtx(h, &cookie);
if (cookie == 0) printf("cookie 0\n");
printf("%Id ", cookie);
ActivateActCtx(h, &cookie);
if (cookie == 0) printf("cookie 0\n");
printf("%Id ", cookie);
for (j = 0 ; j < 0xfff0 ; ++j)
{
if (!ActivateActCtx(h, &cookie))
printf("activate error %lu\n", ::GetLastError());
else
{
if (cookie == 0) printf("cookie 0\n");
if (!DeactivateActCtx(0, cookie))
printf("deactivate error %lu\n", ::GetLastError());
}
}
for ( ; j < 0xffff + 0xf ; ++j)
{
if (!ActivateActCtx(h, &cookie))
printf("activate error %lu\n", ::GetLastError());
printf("%Id ", cookie);
if (cookie == 0) printf("cookie 0\n");
thread = CreateThread(NULL, 0, Test64kThreadMain, reinterpret_cast<void*>(j), 0, &threadId);
}
WaitForSingleObject(thread, INFINITE);
}
void TestDotLocalSingleInstancing()
{
FILE* File = 0;
HMODULE DllHandle = 0;
{
WCHAR DotLocal[MAX_PATH];
if (!Kernel32.GetModuleFileNameW(GetMyHandle(), DotLocal, NUMBER_OF(DotLocal) - sizeof(".local")))
ThrowLastError();
wcscat(DotLocal, L".local");
File = _wfopen(DotLocal, L"w");
fprintf(File, "\n");
fclose(File);
}
{
WCHAR System32Mshtml[MAX_PATH];
WCHAR LocalMshtml[MAX_PATH];
WCHAR ResultingMshtml[MAX_PATH];
if (!GetSystemDirectoryW(System32Mshtml, NUMBER_OF(System32Mshtml) - sizeof("\\Mshtml.dll")))
ThrowLastError();
wcscat(System32Mshtml, L"\\Mshtml.dll");
if (!Kernel32.GetModuleFileNameW(GetMyHandle(), LocalMshtml, NUMBER_OF(LocalMshtml) - sizeof("\\Mshtml.dll")))
ThrowLastError();
*wcsrchr(LocalMshtml, '\\') = 0;
wcscat(LocalMshtml, L"\\Mshtml.dll");
//DllHandle = LoadLibraryW(L"Mshtml.dll");
//Trace("LoadLibrary(Mshtml): %p\n", DllHandle);
if (!CopyFileW(System32Mshtml, LocalMshtml, FALSE))
ThrowLastError();
Trace("copy %ls -> %ls\n", System32Mshtml, LocalMshtml);
ULONG i;
for (i = 0 ; i != 4 ; i += 1)
{
DllHandle = LoadLibraryW(System32Mshtml);
wcscpy(ResultingMshtml, L"FAILED");
if (DllHandle != NULL)
Kernel32.GetModuleFileNameW(DllHandle, ResultingMshtml, RTL_NUMBER_OF(ResultingMshtml));
Trace("LoadLibrary(%ls): %p %ls\n", System32Mshtml, DllHandle, ResultingMshtml);
}
}
}
void
TestCreateActCtx(
int n,
wchar_t **args
)
{
ACTCTXW acw;
int i;
WCHAR rgwchSource[MAX_PATH];
PCWSTR pszResource;
HANDLE hActCtx;
DWORD dwLastError;
for (i=0; i<n; i++)
{
PCWSTR arg = args[i];
PCWSTR semi = wcschr(arg, L';');
memset(&acw, 0, sizeof(acw));
acw.cbSize = sizeof(acw);
if (semi == NULL)
{
acw.lpSource = arg;
}
else
{
int cch = (int) (semi - arg);
if (cch >= NUMBER_OF(rgwchSource))
cch = NUMBER_OF(rgwchSource) - 1;
memcpy(rgwchSource, arg, cch * sizeof(WCHAR));
rgwchSource[cch] = L'\0';
if (semi[1] == L'#')
{
wchar_t *pszDummy;
pszResource = MAKEINTRESOURCEW(wcstoul(semi+1, &pszDummy, 10));
}
else
{
pszResource = semi+1;
}
acw.lpSource = rgwchSource;
acw.lpResourceName = pszResource;
acw.dwFlags |= ACTCTX_FLAG_RESOURCE_NAME_VALID;
}
hActCtx = ::CreateActCtxW(&acw);
dwLastError = ::GetLastError();
printf("CreateActCtxW() on \"%ls\" returned %p\n", arg, hActCtx);
if (hActCtx == INVALID_HANDLE_VALUE)
{
printf(" ::GetLastError() = %lu\n", dwLastError);
}
::ReleaseActCtx(hActCtx);
}
}
const char comctlv6manifest[]=
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"
"<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
"<assemblyIdentity"
" name=\"Microsoft.Windows.Shell.notepad\""
" processorArchitecture=\"x86\""
" version=\"5.1.0.0\""
" type=\"win32\"/>"
"<dependency>"
" <dependentAssembly>"
" <assemblyIdentity"
" type=\"win32\""
" name=\"Microsoft.Windows.Common-Controls\""
" version=\"6.0.0.0\""
" processorArchitecture=\"x86\""
" publicKeyToken=\"6595b64144ccf1df\""
" language=\"*\""
" />"
" </dependentAssembly>"
"</dependency>"
"</assembly>"
;
const char comctlv5manifest[]=
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"
"<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
"<assemblyIdentity"
" name=\"Microsoft.Windows.Shell.notepad\""
" processorArchitecture=\"x86\""
" version=\"5.1.0.0\""
" type=\"win32\"/>"
"</assembly>"
;
void TestCreateActctxAdminOverride()
{
WCHAR exe[MAX_PATH];
WCHAR dll[MAX_PATH];
WCHAR comctl[MAX_PATH];
WCHAR manifest[MAX_PATH];
ACTCTXW Actctx = {sizeof(Actctx)};
FILE* File = NULL;
ULONG_PTR ulCookie = 0;
HMODULE DllHandle = 0;
HANDLE ActctxHandle;
GUID Guid = { 0 };
wcscpy(exe, GetMyModuleFullPath());
wcscpy(dll, GetMyModuleFullPath());
wcscat(dll, L".dll");
CopyFileW(exe, dll, FALSE);
SetDllBitInPeImage(dll);
#if 0
wcscpy(String, GetMyModuleFullPath());
wcscat(String, L".Manifest");
DeleteFileW(String);
Trace("DeleteFile(%ls)\n", String);
wcscpy(String, GetMyModuleFullPath());
wcscat(String, L".2.Manifest");
DeleteFileW(String);
Trace("DeleteFile(%ls)\n", String);
wcscpy(String, GetMyModuleFullPath());
wcscat(String, L".3.Manifest");
DeleteFileW(String);
Trace("DeleteFile(%ls)\n", String);
#endif
Actctx.lpSource = dll;
/*
ActctxHandle = CreateActCtxW(&Actctx);
if (ActctxHandle == INVALID_HANDLE_VALUE)
return;
Trace("CreateActCtxW succeeded\n");
*/
//
// manfile is number to put in the manifest file name, 0 for none
// good is what the contents of the file are, 0=>bad, 1=>v5, 2=>v6
// res is what resource id to ask for
//
for (int manfile = 0 ; manfile != 4 ; manfile += 1)
{
WCHAR Number[RTL_BITS_OF(ULONG_PTR) + 3];
for (int good = 0 ; good != 3 ; good += 1)
{
for (int res = -1 ; res != 4 ; res += 1)
{
Trace("---------------------------------------------------------------\n");
Trace("resourceid is %d%s\n", res, (res != -1) ? "" : " (flag not set)");
if (res != -1)
{
Actctx.lpResourceName = MAKEINTRESOURCEW(res);
Actctx.dwFlags |= ACTCTX_FLAG_RESOURCE_NAME_VALID;
Actctx.lpResourceName = MAKEINTRESOURCEW(res);
}
else
{
Actctx.dwFlags &= ~ACTCTX_FLAG_RESOURCE_NAME_VALID;
}
for (int delman = 0 ; delman != 4 ; delman += 1)
{
Number[0] = 0;
if (delman)
swprintf(Number, L".%d", delman);
swprintf(manifest, L"%ls%ls%ls%ls", GetMyModuleFullPathWithoutExtension(), L".dll", Number, L".Manifest");
/*
CoCreateGuid(&Guid);
swprintf(String3, L"%ls%I64x%I64x", GetMyModuleFullPath(), *reinterpret_cast<__int64*>(&Guid), *(1+reinterpret_cast<__int64*>(&Guid)));
if (!MoveFileW(String, String3) && ::GetLastError() != ERROR_FILE_NOT_FOUND)
Trace("MoveFile(%ls -> %ls) FAILED %d\n", String, String3, ::GetLastError());
else
;//Trace("MoveFile(%ls -> %ls)\n", String, String3);
*/
if (!DeleteFileW(manifest) && ::GetLastError() != ERROR_FILE_NOT_FOUND)
Trace("DeleteFile(%ls) FAILED %d\n", manifest, ::GetLastError());
else
;//Trace("DeleteFile(%ls)\n", String3);
}
Number[0] = 0;
if (manfile != 0)
{
swprintf(Number, L".%d", manfile);
}
swprintf(manifest, L"%ls%ls%ls%ls", GetMyModuleFullPathWithoutExtension(), L".dll", Number, L".Manifest");
//Trace("fopen(%ls)\n", String);
File = _wfopen(manifest, L"w+");
if (File == NULL)
{
perror("fopen");
}
switch (good)
{
case 0:
fprintf(File, "bad");
Trace("%ls is bad\n", manifest);
break;
case 1:
fprintf(File, "%s", comctlv5manifest);
Trace("%ls is comctlv5manifest\n", manifest);
break;
case 2:
fprintf(File, "%s", comctlv6manifest);
Trace("%ls is comctlv6manifest\n", manifest);
break;
}
fclose(File);
ActctxHandle = CreateActCtxW(&Actctx);
if (ActctxHandle == INVALID_HANDLE_VALUE)
{
Trace("CreateActCtxW failed %d\n", ::GetLastError());
ulCookie = 0;
}
else
{
Trace("CreateActCtxW succeeded %p\n", ActctxHandle);
ActivateActCtx(ActctxHandle, &ulCookie);
}
__try
{
PWSTR filePart;
comctl[0] = 0;
SearchPathW(NULL, L"comctl32.dll", NULL, RTL_NUMBER_OF(comctl), comctl, &filePart);
}
__finally
{
if (ActctxHandle != INVALID_HANDLE_VALUE)
DeactivateActCtx(0, ulCookie);
}
Trace("SearchPathW(comctl32.dll): %ls\n", comctl);
}
}
}
}
void TestCreateActctxLikeCreateProcess()
{
#if defined(ACTCTX_FLAG_LIKE_CREATEPROCESS)
WCHAR comctl[MAX_PATH];
WCHAR manifest[MAX_PATH];
ACTCTXW Actctx = {sizeof(Actctx)};
FILE* File = NULL;
ULONG_PTR ulCookie = 0;
HMODULE DllHandle = 0;
HANDLE ActctxHandle;
PWSTR filePart;
Actctx.lpSource = GetMyModuleFullPath();
Actctx.dwFlags = ACTCTX_FLAG_LIKE_CREATEPROCESS;
wcscpy(manifest, GetMyModuleFullPath());
wcscat(manifest, L".Manifest");
DeleteFileW(manifest);
//Trace("DeleteFile(%ls)\n", manifest);
ActctxHandle = CreateActCtxW(&Actctx);
if (ActctxHandle == INVALID_HANDLE_VALUE)
{
Trace("CreateActCtxW failed %d\n", ::GetLastError());
ulCookie = 0;
}
else
{
Trace("CreateActCtxW succeeded %p\n", ActctxHandle);
ActivateActCtx(ActctxHandle, &ulCookie);
}
__try
{
comctl[0] = 0;
SearchPathW(NULL, L"comctl32.dll", NULL, RTL_NUMBER_OF(comctl), comctl, &filePart);
}
__finally
{
if (ActctxHandle != INVALID_HANDLE_VALUE)
DeactivateActCtx(0, ulCookie);
}
Trace("SearchPathW(comctl32.dll): %ls\n", comctl);
File = _wfopen(manifest, L"w");
fprintf(File, "%s", comctlv5manifest);
fclose(File);
Trace("%ls == comctlv5manifest\n", manifest);
ActctxHandle = CreateActCtxW(&Actctx);
if (ActctxHandle == INVALID_HANDLE_VALUE)
{
Trace("CreateActCtxW failed %d\n", ::GetLastError());
ulCookie = 0;
}
else
{
Trace("CreateActCtxW succeeded %p\n", ActctxHandle);
ActivateActCtx(ActctxHandle, &ulCookie);
}
__try
{
comctl[0] = 0;
SearchPathW(NULL, L"comctl32.dll", NULL, RTL_NUMBER_OF(comctl), comctl, &filePart);
}
__finally
{
if (ActctxHandle != INVALID_HANDLE_VALUE)
DeactivateActCtx(0, ulCookie);
}
Trace("SearchPathW(comctl32.dll): %ls\n", comctl);
File = _wfopen(manifest, L"w");
fprintf(File, "%ls", comctlv6manifest);
fclose(File);
Trace("%ls == comctlv6manifest\n", manifest);
ActctxHandle = CreateActCtxW(&Actctx);
if (ActctxHandle == INVALID_HANDLE_VALUE)
{
Trace("CreateActCtxW failed %d\n", ::GetLastError());
ulCookie = 0;
}
else
{
Trace("CreateActCtxW succeeded %p\n", ActctxHandle);
ActivateActCtx(ActctxHandle, &ulCookie);
}
__try
{
comctl[0] = 0;
SearchPathW(NULL, L"comctl32.dll", NULL, RTL_NUMBER_OF(comctl), comctl, &filePart);
}
__finally
{
if (ActctxHandle != INVALID_HANDLE_VALUE)
DeactivateActCtx(0, ulCookie);
}
Trace("SearchPathW(comctl32.dll): %ls\n", comctl);
#endif
}
void
TestQueryManifestInformationBasic(
PCWSTR pszManifest
)
{
PSXS_QUERY_MANIFEST_INFORMATION pfn = NULL;
LoadSxs();
struct {
SXS_MANIFEST_INFORMATION_BASIC mib;
WCHAR rgwchSpaceForIdentity[1024];
WCHAR rgwchSpaceForDirName[1024];
} buff;
GetSxsProc("SxsQueryManifestInformation", &pfn);
if (!(*pfn)(0, pszManifest, SXS_QUERY_MANIFEST_INFORMATION_INFOCLASS_BASIC, 0, sizeof(buff), &buff, NULL)) {
fprintf(stderr, "%s failed!\n", __FUNCTION__);
}
}
void TestImage()
{
PIMAGE_RESOURCE_DIRECTORY ImageResourceDirectory = (PIMAGE_RESOURCE_DIRECTORY)4;
PIMAGE_RESOURCE_DIRECTORY_ENTRY ImageResourceDirectoryEntry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)4;;
printf("ImageResourceDirectory %p\n", ImageResourceDirectory);
printf("ImageResourceDirectory + 1 %p\n", ImageResourceDirectory + 1);
printf("ImageResourceDirectoryEntry %p\n", ImageResourceDirectoryEntry);
printf("ImageResourceDirectoryEntry + 1 %p\n", ImageResourceDirectoryEntry + 1);
}
class CSxsTestCleanup : public CCleanupBase
{
public:
VOID DeleteYourself() { }
~CSxsTestCleanup() { }
};
#define private public
#include "sxsprotect.h"
#undef private
void TestInterlockedAlignment()
{
__declspec(align(16)) SLIST_HEADER SlistHeader;
RtlInitializeSListHead(&SlistHeader);
CSxsTestCleanup* pc = new CSxsTestCleanup();
printf("%p\n", pc);
printf("%p\n", static_cast<SINGLE_LIST_ENTRY*>(pc));
SxspAtExit(pc);
CProtectionRequestRecord* pr = new CProtectionRequestRecord;
printf("%p\n", pr);
printf("%p\n", &pr->m_ListHeader);
CStringListEntry* psle = new CStringListEntry;
printf("%p\n", psle);
printf("%p\n", static_cast<SINGLE_LIST_ENTRY*>(psle));
RtlInterlockedPushEntrySList(&SlistHeader, pc);
RtlInterlockedPushEntrySList(&SlistHeader, psle);
RtlQueryDepthSList(&SlistHeader);
RtlInterlockedPopEntrySList(&SlistHeader);
RtlInterlockedFlushSList(&SlistHeader);
// untested: RtlInterlockedPushListSList
RtlInterlockedPushEntrySList(&pr->m_ListHeader, pc);
RtlInterlockedPushEntrySList(&pr->m_ListHeader, psle);
RtlQueryDepthSList(&pr->m_ListHeader);
RtlInterlockedPopEntrySList(&pr->m_ListHeader);
RtlInterlockedFlushSList(&pr->m_ListHeader);
// untested: RtlInterlockedPushListSList
printf("success\n");
}
void TestCreateActctxWindowsShellManifest()
{
WCHAR WindowsShellManifestFileName[MAX_PATH];
ACTCTXW ActCtx = { sizeof(ActCtx) };
HANDLE ActCtxHandle = 0;
WindowsShellManifestFileName[0] = 0;
GetWindowsDirectoryW(WindowsShellManifestFileName, NUMBER_OF(WindowsShellManifestFileName) - 64);
wcscat(WindowsShellManifestFileName, L"\\WindowsShell.Manifest");
ActCtx.lpSource = WindowsShellManifestFileName;
ActCtxHandle = CreateActCtxW(&ActCtx);
Trace("TestCreateActctxWindowsShellManifest: %p, %lu\n", ActCtxHandle, ::GetLastError());
ReleaseActCtx(ActCtxHandle);
}
class CObjectTypes
{
protected:
std::vector<BYTE> m_ByteBuffer;
PSYSTEM_OBJECTTYPE_INFORMATION m_TypedBuffer;
public:
};
void TestCreateGlobalEvent()
{
if (!::CreateEventW(NULL, FALSE, FALSE, L"MGRIER"))
return;
Sleep(500000);
}
class CObjectSnapshot
{
protected:
//
// This interface is not very good, but it's easy..the entries
// are of variable size...
//
std::vector<BYTE> m_ByteBuffer;
SIZE_T m_Size;
//
// Some operations, like sorting, require us to move all the string data
// out of the elements. We do not manage this data in a lossless way.
//
// Ultimately, you may benefit from copying/transforming the data completely.
//
std::vector<BYTE> m_StringData;
public:
SIZE_T size() const { return m_Size; }
class iterator;
class const_iterator
{
protected:
const SYSTEM_OBJECT_INFORMATION* m_p;
public:
~const_iterator() { }
void operator=(const const_iterator& x) { m_p = x.m_p; }
const_iterator(const const_iterator& x) : m_p(x.m_p) { }
const_iterator(const BYTE* p = NULL) : m_p(reinterpret_cast<const SYSTEM_OBJECT_INFORMATION*>(p)) { }
//void operator=(const iterator& x);
//const_iterator(const iterator& x);
bool operator==(const const_iterator& i) const
{
return (m_p == i.m_p);
}
bool operator!=(const const_iterator& i) const
{
return (m_p != i.m_p);
}
const SYSTEM_OBJECT_INFORMATION& operator*() const { return *m_p; }
void operator++()
{
if (m_p != NULL)
{
if (m_p->NextEntryOffset != 0)
m_p = reinterpret_cast<const SYSTEM_OBJECT_INFORMATION*>(reinterpret_cast<const BYTE*>(m_p) + m_p->NextEntryOffset);
else
m_p = NULL; // end
}
}
const_iterator operator++(int)
{
const_iterator tmp = *this;
++*this;;
return tmp;
}
};
class iterator : public const_iterator
{
private:
void operator=(const const_iterator&);
public:
~iterator() { }
iterator(BYTE* p = NULL) : const_iterator(p) { }
SYSTEM_OBJECT_INFORMATION& operator*() { return const_cast<SYSTEM_OBJECT_INFORMATION&>(*m_p); }
};
const_iterator begin() const { return const_iterator(&m_ByteBuffer[0]); }
iterator begin() { return iterator(&m_ByteBuffer[0]); }
const_iterator end() const { return const_iterator(); }
iterator end() { return iterator(); }
void swap(CObjectSnapshot& x)
{
std::swap(m_ByteBuffer, x.m_ByteBuffer);
std::swap(m_Size, x.m_Size);
}
CObjectSnapshot() { }
~CObjectSnapshot() { }
};
class CHandleSnapshot
{
protected:
std::vector<BYTE> m_ByteBuffer;
PSYSTEM_HANDLE_INFORMATION_EX m_TypedBuffer;
public:
SIZE_T size() const { return m_TypedBuffer->NumberOfHandles; }
SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX* begin() { return &m_TypedBuffer->Handles[0]; }
const SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX* begin() const { return &m_TypedBuffer->Handles[0]; }
SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX* end() { return begin() + size(); }
const SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX* end() const { return begin() + size(); }
SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX& operator[](size_t index) { return *(begin() + index); }
const SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX& operator[](size_t index) const { return *(begin() + index); }
void reserve(SIZE_T n)
{
resize(n); // since there's no constructor..
}
void resize(SIZE_T n)
{
m_ByteBuffer.resize(sizeof(SYSTEM_HANDLE_INFORMATION_EX) + (n - 1) * sizeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX));
Resync();
m_TypedBuffer->NumberOfHandles = n;
}
void swap(CHandleSnapshot& x)
{
std::swap(m_ByteBuffer, x.m_ByteBuffer);
x.Resync();
Resync();
}
CHandleSnapshot() : m_TypedBuffer(NULL) { }
~CHandleSnapshot() { }
void GetHandlesForCurrentProcess()
{
GetHandlesForProcess(GetCurrentProcessId());
}
void GetHandlesForProcess(ULONG_PTR pid)
{
GetHandlesForSystem();
FilterByProcessId(pid);
}
void GetHandlesForSystem()
{
//
// the actual needed size can be very large, over 256k
//
ULONG Size = 0;
m_TypedBuffer = NULL;
m_ByteBuffer.resize(sizeof(SYSTEM_HANDLE_INFORMATION_EX));
NTSTATUS Status = NtQuerySystemInformation(SystemExtendedHandleInformation, &m_ByteBuffer[0], static_cast<ULONG>(m_ByteBuffer.size()), &Size);
while (Status == STATUS_INFO_LENGTH_MISMATCH && Size != 0)
{
//
// since it is transient, let's be safe and double it
//
m_ByteBuffer.resize(Size * 2);
Status = NtQuerySystemInformation(SystemExtendedHandleInformation, &m_ByteBuffer[0], static_cast<ULONG>(m_ByteBuffer.size()), &Size);
}
if (!NT_SUCCESS(Status))
{
Trace("NtQuerySystemInformation failed 0x%lx\n", Status);
return;
}
m_ByteBuffer.resize(Size);
m_TypedBuffer = reinterpret_cast<PSYSTEM_HANDLE_INFORMATION_EX>(&m_ByteBuffer[0]);
Trace("%Id total handles system-wide\n", m_TypedBuffer->NumberOfHandles);
}
void FilterByProcessId(ULONG_PTR pid)
{
SIZE_T Scan = 0;
SIZE_T Keep = 0;
for (Scan = 0 ; Scan != m_TypedBuffer->NumberOfHandles ; Scan += 1)
{
if (m_TypedBuffer->Handles[Scan].UniqueProcessId == pid)
{
if (Keep != Scan)
m_TypedBuffer->Handles[Keep] = m_TypedBuffer->Handles[Scan]; // struct copy
Keep += 1;
}
}
m_TypedBuffer->NumberOfHandles = Keep;
}
void Resync()
{
m_TypedBuffer = reinterpret_cast<PSYSTEM_HANDLE_INFORMATION_EX>(&m_ByteBuffer[0]);
}
CHandleSnapshot(const CHandleSnapshot& x) : m_TypedBuffer(NULL)
{
this->m_ByteBuffer = x.m_ByteBuffer;
Resync();
}
void operator=(const CHandleSnapshot& x)
{
this->m_ByteBuffer = x.m_ByteBuffer;
Resync();
}
class CHandleValueOperatorLessThan
{
public:
bool operator()(const SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX& x, const SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX& y)
{
return (x.HandleValue < y.HandleValue);
}
};
void SortByHandleValue()
{
std::sort(begin(), end(), CHandleValueOperatorLessThan());
}
void operator-=(/*const*/CHandleSnapshot& x)
{
SortByHandleValue();
x.SortByHandleValue();
CHandleSnapshot temp(*this);
resize(
std::set_difference(temp.begin(), temp.end(), x.begin(), x.end(), begin(), CHandleValueOperatorLessThan())
- begin());
}
void Dump()
{
}
};
class CHandleSnapshots
{
public:
void Begin() { m_Begin.GetHandlesForCurrentProcess(); }
void End() { m_End.GetHandlesForCurrentProcess(); m_Diff = m_Begin; m_Diff -= m_End; }
CHandleSnapshot m_Begin;
CHandleSnapshot m_End;
CHandleSnapshot m_Diff;
};
void Pause()
{
Trace("Press a key to continue\n");
getchar();
}
void TestHandleLeaks()
{
WCHAR WindowsDirectory[MAX_PATH];
ULONG i = 0;
CFusionFile DevNull;
//SECURITY_ATTRIBUTES SecurityAttributes = { sizeof(SecurityAttributes), NULL, TRUE};
WindowsDirectory[0] = 0;
DevNull = CreateFileW(L"nul:", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL/*&SecurityAttributes*/, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (DevNull == INVALID_HANDLE_VALUE)
Trace("Open(nul:) failed %ld\n", ::GetLastError());
GetWindowsDirectoryW(WindowsDirectory, NUMBER_OF(WindowsDirectory) - 64);
{
const WCHAR SubFunction[] = L"CreateActCtx";
CHandleSnapshots handleSnapshots;
handleSnapshots.Begin();
Trace("%s Begin %ls : %Id handles\n", __FUNCTION__, SubFunction, handleSnapshots.m_Begin.size());
{
WCHAR WindowsShellManifestFileName[MAX_PATH];
ACTCTXW ActCtx = { sizeof(ActCtx) };
HANDLE ActCtxHandle = 0;
WindowsShellManifestFileName[0] = 0;
wcscpy(WindowsShellManifestFileName, WindowsDirectory);
wcscat(WindowsShellManifestFileName, L"\\WindowsShell.Manifest");
ActCtx.lpSource = WindowsShellManifestFileName;
for (i = 0 ; i != 100 ; ++i)
{
HANDLE ActCtxHandle = CreateActCtxW(&ActCtx);
if (ActCtxHandle == INVALID_HANDLE_VALUE)
Trace("TestCreateActctxWindowsShellManifest: %p, %lu\n", ActCtxHandle, ::GetLastError());
else
ReleaseActCtx(ActCtxHandle);
}
}
handleSnapshots.End();
Trace("%s End %ls : %Id handles\n", __FUNCTION__, SubFunction, handleSnapshots.m_End.size());
if (handleSnapshots.m_Diff.size() != 0)
{
Trace("%s Diff %ls : %Id handles\n", __FUNCTION__, SubFunction, handleSnapshots.m_Diff.size());
}
}
Pause();
{
const WCHAR SubFunction[] = L"CreateActCtx + LoadLibrary(comctl32)";
CHandleSnapshots handleSnapshots;
handleSnapshots.Begin();
Trace("%s Begin %ls : %Id handles\n", __FUNCTION__, SubFunction, handleSnapshots.m_Begin.size());
{
WCHAR WindowsShellManifestFileName[MAX_PATH];
ACTCTXW ActCtx = { sizeof(ActCtx) };
HANDLE ActCtxHandle = 0;
WindowsShellManifestFileName[0] = 0;
wcscpy(WindowsShellManifestFileName, WindowsDirectory);
wcscat(WindowsShellManifestFileName, L"\\WindowsShell.Manifest");
ActCtx.lpSource = WindowsShellManifestFileName;
for (i = 0 ; i != 100 ; ++i)
{
ULONG_PTR ulCookie = 0;
HANDLE ActCtxHandle = CreateActCtxW(&ActCtx);
if (ActCtxHandle == INVALID_HANDLE_VALUE)
Trace("TestCreateActctxWindowsShellManifest: %p, %lu\n", ActCtxHandle, ::GetLastError());
else
{
ActivateActCtx(ActCtxHandle, &ulCookie);
HMODULE Comctl = LoadLibraryW(L"comctl32.dll");
if (i == 1)
{
CHandleSnapshot handleSnapshot;
handleSnapshot.GetHandlesForCurrentProcess();
Trace("Comctl32.dll loaded first time %Id\n", handleSnapshot.size());
Pause();
}
FreeLibrary(Comctl);
if (i == 1)
{
CHandleSnapshot handleSnapshot;
handleSnapshot.GetHandlesForCurrentProcess();
Trace("Comctl32.dll unloaded first time %Id\n", handleSnapshot.size());
Pause();
}
if (ulCookie != 0)
DeactivateActCtx(0, ulCookie);
ReleaseActCtx(ActCtxHandle);
if (i == 1)
{
CHandleSnapshot handleSnapshot;
handleSnapshot.GetHandlesForCurrentProcess();
Trace("Comctl32.dll unloaded + ReleaseActCtxfirst time %Id\n", handleSnapshot.size());
Pause();
}
}
}
}
handleSnapshots.End();
Trace("%s End %ls : %Id handles\n", __FUNCTION__, SubFunction, handleSnapshots.m_End.size());
if (handleSnapshots.m_Diff.size() != 0)
{
Trace("%s Diff %ls : %Id handles\n", __FUNCTION__, SubFunction, handleSnapshots.m_Diff.size());
}
}
Pause();
{
WCHAR Me[MAX_PATH];
STARTUPINFOW StartupInfo = {sizeof(StartupInfo)};
PROCESS_INFORMATION ProcessInfo = {0};
static const WCHAR SubFunction[] = L"CreateProcess";
Kernel32.GetModuleFileNameW(NULL, Me, NUMBER_OF(Me));
CHandleSnapshots handleSnapshots;
handleSnapshots.Begin();
Trace("%s Begin %ls : %Id handles\n", __FUNCTION__, SubFunction, handleSnapshots.m_Begin.size());
for (i = 0 ; i != 100 ; ++i)
{
StartupInfo.hStdOutput = DevNull;
StartupInfo.hStdError = DevNull;
StartupInfo.dwFlags = STARTF_USESTDHANDLES;
if (!CreateProcessW(Me, NULL, NULL, NULL, FALSE, 0, NULL, NULL, &StartupInfo, &ProcessInfo))
{
Trace("CreateProcess failed %ld\n", ::GetLastError());
}
else
{
WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
WaitForSingleObject(ProcessInfo.hThread, INFINITE);
if (!CloseHandle(ProcessInfo.hProcess))
Trace("CloseHandle(Process %p) failed %ld\n", ProcessInfo.hProcess, ::GetLastError());
if (!CloseHandle(ProcessInfo.hThread))
Trace("CloseHandle(Thread %p) failed %ld\n", ProcessInfo.hThread, ::GetLastError());
}
}
handleSnapshots.End();
Trace("%s End %ls : %Id handles\n", __FUNCTION__, SubFunction, handleSnapshots.m_End.size());
if (handleSnapshots.m_Diff.size() != 0)
{
Trace("%s Diff %ls : %Id handles\n", __FUNCTION__, SubFunction, handleSnapshots.m_Diff.size());
}
}
Pause();
{
WCHAR SubFunction[sizeof("LoadLibrary xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")];
WCHAR DllPath[MAX_PATH];
ULONG j = 0;
const static PCWSTR Leaves[] = {
L"mshtml.dll",
L"wintrust.dll",
L"shell32.dll",
L"crypt32.dll",
L"msxml.dll",
L"shdocvw.dll",
L"msxml2.dll",
L"msxml3.dll"
};
for (j = 0 ; j != NUMBER_OF(Leaves) ; ++j)
{
SubFunction[0] = 0;
wcscat(SubFunction, L"LoadLibrary ");
wcscat(SubFunction, Leaves[j]);
DllPath[0] = 0;
wcscat(DllPath, WindowsDirectory);
wcscat(DllPath, L"\\system32\\");
wcscat(DllPath, Leaves[j]);
CHandleSnapshots handleSnapshots;
handleSnapshots.Begin();
Trace("%s Begin %ls : %Id handles\n", __FUNCTION__, SubFunction, handleSnapshots.m_Begin.size());
for (i = 0 ; i != 20 ; ++i)
{
HMODULE DllHandle;
if ((DllHandle = LoadLibraryW(DllPath)) != NULL)
FreeLibrary(DllHandle);
else
Trace("LoadLibraryW(%ls) failed %ld\n", DllPath, ::GetLastError());
}
handleSnapshots.End();
Trace("%s End %ls : %Id handles\n", __FUNCTION__, SubFunction, handleSnapshots.m_End.size());
if (handleSnapshots.m_Diff.size() != 0)
{
Trace("%s Diff %s : %Id handles\n", __FUNCTION__, SubFunction, handleSnapshots.m_Diff.size());
}
}
}
Pause();
}
#define YET_ANOTHER_PASTE(x,y) x##y
#define YET_YET_ANOTHER_PASTE(x,y) YET_ANOTHER_PASTE(x,y)
#define LSXS_PROCESSOR_ARCHITECTURE YET_YET_ANOTHER_PASTE(L, SXS_PROCESSOR_ARCHITECTURE)
const WCHAR ToolsCrtManifest[]=
L"<?xml version=\"1.0\" standalone=\"yes\"?>"
L"<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
L"<assemblyIdentity"
L" name=\"Microsoft.Windows.SxsTest.ToolsCrtClient\""
L" processorArchitecture=\"" LSXS_PROCESSOR_ARCHITECTURE L"\"" /* Note that this only actually exists on x86 */
L" version=\"5.1.0.0\""
L" type=\"win32\"/>"
L"<dependency>"
L" <dependentAssembly>"
L" <assemblyIdentity"
L" type=\"win32\""
L" name=\"Microsoft.Tools.VisualCPlusPlus.Runtime-Libraries\""
L" version=\"6.0.0.0\""
L" processorArchitecture=\"" LSXS_PROCESSOR_ARCHITECTURE L"\""
L" publicKeyToken=\"6595b64144ccf1df\""
L" language=\"*\""
L" />"
L" </dependentAssembly>"
L"</dependency>"
L"</assembly>"
;
const WCHAR WindowsCrtManifest[]=
L"<?xml version=\"1.0\" standalone=\"yes\"?>"
L"<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
L"<assemblyIdentity"
L" name=\"Microsoft.Windows.SxsTest.WindowsCrtClient\""
L" processorArchitecture=\"" LSXS_PROCESSOR_ARCHITECTURE L"\""
L" version=\"5.1.0.0\""
L" type=\"win32\"/>"
L"<dependency>"
L" <dependentAssembly>"
L" <assemblyIdentity"
L" type=\"win32\""
L" name=\"Microsoft.Windows.CPlusPlusRuntime\""
L" version=\"7.0.0.0\""
L" processorArchitecture=\"" LSXS_PROCESSOR_ARCHITECTURE L"\""
L" publicKeyToken=\"6595b64144ccf1df\""
L" language=\"*\""
L" />"
L" </dependentAssembly>"
L"</dependency>"
L"</assembly>"
;
void TestCRuntimeAsms()
{
CFusionActCtxHandle WindowsCrtActCtxHandle;
CFusionActCtxHandle ToolsCrtActCtxHandle;
WindowsCrtActCtxHandle = ::CreateActivationContextFromStringW(WindowsCrtManifest);
if (WindowsCrtActCtxHandle == INVALID_HANDLE_VALUE)
::Trace("CreateActCtx(WindowsCrtManifest %p) failed %ld\n", WindowsCrtManifest, ::GetLastError());
ToolsCrtActCtxHandle = ::CreateActivationContextFromStringW(ToolsCrtManifest);
if (ToolsCrtActCtxHandle == INVALID_HANDLE_VALUE)
::Trace("CreateActCtx(WindowsCrtManifest %p) failed %ld\n", WindowsCrtManifest, ::GetLastError());
CFusionActCtxScope ToolsCrtActCtxScope;
CFusionActCtxScope WindowsCrtActCtxScope;
if (!WindowsCrtActCtxScope.Win32Activate(WindowsCrtActCtxHandle))
::Trace("Activate(WindowsCrtActCtxHandle %p) failed %ld\n", WindowsCrtActCtxHandle, ::GetLastError());
if (!ToolsCrtActCtxScope.Win32Activate(ToolsCrtActCtxHandle))
::Trace("Activate(ToolsCrtActCtxHandle %p) failed %ld\n", ToolsCrtActCtxHandle, ::GetLastError());
CStringBuffer MsvcrtBuffer;
CStringBuffer AtlBuffer;
//::SearchPathW();
}
/*
<comInterfaceExternalProxyStub
name="IPropertyPage"
iid="{B196B28D-BAB4-101A-B69C-00AA00341D07}"
proxyStubClsid32="{B196B286-BAB4-101A-B69C-00AA00341D07}"
numMethods="14"
baseInterface="{00000000-0000-0000-C000-000000000046}"
>
<comInterfaceExternalProxyStub
name="IPropertyPage2"
iid="{01E44665-24AC-101B-84ED-08002B2EC713}"
proxyStubClsid32="{B196B286-BAB4-101A-B69C-00AA00341D07}"
numMethods="15"
baseInterface="{B196B28D-BAB4-101A-B69C-00AA00341D07}"
>
<comInterfaceExternalProxyStub
name="IPropertyNotifySink"
iid="{9BFBBC02-EFF1-101A-84ED-00AA00341D07}"
proxyStubClsid32="{B196B286-BAB4-101A-B69C-00AA00341D07}"
baseInterface="{00000000-0000-0000-C000-00 00 00 00 00 46}"
numMethods="5"
>
*/
#if 0
BOOL Win32FormatGuid(
CBaseStringBuffer& buff
REFGUID guid
)
{
FN_PROLOG_WIN32
IFW32FALSE_EXIT(this->Win32ResizeBuffer(64));
IFW32FALSE_EXIT(buff.Win32Format(L"{%08lx-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x}",
guid.Data1,
guid.Data2,
guid.Data3,
guid.Data4[0], guid.Data4[1],
guid.Data4[2], guid.Data4[3], guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7],
));
FN_EPILOG
}
#endif
BOOL Win32Append(
CBaseStringBuffer& s,
PCWSTR t
)
{
FN_PROLOG_WIN32
IFW32FALSE_EXIT(s.Win32Append(t, wcslen(t)));
FN_EPILOG
}
typedef struct _FUSIONTESTP_REG_DATA
{
#define FUSIONTESTP_REG_TYPE_INTERFACE (1)
#define FUSIONTESTP_REG_TYPE_CLASS (2)
ULONG Type;
PCWSTR Name; // for debugging/tracing purposes (should coincide with InterfaceName)
PCWSTR Guid;
union
{
struct
{
WCHAR InprocServerFilePath[MAX_PATH];
WCHAR ThreadingModel[64];
};
struct
{
WCHAR InterfaceName[MAX_PATH];
WCHAR NumMethods[64];
WCHAR ProxyStubClsid[64];
//
// These usually aren't provided.
//
// WCHAR BaseInterface[64];
// WCHAR OLEViewerIViewerCLSID[64];
//
};
};
#define FUSIONTESTP_REG_ROOT_CURRENT_USER (1)
#define FUSIONTESTP_REG_ROOT_LOCAL_MACHINE (2)
#define FUSIONTESTP_REG_ROOT_CLASSES_ROOT (3)
ULONG Root;
//
// It is perhaps a bit inelegant to put this data here, perhaps not..
// We are deliberately a bit sloppy on the refcounting of these right now.
//
//#define FUSIONTESTP_PLAIN_COM_POINTER(t) CSmartRef<t>
#define FUSIONTESTP_PLAIN_COM_POINTER(t) t*
//#define FUSIONTESTP_PLAIN_COM_POINTER(t) void*
FUSIONTESTP_PLAIN_COM_POINTER(IUnknown) CoCreatedObject;
//FUSIONTESTP_PLAIN_COM_POINTER(IUnknown) InterfaceIntoObjectInCreatingThread;
//FUSIONTESTP_PLAIN_COM_POINTER(IUnknown) InterfaceIntoObjectInAnotherThread;
//WCHAR ModulePathInOtherThread[MAX_PATH]; // expected to be oleaut32.dll, but possibly already unloaded
//IID InterfaceIdOfObject;
DWORD GlobalInterfaceTableCookie;
} FUSIONTESTP_REG_DATA, *PFUSIONTESTP_REG_DATA;
typedef const FUSIONTESTP_REG_DATA* PCFUSIONTESTP_REG_DATA;
#if 0
//
// In reality, all three MFC classes implement all three interfaces, but let's broaden
// our minds a bit, ok?
//
BOOL
FusionTestpDynamicallyFindAnyInterfaceIntoObjectExceptIUnknown(
IUnknown* Object,
PCFUSIONTESTP_REG_DATA RegData, // too broad of a type really, but ok
SIZE_T Count,
FUSIONTESTP_PLAIN_COM_POINTER(IUnknown)& InterfaceIntoObject,
SIZE_T& InterfaceId
)
{
BOOL Success = FALSE;
FN_PROLOG_WIN32(Success);
IID LocalInterfaceId = { 0 };
FUSIONTESTP_PLAIN_COM_POINTER(IUnknown) LocalInterfaceIntoObject = NULL;
SIZE_T InterfaceIndex = 0;
InterfaceIntoObject = LocalInterfaceIntoObject;
InterfaceId = LocalInterfaceId;
for ( LocalInterfaceIndex = 0; LocalInterfaceIndex != Count ; LocalInterfaceIndex += 1)
{
FUSIONTESTP_REG_DATA* const p = &RegData[LocalInterfaceIndex];
IFCOMFAILED_EXIT(hr = Ole32.IIDFromString(const_cast<PWSTR>(p->Guid), &InterfaceId));
if (InterfaceId == IID_IUnknown) // shouldn't happen, but easy enough to handle
continue;
hr = Object->QueryInterface(InterfaceId, reinterpret_cast<void**>(&LocalInterfaceIntoObject));
if (SUCCEEDED(hr))
{
::Trace("%s found interface %ls\n", __FUNCTION__, p->Name);
InterfaceIntoObject = LocalInterfaceIntoObject;
InterfaceId = LocalInterfaceId;
Success = TRUE;
goto Exit;
}
}
FN_EPILOG
}
#endif
#define OLEAUT_MARSHALER_CLSID_STRING L"{B196B286-BAB4-101A-B69C-00AA00341D07}"
FUSIONTESTP_REG_DATA FusionTestpMfcRegData[] =
{
{ FUSIONTESTP_REG_TYPE_CLASS, L"Font Property Page", L"{0BE35200-8F91-11CE-9DE3-00AA004BB851}" },
{ FUSIONTESTP_REG_TYPE_CLASS, L"Color Property Page", L"{0BE35201-8F91-11CE-9DE3-00AA004BB851}" },
{ FUSIONTESTP_REG_TYPE_CLASS, L"Picture Property Page", L"{0BE35202-8F91-11CE-9DE3-00AA004BB851}" },
{ FUSIONTESTP_REG_TYPE_INTERFACE, L"IPropertyPage", L"{B196B28D-BAB4-101A-B69C-00AA00341D07}" },
{ FUSIONTESTP_REG_TYPE_INTERFACE, L"IPropertyPage2", L"{01E44665-24AC-101B-84ED-08002B2EC713}" },
{ FUSIONTESTP_REG_TYPE_INTERFACE, L"IPropertyNotifySink", L"{9BFBBC02-EFF1-101A-84ED-00AA00341D07}" },
// Leave this registered, since the manifest does not specify a file.
//{ FUSIONTESTP_REG_TYPE_CLASS, L"oleaut32 marshaller (PSFactoryBuffer)", OLEAUT_MARSHALER_CLSID_STRING }
};
FUSIONTESTP_REG_DATA FusionTestpAtlRegData[1];
const HKEY FusionTestpHkeyRoots[] = { NULL, HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE, HKEY_CLASSES_ROOT };
const PCWSTR FusionTestpClassStringRoots[] = { NULL, L"Software\\Classes\\CLSID\\", L"Software\\Classes\\CLSID\\", L"CLSID\\" };
const PCWSTR FusionTestpInterfaceStringRoots[] = { NULL, L"Software\\Classes\\Interface\\", L"Software\\Classes\\Interface\\", L"Interface\\" };
const PCWSTR* FusionTestpStringRoots[] = { NULL, FusionTestpInterfaceStringRoots, FusionTestpClassStringRoots};
#define FUSIONTESTP_REG_DELETE (1)
#define FUSIONTESTP_REG_RESTORE (2)
#define FUSIONTESTP_REG_BACKUP (3)
BOOL FusionTestpEnumerateRegistryData(FUSIONTESTP_REG_DATA* RegData, ULONG Count, ULONG Mode)
{
BOOL Success = FALSE;
FN_PROLOG_WIN32(Success);
for (ULONG i = 0 ; i != Count ; i += 1)
{
FUSIONTESTP_REG_DATA* const p = &RegData[i];
ULONG MinRoot = 0;
ULONG MaxRoot = 0;
switch (Mode)
{
case FUSIONTESTP_REG_RESTORE:
case FUSIONTESTP_REG_DELETE:
MinRoot = p->Root;
if (MinRoot == 0)
continue;
MaxRoot = MinRoot;
break;
case FUSIONTESTP_REG_BACKUP:
MinRoot = 1;
MaxRoot = 3;
break;
}
//
// It'd be nice if you could embed the if within a switch..
//
for (ULONG root = MinRoot ; root <= MaxRoot ; root += 1)
{
CFusionRegKey regKey;
CFusionRegKey inprocServerKey;
CStringBuffer stringBuffer;
CFusionRegKey numMethodsKey;
CFusionRegKey proxyStubClsidKey;
DWORD dwSize = 0;
DWORD dwType = 0;
CFusionRegKey rootKey(FusionTestpHkeyRoots[root]);
IFW32FALSE_EXIT(Win32Append(stringBuffer, FusionTestpStringRoots[p->Type][root]));
IFW32FALSE_EXIT(Win32Append(stringBuffer, p->Guid));
switch (Mode)
{
case FUSIONTESTP_REG_DELETE:
case FUSIONTESTP_REG_BACKUP:
rootKey.OpenSubKey(regKey, stringBuffer);
break;
case FUSIONTESTP_REG_RESTORE:
IFW32FALSE_EXIT(rootKey.OpenOrCreateSubKey(regKey, stringBuffer));
break;
}
if (regKey != regKey.GetInvalidValue())
{
switch (Mode)
{
case FUSIONTESTP_REG_BACKUP:
p->Root = root;
break;
case FUSIONTESTP_REG_DELETE:
case FUSIONTESTP_REG_RESTORE:
break;
}
switch (p->Type)
{
case FUSIONTESTP_REG_TYPE_CLASS:
switch (Mode)
{
case FUSIONTESTP_REG_BACKUP:
#define FusionTestpQueryRegString(hkey, name, value) \
do { dwSize = sizeof(value); \
RegQueryValueExW(hkey, name, NULL, &dwType, reinterpret_cast<BYTE*>(value), &dwSize); \
} while(false)
if (regKey.OpenSubKey(inprocServerKey, L"InprocServer32"))
{
FusionTestpQueryRegString(inprocServerKey, NULL, p->InprocServerFilePath);
FusionTestpQueryRegString(inprocServerKey, L"ThreadingModel", p->ThreadingModel);
}
break;
case FUSIONTESTP_REG_RESTORE:
if (regKey.OpenOrCreateSubKey(inprocServerKey, L"InprocServer32"))
{
#define FusionTestpRegStringSize(x) static_cast<ULONG>(((wcslen(x) + 1)*sizeof((x)[0])))
#define FusionTestpSetRegString(hkey, name, value) \
do { if (value[0] != 0) \
RegSetValueExW(hkey, name, NULL, REG_SZ, reinterpret_cast<const BYTE*>(value), FusionTestpRegStringSize(value)); \
} while(false)
FusionTestpSetRegString(inprocServerKey, NULL, p->InprocServerFilePath);
FusionTestpSetRegString(inprocServerKey, L"ThreadingModel", p->ThreadingModel);
}
break;
case FUSIONTESTP_REG_DELETE:
break;
}
break;
case FUSIONTESTP_REG_TYPE_INTERFACE:
switch (Mode)
{
case FUSIONTESTP_REG_BACKUP:
FusionTestpQueryRegString(regKey, NULL, p->InterfaceName);
if (regKey.OpenSubKey(numMethodsKey, L"NumMethods"))
FusionTestpQueryRegString(numMethodsKey, NULL, p->NumMethods);
if (regKey.OpenSubKey(proxyStubClsidKey, L"ProxyStubClsid32"))
FusionTestpQueryRegString(proxyStubClsidKey, NULL, p->ProxyStubClsid);
break;
case FUSIONTESTP_REG_RESTORE:
FusionTestpSetRegString(regKey, NULL, p->InterfaceName);
if (regKey.OpenOrCreateSubKey(numMethodsKey, L"NumMethods"))
FusionTestpSetRegString(numMethodsKey, NULL, p->NumMethods);
if (regKey.OpenOrCreateSubKey(proxyStubClsidKey, L"ProxyStubClsid32"))
FusionTestpSetRegString(proxyStubClsidKey, NULL, p->ProxyStubClsid);
case FUSIONTESTP_REG_DELETE:
break;
}
break;
}
switch (Mode)
{
case FUSIONTESTP_REG_DELETE:
regKey.DestroyKeyTree();
break;
case FUSIONTESTP_REG_BACKUP:
case FUSIONTESTP_REG_RESTORE:
break;
}
break;
}
}
}
FN_EPILOG
}
#if 0 // Use CoWaitForMultipleHandles instead, it is much safer because it only
// pumps particular messages.
void FusionTestpPumpMessages()
{
MSG msg;
BOOL bRet;
while ((bRet = ::GetMessageW(&msg, NULL, 0, 0)) != 0)
{
if (bRet == -1)
return;
else
{
::TranslateMessage(&msg);
if (::IsWindowUnicode(msg.hwnd))
::DispatchMessageW(&msg);
else
::DispatchMessage(&msg);
}
}
}
#endif
HMODULE FusionTestpHmoduleFromComObject(IUnknown* unk)
{
void** ppv = reinterpret_cast<void**>(unk);
void* pv = *ppv;
MEMORY_BASIC_INFORMATION MemBasicInfo = { 0 };
SIZE_T dw = 0;
if ((dw = Kernel32.VirtualQuery(pv, &MemBasicInfo, sizeof(MemBasicInfo))) == 0
|| (dw < RTL_SIZEOF_THROUGH_FIELD(MEMORY_BASIC_INFORMATION, BaseAddress)))
{
::Trace("VirtualQuery(%p) failed %lu\n", pv, ::GetLastError());
return NULL;
}
return reinterpret_cast<HMODULE>(MemBasicInfo.AllocationBase);
}
DWORD WINAPI FusionTestpMfcCreateAndMarshalThreadMain(LPVOID pvShouldBeAbleToMarshal)
{
BOOL Success = FALSE;
FN_PROLOG_WIN32(Success);
HRESULT hr = 0;
const bool ShouldBeAbleToMarshal = (pvShouldBeAbleToMarshal != NULL ? true : false);
Ole32.CoInitialize(NULL);
//
// For each interface, make sure we can unmarshal at least one object.
//
for (ULONG InterfaceIndex = 0 ; InterfaceIndex != NUMBER_OF(::FusionTestpMfcRegData) ; InterfaceIndex += 1)
{
FUSIONTESTP_REG_DATA* const pi = &::FusionTestpMfcRegData[InterfaceIndex];
switch (pi->Type)
{
case FUSIONTESTP_REG_TYPE_CLASS:
continue;
case FUSIONTESTP_REG_TYPE_INTERFACE:
IID InterfaceId = { 0 };
FUSIONTESTP_PLAIN_COM_POINTER(IUnknown) InterfaceIntoObjectInAnotherThread = NULL;
IFCOMFAILED_EXIT(hr = Ole32.IIDFromString(const_cast<PWSTR>(pi->Guid), &InterfaceId));
// nested loop..
for (ULONG ClassIndex = 0 ;
ClassIndex != NUMBER_OF(::FusionTestpMfcRegData) ;
ClassIndex += 1)
{
CLSID ClassId = { 0 };
FUSIONTESTP_REG_DATA* const pc = &::FusionTestpMfcRegData[ClassIndex];
switch (pc->Type)
{
case FUSIONTESTP_REG_TYPE_INTERFACE:
continue;
case FUSIONTESTP_REG_TYPE_CLASS:
WCHAR ModulePathInOtherThread[MAX_PATH];
ModulePathInOtherThread[0] = 0;
ASSERT(pc->GlobalInterfaceTableCookie != 0);
IFCOMFAILED_EXIT(hr = Ole32.CLSIDFromString(const_cast<PWSTR>(pc->Guid), &ClassId));
hr = g.GlobalInterfaceTable->GetInterfaceFromGlobal(
pc->GlobalInterfaceTableCookie, InterfaceId,
reinterpret_cast<void**>(&InterfaceIntoObjectInAnotherThread));
if (SUCCEEDED(hr))
{
IFW32FALSE_EXIT(Kernel32.GetModuleFileNameW(
::FusionTestpHmoduleFromComObject(InterfaceIntoObjectInAnotherThread),
ModulePathInOtherThread, NUMBER_OF(ModulePathInOtherThread)));
}
if (SUCCEEDED(hr) && ShouldBeAbleToMarshal)
{
Trace("%s SUCCESSfully marshaled interface %ls on class %ls using proxy/stub in %ls\n",
__FUNCTION__, pi->Name, pc->Name, ModulePathInOtherThread);
g.Successes += 1;
}
else if (SUCCEEDED(hr) && !ShouldBeAbleToMarshal)
{
// unexpected success -> ERROR
Trace("%s FAILED to fail to marshal interface %ls on class %ls (using proxy/stub in %ls)\n",
__FUNCTION__, pi->Name, pc->Name, ModulePathInOtherThread);
g.Failures += 1;
}
else if (FAILED(hr) && ShouldBeAbleToMarshal)
{
// keep looping, try other objects
}
else if (FAILED(hr) && !ShouldBeAbleToMarshal)
{
// keep looping, make sure none succeed
//::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));
}
break;
}
if (InterfaceIntoObjectInAnotherThread != NULL && ShouldBeAbleToMarshal)
{
// one successful unmarshal is enough
break;
}
}
// use the nullness of InterfaceIntoObjectInAnotherThread as a summary of the loop
if (InterfaceIntoObjectInAnotherThread == NULL && ShouldBeAbleToMarshal)
{
::Trace("%s FAILURE Unable to marshal interface %ls (%ls)\n", __FUNCTION__, pi->Name, pi->Guid);
g.Failures += 1;
}
else if (InterfaceIntoObjectInAnotherThread == NULL && !ShouldBeAbleToMarshal)
{
::Trace("%s GOOD Unable to marshal interface %ls without actctx as expected\n", __FUNCTION__, pi->Name);
g.Successes += 1;
}
break;
}
}
Ole32.CoUninitialize();
FN_EPILOG
}
BOOL TestMfcCreateAndMarshal()
{
BOOL Success = FALSE;
FN_PROLOG_WIN32(Success);
ULONG i = 0;
HRESULT hr = 0;
HANDLE ThreadHandle = 0;
DWORD Ignored = 0;
CFusionActCtxHandle ToolsCrtActCtxHandle;
::FusionTestpEnumerateRegistryData(::FusionTestpMfcRegData, NUMBER_OF(::FusionTestpMfcRegData), FUSIONTESTP_REG_BACKUP);
::FusionTestpEnumerateRegistryData(::FusionTestpMfcRegData, NUMBER_OF(::FusionTestpMfcRegData), FUSIONTESTP_REG_DELETE);
Ole32.CoInitialize(NULL);
//
// Verify that we cannot create any of the classes.
//
for (i = 0 ; i != NUMBER_OF(::FusionTestpMfcRegData) ; i += 1)
{
CSmartRef<IUnknown> unk;
CLSID ClassId = { 0 };
FUSIONTESTP_REG_DATA* const p = &::FusionTestpMfcRegData[i];
switch (p->Type)
{
case FUSIONTESTP_REG_TYPE_INTERFACE:
break;
case FUSIONTESTP_REG_TYPE_CLASS:
IFCOMFAILED_EXIT(hr = Ole32.CLSIDFromString(const_cast<PWSTR>(p->Guid), &ClassId));
hr = Ole32.CoCreateInstance(ClassId, NULL, CLSCTX_INPROC_SERVER, IID_IUnknown, reinterpret_cast<void**>(&unk));
if (SUCCEEDED(hr))
{
::Trace("%s BAD, no registry, no actctx CoCreate(%ls) SUCCEEDED, not expected\n", __FUNCTION__, p->Name);
g.Failures += 1;
}
else
{
::Trace("%s GOOD, no registry, no actctx CoCreate(%ls) FAILed 0x%lx, as expected\n", __FUNCTION__, p->Name, hr);
g.Successes += 1;
}
break;
}
}
//
// Create and activate the context.
//
ToolsCrtActCtxHandle = ::CreateActivationContextFromStringW(ToolsCrtManifest);
if (ToolsCrtActCtxHandle == INVALID_HANDLE_VALUE)
::Trace("CreateActCtx(WindowsCrtManifest %p) failed %ld\n", WindowsCrtManifest, ::GetLastError());
{
CFusionActCtxScope ToolsCrtActCtxScope;
if (!ToolsCrtActCtxScope.Win32Activate(ToolsCrtActCtxHandle))
::Trace("Activate(ToolsCrtActCtxHandle %p) failed %ld\n", ToolsCrtActCtxHandle, ::GetLastError());
//
// Now create each class and print the .dll it came from.
// And put it in the global interface table for later unmarshalling.
//
IFCOMFAILED_EXIT(hr = Ole32.CoCreateInstance(CLSID_StdGlobalInterfaceTable,NULL, CLSCTX_INPROC_SERVER,
IID_IGlobalInterfaceTable, reinterpret_cast<void**>(&g.GlobalInterfaceTable)));
for (i = 0 ; i != NUMBER_OF(::FusionTestpMfcRegData) ; i += 1)
{
CLSID ClassId = { 0 };
FUSIONTESTP_REG_DATA* const p = &::FusionTestpMfcRegData[i];
//
// We are not supposed to be able to cocreate this here.
//
if (FusionpStrCmpI(p->Guid, OLEAUT_MARSHALER_CLSID_STRING) == 0)
continue;
switch (p->Type)
{
case FUSIONTESTP_REG_TYPE_INTERFACE:
break;
case FUSIONTESTP_REG_TYPE_CLASS:
IFCOMFAILED_EXIT(hr = Ole32.CLSIDFromString(const_cast<PWSTR>(p->Guid), &ClassId));
hr = Ole32.CoCreateInstance(ClassId, NULL, CLSCTX_INPROC_SERVER, IID_IUnknown,
reinterpret_cast<void**>(&p->CoCreatedObject));
if (FAILED(hr))
{
Trace("%s Failure: CoCreate(%ls) FAILED\n", __FUNCTION__, p->Name);
g.Failures += 1;
}
else
{
WCHAR ComObjectModule[MAX_PATH];
ComObjectModule[0] = 0;
IFW32FALSE_EXIT(Kernel32.GetModuleFileNameW(
::FusionTestpHmoduleFromComObject(p->CoCreatedObject), ComObjectModule, NUMBER_OF(ComObjectModule)));
Trace("%s SUCCESSfully cocreated %p of type %ls from %ls with actctx influence\n",
__FUNCTION__, p->CoCreatedObject, p->Name, ComObjectModule);
g.Successes += 1;
#if 0
//
// Put it in the global interface table for later marshalling.
// It does not make sense to use IUnknown here, because ole32 can always
// marshal IUnknown itself without any proxy/stubs found via the
// registry or fusion (see also my special message pumper in vsee that
// takes advantage of this feature...)
//
IFW32FALSE_EXIT(
FusionTestpDynamicallyFindAnyInterfaceIntoObjectExceptIUnknown(
p->CoCreatedObject,
::FusionTestpMfcRegData,
RTL_NUMBER_OF(::FusionTestpMfcRegData),
p->InterfaceIntoObjectInCreatingThread,
p->InterfaceIdOfObject
));
IFCOMFAILED_EXIT(hr = g.GlobalInterfaceTable->RegisterInterfaceInGlobal(
p->InterfaceIntoObjectInCreatingThread,
p->InterfaceIdOfObject,
&p->GlobalInterfaceTableCookie
));
#else
//
// It'll still have to look for the proxy/stub at unmarshal time. This is fine.
//
IFCOMFAILED_EXIT(hr = g.GlobalInterfaceTable->RegisterInterfaceInGlobal(
p->CoCreatedObject,
IID_IUnknown,
&p->GlobalInterfaceTableCookie
));
#endif
}
break;
}
}
}
{
CFusionActCtxScope ToolsCrtActCtxScope;
if (!ToolsCrtActCtxScope.Win32Activate(ToolsCrtActCtxHandle))
::Trace("Activate(ToolsCrtActCtxHandle %p) failed %ld\n", ToolsCrtActCtxHandle, ::GetLastError());
//
// try marshalling with the actctx activated, it should work (not NULL => expected success==TRUE)
//
ThreadHandle = CreateThread(NULL, 0, FusionTestpMfcCreateAndMarshalThreadMain, &Ignored, 0, &Ignored);
CoWaitForMultipleHandles(0, INFINITE, 1, &ThreadHandle, &Ignored);
CloseHandle(ThreadHandle);
}
#if 0
//
// If interfaces are _really_never_ changed, (but doesn't Fusion let you violate that?),
// this test case isn't valid. COM does caching and prefills caches when you may not expect
// (like when you put stuff in the GlobalInterfaceTable), and it does not invalidate its caches
// because of actctx pushes and pops.
//
{
//
// try marshalling without the actctx activated, it should NOT work (NULL => expected success==FALSE)
//
ThreadHandle = CreateThread(NULL, 0, FusionTestpMfcCreateAndMarshalThreadMain, NULL, 0, &Ignored);
CoWaitForMultipleHandles(0, INFINITE, 1, &ThreadHandle, &Ignored);
CloseHandle(ThreadHandle);
}
#endif
Ole32.CoUninitialize();
//::FusionTestpEnumerateRegistryData(::FusionTestpMfcRegData, NUMBER_OF(::FusionTestpMfcRegData), FUSIONTESTP_REG_RESTORE);
FN_EPILOG
}
void TestAtlCreate()
{
::FusionTestpEnumerateRegistryData(FusionTestpAtlRegData, NUMBER_OF(FusionTestpAtlRegData), FUSIONTESTP_REG_BACKUP);
::FusionTestpEnumerateRegistryData(FusionTestpAtlRegData, NUMBER_OF(FusionTestpAtlRegData), FUSIONTESTP_REG_DELETE);
::FusionTestpEnumerateRegistryData(FusionTestpAtlRegData, NUMBER_OF(FusionTestpAtlRegData), FUSIONTESTP_REG_RESTORE);
}
BOOL TestPrivateSha1Impl(
PCWSTR pcwszDirName
)
{
FN_PROLOG_WIN32
CFusionArray<BYTE> rgbShaState;
CFusionFile ffInputFile;
BYTE bChunkletBuffer[4096];
CSmallStringBuffer sbHashedString;
DWORD dwReadData;
HCRYPTPROV hProvider;
HCRYPTHASH hHash;
CFusionHash fHashObject;
IFW32FALSE_EXIT(fHashObject.Win32Initialize(CALG_SHA1));
IFW32FALSE_EXIT(ffInputFile.Win32CreateFile(
pcwszDirName,
GENERIC_READ,
FILE_SHARE_READ,
OPEN_EXISTING));
IFW32FALSE_EXIT(CryptAcquireContextW(
&hProvider,
NULL,
NULL,
PROV_RSA_FULL,
CRYPT_SILENT | CRYPT_VERIFYCONTEXT ));
IFW32FALSE_EXIT(CryptCreateHash(
hProvider,
CALG_SHA1,
0,
0,
&hHash ));
do
{
IFW32FALSE_EXIT(::ReadFile(
ffInputFile,
bChunkletBuffer,
sizeof(bChunkletBuffer),
&dwReadData,
NULL));
IFW32FALSE_EXIT(fHashObject.Win32HashData(bChunkletBuffer, dwReadData));
IFW32FALSE_EXIT(CryptHashData(hHash, bChunkletBuffer, dwReadData, 0));
}
while ( dwReadData != 0 );
IFW32FALSE_EXIT(fHashObject.Win32GetValue(rgbShaState));
wprintf(L"%ls (private) hashed to ", pcwszDirName);
for ( SIZE_T n = 0; n < rgbShaState.GetSize(); n++ )
{
wprintf(L"%02x", rgbShaState[n]);
}
IFW32FALSE_EXIT(CryptGetHashParam(
hHash,
HP_HASHVAL,
bChunkletBuffer,
&(dwReadData = sizeof(bChunkletBuffer)),
0));
wprintf(L"\n%ls (regular) hashed to ", pcwszDirName);
for ( SIZE_T n = 0; n < dwReadData; n++ )
{
wprintf(L"%02x", bChunkletBuffer[n]);
}
IFW32FALSE_EXIT(CryptReleaseContext(hProvider, 0));
FN_EPILOG
}
void TestAlignment()
{
CCleanupBase* p = reinterpret_cast<CCleanupBase*>(ULONG_PTR(0xffff0000));
SINGLE_LIST_ENTRY* q = p;
printf("%p %Ix\n", q, ULONG_PTR(q) % 16);
}
void TestCreateActCtx_PE_flags0()
{
WCHAR SyssetupDll[MAX_PATH * 2];
ACTCTXW ActCtx = {sizeof(ActCtx)};
CFusionActCtxHandle ActCtxHandle;
GetSystemDirectoryW(SyssetupDll, MAX_PATH);
wcscat(SyssetupDll, L"\\syssetup.dll");
ActCtx.lpSource = SyssetupDll;
printf("%s\n", ActCtxHandle.Win32Create(&ActCtx) ? "true" : "false");
}
void
TestUninstall(
PCWSTR ManifestPath,
PCWSTR ReferenceString
)
{
SXS_UNINSTALLW UninstallParameters = {sizeof(UninstallParameters)};
SXS_INSTALL_REFERENCEW Reference = {sizeof(Reference)};
PSXS_UNINSTALL_W_ROUTINE Uninstall = NULL;
PSXS_QUERY_MANIFEST_INFORMATION QueryManifestInformation;
BYTE ManifestInformationBuffer[1UL << 16];
PSXS_MANIFEST_INFORMATION_BASIC ManifestBasicInfo = reinterpret_cast<PSXS_MANIFEST_INFORMATION_BASIC>(&ManifestInformationBuffer);
DWORD Disposition = 0;
BOOL Success = FALSE;
LoadSxs();
GetSxsProc("SxsUninstallW", &Uninstall);
GetSxsProc("SxsQueryManifestInformation", &QueryManifestInformation);
Success = QueryManifestInformation(0, ManifestPath,
SXS_QUERY_MANIFEST_INFORMATION_INFOCLASS_BASIC, 0, sizeof(ManifestInformationBuffer),
ManifestBasicInfo, NULL);
printf("QueryManifestInformation(%ls)->(%ls, %ls)\n", ManifestPath, ManifestBasicInfo->lpIdentity, ManifestBasicInfo->lpShortName);
UninstallParameters.dwFlags |= SXS_UNINSTALL_FLAG_REFERENCE_VALID;
UninstallParameters.lpInstallReference = &Reference;
UninstallParameters.lpAssemblyIdentity = ManifestBasicInfo->lpIdentity;
Reference.lpIdentifier = ReferenceString;
Reference.guidScheme = SXS_INSTALL_REFERENCE_SCHEME_OPAQUESTRING;
Success = Uninstall(&UninstallParameters, &Disposition);
printf("TestUninstall(%ls, %ls) : %s, 0x%lx\n", ManifestPath, ReferenceString, Success ? "true" : "false", Disposition);
}
BOOL
TestNewSxsInstallAPI(
PCWSTR pcwszManifest
)
{
BOOL fSuccess = FALSE;
PSXS_INSTALL_W sxsInstallW = NULL;
PSXS_UNINSTALL_ASSEMBLYW sxsUninstallW = NULL;
SXS_INSTALLW Info = {sizeof(Info)};
SXS_INSTALL_REFERENCEW Reference = {sizeof(Reference)};
SXS_UNINSTALLW Uninstall = {sizeof(Uninstall)};
DWORD dwDisposition;
Info.dwFlags = SXS_INSTALL_FLAG_REPLACE_EXISTING |
SXS_INSTALL_FLAG_REFERENCE_VALID |
SXS_INSTALL_FLAG_CODEBASE_URL_VALID |
SXS_INSTALL_FLAG_LOG_FILE_NAME_VALID;
Info.lpManifestPath = pcwszManifest;
Info.lpCodebaseURL = Info.lpManifestPath;
Info.lpReference = &Reference;
Info.lpLogFileName = L"c:\\thelogfile";
DWORD dwAttribute = GetFileAttributesW(pcwszManifest);
if ( dwAttribute == 0xffffffff) // non-exist
goto Exit;
if ( dwAttribute & FILE_ATTRIBUTE_DIRECTORY) // install from a directory recursively
{
Info.dwFlags |= SXS_INSTALL_FLAG_FROM_DIRECTORY_RECURSIVE;
}
Reference.guidScheme = SXS_INSTALL_REFERENCE_SCHEME_OPAQUESTRING;
Reference.lpIdentifier = L"Sxs installation";
LoadSxs();
GetSxsProc(SXS_INSTALL_W, &sxsInstallW);
GetSxsProc(SXS_UNINSTALL_ASSEMBLYW, &sxsUninstallW);
if (!(*sxsInstallW)(&Info))
{
goto Exit;
}
Uninstall.dwFlags = SXS_UNINSTALL_FLAG_USE_INSTALL_LOG;
Uninstall.lpInstallLogFile = L"c:\\thelogfile";
if (!(*sxsUninstallW)(&Uninstall, &dwDisposition))
{
goto Exit;
}
fSuccess = TRUE;
Exit:
if (!fSuccess)
{
fprintf(stderr, "%s failed!\n", __FUNCTION__);
return EXIT_FAILURE;
}
else
return EXIT_SUCCESS;
}
VOID
NTAPI
SimpleContextNotification(
IN ULONG NotificationType,
IN PACTIVATION_CONTEXT ActivationContext,
IN const VOID *ActivationContextData,
IN PVOID NotificationContext,
IN PVOID NotificationData,
IN OUT PBOOLEAN DisableNotification
)
{
switch (NotificationType)
{
case ACTIVATION_CONTEXT_NOTIFICATION_DESTROY:
RTL_SOFT_VERIFY(NT_SUCCESS(NtUnmapViewOfSection(NtCurrentProcess(), (PVOID) ActivationContextData)));
break;
default:
// Otherwise, we don't need to see this notification ever again.
*DisableNotification = TRUE;
break;
}
}
BOOL
MakeActCtxFromCurrentSxsDll(
PCWSTR pcwszFileName,
HANDLE *phActCtx
)
{
FN_PROLOG_WIN32;
SXS_GENERATE_ACTIVATION_CONTEXT_PARAMETERS Parameters = {0};
PACTIVATION_CONTEXT pContextCreated = NULL;
CStringBuffer AssemblyDirectory;
CFileStream SourceManifestStream;
PVOID pvMappedSection = NULL;
NTSTATUS status;
BOOL (WINAPI *pfnSxsGenerateActivationContext)(PSXS_GENERATE_ACTIVATION_CONTEXT_PARAMETERS Parameters);
*phActCtx = INVALID_HANDLE_VALUE;
LoadSxs();
GetSxsProc("SxsGenerateActivationContext", &pfnSxsGenerateActivationContext);
IFW32FALSE_EXIT(SourceManifestStream.OpenForRead(pcwszFileName, CImpersonationData(), FILE_SHARE_READ, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN));
Parameters.Manifest.Path = pcwszFileName;
Parameters.Manifest.PathType = ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE;
Parameters.Manifest.Stream = &SourceManifestStream;
IFW32FALSE_EXIT(AssemblyDirectory.Win32Assign(pcwszFileName, ::wcslen(pcwszFileName)));
AssemblyDirectory.RemoveLastPathElement();
Parameters.AssemblyDirectory = AssemblyDirectory;
Parameters.ProcessorArchitecture = 0;
Parameters.LangId = GetUserDefaultUILanguage();
IFW32FALSE_EXIT(pfnSxsGenerateActivationContext(&Parameters));
IFW32NULL_EXIT(pvMappedSection = MapViewOfFile(Parameters.SectionObjectHandle, FILE_MAP_READ, 0, 0, 0));
status = RtlCreateActivationContext(
0,
pvMappedSection,
0,
SimpleContextNotification,
NULL,
&pContextCreated);
if (!NT_SUCCESS(status)) {
ORIGINATE_WIN32_FAILURE_AND_EXIT(RtlCreateActivationContext, RtlNtStatusToDosError(status));
}
*phActCtx = pContextCreated;
FN_EPILOG;
}
BOOL SimpleTestFindAndUseSurrogateInformation(PCWSTR filename, PCWSTR GuidToDisplay)
{
FN_PROLOG_WIN32;
SXS_GENERATE_ACTIVATION_CONTEXT_PARAMETERS Parameters = {0};
BOOL (WINAPI *pfnSxsGenerateActivationContext)(PSXS_GENERATE_ACTIVATION_CONTEXT_PARAMETERS Parameters);
CFileStream SourceManifestStream;
CStringBuffer AssemblyDirectory;
BOOL fCreatedOk = false;
GUID GuidToFind;
LoadSxs();
GetSxsProc("SxsGenerateActivationContext", &pfnSxsGenerateActivationContext);
IFW32FALSE_EXIT(SxspParseGUID(GuidToDisplay, ::wcslen(GuidToDisplay), GuidToFind));
IFW32FALSE_EXIT(SourceManifestStream.OpenForRead(filename, CImpersonationData(), FILE_SHARE_READ, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN));
Parameters.Manifest.Path = filename;
Parameters.Manifest.PathType = ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE;
Parameters.Manifest.Stream = &SourceManifestStream;
IFW32FALSE_EXIT(AssemblyDirectory.Win32Assign(filename, ::wcslen(filename)));
AssemblyDirectory.RemoveLastPathElement();
Parameters.AssemblyDirectory = AssemblyDirectory;
Parameters.ProcessorArchitecture = 0;
Parameters.LangId = GetUserDefaultUILanguage();
fCreatedOk = pfnSxsGenerateActivationContext(&Parameters);
//
// Spiffy, we've got the thing.
//
if (fCreatedOk && (Parameters.SectionObjectHandle != INVALID_HANDLE_VALUE) && (Parameters.SectionObjectHandle != NULL))
{
PACTIVATION_CONTEXT pActivationContext = NULL;
NTSTATUS status;
ULONG_PTR ulCookie;
ACTCTX_SECTION_KEYED_DATA Data = { sizeof(Data) };
// PCACTIVATION_CONTEXT_DATA_CLR_SURROGATE pFoundData;
/*
status = RtlCreateActivationContext(
0,
Parameters.SectionObjectHandle,
0,
SimpleContextNotification,
NULL,
&pActivationContext);
*/
if (ActivateActCtx(static_cast<HANDLE>(pActivationContext), &ulCookie))
{
status = FindActCtxSectionGuid(
0,
NULL,
ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES,
&GuidToFind,
&Data);
DeactivateActCtx(0, ulCookie);
ReleaseActCtx(static_cast<HANDLE>(pActivationContext));
}
}
FN_EPILOG
}
void TestFindAndUseSurrogateInformation(PCWSTR pcwsz, PCWSTR GuidToDisplay)
{
ACTCTXW actctx = { sizeof(actctx) };
HANDLE hActCtx = INVALID_HANDLE_VALUE;
GUID GuidToFind;
ACTCTX_SECTION_KEYED_DATA Data = { sizeof(Data) };
PCACTIVATION_CONTEXT_DATA_CLR_SURROGATE pFoundData;
BOOL status;
ULONG_PTR ulCookie;
SxspParseGUID(GuidToDisplay, wcslen(GuidToDisplay), GuidToFind);
actctx.lpSource = pcwsz;
hActCtx = CreateActCtxW(&actctx);
if ((hActCtx == INVALID_HANDLE_VALUE) || (hActCtx == NULL))
{
printf("Sorry, can't find file %ls, error %d", pcwsz, ::GetLastError());
return;
}
ActivateActCtx(hActCtx, &ulCookie);
__try {
status = FindActCtxSectionGuid(
0,
NULL,
ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES,
&GuidToFind,
&Data);
pFoundData = (PCACTIVATION_CONTEXT_DATA_CLR_SURROGATE)Data.lpData;
wprintf(L"The guid %ls maps to assembly '%.*ls', runtime version '%.*ls', module '%.*ls'\n",
GuidToDisplay,
pFoundData->TypeNameLength / 2,
(PCWSTR)(((PBYTE)pFoundData) + pFoundData->TypeNameOffset),
pFoundData->VersionLength / 2,
(PCWSTR)(((PBYTE)pFoundData) + pFoundData->VersionOffset));
}
__finally
{
if (ulCookie != 0)
DeactivateActCtx(0, ulCookie);
}
ReleaseActCtx(hActCtx);
}
BOOL
TestSxsExportedSurrogateStuff(
PCWSTR pcwszManifest,
PCWSTR pcwszWhat,
PCWSTR pcwszData
)
{
FN_PROLOG_WIN32;
PFN_SXS_FIND_CLR_CLASS_INFO pfnClrClass = NULL;
PFN_SXS_FIND_CLR_SURROGATE_INFO pfnClrSurrogate = NULL;
PFN_SXS_LOOKUP_CLR_GUID pfnClrLookup = NULL;
SIZE_T cbRequired = 0;
BOOL f = false;
PVOID pvTargetBuffer = NULL;
PCSXS_CLR_SURROGATE_INFORMATION pSurrogateInfo = NULL;
PCSXS_CLR_CLASS_INFORMATION pClassInfo = NULL;
CFusionActCtxHandle hActCtxCreated;
CFusionActCtxScope ActivationScope;
ACTCTXW ActCtxStruct = {sizeof(ActCtxStruct)};
LoadSxs();
GetSxsProc(SXS_FIND_CLR_SURROGATE_INFO, &pfnClrSurrogate);
GetSxsProc(SXS_FIND_CLR_CLASS_INFO, &pfnClrClass);
GetSxsProc(SXS_LOOKUP_CLR_GUID, &pfnClrLookup);
IFW32FALSE_EXIT(MakeActCtxFromCurrentSxsDll(pcwszManifest, &hActCtxCreated));
IFW32FALSE_EXIT(ActivationScope.Win32Activate(hActCtxCreated));
if (lstrcmpiW(pcwszWhat, L"clrprogid") == 0)
{
f = pfnClrClass(
SXS_FIND_CLR_CLASS_SEARCH_PROGID | SXS_FIND_CLR_CLASS_GET_ALL,
(PVOID)pcwszData,
hActCtxCreated,
NULL, 0, &cbRequired);
if (!f)
{
SIZE_T cbWritten = 0;
pvTargetBuffer = HeapAlloc(GetProcessHeap(), 0, cbRequired);
pfnClrClass(
SXS_FIND_CLR_CLASS_SEARCH_PROGID | SXS_FIND_CLR_CLASS_GET_ALL,
(PVOID)pcwszData,
hActCtxCreated,
pvTargetBuffer,
cbRequired,
&cbWritten);
pClassInfo = (PCSXS_CLR_CLASS_INFORMATION)pvTargetBuffer;
}
}
else if (lstrcmpiW(pcwszWhat, L"clrguid") == 0)
{
GUID ParsedGuid;
IFW32FALSE_EXIT(SxspParseGUID(pcwszData, wcslen(pcwszData), ParsedGuid));
f = pfnClrClass(
SXS_FIND_CLR_CLASS_SEARCH_GUID | SXS_FIND_CLR_CLASS_GET_ALL,
(PVOID)&ParsedGuid,
hActCtxCreated,
NULL, 0, &cbRequired);
if (!f)
{
SIZE_T cbWritten = 0;
pvTargetBuffer = HeapAlloc(GetProcessHeap(), 0, cbRequired);
pfnClrClass(
SXS_FIND_CLR_CLASS_SEARCH_GUID | SXS_FIND_CLR_CLASS_GET_ALL,
(PVOID)&ParsedGuid,
hActCtxCreated,
pvTargetBuffer, cbRequired, &cbWritten);
pClassInfo = (PCSXS_CLR_CLASS_INFORMATION)pvTargetBuffer;
}
}
else if (lstrcmpiW(pcwszWhat, L"lookup") == 0)
{
GUID ParsedGuid;
PCSXS_GUID_INFORMATION_CLR pGuidInfo = NULL;
IFW32FALSE_EXIT(SxspParseGUID(pcwszData, wcslen(pcwszData), ParsedGuid));
f = pfnClrLookup(
SXS_LOOKUP_CLR_GUID_FIND_ANY,
&ParsedGuid,
hActCtxCreated,
NULL,
0,
&cbRequired);
if (!f)
{
SIZE_T cbWritten = 0;
pvTargetBuffer = HeapAlloc(GetProcessHeap(), 0, cbRequired);
f = pfnClrLookup(
SXS_LOOKUP_CLR_GUID_FIND_ANY,
&ParsedGuid,
hActCtxCreated,
pvTargetBuffer,
cbRequired,
&cbWritten);
pGuidInfo = (PCSXS_GUID_INFORMATION_CLR)pvTargetBuffer;
}
}
else if (lstrcmpiW(pcwszWhat, L"surrogate") == 0)
{
GUID ParsedGuid;
IFW32FALSE_EXIT(SxspParseGUID(pcwszData, wcslen(pcwszData), ParsedGuid));
f = pfnClrSurrogate(
SXS_FIND_CLR_SURROGATE_USE_ACTCTX | SXS_FIND_CLR_SURROGATE_GET_ALL,
&ParsedGuid,
hActCtxCreated,
NULL, 0, &cbRequired);
if (!f)
{
SIZE_T cbWritten = 0;
pvTargetBuffer = HeapAlloc(GetProcessHeap(), 0, cbRequired);
pfnClrSurrogate(
SXS_FIND_CLR_SURROGATE_USE_ACTCTX | SXS_FIND_CLR_SURROGATE_GET_ALL,
&ParsedGuid,
hActCtxCreated,
pvTargetBuffer, cbRequired, &cbWritten);
pSurrogateInfo = (PCSXS_CLR_SURROGATE_INFORMATION)pvTargetBuffer;
}
}
FN_EPILOG;
}