1443 lines
51 KiB
C
1443 lines
51 KiB
C
/*++
|
|
|
|
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 <ntos.h>
|
|
#include <ntrtl.h>
|
|
#include <nturtl.h>
|
|
#include <sxstypes.h>
|
|
#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; i<EntryCount; i++) {
|
|
if (AssemblyRosterEntryList[i].Flags & ACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_ENTRY_ROOT)
|
|
break;
|
|
}
|
|
|
|
if (i == EntryCount) {
|
|
DbgPrintEx(
|
|
DPFLTR_SXS_ID,
|
|
DPFLTR_ERROR_LEVEL,
|
|
"SXS: %s() found activation context data at %p with assembly roster that has no root\n",
|
|
__FUNCTION__,
|
|
ActivationContextData);
|
|
Status = STATUS_SXS_INVALID_ACTCTXDATA_FORMAT;
|
|
goto Exit;
|
|
}
|
|
|
|
RootAssemblyInformation = (PCACTIVATION_CONTEXT_DATA_ASSEMBLY_INFORMATION) (((ULONG_PTR) ActivationContextData) + AssemblyRosterEntryList[i].AssemblyInformationOffset);
|
|
AssemblyGlobalInformation = (PCACTIVATION_CONTEXT_DATA_ASSEMBLY_GLOBAL_INFORMATION) UserData;
|
|
|
|
// Ok, we have everything we could need. Figure out the size of the buffer required.
|
|
|
|
BytesNeeded = sizeof(ACTIVATION_CONTEXT_DETAILED_INFORMATION);
|
|
|
|
if (RootAssemblyInformation->ManifestPathLength != 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
|