320 lines
11 KiB
C++
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;
|
|
}
|