|
|
/*++
Copyright (c) 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(); 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;
if (pcbWrittenOrRequired != NULL) *pcbWrittenOrRequired = 0;
PARAMETER_CHECK(dwFlags == 0); PARAMETER_CHECK(pszSource != NULL); PARAMETER_CHECK((dwInfoClassSpecificFlags & ~( SXS_QUERY_MANIFEST_INFORMATION_INFOCLASS_BASIC_FLAG_OMIT_IDENTITY | SXS_QUERY_MANIFEST_INFORMATION_INFOCLASS_BASIC_FLAG_OMIT_SHORTNAME)) == 0); PARAMETER_CHECK((cbBuffer == 0) || (lpBuffer != NULL)); PARAMETER_CHECK((cbBuffer != 0) || (pcbWrittenOrRequired != NULL));
//
// If this is a DLL source, then 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->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)); }
//
// Smarter than the average bear - knows how to handle string buffers and full
// paths.
//
IFW32FALSE_EXIT(::SxspGetFullPathName(pszSource, buffManifestPath, 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);
{ CProbedAssemblyInformation AssemblyInformation;
//
// 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 { IFW32FALSE_EXIT( DllStream.Initialize( buffManifestPath, ((pcSourceInfo->dwFlags & SXS_QUERY_MANIFEST_INFORMATION_DLL_SOURCE_FLAG_RESOURCE_TYPE_VALID) ? pcSourceInfo->pcwszResourceType : (PCWSTR)RT_MANIFEST), ((pcSourceInfo->dwFlags & SXS_QUERY_MANIFEST_INFORMATION_DLL_SOURCE_FLAG_RESOURCE_ID_VALID) ? pcSourceInfo->pcwszResourceName : NULL), ((pcSourceInfo->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(&ActCtxGenCtx)); 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(ImpersonationData)); IFW32FALSE_EXIT(SxspInitAssembly(Asm, AssemblyInformation));
//
// The assembly information now owns the stream
//
pStream->Release(); }
Asm->m_AssemblyRosterIndex = 1; // set it to be the root...
IFW32FALSE_EXIT(::SxspIncorporateAssembly(&ActCtxGenCtx, Asm)); IFW32FALSE_EXIT(::SxspFireActCtxGenEnding(&ActCtxGenCtx));
AssemblyIdentity = Asm->m_ProbedAssemblyInformation.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, NULL, buffShortName));
cchRequired += (buffShortName.Cch() + 1); }
// GENERAL REVIEW: What does this do with alignment on ia64? Shouldn't we pad out to
// the next N bytes?
//
cbRequired = sizeof(SXS_MANIFEST_INFORMATION_BASIC) + (cchRequired * sizeof(WCHAR));
if (cbRequired > cbBuffer) { if (pcbWrittenOrRequired != NULL) *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 }
|