/*++ 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 #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 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(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 }