/*++ Copyright (c) Microsoft Corporation Module Name: sxsquery.c Abstract: Side-by-side activation support for Windows/NT Implementation of query functions over activation contexts Author: Michael Grier (MGrier) 1/18/2001 Revision History: 1/18/2001 - MGrier - initial; split off from sxsactctx.c. 3/15/2001 - xiaoyuw - add support query for Assembly of Actctx and files of Assembly info 5/2001 - JayKrell - more query support (from hmodule, from address, noaddref) --*/ #if defined(__cplusplus) extern "C" { #endif #pragma warning(disable:4214) // bit field types other than int #pragma warning(disable:4201) // nameless struct/union #pragma warning(disable:4115) // named type definition in parentheses #pragma warning(disable:4127) // condition expression is constant #include #include #include #include #include "sxsp.h" #include "ldrp.h" VOID RtlpLocateActivationContextSectionForQuery( OUT PULONG Disposition, OUT NTSTATUS* Status, PVOID Buffer, SIZE_T InLength, PSIZE_T OutLength OPTIONAL, SIZE_T MinimumLength, IN PCACTIVATION_CONTEXT_DATA ActivationContextData, IN CONST GUID * ExtensionGuid OPTIONAL, IN ULONG Id, OUT PCVOID * SectionData, OUT ULONG * SectionLength ) { #define RTLP_LOCATE_ACTIVATION_CONTEXT_SECTION_FOR_QUERY_CONTINUE (1) #define RTLP_LOCATE_ACTIVATION_CONTEXT_SECTION_FOR_QUERY_RETURN (2) ASSERT(Status != NULL); ASSERT(Disposition != NULL); if (ActivationContextData != NULL) { *Status = RtlpLocateActivationContextSection(ActivationContextData, ExtensionGuid, Id, SectionData, SectionLength); if (*Status != STATUS_SXS_SECTION_NOT_FOUND) { if (NT_SUCCESS(*Status)) *Disposition = RTLP_LOCATE_ACTIVATION_CONTEXT_SECTION_FOR_QUERY_CONTINUE; else *Disposition = RTLP_LOCATE_ACTIVATION_CONTEXT_SECTION_FOR_QUERY_RETURN; return; } } *Disposition = RTLP_LOCATE_ACTIVATION_CONTEXT_SECTION_FOR_QUERY_RETURN; if (MinimumLength > InLength) { *Status = STATUS_BUFFER_TOO_SMALL; return; } RtlZeroMemory(Buffer, MinimumLength); if (OutLength != NULL) *OutLength = MinimumLength; *Status = STATUS_SUCCESS; } NTSTATUS RtlpCrackActivationContextStringSectionHeader( IN PCVOID SectionBase, IN SIZE_T SectionLength, OUT ULONG *FormatVersion OPTIONAL, OUT ULONG *DataFormatVersion OPTIONAL, OUT ULONG *SectionFlags OPTIONAL, OUT ULONG *ElementCount OPTIONAL, OUT PCACTIVATION_CONTEXT_STRING_SECTION_ENTRY *Elements OPTIONAL, OUT ULONG *HashAlgorithm OPTIONAL, OUT PCVOID *SearchStructure OPTIONAL, OUT ULONG *UserDataLength OPTIONAL, OUT PCVOID *UserData OPTIONAL ) { NTSTATUS Status = STATUS_INTERNAL_ERROR; // in case someone forgets to set it... PCACTIVATION_CONTEXT_STRING_SECTION_HEADER Header = (PCACTIVATION_CONTEXT_STRING_SECTION_HEADER) SectionBase; if (FormatVersion != NULL) *FormatVersion = 0; if (DataFormatVersion != NULL) *DataFormatVersion = 0; if (SectionFlags != NULL) *SectionFlags = 0; if (ElementCount != NULL) *ElementCount = 0; if (Elements != NULL) *Elements = NULL; if (HashAlgorithm != NULL) *HashAlgorithm = 0; if (SearchStructure != NULL) *SearchStructure = NULL; if (UserDataLength != NULL) *UserDataLength = 0; if (UserData != NULL) *UserData = NULL; if (SectionLength < (RTL_SIZEOF_THROUGH_FIELD(ACTIVATION_CONTEXT_STRING_SECTION_HEADER, HeaderSize))) { DbgPrintEx( DPFLTR_SXS_ID, DPFLTR_ERROR_LEVEL, "SXS: %s() passed string section at %p only %lu bytes long; that's not even enough for the 4-byte magic and 4-byte header length!\n", __FUNCTION__, SectionBase, SectionLength); Status = STATUS_SXS_INVALID_ACTCTXDATA_FORMAT; goto Exit; } if (Header->Magic != ACTIVATION_CONTEXT_STRING_SECTION_MAGIC) { DbgPrintEx( DPFLTR_SXS_ID, DPFLTR_ERROR_LEVEL, "SXS: %s() found assembly information section with wrong magic value\n" " Expected %lu; got %lu\n", __FUNCTION__, ACTIVATION_CONTEXT_STRING_SECTION_MAGIC, Header->Magic); Status = STATUS_SXS_INVALID_ACTCTXDATA_FORMAT; goto Exit; } // Pedantic: check to see if the header size claimed includes the header size field so that we can safely use it. if (!RTL_CONTAINS_FIELD(Header, Header->HeaderSize, HeaderSize)) { DbgPrintEx( DPFLTR_SXS_ID, DPFLTR_ERROR_LEVEL, "SXS: %s() passed string section at %p claims %lu byte header size; that doesn't even include the HeaderSize member!\n", __FUNCTION__, Header, Header->HeaderSize); Status = STATUS_SXS_INVALID_ACTCTXDATA_FORMAT; goto Exit; } // Now we're just going to jump forward to the last known member that we expect to see; UserDataSize... if (!RTL_CONTAINS_FIELD(Header, Header->HeaderSize, UserDataSize)) { DbgPrintEx( DPFLTR_SXS_ID, DPFLTR_ERROR_LEVEL, "SXS: %s() passed string section at %p with too small of a header\n" " HeaderSize: %lu\n" " Required: %lu\n", __FUNCTION__, Header, Header->HeaderSize, RTL_SIZEOF_THROUGH_FIELD(ACTIVATION_CONTEXT_STRING_SECTION_HEADER, UserDataSize)); Status = STATUS_SXS_INVALID_ACTCTXDATA_FORMAT; goto Exit; } if ((Header->ElementListOffset != 0) && (Header->ElementListOffset < Header->HeaderSize)) { DbgPrintEx( DPFLTR_SXS_ID, DPFLTR_ERROR_LEVEL, "SXS: %s() found assembly information section with element list overlapping section header\n" " Section header: %p\n" " Header Size: %lu\n" " ElementListOffset: %lu\n", __FUNCTION__, Header, Header->HeaderSize, Header->ElementListOffset); Status = STATUS_SXS_INVALID_ACTCTXDATA_FORMAT; goto Exit; } if ((Header->SearchStructureOffset != 0) && (Header->SearchStructureOffset < Header->HeaderSize)) { DbgPrintEx( DPFLTR_SXS_ID, DPFLTR_ERROR_LEVEL, "SXS: %s() found assembly information section with search structure overlapping section header\n" " Section header: %p\n" " Header Size: %lu\n" " SearchStructureOffset: %lu\n", __FUNCTION__, Header, Header->HeaderSize, Header->SearchStructureOffset); Status = STATUS_SXS_INVALID_ACTCTXDATA_FORMAT; goto Exit; } if ((Header->UserDataOffset != 0) && (Header->UserDataOffset < Header->HeaderSize)) { DbgPrintEx( DPFLTR_SXS_ID, DPFLTR_ERROR_LEVEL, "SXS: %s() found assembly information section with user data overlapping section header\n" " Section header: %p\n" " Header Size: %lu\n" " User Data Offset: %lu\n", __FUNCTION__, Header, Header->HeaderSize, Header->UserDataOffset); Status = STATUS_SXS_INVALID_ACTCTXDATA_FORMAT; goto Exit; } if (Header->UserDataSize < sizeof(ACTIVATION_CONTEXT_DATA_ASSEMBLY_GLOBAL_INFORMATION)) { DbgPrintEx( DPFLTR_SXS_ID, DPFLTR_ERROR_LEVEL, "SXS: %s() found assembly information section with user data too small\n" " Section header: %p\n" " UserDataSize: %lu; needed: %lu\n", __FUNCTION__, Header, Header->UserDataSize, sizeof(ACTIVATION_CONTEXT_DATA_ASSEMBLY_GLOBAL_INFORMATION)); Status = STATUS_SXS_INVALID_ACTCTXDATA_FORMAT; goto Exit; } if ((Header->UserDataOffset + Header->UserDataSize) > SectionLength) { DbgPrintEx( DPFLTR_SXS_ID, DPFLTR_ERROR_LEVEL, "SXS: %s() found assembly information section with user data extending beyond section data\n" " Section header: %p\n" " UserDataSize: %lu\n" " UserDataOffset: %lu\n" " Section size: %lu\n", __FUNCTION__, Header, Header->UserDataSize, Header->UserDataOffset, SectionLength); Status = STATUS_SXS_INVALID_ACTCTXDATA_FORMAT; goto Exit; } if (FormatVersion != NULL) *FormatVersion = Header->FormatVersion; if (DataFormatVersion != NULL) *DataFormatVersion = Header->DataFormatVersion; if (SectionFlags != NULL) *SectionFlags = Header->Flags; if (ElementCount != NULL) *ElementCount = Header->ElementCount; if (Elements != NULL) { if (Header->ElementListOffset == 0) *Elements = NULL; else *Elements = (PCACTIVATION_CONTEXT_STRING_SECTION_ENTRY) (((ULONG_PTR) Header) + Header->ElementListOffset); } if (HashAlgorithm != NULL) *HashAlgorithm = Header->HashAlgorithm; if (SearchStructure != NULL) { if (Header->SearchStructureOffset == 0) *SearchStructure = NULL; else *SearchStructure = (PCVOID) (((ULONG_PTR) Header) + Header->SearchStructureOffset); } if (UserDataLength != NULL) *UserDataLength = Header->UserDataSize; if (UserData != NULL) { if (Header->UserDataOffset == 0) *UserData = NULL; else *UserData = (PCVOID) (((ULONG_PTR) Header) + Header->UserDataOffset); } Status = STATUS_SUCCESS; Exit: return Status; } NTSTATUS RtlpGetActiveActivationContextApplicationDirectory( IN SIZE_T InLength, OUT PVOID OutBuffer, OUT SIZE_T *OutLength ) // This is never used. { NTSTATUS Status = STATUS_INTERNAL_ERROR; PCRTL_ACTIVATION_CONTEXT_STACK_FRAME Frame = NULL; PCACTIVATION_CONTEXT_DATA ActivationContextData = NULL; PCACTIVATION_CONTEXT_STRING_SECTION_HEADER Header = NULL; const PPEB Peb = NtCurrentPeb(); const PTEB Teb = NtCurrentTeb(); PCVOID pvTemp = NULL; ULONG ulTemp = 0; PCACTIVATION_CONTEXT_DATA_ASSEMBLY_GLOBAL_INFORMATION GlobalInfo = NULL; if (OutLength != NULL) *OutLength = 0; if (((InLength != 0) && (OutBuffer == NULL)) || ((OutBuffer == NULL) && (OutLength == NULL))) { DbgPrintEx( DPFLTR_SXS_ID, DPFLTR_ERROR_LEVEL, "SXS: %s(): called with invalid parameters\n" " InLength = %Iu\n" " OutBuffer = %p\n" " OutLength = %p\n", __FUNCTION__, InLength, OutBuffer, OutLength); Status = STATUS_INVALID_PARAMETER; goto Exit; } Frame = Teb->ActivationContextStack.ActiveFrame; if (Frame == NULL) { ActivationContextData = Peb->ActivationContextData; } else { ActivationContextData = Frame->ActivationContext->ActivationContextData; } // We need to find the assembly metadata section... Status = RtlpLocateActivationContextSection(ActivationContextData, NULL, ACTIVATION_CONTEXT_SECTION_ASSEMBLY_INFORMATION, &pvTemp, &ulTemp); if (!NT_SUCCESS(Status)) goto Exit; if (ulTemp < sizeof(ACTIVATION_CONTEXT_STRING_SECTION_HEADER)) { DbgPrintEx( DPFLTR_SXS_ID, DPFLTR_ERROR_LEVEL, "SXS: %s() found assembly information string section with header too small\n" " Expected at least %lu; got %lu bytes\n", __FUNCTION__, sizeof(ACTIVATION_CONTEXT_STRING_SECTION_HEADER), ulTemp); Status = STATUS_SXS_INVALID_ACTCTXDATA_FORMAT; goto Exit; } Header = (PCACTIVATION_CONTEXT_STRING_SECTION_HEADER) pvTemp; if (Header->Magic != ACTIVATION_CONTEXT_STRING_SECTION_MAGIC) { DbgPrintEx( DPFLTR_SXS_ID, DPFLTR_ERROR_LEVEL, "SXS: %s() found assembly information section with wrong magic value\n" " Expected %lu; got %lu\n", __FUNCTION__, ACTIVATION_CONTEXT_STRING_SECTION_MAGIC, Header->Magic); Status = STATUS_SXS_INVALID_ACTCTXDATA_FORMAT; goto Exit; } if (Header->UserDataOffset < sizeof(ACTIVATION_CONTEXT_STRING_SECTION_HEADER)) { DbgPrintEx( DPFLTR_SXS_ID, DPFLTR_ERROR_LEVEL, "SXS: %s() found assembly information section with user data overlapping section header\n" " Section header: %p\n" " User Data Offset: %lu\n", __FUNCTION__, Header, Header->UserDataOffset); Status = STATUS_SXS_INVALID_ACTCTXDATA_FORMAT; goto Exit; } if (Header->UserDataSize < sizeof(ACTIVATION_CONTEXT_DATA_ASSEMBLY_GLOBAL_INFORMATION)) { DbgPrintEx( DPFLTR_SXS_ID, DPFLTR_ERROR_LEVEL, "SXS: %s() found assembly information section with user data too small\n" " Section header: %p\n" " UserDataSize: %lu; needed: %lu\n", __FUNCTION__, Header, Header->UserDataSize, sizeof(ACTIVATION_CONTEXT_DATA_ASSEMBLY_GLOBAL_INFORMATION)); Status = STATUS_SXS_INVALID_ACTCTXDATA_FORMAT; goto Exit; } if ((Header->UserDataOffset + Header->UserDataSize) > ulTemp) { DbgPrintEx( DPFLTR_SXS_ID, DPFLTR_ERROR_LEVEL, "SXS: %s() found assembly information section with user data extending beyond section data\n" " Section header: %p\n" " UserDataSize: %lu\n" " UserDataOffset: %lu\n" " Section size: %lu\n", __FUNCTION__, Header, Header->UserDataSize, Header->UserDataOffset, ulTemp); Status = STATUS_SXS_INVALID_ACTCTXDATA_FORMAT; goto Exit; } GlobalInfo = (PCACTIVATION_CONTEXT_DATA_ASSEMBLY_GLOBAL_INFORMATION) (((ULONG_PTR) Header) + Header->UserDataOffset); if (GlobalInfo->Size < sizeof(ACTIVATION_CONTEXT_DATA_ASSEMBLY_GLOBAL_INFORMATION)) { DbgPrintEx( DPFLTR_SXS_ID, DPFLTR_ERROR_LEVEL, "SXS: %s() found assembly information section global data with size less than structure size\n" " Section header: %p\n" " Global Info: %p\n" " Global Info Size: %lu\n" " Structure size: %lu\n", __FUNCTION__, Header, GlobalInfo, GlobalInfo->Size, sizeof(ACTIVATION_CONTEXT_DATA_ASSEMBLY_GLOBAL_INFORMATION)); Status = STATUS_SXS_INVALID_ACTCTXDATA_FORMAT; goto Exit; } if (GlobalInfo->ApplicationDirectoryOffset != 0) { if (GlobalInfo->ApplicationDirectoryOffset < sizeof(ACTIVATION_CONTEXT_DATA_ASSEMBLY_GLOBAL_INFORMATION)) { DbgPrintEx( DPFLTR_SXS_ID, DPFLTR_ERROR_LEVEL, "SXS: %s() found assembly information section global data with app dir offset within base structure\n" " Section header: %p\n" " GlobalInfo: %p\n" " ApplicationDirectoryOffset: %lu\n", __FUNCTION__, Header, GlobalInfo, GlobalInfo->ApplicationDirectoryOffset); Status = STATUS_SXS_INVALID_ACTCTXDATA_FORMAT; goto Exit; } if ((GlobalInfo->ApplicationDirectoryOffset + GlobalInfo->ApplicationDirectoryLength) > GlobalInfo->Size) { DbgPrintEx( DPFLTR_SXS_ID, DPFLTR_ERROR_LEVEL, "SXS: %s() found assembly information section global data with app dir extending beyond end of global data\n" " Section header: %p\n" " GlobalInfo: %p\n" " ApplicationDirectoryOffset: %lu\n" " ApplicationDirectoryLength: %lu\n" " GlobalInfo size: %lu\n", __FUNCTION__, Header, GlobalInfo, GlobalInfo->ApplicationDirectoryOffset, GlobalInfo->ApplicationDirectoryLength, GlobalInfo->Size); Status = STATUS_SXS_INVALID_ACTCTXDATA_FORMAT; goto Exit; } if (InLength < GlobalInfo->ApplicationDirectoryLength) { if (OutLength != NULL) *OutLength = GlobalInfo->ApplicationDirectoryLength; Status = STATUS_BUFFER_TOO_SMALL; goto Exit; } RtlCopyMemory( OutBuffer, (PVOID) (((ULONG_PTR) GlobalInfo) + GlobalInfo->ApplicationDirectoryOffset), GlobalInfo->ApplicationDirectoryLength); if (OutLength != NULL) *OutLength = GlobalInfo->ApplicationDirectoryLength; } else { // Hmm... there's just no application directory if (OutLength != NULL) *OutLength = 0; // I think we already did this but what the heck } Status = STATUS_SUCCESS; Exit: return Status; } #define \ RTLP_QUERY_INFORMATION_ACTIVATION_CONTEXT_BASIC_INFORMATION_FLAG_NO_ADDREF (0x00000001) NTSTATUS RtlpQueryInformationActivationContextBasicInformation( IN ULONG Flags, IN PCACTIVATION_CONTEXT ConstActivationContext, IN PCACTIVATION_CONTEXT_DATA ActivationContextData, IN ULONG SubInstanceIndex, OUT PVOID Buffer, IN SIZE_T InLength, OUT PSIZE_T OutLength OPTIONAL ) { NTSTATUS Status = STATUS_INTERNAL_ERROR; PACTIVATION_CONTEXT ActivationContext = RTL_CONST_CAST(PACTIVATION_CONTEXT)(ConstActivationContext); PACTIVATION_CONTEXT_BASIC_INFORMATION Info = (PACTIVATION_CONTEXT_BASIC_INFORMATION) Buffer; if (OutLength != NULL) *OutLength = 0; if (SubInstanceIndex != 0) { DbgPrintEx( DPFLTR_SXS_ID, DPFLTR_ERROR_LEVEL, "SXS: %s() received invalid non-zero sub-instance index %lu\n", __FUNCTION__, SubInstanceIndex); Status = STATUS_INVALID_PARAMETER; goto Exit; } if (InLength < sizeof(ACTIVATION_CONTEXT_BASIC_INFORMATION)) { if (OutLength != NULL) { *OutLength = sizeof(ACTIVATION_CONTEXT_BASIC_INFORMATION); } Status = STATUS_BUFFER_TOO_SMALL; goto Exit; } if (ActivationContextData != NULL) Info->Flags = ActivationContextData->Flags; else Info->Flags = 0; if ((Flags & RTLP_QUERY_INFORMATION_ACTIVATION_CONTEXT_BASIC_INFORMATION_FLAG_NO_ADDREF) == 0) { RtlAddRefActivationContext(ActivationContext); } Info->ActivationContext = ActivationContext; if (OutLength != NULL) *OutLength = sizeof(ACTIVATION_CONTEXT_BASIC_INFORMATION); Status = STATUS_SUCCESS; Exit: return Status; } NTSTATUS RtlpQueryInformationActivationContextDetailedInformation( PCACTIVATION_CONTEXT_DATA ActivationContextData, ULONG SubInstanceIndex, OUT PVOID Buffer, IN SIZE_T InLength, OUT PSIZE_T OutLength OPTIONAL ) { NTSTATUS Status = STATUS_INTERNAL_ERROR; PACTIVATION_CONTEXT_DETAILED_INFORMATION Info = (PACTIVATION_CONTEXT_DETAILED_INFORMATION) Buffer; SIZE_T BytesNeeded = 0; PCVOID StringSectionHeader; ULONG StringSectionSize; ULONG DataFormatVersion; PCVOID UserData; ULONG UserDataSize; PCACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_HEADER AssemblyRosterHeader = NULL; PCACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_ENTRY AssemblyRosterEntryList = NULL; PCACTIVATION_CONTEXT_DATA_ASSEMBLY_INFORMATION RootAssemblyInformation = NULL; PCACTIVATION_CONTEXT_DATA_ASSEMBLY_GLOBAL_INFORMATION AssemblyGlobalInformation = NULL; ULONG i; ULONG EntryCount; PWSTR Cursor = NULL; ULONG RtlpLocateActivationContextSectionForQueryDisposition = 0; if (OutLength != NULL) *OutLength = 0; if (SubInstanceIndex != 0) { DbgPrintEx( DPFLTR_SXS_ID, DPFLTR_ERROR_LEVEL, "SXS: %s() received invalid non-zero sub-instance index %lu\n", __FUNCTION__, SubInstanceIndex); Status = STATUS_INVALID_PARAMETER; goto Exit; } // We can't actually do the easy check of InLength against the structure size; we have to figure out the // total bytes we need to include all the paths, etc. // We need to find the assembly metadata section... RtlpLocateActivationContextSectionForQuery( &RtlpLocateActivationContextSectionForQueryDisposition, &Status, Buffer, InLength, OutLength, sizeof(*Info), ActivationContextData, NULL, ACTIVATION_CONTEXT_SECTION_ASSEMBLY_INFORMATION, &StringSectionHeader, &StringSectionSize ); switch (RtlpLocateActivationContextSectionForQueryDisposition) { case RTLP_LOCATE_ACTIVATION_CONTEXT_SECTION_FOR_QUERY_RETURN: goto Exit; case RTLP_LOCATE_ACTIVATION_CONTEXT_SECTION_FOR_QUERY_CONTINUE: break; } Status = RtlpCrackActivationContextStringSectionHeader( StringSectionHeader, StringSectionSize, NULL, &DataFormatVersion, NULL, NULL, NULL, NULL, NULL, &UserDataSize, &UserData); if (!NT_SUCCESS(Status)) goto Exit; AssemblyRosterHeader = (PCACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_HEADER) (((ULONG_PTR) ActivationContextData) + ActivationContextData->AssemblyRosterOffset); AssemblyRosterEntryList = (PCACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_ENTRY) (((ULONG_PTR) ActivationContextData) + AssemblyRosterHeader->FirstEntryOffset); EntryCount = AssemblyRosterHeader->EntryCount; // 1-based counting for Asseblies in the actctx for (i=1; iManifestPathLength != 0) BytesNeeded += (RootAssemblyInformation->ManifestPathLength + sizeof(WCHAR)); if (RootAssemblyInformation->PolicyPathLength != 0) BytesNeeded += (RootAssemblyInformation->PolicyPathLength + sizeof(WCHAR)); if (AssemblyGlobalInformation->ApplicationDirectoryLength != 0) BytesNeeded += (AssemblyGlobalInformation->ApplicationDirectoryLength + sizeof(WCHAR)); if (BytesNeeded > InLength) { if (OutLength != NULL) *OutLength = BytesNeeded; Status = STATUS_BUFFER_TOO_SMALL; goto Exit; } // Wow, it's all there and ready to go. Let's fill in! Cursor = (PWSTR) (Info + 1); Info->dwFlags = ActivationContextData->Flags; Info->ulFormatVersion = ActivationContextData->FormatVersion; Info->ulAssemblyCount = AssemblyRosterHeader->EntryCount - 1; Info->ulRootManifestPathType = RootAssemblyInformation->ManifestPathType; Info->ulRootManifestPathChars = (RootAssemblyInformation->ManifestPathLength / sizeof(WCHAR)); Info->lpRootManifestPath = NULL; Info->ulRootConfigurationPathType = RootAssemblyInformation->PolicyPathType; Info->ulRootConfigurationPathChars = (RootAssemblyInformation->PolicyPathLength / sizeof(WCHAR)); Info->lpRootConfigurationPath = NULL; Info->ulAppDirPathType = AssemblyGlobalInformation->ApplicationDirectoryPathType; Info->ulAppDirPathChars = (AssemblyGlobalInformation->ApplicationDirectoryLength / sizeof(WCHAR)); Info->lpAppDirPath = NULL; // And copy the strings... if (RootAssemblyInformation->ManifestPathLength != 0) { RtlCopyMemory( Cursor, (PVOID) (((ULONG_PTR) StringSectionHeader) + RootAssemblyInformation->ManifestPathOffset), RootAssemblyInformation->ManifestPathLength); Info->lpRootManifestPath = Cursor; Cursor = (PWSTR) (((ULONG_PTR) Cursor) + RootAssemblyInformation->ManifestPathLength); *Cursor++ = L'\0'; } if (RootAssemblyInformation->PolicyPathLength != 0) { RtlCopyMemory( Cursor, (PVOID) (((ULONG_PTR) StringSectionHeader) + RootAssemblyInformation->PolicyPathOffset), RootAssemblyInformation->PolicyPathLength); Info->lpRootConfigurationPath = Cursor; Cursor = (PWSTR) (((ULONG_PTR) Cursor) + RootAssemblyInformation->PolicyPathLength); *Cursor++ = L'\0'; } if (AssemblyGlobalInformation->ApplicationDirectoryLength != 0) { RtlCopyMemory( Cursor, (PVOID) (((ULONG_PTR) AssemblyGlobalInformation) + AssemblyGlobalInformation->ApplicationDirectoryOffset), AssemblyGlobalInformation->ApplicationDirectoryLength); Info->lpAppDirPath = Cursor; Cursor = (PWSTR) (((ULONG_PTR) Cursor) + AssemblyGlobalInformation->ApplicationDirectoryLength); *Cursor++ = L'\0'; } ASSERT((((ULONG_PTR) Cursor) - ((ULONG_PTR) Info)) == BytesNeeded); if (OutLength != NULL) *OutLength = BytesNeeded; Status = STATUS_SUCCESS; Exit: return Status; } NTSTATUS RtlpQueryAssemblyInformationActivationContextDetailedInformation( PCACTIVATION_CONTEXT_DATA ActivationContextData, ULONG SubInstanceIndex, // 0-based index of assembly OUT PVOID Buffer, IN SIZE_T InLength, OUT PSIZE_T OutLength OPTIONAL ) { NTSTATUS Status = STATUS_INTERNAL_ERROR; SIZE_T BytesNeeded = 0; PACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION Info= (PACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION)Buffer; PCVOID StringSectionHeader; ULONG StringSectionSize; PWSTR Cursor = NULL; PCACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_HEADER AssemblyRosterHeader = NULL; PCACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_ENTRY AssemblyRosterEntryList = NULL; PACTIVATION_CONTEXT_DATA_ASSEMBLY_INFORMATION AssemlbyDataInfo = NULL; ULONG RtlpLocateActivationContextSectionForQueryDisposition = 0; if (OutLength != NULL) *OutLength = 0; // We can't actually do the easy check of InLength against the structure size; we have to figure out the // total bytes we need to include all the paths, etc. AssemblyRosterHeader = (PCACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_HEADER) (((ULONG_PTR) ActivationContextData) + ActivationContextData->AssemblyRosterOffset); AssemblyRosterEntryList = (PCACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_ENTRY) (((ULONG_PTR) ActivationContextData) + AssemblyRosterHeader->FirstEntryOffset); if (SubInstanceIndex > AssemblyRosterHeader->EntryCount) // AssemblyRosterHeader->EntryCount is 1-based, { DbgPrintEx( DPFLTR_SXS_ID, DPFLTR_ERROR_LEVEL, "SXS: %s() received invalid sub-instance index %lu out of %lu Assemblies in the Acitvation Context\n", __FUNCTION__, SubInstanceIndex, AssemblyRosterHeader->EntryCount ); Status = STATUS_INVALID_PARAMETER; goto Exit; } AssemlbyDataInfo = (PACTIVATION_CONTEXT_DATA_ASSEMBLY_INFORMATION)((ULONG_PTR)ActivationContextData + AssemblyRosterEntryList[SubInstanceIndex].AssemblyInformationOffset); // We need to find the assembly metadata section... RtlpLocateActivationContextSectionForQuery( &RtlpLocateActivationContextSectionForQueryDisposition, &Status, Buffer, InLength, OutLength, sizeof(ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION), ActivationContextData, NULL, ACTIVATION_CONTEXT_SECTION_ASSEMBLY_INFORMATION, &StringSectionHeader, &StringSectionSize ); switch (RtlpLocateActivationContextSectionForQueryDisposition) { case RTLP_LOCATE_ACTIVATION_CONTEXT_SECTION_FOR_QUERY_RETURN: goto Exit; case RTLP_LOCATE_ACTIVATION_CONTEXT_SECTION_FOR_QUERY_CONTINUE: break; } // Figure out the size of the buffer required. BytesNeeded = sizeof(ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION); if (AssemlbyDataInfo->EncodedAssemblyIdentityLength != 0 ) BytesNeeded += (AssemlbyDataInfo->EncodedAssemblyIdentityLength + sizeof(WCHAR)); if (AssemlbyDataInfo->ManifestPathLength != 0 ) BytesNeeded += (AssemlbyDataInfo->ManifestPathLength + sizeof(WCHAR)); if (AssemlbyDataInfo->PolicyPathLength != 0 ) BytesNeeded += (AssemlbyDataInfo->PolicyPathLength + sizeof(WCHAR)); if (AssemlbyDataInfo->AssemblyDirectoryNameLength != 0 ) BytesNeeded += (AssemlbyDataInfo->AssemblyDirectoryNameLength + sizeof(WCHAR)); if (BytesNeeded > InLength) { if (OutLength != NULL) *OutLength = BytesNeeded; Status = STATUS_BUFFER_TOO_SMALL; goto Exit; } // fill in the struct Cursor = (PWSTR) (Info + 1); Info->ulFlags = AssemlbyDataInfo->Flags; Info->ulEncodedAssemblyIdentityLength = AssemlbyDataInfo->EncodedAssemblyIdentityLength; Info->ulManifestPathType = AssemlbyDataInfo->ManifestPathType; Info->ulManifestPathLength = AssemlbyDataInfo->ManifestPathLength ; Info->liManifestLastWriteTime = AssemlbyDataInfo->ManifestLastWriteTime; Info->ulPolicyPathType = AssemlbyDataInfo->PolicyPathType; Info->ulPolicyPathLength = AssemlbyDataInfo->PolicyPathLength; Info->liPolicyLastWriteTime = AssemlbyDataInfo->PolicyLastWriteTime; Info->ulMetadataSatelliteRosterIndex = AssemlbyDataInfo->MetadataSatelliteRosterIndex; Info->ulManifestVersionMajor = AssemlbyDataInfo->ManifestVersionMajor; Info->ulManifestVersionMinor = AssemlbyDataInfo->ManifestVersionMinor; Info->ulPolicyVersionMajor = AssemlbyDataInfo->PolicyVersionMajor; Info->ulPolicyVersionMinor = AssemlbyDataInfo->PolicyVersionMinor; Info->ulAssemblyDirectoryNameLength = AssemlbyDataInfo->AssemblyDirectoryNameLength; // in bytes Info->lpAssemblyEncodedAssemblyIdentity = NULL; Info->lpAssemblyManifestPath = NULL; Info->lpAssemblyPolicyPath = NULL; Info->lpAssemblyDirectoryName = NULL; Info->ulFileCount = AssemlbyDataInfo->NumOfFilesInAssembly; if (AssemlbyDataInfo->EncodedAssemblyIdentityLength != 0) { RtlCopyMemory( Cursor, (PVOID) (((ULONG_PTR) StringSectionHeader) + AssemlbyDataInfo->EncodedAssemblyIdentityOffset), AssemlbyDataInfo->EncodedAssemblyIdentityLength); Info->lpAssemblyEncodedAssemblyIdentity = Cursor; Cursor = (PWSTR) (((ULONG_PTR) Cursor) + AssemlbyDataInfo->EncodedAssemblyIdentityLength); *Cursor++ = L'\0'; } if (AssemlbyDataInfo->ManifestPathLength != 0) { RtlCopyMemory( Cursor, (PVOID) (((ULONG_PTR) StringSectionHeader) + AssemlbyDataInfo->ManifestPathOffset), AssemlbyDataInfo->ManifestPathLength); Info->lpAssemblyManifestPath = Cursor; Cursor = (PWSTR) (((ULONG_PTR) Cursor) + AssemlbyDataInfo->ManifestPathLength); *Cursor++ = L'\0'; } if (AssemlbyDataInfo->PolicyPathLength != 0) { RtlCopyMemory( Cursor, (PVOID) (((ULONG_PTR) StringSectionHeader) + AssemlbyDataInfo->PolicyPathOffset), AssemlbyDataInfo->PolicyPathLength); Info->lpAssemblyPolicyPath = Cursor; Cursor = (PWSTR) (((ULONG_PTR) Cursor) + AssemlbyDataInfo->PolicyPathLength); *Cursor++ = L'\0'; } if (AssemlbyDataInfo->AssemblyDirectoryNameLength != 0) { RtlCopyMemory( Cursor, (PVOID) (((ULONG_PTR) StringSectionHeader) + AssemlbyDataInfo->AssemblyDirectoryNameOffset), AssemlbyDataInfo->AssemblyDirectoryNameLength); Info->lpAssemblyDirectoryName = Cursor; Cursor = (PWSTR) (((ULONG_PTR) Cursor) + AssemlbyDataInfo->AssemblyDirectoryNameLength); *Cursor++ = L'\0'; } ASSERT((((ULONG_PTR) Cursor) - ((ULONG_PTR) Info)) == BytesNeeded); if (OutLength != NULL) *OutLength = BytesNeeded; Status = STATUS_SUCCESS; Exit: return Status; } NTSTATUS RtlpQueryFilesInAssemblyInformationActivationContextDetailedInformation( PCACTIVATION_CONTEXT_DATA ActivationContextData, PCACTIVATION_CONTEXT_QUERY_INDEX SubInstanceIndex, OUT PVOID Buffer, IN SIZE_T InLength, OUT PSIZE_T OutLength OPTIONAL ) { NTSTATUS Status = STATUS_INTERNAL_ERROR; SIZE_T BytesNeeded = 0; PASSEMBLY_DLL_REDIRECTION_DETAILED_INFORMATION Info= (PASSEMBLY_DLL_REDIRECTION_DETAILED_INFORMATION)Buffer; PCACTIVATION_CONTEXT_STRING_SECTION_HEADER StringSectionHeader=NULL; ULONG StringSectionSize; PWSTR Cursor = NULL; PCACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_HEADER AssemblyRosterHeader = NULL; PCACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_ENTRY AssemblyRosterEntryList = NULL; PCACTIVATION_CONTEXT_STRING_SECTION_ENTRY ElementList = NULL; PCACTIVATION_CONTEXT_DATA_DLL_REDIRECTION EntryData = NULL; ULONG i, CounterForFilesFoundInSpecifiedAssembly; PCACTIVATION_CONTEXT_DATA_DLL_REDIRECTION_PATH_SEGMENT PathSegments = NULL; ULONG RtlpLocateActivationContextSectionForQueryDisposition = 0; if (OutLength != NULL) *OutLength = 0; // We can't actually do the easy check of InLength against the structure size; we have to figure out the // total bytes we need to include all the paths, etc. AssemblyRosterHeader = (PCACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_HEADER) (((ULONG_PTR) ActivationContextData) + ActivationContextData->AssemblyRosterOffset); AssemblyRosterEntryList = (PCACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_ENTRY) (((ULONG_PTR) ActivationContextData) + AssemblyRosterHeader->FirstEntryOffset); if (SubInstanceIndex->ulAssemblyIndex >= AssemblyRosterHeader->EntryCount - 1)// AssemblyRosterHeader->EntryCount is 1-based, { DbgPrintEx( DPFLTR_SXS_ID, DPFLTR_ERROR_LEVEL, "SXS: %s() received invalid sub-instance index %lu out of %lu Assemblies in the Acitvation Context\n", __FUNCTION__, SubInstanceIndex->ulAssemblyIndex, AssemblyRosterHeader->EntryCount ); Status = STATUS_INVALID_PARAMETER; goto Exit; } // We need to find the assembly metadata section... RtlpLocateActivationContextSectionForQuery( &RtlpLocateActivationContextSectionForQueryDisposition, &Status, Buffer, InLength, OutLength, sizeof(ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION), ActivationContextData, NULL, ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION, (PCVOID*)&StringSectionHeader, &StringSectionSize ); switch (RtlpLocateActivationContextSectionForQueryDisposition) { case RTLP_LOCATE_ACTIVATION_CONTEXT_SECTION_FOR_QUERY_RETURN: goto Exit; case RTLP_LOCATE_ACTIVATION_CONTEXT_SECTION_FOR_QUERY_CONTINUE: break; } if (SubInstanceIndex->ulFileIndexInAssembly >= StringSectionHeader->ElementCount) { DbgPrintEx( DPFLTR_SXS_ID, DPFLTR_ERROR_LEVEL, "SXS: %s() received invalid file index (%d) in Assembly (%d)\n", __FUNCTION__, SubInstanceIndex->ulFileIndexInAssembly, SubInstanceIndex->ulAssemblyIndex, StringSectionHeader->ElementCount ); Status = STATUS_INVALID_PARAMETER; goto Exit; } if (StringSectionHeader->ElementListOffset != 0) ElementList = (PCACTIVATION_CONTEXT_STRING_SECTION_ENTRY)(((ULONG_PTR)StringSectionHeader) + StringSectionHeader->ElementListOffset); else { Status = STATUS_INTERNAL_ERROR; goto Exit; } CounterForFilesFoundInSpecifiedAssembly = 0 ; EntryData = NULL; for ( i = 0 ; i < StringSectionHeader->ElementCount; i++ ) { // for a specified assembly if (ElementList[i].AssemblyRosterIndex == SubInstanceIndex->ulAssemblyIndex + 1) { // for specified file in this assembly if (CounterForFilesFoundInSpecifiedAssembly == SubInstanceIndex->ulFileIndexInAssembly) { if (ElementList[i].Offset != 0) { // we found the right one EntryData = (PCACTIVATION_CONTEXT_DATA_DLL_REDIRECTION)(((ULONG_PTR)StringSectionHeader) + ElementList[i].Offset); break; } } CounterForFilesFoundInSpecifiedAssembly ++; } } if (EntryData == NULL ) { Status = STATUS_INTERNAL_ERROR; goto Exit; } // figure out buffer size needed BytesNeeded = sizeof(ASSEMBLY_DLL_REDIRECTION_DETAILED_INFORMATION); if (ElementList[i].KeyLength != 0) BytesNeeded += (ElementList[i].KeyLength + sizeof(WCHAR)); // for filename if (EntryData->TotalPathLength != 0) BytesNeeded += (EntryData->TotalPathLength + sizeof(WCHAR)); if (BytesNeeded > InLength) { if (OutLength != NULL) *OutLength = BytesNeeded; Status = STATUS_BUFFER_TOO_SMALL; goto Exit; } // let us fill in Cursor = (PWSTR) (Info + 1); Info->ulFlags = EntryData->Flags; Info->ulFilenameLength = ElementList[i].KeyLength; Info->ulPathLength = EntryData->TotalPathLength; Info->lpFileName = NULL; Info->lpFilePath = NULL; // copy the strings... // copy the filename if (ElementList[i].KeyLength != 0) { RtlCopyMemory( Cursor, (PVOID) (((ULONG_PTR) StringSectionHeader) + ElementList[i].KeyOffset), ElementList[i].KeyLength); Info->lpFileName = Cursor; Cursor = (PWSTR) (((ULONG_PTR) Cursor) + ElementList[i].KeyLength); *Cursor++ = L'\0'; } // concatenate the path if (EntryData->TotalPathLength != 0) { if (EntryData->PathSegmentOffset != 0) PathSegments = (PCACTIVATION_CONTEXT_DATA_DLL_REDIRECTION_PATH_SEGMENT)(StringSectionHeader + EntryData->PathSegmentOffset); if (PathSegments != NULL) { Info->lpFilePath = Cursor; for (i=0; i < EntryData->PathSegmentCount; i++) { if (PathSegments[i].Offset != 0) { RtlCopyMemory( Cursor, (PVOID) (((ULONG_PTR) StringSectionHeader) + PathSegments[i].Offset), PathSegments[i].Length); Cursor = (PWSTR) (((ULONG_PTR) Cursor) + PathSegments[i].Length); } } *Cursor++ = L'\0'; } } ASSERT((((ULONG_PTR) Cursor) - ((ULONG_PTR) Info)) == BytesNeeded); Status = STATUS_SUCCESS; Exit: return Status; } NTSTATUS NTAPI RtlQueryInformationActivationContext( IN ULONG Flags, IN PCACTIVATION_CONTEXT ActivationContext, IN PVOID SubInstanceIndex, IN ACTIVATION_CONTEXT_INFO_CLASS InfoClass, OUT PVOID Buffer, IN SIZE_T InLength, OUT PSIZE_T OutLength OPTIONAL ) { NTSTATUS Status = STATUS_INTERNAL_ERROR; BOOLEAN LoaderLockLocked = FALSE; PVOID LoaderLockCookie = NULL; PCACTIVATION_CONTEXT_DATA ActivationContextData = NULL; __try { if (OutLength != NULL) { *OutLength = 0; } if ((Flags & ~( RTL_QUERY_INFORMATION_ACTIVATION_CONTEXT_FLAG_USE_ACTIVE_ACTIVATION_CONTEXT | RTL_QUERY_INFORMATION_ACTIVATION_CONTEXT_FLAG_ACTIVATION_CONTEXT_IS_MODULE | RTL_QUERY_INFORMATION_ACTIVATION_CONTEXT_FLAG_ACTIVATION_CONTEXT_IS_ADDRESS | RTL_QUERY_INFORMATION_ACTIVATION_CONTEXT_FLAG_NO_ADDREF )) != 0) { DbgPrintEx( DPFLTR_SXS_ID, DPFLTR_ERROR_LEVEL, "SXS: %s() - Caller passed invalid flags (0x%08lx)\n", __FUNCTION__, Flags); Status = STATUS_INVALID_PARAMETER_1; goto Exit; } // // REVIEW do we really care? // And check that no other infoclass really does include an optionally addrefed actctx. // if ((Flags & RTL_QUERY_INFORMATION_ACTIVATION_CONTEXT_FLAG_NO_ADDREF) != 0 && InfoClass != ActivationContextBasicInformation) { DbgPrintEx( DPFLTR_SXS_ID, DPFLTR_ERROR_LEVEL, "SXS: %s() - Caller passed meaningless flags/class combination (0x%08lx/0x%08lx)\n", __FUNCTION__, Flags, InfoClass); Status = STATUS_INVALID_PARAMETER_1; goto Exit; } if ((InfoClass != ActivationContextBasicInformation) && (InfoClass != ActivationContextDetailedInformation) && (InfoClass != AssemblyDetailedInformationInActivationContxt ) && (InfoClass != FileInformationInAssemblyOfAssemblyInActivationContxt)) { DbgPrintEx( DPFLTR_SXS_ID, DPFLTR_ERROR_LEVEL, "SXS: %s() - caller asked for unknown information class %lu\n", __FUNCTION__, InfoClass); Status = STATUS_INVALID_PARAMETER_3; goto Exit; } if ((InLength != 0) && (Buffer == NULL)) { DbgPrintEx( DPFLTR_SXS_ID, DPFLTR_ERROR_LEVEL, "SXS: %s() - caller passed nonzero buffer length but NULL buffer pointer\n", __FUNCTION__); Status = STATUS_INVALID_PARAMETER_4; goto Exit; } if ((InLength == 0) && (OutLength == NULL)) { DbgPrintEx( DPFLTR_SXS_ID, DPFLTR_ERROR_LEVEL, "SXS: %s() - caller supplied no buffer to populate and no place to return required byte count\n", __FUNCTION__); Status = STATUS_INVALID_PARAMETER_6; goto Exit; } switch ( Flags & ( RTL_QUERY_INFORMATION_ACTIVATION_CONTEXT_FLAG_USE_ACTIVE_ACTIVATION_CONTEXT | RTL_QUERY_INFORMATION_ACTIVATION_CONTEXT_FLAG_ACTIVATION_CONTEXT_IS_MODULE | RTL_QUERY_INFORMATION_ACTIVATION_CONTEXT_FLAG_ACTIVATION_CONTEXT_IS_ADDRESS )) { default: DbgPrintEx( DPFLTR_SXS_ID, DPFLTR_ERROR_LEVEL, "SXS: %s() - Caller passed invalid flags (0x%08lx)\n", __FUNCTION__, Flags); Status = STATUS_INVALID_PARAMETER_1; goto Exit; case 0: break; case RTL_QUERY_INFORMATION_ACTIVATION_CONTEXT_FLAG_USE_ACTIVE_ACTIVATION_CONTEXT: { PCRTL_ACTIVATION_CONTEXT_STACK_FRAME Frame; if (ActivationContext != NULL) { DbgPrintEx( DPFLTR_SXS_ID, DPFLTR_ERROR_LEVEL, "SXS: %s() - caller asked to use active activation context but passed %p\n", __FUNCTION__, ActivationContext); Status = STATUS_INVALID_PARAMETER_2; goto Exit; } Frame = NtCurrentTeb()->ActivationContextStack.ActiveFrame; if (Frame != NULL) { ActivationContext = Frame->ActivationContext; } } break; case RTL_QUERY_INFORMATION_ACTIVATION_CONTEXT_FLAG_ACTIVATION_CONTEXT_IS_ADDRESS: { PVOID DllHandle; if (ActivationContext == NULL) { DbgPrintEx( DPFLTR_SXS_ID, DPFLTR_ERROR_LEVEL, "SXS: %s() - Caller asked to use activation context from address in .dll but passed NULL\n", __FUNCTION__ ); Status = STATUS_INVALID_PARAMETER_2; goto Exit; } Status = LdrLockLoaderLock(0, NULL, &LoaderLockCookie); if (!NT_SUCCESS(Status)) { goto Exit; } LoaderLockLocked = TRUE; DllHandle = RtlPcToFileHeader((PVOID)(PCVOID)ActivationContext, &DllHandle); if (DllHandle == NULL) { DbgPrintEx( DPFLTR_SXS_ID, DPFLTR_ERROR_LEVEL, "SXS: %s() - Caller passed invalid address, not in any .dll (%p)\n", __FUNCTION__, ActivationContext); Status = STATUS_DLL_NOT_FOUND; // REVIEW goto Exit; } ActivationContext = (PCACTIVATION_CONTEXT)DllHandle; } // FALLTHROUGH case RTL_QUERY_INFORMATION_ACTIVATION_CONTEXT_FLAG_ACTIVATION_CONTEXT_IS_MODULE: { PLDR_DATA_TABLE_ENTRY LdrDataTableEntry; if (ActivationContext == NULL) { DbgPrintEx( DPFLTR_SXS_ID, DPFLTR_ERROR_LEVEL, "SXS: %s() - Caller asked to use activation context from hmodule but passed NULL\n", __FUNCTION__ ); Status = STATUS_INVALID_PARAMETER_2; goto Exit; } if (!LoaderLockLocked) { Status = LdrLockLoaderLock(0, NULL, &LoaderLockCookie); if (!NT_SUCCESS(Status)) goto Exit; LoaderLockLocked = TRUE; } if (!LdrpCheckForLoadedDllHandle((PVOID)(PCVOID)ActivationContext, &LdrDataTableEntry)) { DbgPrintEx( DPFLTR_SXS_ID, DPFLTR_ERROR_LEVEL, "SXS: %s() - Caller passed invalid hmodule (%p)\n", __FUNCTION__, ActivationContext); Status = STATUS_DLL_NOT_FOUND; // REVIEW goto Exit; } ActivationContext = LdrDataTableEntry->EntryPointActivationContext; } break; } Status = RtlpGetActivationContextData( RTLP_GET_ACTIVATION_CONTEXT_DATA_MAP_NULL_TO_EMPTY, ActivationContext, NULL, &ActivationContextData); if (!NT_SUCCESS(Status)) goto Exit; if (ActivationContextData == NULL) { switch (InfoClass) { case ActivationContextBasicInformation: default: break; case ActivationContextDetailedInformation: case AssemblyDetailedInformationInActivationContxt: case FileInformationInAssemblyOfAssemblyInActivationContxt: Status = STATUS_INVALID_PARAMETER_1; goto Exit; } } switch (InfoClass) { case ActivationContextBasicInformation: { ULONG BasicInfoFlags = 0; if ((Flags & RTL_QUERY_INFORMATION_ACTIVATION_CONTEXT_FLAG_NO_ADDREF) != 0) { BasicInfoFlags |= RTLP_QUERY_INFORMATION_ACTIVATION_CONTEXT_BASIC_INFORMATION_FLAG_NO_ADDREF; } Status = RtlpQueryInformationActivationContextBasicInformation( BasicInfoFlags, ActivationContext, ActivationContextData, 0, Buffer, InLength, OutLength ); if (!NT_SUCCESS(Status)) goto Exit; } break; case ActivationContextDetailedInformation: Status = RtlpQueryInformationActivationContextDetailedInformation( ActivationContextData, 0, Buffer, InLength, OutLength ); if (!NT_SUCCESS(Status)) goto Exit; break; case AssemblyDetailedInformationInActivationContxt: if (SubInstanceIndex == NULL) { Status = STATUS_INVALID_PARAMETER; goto Exit; } Status = RtlpQueryAssemblyInformationActivationContextDetailedInformation( ActivationContextData, *((ULONG *)SubInstanceIndex), Buffer, InLength, OutLength ); if (!NT_SUCCESS(Status)) goto Exit; break; case FileInformationInAssemblyOfAssemblyInActivationContxt: Status = RtlpQueryFilesInAssemblyInformationActivationContextDetailedInformation( ActivationContextData, ((ACTIVATION_CONTEXT_QUERY_INDEX *)SubInstanceIndex), Buffer, InLength, OutLength ); if (!NT_SUCCESS(Status)) goto Exit; break; default: DbgPrintEx( DPFLTR_SXS_ID, DPFLTR_ERROR_LEVEL, "SXS: %s() - internal coding error; missing switch statement branch for InfoClass == %lu\n", __FUNCTION__, InfoClass); Status = STATUS_INTERNAL_ERROR; goto Exit; } Status = STATUS_SUCCESS; Exit: ; } __finally { if (LoaderLockLocked) LdrUnlockLoaderLock(0, LoaderLockCookie); } return Status; } NTSTATUS NTAPI RtlQueryInformationActiveActivationContext( IN ACTIVATION_CONTEXT_INFO_CLASS InfoClass, OUT PVOID OutBuffer, IN SIZE_T InLength, OUT PSIZE_T OutLength OPTIONAL ) { return RtlQueryInformationActivationContext( RTL_QUERY_INFORMATION_ACTIVATION_CONTEXT_FLAG_USE_ACTIVE_ACTIVATION_CONTEXT, NULL, 0, InfoClass, OutBuffer, InLength, OutLength); } #if defined(__cplusplus) } /* extern "C" */ #endif