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

320 lines
11 KiB
C++

/*++
Copyright (c) 2001 Microsoft Corporation
Module Name:
query.cpp
Abstract:
Information querying functions for sxs.dll
Author:
Michael J. Grier (MGrier) 22-May-2001
Revision History:
--*/
#include "stdinc.h"
#include <windows.h>
#include "sxsp.h"
BOOL
SxspQueryManifestInformationBasic(
IN DWORD dwFlags,
IN PCWSTR pszSource,
IN DWORD dwInfoClassSpecificFlags,
IN SIZE_T cbBuffer,
OUT PVOID lpBuffer,
OUT PSIZE_T cbWrittenOrRequired OPTIONAL
);
BOOL
SxsQueryManifestInformation(
IN DWORD dwFlags,
IN PCWSTR pszSource,
IN ULONG ulInfoClass,
IN DWORD dwInfoClassSpecificFlags,
IN SIZE_T cbBuffer,
OUT PVOID lpBuffer,
OUT PSIZE_T pcbWrittenOrRequired OPTIONAL
)
{
FN_PROLOG_WIN32;
if (pcbWrittenOrRequired != NULL)
*pcbWrittenOrRequired = 0;
PARAMETER_CHECK((dwFlags & ~SXS_QUERY_MANIFEST_INFORMATION_FLAG_SOURCE_IS_DLL) == 0);
PARAMETER_CHECK(pszSource != NULL);
PARAMETER_CHECK(ulInfoClass == SXS_QUERY_MANIFEST_INFORMATION_INFOCLASS_BASIC);
// ignore infoclass specific flags
PARAMETER_CHECK((cbBuffer == 0) || (lpBuffer != NULL)); // can't have a nonzero-sized buffer with a NULL pointer to it
PARAMETER_CHECK((cbBuffer != 0) || (pcbWrittenOrRequired != NULL));
switch (ulInfoClass)
{
default:
INTERNAL_ERROR_CHECK(
(ulInfoClass == SXS_QUERY_MANIFEST_INFORMATION_INFOCLASS_BASIC)
);
ORIGINATE_WIN32_FAILURE_AND_EXIT(InternalErrorNoCaseForInfoClass, ERROR_INTERNAL_ERROR);
break;
case SXS_QUERY_MANIFEST_INFORMATION_INFOCLASS_BASIC:
IFW32FALSE_EXIT(
::SxspQueryManifestInformationBasic(
dwFlags,
pszSource,
dwInfoClassSpecificFlags,
cbBuffer,
lpBuffer,
pcbWrittenOrRequired));
break;
}
FN_EPILOG;
}
BOOL
SxspQueryManifestInformationBasic(
IN DWORD dwFlags,
IN PCWSTR pszSource,
IN DWORD dwInfoClassSpecificFlags,
IN SIZE_T cbBuffer,
OUT PVOID lpBuffer,
OUT PSIZE_T pcbWrittenOrRequired OPTIONAL
)
{
FN_PROLOG_WIN32;
ACTCTXGENCTX ActCtxGenCtx;
ULONG ManifestFlags;
CImpersonationData ImpersonationData;
PCWSTR Slash = NULL;
CSmartRef<ASSEMBLY> Asm;
CStringBuffer buffManifestPath;
USHORT ProcessorArchitecture = ::SxspGetSystemProcessorArchitecture();
LANGID LangId = ::GetUserDefaultUILanguage();
CStringBufferAccessor acc;
SIZE_T cch, cchRequired;
SIZE_T cbRequired, cbLeft, cbWritten;
PCASSEMBLY_IDENTITY AssemblyIdentity = NULL;
CStringBuffer buffShortName;
PWSTR Cursor;
PSXS_MANIFEST_INFORMATION_BASIC psmib;
CResourceStream DllStream;
CFileStream FileStream;
IStream* pStream = NULL;
CProbedAssemblyInformation AssemblyInformation;
if (pcbWrittenOrRequired != NULL)
*pcbWrittenOrRequired = 0;
// We'll assume that SxsQueryManifestInformation checked everything
// except dwInfoClassSpecificFlags.
PARAMETER_CHECK((dwInfoClassSpecificFlags & ~(
SXS_QUERY_MANIFEST_INFORMATION_INFOCLASS_BASIC_FLAG_OMIT_IDENTITY |
SXS_QUERY_MANIFEST_INFORMATION_INFOCLASS_BASIC_FLAG_OMIT_SHORTNAME)) == 0);
//
// If this is a DLL source, then ensure that the size is at least big enough for our basic
// data, and ensure that the flags are zero (in this rev, that's all that's allowed.
//
if (dwFlags & SXS_QUERY_MANIFEST_INFORMATION_FLAG_SOURCE_IS_DLL)
{
PCSXS_MANIFEST_INFORMATION_SOURCE_DLL pDllSource = (PCSXS_MANIFEST_INFORMATION_SOURCE_DLL)pszSource;
const DWORD dwValidFlags =
SXS_QUERY_MANIFEST_INFORMATION_DLL_SOURCE_FLAG_RESOURCE_LANGUAGE_VALID |
SXS_QUERY_MANIFEST_INFORMATION_DLL_SOURCE_FLAG_RESOURCE_TYPE_VALID |
SXS_QUERY_MANIFEST_INFORMATION_DLL_SOURCE_FLAG_RESOURCE_ID_VALID;
PARAMETER_CHECK(pDllSource->dwSize >= sizeof(SXS_MANIFEST_INFORMATION_SOURCE_DLL));
PARAMETER_CHECK((pDllSource->dwFlags & ~dwValidFlags) == 0);
PARAMETER_CHECK(pDllSource->pcwszDllPath!= NULL);
PARAMETER_CHECK(((pDllSource->dwFlags & SXS_QUERY_MANIFEST_INFORMATION_DLL_SOURCE_FLAG_RESOURCE_LANGUAGE_VALID) == 0) || (pDllSource->Language != 0));
PARAMETER_CHECK(((pDllSource->dwFlags & SXS_QUERY_MANIFEST_INFORMATION_DLL_SOURCE_FLAG_RESOURCE_TYPE_VALID) == 0) || (pDllSource->pcwszResourceType != NULL));
PARAMETER_CHECK(((pDllSource->dwFlags & SXS_QUERY_MANIFEST_INFORMATION_DLL_SOURCE_FLAG_RESOURCE_ID_VALID) == 0) || (pDllSource->pcwszResourceName != NULL));
}
IFW32FALSE_EXIT(
::SxspInitActCtxGenCtx(
&ActCtxGenCtx, // context out
MANIFEST_OPERATION_VALIDATE_SYNTAX,
0,
0,
ImpersonationData,
ProcessorArchitecture,
LangId,
ACTIVATION_CONTEXT_PATH_TYPE_NONE,
0,
NULL));
IFALLOCFAILED_EXIT(Asm = new ASSEMBLY);
//
// For DLL sources, tease apart the version and whatnot from the
// structure passed in.
//
if (dwFlags & SXS_QUERY_MANIFEST_INFORMATION_FLAG_SOURCE_IS_DLL)
{
PCSXS_MANIFEST_INFORMATION_SOURCE_DLL pcSourceInfo = (PCSXS_MANIFEST_INFORMATION_SOURCE_DLL)pszSource;
IFW32FALSE_EXIT(SxspGetFullPathName(pcSourceInfo->pcwszDllPath, buffManifestPath, NULL));
//
// Default action... just go use the normal "find the first in the dll" thing
//
if (pcSourceInfo->dwFlags == 0)
{
IFW32FALSE_EXIT(DllStream.Initialize(buffManifestPath, (PCWSTR)RT_MANIFEST));
}
else
{
const DWORD dwFlags = pcSourceInfo->dwFlags;
IFW32FALSE_EXIT(
DllStream.Initialize(
buffManifestPath,
((dwFlags & SXS_QUERY_MANIFEST_INFORMATION_DLL_SOURCE_FLAG_RESOURCE_TYPE_VALID) ? pcSourceInfo->pcwszResourceType : (PCWSTR)RT_MANIFEST),
((dwFlags & SXS_QUERY_MANIFEST_INFORMATION_DLL_SOURCE_FLAG_RESOURCE_ID_VALID) ? pcSourceInfo->pcwszResourceName : NULL),
((dwFlags & SXS_QUERY_MANIFEST_INFORMATION_DLL_SOURCE_FLAG_RESOURCE_LANGUAGE_VALID) ? (WORD)pcSourceInfo->Language : (WORD)MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL))));
}
pStream = &DllStream;
}
//
// Otherwise, dumb file.
//
else
{
IFW32FALSE_EXIT(SxspGetFullPathName(pszSource, buffManifestPath, NULL));
IFW32FALSE_EXIT(
FileStream.OpenForRead(
buffManifestPath,
CImpersonationData(),
FILE_SHARE_READ,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL));
pStream = &FileStream;
}
ManifestFlags = ASSEMBLY_MANIFEST_FILETYPE_STREAM;
IFW32FALSE_EXIT(AssemblyInformation.Initialize());
IFW32FALSE_EXIT(AssemblyInformation.SetManifestFlags(ManifestFlags));
IFW32FALSE_EXIT(AssemblyInformation.SetManifestStream(pStream));
IFW32FALSE_EXIT(AssemblyInformation.SetManifestPath(ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE, buffManifestPath));
IFW32FALSE_EXIT(AssemblyInformation.SetManifestLastWriteTime(&ActCtxGenCtx));
IFW32FALSE_EXIT(::SxspInitAssembly(Asm, AssemblyInformation));
Asm->m_AssemblyRosterIndex = 1; // set it to be the root...
IFW32FALSE_EXIT(::SxspIncorporateAssembly(&ActCtxGenCtx, Asm));
IFW32FALSE_EXIT(::SxspFireActCtxGenEnding(&ActCtxGenCtx));
pStream->Release();
AssemblyIdentity = Asm->m_Information.GetAssemblyIdentity();
cchRequired = 0;
if ((dwInfoClassSpecificFlags & SXS_QUERY_MANIFEST_INFORMATION_INFOCLASS_BASIC_FLAG_OMIT_IDENTITY) == 0)
{
SIZE_T TextuallyEncodedIdentityBufferBytes = 0;
IFW32FALSE_EXIT(
::SxsComputeAssemblyIdentityEncodedSize(
0,
AssemblyIdentity,
NULL,
SXS_ASSEMBLY_IDENTITY_ENCODING_DEFAULTGROUP_TEXTUAL,
&TextuallyEncodedIdentityBufferBytes));
INTERNAL_ERROR_CHECK((TextuallyEncodedIdentityBufferBytes % sizeof(WCHAR)) == 0);
cchRequired += ((TextuallyEncodedIdentityBufferBytes / sizeof(WCHAR)) + 1);
}
if ((dwInfoClassSpecificFlags & SXS_QUERY_MANIFEST_INFORMATION_INFOCLASS_BASIC_FLAG_OMIT_SHORTNAME) == 0)
{
IFW32FALSE_EXIT(
::SxspGenerateSxsPath(
SXSP_GENERATE_SXS_PATH_FLAG_OMIT_ROOT,
SXSP_GENERATE_SXS_PATH_PATHTYPE_ASSEMBLY,
NULL, 0,
AssemblyIdentity,
buffShortName));
cchRequired += (buffShortName.Cch() + 1);
}
cbRequired = sizeof(SXS_MANIFEST_INFORMATION_BASIC) + (cchRequired * sizeof(WCHAR));
if (cbRequired > cbBuffer)
{
*pcbWrittenOrRequired = cbRequired;
ORIGINATE_WIN32_FAILURE_AND_EXIT(BufferTooSmall, ERROR_INSUFFICIENT_BUFFER);
}
psmib = (PSXS_MANIFEST_INFORMATION_BASIC) lpBuffer;
psmib->lpIdentity = NULL;
psmib->lpShortName = NULL;
psmib->ulFileCount = ActCtxGenCtx.m_ulFileCount;
Cursor = (PWSTR) (psmib + 1);
cbLeft = (cbBuffer - sizeof(SXS_MANIFEST_INFORMATION_BASIC));
cbWritten = sizeof(SXS_MANIFEST_INFORMATION_BASIC);
if ((dwInfoClassSpecificFlags & SXS_QUERY_MANIFEST_INFORMATION_INFOCLASS_BASIC_FLAG_OMIT_IDENTITY) == 0)
{
SIZE_T cbActual;
IFW32FALSE_EXIT(
::SxsEncodeAssemblyIdentity(
0,
AssemblyIdentity,
NULL,
SXS_ASSEMBLY_IDENTITY_ENCODING_DEFAULTGROUP_TEXTUAL,
cbLeft,
Cursor,
&cbActual));
INTERNAL_ERROR_CHECK((cbActual % sizeof(WCHAR)) == 0);
INTERNAL_ERROR_CHECK(cbLeft >= cbActual);
psmib->lpIdentity = Cursor;
cbLeft -= cbActual;
cbWritten += cbActual;
Cursor = (PWSTR) (((ULONG_PTR) Cursor) + cbActual);
INTERNAL_ERROR_CHECK(cbLeft >= sizeof(WCHAR));
*Cursor++ = L'\0';
cbLeft -= sizeof(WCHAR);
cbWritten += sizeof(WCHAR);
}
if ((dwInfoClassSpecificFlags & SXS_QUERY_MANIFEST_INFORMATION_INFOCLASS_BASIC_FLAG_OMIT_SHORTNAME) == 0)
{
cch = buffShortName.Cch();
INTERNAL_ERROR_CHECK(cbLeft >= ((cch + 1) * sizeof(WCHAR)));
memcpy(Cursor, static_cast<PCWSTR>(buffShortName), (cch + 1) * sizeof(WCHAR));
psmib->lpShortName = Cursor;
cbLeft -= ((cch + 1) * sizeof(WCHAR));
cbWritten += ((cch + 1) * sizeof(WCHAR));
Cursor += (cch + 1);
}
if (pcbWrittenOrRequired != NULL)
*pcbWrittenOrRequired = cbWritten;
FN_EPILOG;
}